]> granicus.if.org Git - vim/commitdiff
patch 7.4.951 v7.4.951
authorBram Moolenaar <Bram@vim.org>
Thu, 3 Dec 2015 15:33:12 +0000 (16:33 +0100)
committerBram Moolenaar <Bram@vim.org>
Thu, 3 Dec 2015 15:33:12 +0000 (16:33 +0100)
Problem:    Sorting number strings does not work as expected. (Luc Hermitte)
Solution:   Add the 'N" argument to sort()

runtime/doc/eval.txt
src/eval.c
src/testdir/Makefile
src/testdir/test_alot.vim [new file with mode: 0644]
src/testdir/test_sort.vim [new file with mode: 0644]
src/version.c

index 9442996be15b91c930c554d522750ee70da96691..2e89098a665987f1d761fea0b515e26fddf861be 100644 (file)
@@ -5803,6 +5803,10 @@ sort({list} [, {func} [, {dict}]])                       *sort()* *E702*
                strtod() function to parse numbers, Strings, Lists, Dicts and
                Funcrefs will be considered as being 0).
 
+               When {func} is given and it is 'N' then all items will be
+               sorted numerical. This is like 'n' but a string containing
+               digits will be used as the number they represent.
+
                When {func} is a |Funcref| or a function name, this function
                is called to compare items.  The function is invoked with two
                items as argument and must return zero if they are equal, 1 or
@@ -5817,6 +5821,11 @@ sort({list} [, {func} [, {dict}]])                       *sort()* *E702*
                on numbers, text strings will sort next to each other, in the
                same order as they were originally.
 
+               The sort is stable, items which compare equal (as number or as
+               string) will keep their relative position. E.g., when sorting
+               on numbers, text strings will sort next to each other, in the
+               same order as they were originally.
+
                Also see |uniq()|.
 
                Example: >
index 2d6c34b92afa939dfe868bd7989563aecf5884cb..ef0ea5ee2ba6852d754f82f1be66c1996280bcc6 100644 (file)
@@ -17928,6 +17928,7 @@ typedef struct
 
 static int     item_compare_ic;
 static int     item_compare_numeric;
+static int     item_compare_numbers;
 static char_u  *item_compare_func;
 static dict_T  *item_compare_selfdict;
 static int     item_compare_func_err;
@@ -17958,6 +17959,15 @@ item_compare(s1, s2)
     si2 = (sortItem_T *)s2;
     tv1 = &si1->item->li_tv;
     tv2 = &si2->item->li_tv;
+
+    if (item_compare_numbers)
+    {
+       long    v1 = get_tv_number(tv1);
+       long    v2 = get_tv_number(tv2);
+
+       return v1 == v2 ? 0 : v1 > v2 ? 1 : -1;
+    }
+
     /* 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. */
@@ -18091,6 +18101,7 @@ do_sort_uniq(argvars, rettv, sort)
 
        item_compare_ic = FALSE;
        item_compare_numeric = FALSE;
+       item_compare_numbers = FALSE;
        item_compare_func = NULL;
        item_compare_selfdict = NULL;
        if (argvars[1].v_type != VAR_UNKNOWN)
@@ -18116,6 +18127,11 @@ do_sort_uniq(argvars, rettv, sort)
                        item_compare_func = NULL;
                        item_compare_numeric = TRUE;
                    }
+                   else if (STRCMP(item_compare_func, "N") == 0)
+                   {
+                       item_compare_func = NULL;
+                       item_compare_numbers = TRUE;
+                   }
                    else if (STRCMP(item_compare_func, "i") == 0)
                    {
                        item_compare_func = NULL;
index 3f65f435df227ffe5bef8e179b4cb7674166e6b6..c7db9495e5a91f14a78875ed943460084e0bb026 100644 (file)
@@ -69,7 +69,7 @@ SCRIPTS = test1.out test2.out test3.out test4.out test5.out test6.out \
                test_writefile.out
 
 NEW_TESTS = test_assert.res \
-           test_undolevels.res
+           test_alot.res
 
 SCRIPTS_GUI = test16.out
 
diff --git a/src/testdir/test_alot.vim b/src/testdir/test_alot.vim
new file mode 100644 (file)
index 0000000..9763509
--- /dev/null
@@ -0,0 +1,5 @@
+" A series of tests that can run in one Vim invocation.
+" This makes testing go faster, since Vim doesn't need to restart.
+
+source test_undolevels.vim
+source test_sort.vim
diff --git a/src/testdir/test_sort.vim b/src/testdir/test_sort.vim
new file mode 100644 (file)
index 0000000..30dd167
--- /dev/null
@@ -0,0 +1,19 @@
+" Test sort()
+
+func Test_sort_strings()
+  " numbers compared as strings
+  call assert_equal([1, 2, 3], sort([3, 2, 1]))
+  call assert_equal([13, 28, 3], sort([3, 28, 13]))
+endfunc
+
+func Test_sort_numeric()
+  call assert_equal([1, 2, 3], sort([3, 2, 1], 'n'))
+  call assert_equal([3, 13, 28], sort([13, 28, 3], 'n'))
+  " strings are not sorted
+  call assert_equal(['13', '28', '3'], sort(['13', '28', '3'], 'n'))
+endfunc
+
+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
index 31273feb25b7bc05134f8fbdc83a31b2096647b2..4b2a1cbeb0416601de78eac4653d56d00dbb567e 100644 (file)
@@ -741,6 +741,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    951,
 /**/
     950,
 /**/