Hi all,
I've extended :sort command in vim - now it can sort by floating point
values as well as dec/hex/oct. Submitting the change for review.
Kind regards,
Alex
>>>>>>>>>>>>>>>> BEGIN OF HG EXPORT
# HG changeset patch
# User Alex Jakushev <
alex.j...@gmail.com>
# Date 1288482264 -3600
# Node ID a31735077986cf251235d6a007c6552acf5e77d6
# Parent b6ba81f1258fc53fcb030868229971e239d43aee
Help updated for "sort f"
diff -r b6ba81f1258f -r a31735077986 runtime/doc/change.txt
--- a/runtime/doc/change.txt Sun Oct 31 00:17:20 2010 +0100
+++ b/runtime/doc/change.txt Sun Oct 31 00:44:24 2010 +0100
@@ -1585,7 +1585,7 @@
found here: |sort()|.
*:sor* *:sort*
-:[range]sor[t][!] [i][u][r][n][x][o] [/{pattern}/]
+:[range]sor[t][!] [i][u][r][n][x][o][f] [/{pattern}/]
Sort lines in [range]. When no range is given all
lines are sorted.
@@ -1605,6 +1605,14 @@
With [o] sorting is done on the first octal number in
the line (after or inside a {pattern} match).
+ With [f] sorting is done on the Float in the line.
+ The value of Float is determined similar to passing
+ the text (after or inside a {pattern} match) to
+ str2float() function. This option is available only
+ if Vim was compiled with Floating point support.
+
+ Options [n][x][o][f] are mutually exclusive.
+
With [u] only keep the first of a sequence of
identical lines (ignoring case when [i] is used).
Without this flag, a sequence of identical lines
# HG changeset patch
# User Alex Jakushev <
alex.j...@gmail.com>
# Date 1288480640 -3600
# Node ID b6ba81f1258fc53fcb030868229971e239d43aee
# Parent df6b12c84b2359415cd987c016f5de135c680100
Support of sorting by floating point numbers
diff -r df6b12c84b23 -r b6ba81f1258f src/ex_cmds.c
--- a/src/ex_cmds.c Wed Oct 27 18:36:36 2010 +0200
+++ b/src/ex_cmds.c Sun Oct 31 00:17:20 2010 +0100
@@ -17,6 +17,9 @@
#include "vim.h"
#include "version.h"
+#ifdef FEAT_FLOAT
+#include <float.h>
+#endif
#ifdef FEAT_EX_EXTRA
static int linelen __ARGS((int *has_tab));
@@ -282,6 +285,9 @@
static int sort_ic; /* ignore case */
static int sort_nr; /* sort on number */
static int sort_rx; /* sort on regex instead of skipping it */
+#ifdef FEAT_FLOAT
+static int sort_flt; /* sort on floating number */
+#endif
static int sort_abort; /* flag to indicate if sorting has been
interrupted */
@@ -289,8 +295,17 @@
typedef struct
{
linenr_T lnum; /* line number */
- long start_col_nr; /* starting column number or number */
- long end_col_nr; /* ending column number */
+ union {
+ struct
+ {
+ long start_col_nr; /* starting column number */
+ long end_col_nr; /* ending column number */
+ } line;
+ long value; // value if sorting by number (n/o/x)
+#ifdef FEAT_FLOAT
+ float_T value_flt; // value if sorting by float
+#endif
+ } st_u;
} sorti_T;
static int
@@ -320,22 +335,25 @@
if (got_int)
sort_abort = TRUE;
- /* When sorting numbers "start_col_nr" is the number, not the
column
- * number. */
if (sort_nr)
- result = l1.start_col_nr == l2.start_col_nr ? 0
- : l1.start_col_nr > l2.start_col_nr ? 1 : -1;
+ result = l1.st_u.value == l2.st_u.value ? 0
+ : l1.st_u.value > l2.st_u.value ? 1 : -1;
+#ifdef FEAT_FLOAT
+ else if (sort_flt)
+ result = l1.st_u.value_flt == l2.st_u.value_flt ? 0
+ : l1.st_u.value_flt > l2.st_u.value_flt ? 1 : -1;
+#endif
else
{
/* We need to copy one line into "sortbuf1", because there is no
* guarantee that the first pointer becomes invalid when obtaining
the
* second one. */
- STRNCPY(sortbuf1, ml_get(l1.lnum) + l1.start_col_nr,
- l1.end_col_nr - l1.start_col_nr + 1);
- sortbuf1[l1.end_col_nr - l1.start_col_nr] = 0;
- STRNCPY(sortbuf2, ml_get(l2.lnum) + l2.start_col_nr,
- l2.end_col_nr - l2.start_col_nr + 1);
- sortbuf2[l2.end_col_nr - l2.start_col_nr] = 0;
+ STRNCPY(sortbuf1, ml_get(l1.lnum) + l1.st_u.line.start_col_nr,
+ l1.st_u.line.end_col_nr - l1.st_u.line.start_col_nr + 1);
+ sortbuf1[l1.st_u.line.end_col_nr - l1.st_u.line.start_col_nr] = 0;
+ STRNCPY(sortbuf2, ml_get(l2.lnum) + l2.st_u.line.start_col_nr,
+ l2.st_u.line.end_col_nr - l2.st_u.line.start_col_nr + 1);
+ sortbuf2[l2.st_u.line.end_col_nr - l2.st_u.line.start_col_nr] = 0;
result = sort_ic ? STRICMP(sortbuf1, sortbuf2)
: STRCMP(sortbuf1, sortbuf2);
@@ -371,6 +389,7 @@
colnr_T end_col;
int sort_oct; /* sort on octal number */
int sort_hex; /* sort on hex number */
+ int sort_special_all; /* sort on any possible numeric value */
/* Sorting one line is really quick! */
if (count <= 1)
@@ -386,6 +405,9 @@
goto sortend;
sort_abort = sort_ic = sort_rx = sort_nr = sort_oct = sort_hex =
0;
+#ifdef FEAT_FLOAT
+ sort_flt = 0;
+#endif
for (p = eap->arg; *p != NUL; ++p)
{
@@ -401,6 +423,10 @@
sort_oct = 2;
else if (*p == 'x')
sort_hex = 2;
+#ifdef FEAT_FLOAT
+ else if (*p == 'f')
+ sort_flt = 2;
+#endif
else if (*p == 'u')
unique = TRUE;
else if (*p == '"') /* comment start */
@@ -436,14 +462,19 @@
}
}
- /* Can only have one of 'n', 'o' and 'x'. */
- if (sort_nr + sort_oct + sort_hex > 2)
+ sort_special_all = sort_nr + sort_oct + sort_hex;
+#ifdef FEAT_FLOAT
+ sort_special_all += sort_flt;
+#endif
+
+ /* Can only have one of 'f', 'n', 'o' and 'x'. */
+ if (sort_special_all > 2)
{
EMSG(_(e_invarg));
goto sortend;
}
- /* From here on "sort_nr" is used as a flag for any number
sorting. */
+ /* From here on "sort_nr" is used as a flag for any *int* number
sorting. */
sort_nr += sort_oct + sort_hex;
/*
@@ -477,7 +508,7 @@
if (regmatch.regprog != NULL)
end_col = 0;
- if (sort_nr)
+ if (sort_special_all)
{
/* Make sure vim_str2nr doesn't read any digits past the end
* of the match, by temporarily terminating the string there */
@@ -486,25 +517,44 @@
*s2 = NUL;
/* Sorting on number: Store the number itself. */
p = s + start_col;
- if (sort_hex)
- s = skiptohex(p);
- else
- s = skiptodigit(p);
- if (s > p && s[-1] == '-')
- --s; /* include preceding negative sign */
- if (*s == NUL)
- /* empty line should sort before any number */
- nrs[lnum - eap->line1].start_col_nr = -MAXLNUM;
- else
- vim_str2nr(s, NULL, NULL, sort_oct, sort_hex,
- &nrs[lnum - eap->line1].start_col_nr, NULL);
+
+ if (sort_nr)
+ {
+ if (sort_hex)
+ s = skiptohex(p);
+ else
+ s = skiptodigit(p);
+ if (s > p && s[-1] == '-')
+ --s; /* include preceding negative sign */
+ if (*s == NUL)
+ /* empty line should sort before any number */
+ nrs[lnum - eap->line1].st_u.value = -MAXLNUM;
+ else
+ vim_str2nr(s, NULL, NULL, sort_oct, sort_hex,
+ &nrs[lnum - eap->line1].st_u.value, NULL);
+ }
+#ifdef FEAT_FLOAT
+ else if (sort_flt)
+ {
+ s = skipwhite(p);
+ if (*s == '+')
+ s = skipwhite(s + 1);
+
+ if (*s == NUL)
+ /* empty line should sort before any number */
+ nrs[lnum - eap->line1].st_u.value_flt = -DBL_MAX;
+ else
+ nrs[lnum - eap->line1].st_u.value_flt = atof(s);
+ }
+#endif
+
*s2 = c;
}
else
{
/* Store the column to sort at. */
- nrs[lnum - eap->line1].start_col_nr = start_col;
- nrs[lnum - eap->line1].end_col_nr = end_col;
+ nrs[lnum - eap->line1].st_u.line.start_col_nr = start_col;
+ nrs[lnum - eap->line1].st_u.line.end_col_nr = end_col;
}
nrs[lnum - eap->line1].lnum = lnum;
>>>>>>>>>>>>>>>> END OF HG EXPORT