]> granicus.if.org Git - vim/commitdiff
patch 7.4.1143 v7.4.1143
authorBram Moolenaar <Bram@vim.org>
Tue, 19 Jan 2016 22:36:15 +0000 (23:36 +0100)
committerBram Moolenaar <Bram@vim.org>
Tue, 19 Jan 2016 22:36:15 +0000 (23:36 +0100)
Problem:    Can't sort on floating point numbers.
Solution:   Add the "f" flag to ":sort".  (Alex Jakushev)  Also add the "f"
            flag to sort().

runtime/doc/change.txt
src/eval.c
src/ex_cmds.c
src/testdir/test57.in
src/testdir/test57.ok
src/testdir/test_sort.vim
src/version.c

index 6dd20ad8b21b43e687787671ba2dc8e5dd98a3bc..ac1b8b68624ba268ff98da03e6900baba356e72e 100644 (file)
@@ -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.
 
index b42ecc78f1f5ab55e6d4ed65fa94023f868b5024..de30f712ee495c9193b2c442e2dd04b8e6667a18 100644 (file)
@@ -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.
index bb6daa8ca08aa6e83b5628d3db22edfc86545315..11c3cf48ba47c2a91c2f97b723394e84f4376863 100644 (file)
@@ -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;
index 0bb95adc34c9f5dcaefef898af4b33b38b1a0c1a..5f235358b8fbb43c94ac603701ffbfcb385e0bf1 100644 (file)
@@ -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
index 2ac5e59e278a2d7a147465b08e2c312e6b55e7b0..452acf1fc44a6c983c18075f0c09bf6d431679c3 100644 (file)
@@ -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
index 30dd167cd62470350fc52db3a63c6a3ff901178f..32ad7f8ad59cb8bdc6f6f5a2e6f94e6d8e09fa3f 100644 (file)
@@ -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
index 20305c814479b7ffa357a5e135f9e7103f08dd3f..bd2c8f6ac1e8ceb3cd31f309a0b32372b44ba594 100644 (file)
@@ -741,6 +741,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1143,
 /**/
     1142,
 /**/