summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-01-19 23:36:15 +0100
committerBram Moolenaar <Bram@vim.org>2016-01-19 23:36:15 +0100
commitf7edf40448a09e04eec3bd05e043f7fea93b07c9 (patch)
tree044c6550e8bb32b9291c1bc4ba717e46670a1453
parentb8060fe862f684b591f9ac679eac5b2594d6c5a0 (diff)
downloadvim-git-f7edf40448a09e04eec3bd05e043f7fea93b07c9.tar.gz
patch 7.4.1143v7.4.1143
Problem: Can't sort on floating point numbers. Solution: Add the "f" flag to ":sort". (Alex Jakushev) Also add the "f" flag to sort().
-rw-r--r--runtime/doc/change.txt20
-rw-r--r--src/eval.c60
-rw-r--r--src/ex_cmds.c110
-rw-r--r--src/testdir/test57.in18
-rw-r--r--src/testdir/test57.ok13
-rw-r--r--src/testdir/test_sort.vim4
-rw-r--r--src/version.c2
7 files changed, 185 insertions, 42 deletions
diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt
index 6dd20ad8b..ac1b8b686 100644
--- a/runtime/doc/change.txt
+++ b/runtime/doc/change.txt
@@ -1,4 +1,4 @@
-*change.txt* For Vim version 7.4. Last change: 2016 Jan 02
+*change.txt* For Vim version 7.4. Last change: 2016 Jan 19
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1745,7 +1745,7 @@ Vim has a sorting function and a sorting command. The sorting function can be
found here: |sort()|, |uniq()|.
*:sor* *:sort*
-:[range]sor[t][!] [i][u][r][n][x][o][b] [/{pattern}/]
+:[range]sor[t][!] [b][f][i][n][o][r][u][x] [/{pattern}/]
Sort lines in [range]. When no range is given all
lines are sorted.
@@ -1753,10 +1753,18 @@ found here: |sort()|, |uniq()|.
With [i] case is ignored.
+ Options [n][f][x][o][b] are mutually exclusive.
+
With [n] sorting is done on the first decimal number
in the line (after or inside a {pattern} match).
One leading '-' is included in the number.
+ 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.
+
With [x] sorting is done on the first hexadecimal
number in the line (after or inside a {pattern}
match). A leading "0x" or "0X" is ignored.
@@ -1768,10 +1776,10 @@ found here: |sort()|, |uniq()|.
With [b] sorting is done on the first binary number in
the line (after or inside a {pattern} match).
- 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
- will be kept in their original order.
+ With [u] (u stands for unique) only keep the first of
+ a sequence of identical lines (ignoring case when [i]
+ is used). Without this flag, a sequence of identical
+ lines will be kept in their original order.
Note that leading and trailing white space may cause
lines to be different.
diff --git a/src/eval.c b/src/eval.c
index b42ecc78f..de30f712e 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -809,6 +809,9 @@ static typval_T *alloc_tv __ARGS((void));
static typval_T *alloc_string_tv __ARGS((char_u *string));
static void init_tv __ARGS((typval_T *varp));
static long get_tv_number __ARGS((typval_T *varp));
+#ifdef FEAT_FLOAT
+static float_T get_tv_float(typval_T *varp);
+#endif
static linenr_T get_tv_lnum __ARGS((typval_T *argvars));
static linenr_T get_tv_lnum_buf __ARGS((typval_T *argvars, buf_T *buf));
static char_u *get_tv_string __ARGS((typval_T *varp));
@@ -18143,6 +18146,9 @@ typedef struct
static int item_compare_ic;
static int item_compare_numeric;
static int item_compare_numbers;
+#ifdef FEAT_FLOAT
+static int item_compare_float;
+#endif
static char_u *item_compare_func;
static dict_T *item_compare_selfdict;
static int item_compare_func_err;
@@ -18182,6 +18188,16 @@ item_compare(s1, s2)
return v1 == v2 ? 0 : v1 > v2 ? 1 : -1;
}
+#ifdef FEAT_FLOAT
+ if (item_compare_float)
+ {
+ float_T v1 = get_tv_float(tv1);
+ float_T v2 = get_tv_float(tv2);
+
+ return v1 == v2 ? 0 : v1 > v2 ? 1 : -1;
+ }
+#endif
+
/* tv2string() puts quotes around a string and allocates memory. Don't do
* that for string variables. Use a single quote when comparing with a
* non-string to do what the docs promise. */
@@ -18316,6 +18332,9 @@ do_sort_uniq(argvars, rettv, sort)
item_compare_ic = FALSE;
item_compare_numeric = FALSE;
item_compare_numbers = FALSE;
+#ifdef FEAT_FLOAT
+ item_compare_float = FALSE;
+#endif
item_compare_func = NULL;
item_compare_selfdict = NULL;
if (argvars[1].v_type != VAR_UNKNOWN)
@@ -18346,6 +18365,13 @@ do_sort_uniq(argvars, rettv, sort)
item_compare_func = NULL;
item_compare_numbers = TRUE;
}
+#ifdef FEAT_FLOAT
+ else if (STRCMP(item_compare_func, "f") == 0)
+ {
+ item_compare_func = NULL;
+ item_compare_float = TRUE;
+ }
+#endif
else if (STRCMP(item_compare_func, "i") == 0)
{
item_compare_func = NULL;
@@ -21613,6 +21639,40 @@ get_tv_number_chk(varp, denote)
return n;
}
+#ifdef FEAT_FLOAT
+ static float_T
+get_tv_float(varp)
+ typval_T *varp;
+{
+ switch (varp->v_type)
+ {
+ case VAR_NUMBER:
+ return (float_T)(varp->vval.v_number);
+#ifdef FEAT_FLOAT
+ case VAR_FLOAT:
+ return varp->vval.v_float;
+ break;
+#endif
+ case VAR_FUNC:
+ EMSG(_("E891: Using a Funcref as a Float"));
+ break;
+ case VAR_STRING:
+ EMSG(_("E892: Using a String as a Float"));
+ break;
+ case VAR_LIST:
+ EMSG(_("E893: Using a List as a Float"));
+ break;
+ case VAR_DICT:
+ EMSG(_("E894: Using a Dictionary as a Float"));
+ break;
+ default:
+ EMSG2(_(e_intern2), "get_tv_float()");
+ break;
+ }
+ return 0;
+}
+#endif
+
/*
* Get the lnum from the first argument.
* Also accepts ".", "$", etc., but that only works for the current buffer.
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index bb6daa8ca..11c3cf48b 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -275,18 +275,30 @@ linelen(has_tab)
static char_u *sortbuf1;
static char_u *sortbuf2;
-static int sort_ic; /* ignore case */
-static int sort_nr; /* sort on number */
-static int sort_rx; /* sort on regex instead of skipping it */
+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 */
+static int sort_abort; /* flag to indicate if sorting has been interrupted */
/* Struct to store info to be sorted. */
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 integer */
+#ifdef FEAT_FLOAT
+ float_T value_flt; /* value if sorting by float */
+#endif
+ } st_u;
} sorti_T;
static int
@@ -319,19 +331,24 @@ sort_compare(s1, s2)
/* 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);
@@ -382,6 +399,9 @@ ex_sort(eap)
goto sortend;
sort_abort = sort_ic = sort_rx = sort_nr = 0;
+#ifdef FEAT_FLOAT
+ sort_flt = 0;
+#endif
for (p = eap->arg; *p != NUL; ++p)
{
@@ -393,9 +413,16 @@ ex_sort(eap)
sort_rx = TRUE;
else if (*p == 'n')
{
- sort_nr = 2;
+ sort_nr = 1;
++format_found;
}
+#ifdef FEAT_FLOAT
+ else if (*p == 'f')
+ {
+ sort_flt = 1;
+ ++format_found;
+ }
+#endif
else if (*p == 'b')
{
sort_what = STR2NR_BIN + STR2NR_FORCE;
@@ -460,7 +487,8 @@ ex_sort(eap)
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 integer number
+ * sorting. */
sort_nr += sort_what;
/*
@@ -494,7 +522,7 @@ ex_sort(eap)
if (regmatch.regprog != NULL)
end_col = 0;
- if (sort_nr)
+ if (sort_nr || sort_flt)
{
/* Make sure vim_str2nr doesn't read any digits past the end
* of the match, by temporarily terminating the string there */
@@ -503,27 +531,45 @@ ex_sort(eap)
*s2 = NUL;
/* Sorting on number: Store the number itself. */
p = s + start_col;
- if (sort_what & STR2NR_HEX)
- s = skiptohex(p);
- else if (sort_what & STR2NR_BIN)
- s = skiptobin(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;
+ if (sort_nr)
+ {
+ if (sort_what & STR2NR_HEX)
+ s = skiptohex(p);
+ else if (sort_what & STR2NR_BIN)
+ s = skiptobin(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_what,
+ &nrs[lnum - eap->line1].st_u.value, NULL, 0);
+ }
+#ifdef FEAT_FLOAT
else
- vim_str2nr(s, NULL, NULL, sort_what,
- &nrs[lnum - eap->line1].start_col_nr, NULL, 0);
+ {
+ 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 =
+ strtod((char *)s, NULL);
+ }
+#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;
diff --git a/src/testdir/test57.in b/src/testdir/test57.in
index 0bb95adc3..5f235358b 100644
--- a/src/testdir/test57.in
+++ b/src/testdir/test57.in
@@ -32,6 +32,7 @@ STARTTEST
:/^t27:/+1,/^t28/-1sort no
:/^t28:/+1,/^t29/-1sort b
:/^t29:/+1,/^t30/-1sort b
+:/^t30:/+1,/^t31/-1sort f
:/^t01:/,$wq! test.out
ENDTEST
@@ -496,9 +497,9 @@ c321d
b322b
b321
b321b
-t28: binary
+t28: binary
0b111000
0b101100
0b101001
@@ -513,9 +514,9 @@ t28: binary
0b100010
0b100100
0b100010
-t29: binary with leading characters
+t29: binary with leading characters
0b100010
0b010000
0b101001
@@ -530,4 +531,15 @@ ab0b100000
0b101010
0b000000
b0b111000
-t30: done
+
+
+t30: float
+1.234
+0.88
+123.456
+1.15e-6
+-1.1e3
+-1.01e3
+
+
+t31: done
diff --git a/src/testdir/test57.ok b/src/testdir/test57.ok
index 2ac5e59e2..452acf1fc 100644
--- a/src/testdir/test57.ok
+++ b/src/testdir/test57.ok
@@ -453,6 +453,8 @@ c321d
b322b
b321
b321b
+
+
t28: binary
@@ -487,4 +489,13 @@ a0b101001
0b101010
b0b101100
b0b111000
-t30: done
+t30: float
+
+
+-1.1e3
+-1.01e3
+1.15e-6
+0.88
+1.234
+123.456
+t31: done
diff --git a/src/testdir/test_sort.vim b/src/testdir/test_sort.vim
index 30dd167cd..32ad7f8ad 100644
--- a/src/testdir/test_sort.vim
+++ b/src/testdir/test_sort.vim
@@ -17,3 +17,7 @@ func Test_sort_numbers()
call assert_equal([3, 13, 28], sort([13, 28, 3], 'N'))
call assert_equal(['3', '13', '28'], sort(['13', '28', '3'], 'N'))
endfunc
+
+func Test_sort_float()
+ call assert_equal([0.28, 3, 13.5], sort([13.5, 0.28, 3], 'f'))
+endfunc
diff --git a/src/version.c b/src/version.c
index 20305c814..bd2c8f6ac 100644
--- a/src/version.c
+++ b/src/version.c
@@ -742,6 +742,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1143,
+/**/
1142,
/**/
1141,