]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 8.2.0860: cannot use CTRL-A and CTRL-X on unsigned numbers v8.2.0860
authorBram Moolenaar <Bram@vim.org>
Sun, 31 May 2020 13:08:59 +0000 (15:08 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 31 May 2020 13:08:59 +0000 (15:08 +0200)
Problem:    Cannot use CTRL-A and CTRL-X on unsigned numbers.
Solution:   Add "unsigned" to 'nrformats'. (Naruhiko Nishino, closes #6144)

runtime/doc/options.txt
src/ops.c
src/optionstr.c
src/testdir/test_increment.vim
src/version.c

index a805a0c270840db173139531421c1893ce77c585..d4d87872c869d1041665d11e33207e95a39bf93d 100644 (file)
@@ -5427,6 +5427,15 @@ A jump table for the options with a short description can be found at |Q_op|.
        bin     If included, numbers starting with "0b" or "0B" will be
                considered to be binary.  Example: Using CTRL-X on
                "0b1000" subtracts one, resulting in "0b0111".
+       unsigned    If included, numbers are recognized as unsigned. Thus a
+               leading dash or negative sign won't be considered as part of
+               the number.  Examples:
+                   Using CTRL-X on "2020" in "9-2020" results in "9-2019"
+                   (without "unsigned" it would become "9-2021").
+                   Using CTRL-A on "2020" in "9-2020" results in "9-2021"
+                   (without "unsigned" it would become "9-2019").
+                   Using CTRL-X on "0" or "18446744073709551615" (2^64) has
+                   no effect, overflow is prevented.
        Numbers which simply begin with a digit in the range 1-9 are always
        considered decimal.  This also happens for numbers that are not
        recognized as octal or hex.
index ed1688635d9b377eeb14ab688776dc81e21e0a41..14d1ed45dd3042802a0c55dcb003baa4b78eb3bb 100644 (file)
--- a/src/ops.c
+++ b/src/ops.c
@@ -2428,10 +2428,11 @@ do_addsub(
     char_u     *ptr;
     int                c;
     int                todel;
-    int                dohex;
-    int                dooct;
-    int                dobin;
-    int                doalp;
+    int                do_hex;
+    int                do_oct;
+    int                do_bin;
+    int                do_alpha;
+    int                do_unsigned;
     int                firstdigit;
     int                subtract;
     int                negative = FALSE;
@@ -2443,10 +2444,11 @@ do_addsub(
     pos_T      startpos;
     pos_T      endpos;
 
-    dohex = (vim_strchr(curbuf->b_p_nf, 'x') != NULL); // "heX"
-    dooct = (vim_strchr(curbuf->b_p_nf, 'o') != NULL); // "Octal"
-    dobin = (vim_strchr(curbuf->b_p_nf, 'b') != NULL); // "Bin"
-    doalp = (vim_strchr(curbuf->b_p_nf, 'p') != NULL); // "alPha"
+    do_hex = (vim_strchr(curbuf->b_p_nf, 'x') != NULL);        // "heX"
+    do_oct = (vim_strchr(curbuf->b_p_nf, 'o') != NULL);        // "Octal"
+    do_bin = (vim_strchr(curbuf->b_p_nf, 'b') != NULL);        // "Bin"
+    do_alpha = (vim_strchr(curbuf->b_p_nf, 'p') != NULL);      // "alPha"
+    do_unsigned = (vim_strchr(curbuf->b_p_nf, 'u') != NULL);   // "Unsigned"
 
     curwin->w_cursor = *pos;
     ptr = ml_get(pos->lnum);
@@ -2460,7 +2462,7 @@ do_addsub(
      */
     if (!VIsual_active)
     {
-       if (dobin)
+       if (do_bin)
            while (col > 0 && vim_isbdigit(ptr[col]))
            {
                --col;
@@ -2468,7 +2470,7 @@ do_addsub(
                    col -= (*mb_head_off)(ptr, ptr + col);
            }
 
-       if (dohex)
+       if (do_hex)
            while (col > 0 && vim_isxdigit(ptr[col]))
            {
                --col;
@@ -2476,8 +2478,8 @@ do_addsub(
                    col -= (*mb_head_off)(ptr, ptr + col);
            }
 
-       if (       dobin
-               && dohex
+       if (       do_bin
+               && do_hex
                && ! ((col > 0
                    && (ptr[col] == 'X'
                        || ptr[col] == 'x')
@@ -2499,7 +2501,7 @@ do_addsub(
            }
        }
 
-       if ((       dohex
+       if ((       do_hex
                && col > 0
                && (ptr[col] == 'X'
                    || ptr[col] == 'x')
@@ -2507,7 +2509,7 @@ do_addsub(
                && (!has_mbyte ||
                    !(*mb_head_off)(ptr, ptr + col - 1))
                && vim_isxdigit(ptr[col + 1])) ||
-           (       dobin
+           (       do_bin
                && col > 0
                && (ptr[col] == 'B'
                    || ptr[col] == 'b')
@@ -2530,12 +2532,12 @@ do_addsub(
 
            while (ptr[col] != NUL
                    && !vim_isdigit(ptr[col])
-                   && !(doalp && ASCII_ISALPHA(ptr[col])))
+                   && !(do_alpha && ASCII_ISALPHA(ptr[col])))
                col += mb_ptr2len(ptr + col);
 
            while (col > 0
                    && vim_isdigit(ptr[col - 1])
-                   && !(doalp && ASCII_ISALPHA(ptr[col])))
+                   && !(do_alpha && ASCII_ISALPHA(ptr[col])))
            {
                --col;
                if (has_mbyte)
@@ -2548,7 +2550,7 @@ do_addsub(
     {
        while (ptr[col] != NUL && length > 0
                && !vim_isdigit(ptr[col])
-               && !(doalp && ASCII_ISALPHA(ptr[col])))
+               && !(do_alpha && ASCII_ISALPHA(ptr[col])))
        {
            int mb_len = mb_ptr2len(ptr + col);
 
@@ -2560,7 +2562,8 @@ do_addsub(
            goto theend;
 
        if (col > pos->col && ptr[col - 1] == '-'
-               && (!has_mbyte || !(*mb_head_off)(ptr, ptr + col - 1)))
+               && (!has_mbyte || !(*mb_head_off)(ptr, ptr + col - 1))
+               && !do_unsigned)
        {
            negative = TRUE;
            was_positive = FALSE;
@@ -2571,13 +2574,13 @@ do_addsub(
      * If a number was found, and saving for undo works, replace the number.
      */
     firstdigit = ptr[col];
-    if (!VIM_ISDIGIT(firstdigit) && !(doalp && ASCII_ISALPHA(firstdigit)))
+    if (!VIM_ISDIGIT(firstdigit) && !(do_alpha && ASCII_ISALPHA(firstdigit)))
     {
        beep_flush();
        goto theend;
     }
 
-    if (doalp && ASCII_ISALPHA(firstdigit))
+    if (do_alpha && ASCII_ISALPHA(firstdigit))
     {
        // decrement or increment alphabetic character
        if (op_type == OP_NR_SUB)
@@ -2626,7 +2629,8 @@ do_addsub(
        if (col > 0 && ptr[col - 1] == '-'
                && (!has_mbyte ||
                    !(*mb_head_off)(ptr, ptr + col - 1))
-               && !visual)
+               && !visual
+               && !do_unsigned)
        {
            // negative number
            --col;
@@ -2639,9 +2643,9 @@ do_addsub(
                    : length);
 
        vim_str2nr(ptr + col, &pre, &length,
-               0 + (dobin ? STR2NR_BIN : 0)
-                   + (dooct ? STR2NR_OCT : 0)
-                   + (dohex ? STR2NR_HEX : 0),
+               0 + (do_bin ? STR2NR_BIN : 0)
+                   + (do_oct ? STR2NR_OCT : 0)
+                   + (do_hex ? STR2NR_HEX : 0),
                NULL, &n, maxlen, FALSE);
 
        // ignore leading '-' for hex and octal and bin numbers
@@ -2687,6 +2691,17 @@ do_addsub(
                negative = FALSE;
        }
 
+       if (do_unsigned && negative)
+       {
+           if (subtract)
+               // sticking at zero.
+               n = (uvarnumber_T)0;
+           else
+               // sticking at 2^64 - 1.
+               n = (uvarnumber_T)(-1);
+           negative = FALSE;
+       }
+
        if (visual && !was_positive && !negative && col > 0)
        {
            // need to remove the '-'
@@ -2780,7 +2795,7 @@ do_addsub(
         * Don't do this when
         * the result may look like an octal number.
         */
-       if (firstdigit == '0' && !(dooct && pre == 0))
+       if (firstdigit == '0' && !(do_oct && pre == 0))
            while (length-- > 0)
                *ptr++ = '0';
        *ptr = NUL;
index c03d994c3257957bc39dbf582d92c4a46358cafd..ddb6c50f3058468b802463b93d8c868a8a65fa0e 100644 (file)
@@ -21,7 +21,7 @@ static char *(p_bo_values[]) = {"all", "backspace", "cursor", "complete",
                                 "hangul", "insertmode", "lang", "mess",
                                 "showmatch", "operator", "register", "shell",
                                 "spell", "wildmode", NULL};
-static char *(p_nf_values[]) = {"bin", "octal", "hex", "alpha", NULL};
+static char *(p_nf_values[]) = {"bin", "octal", "hex", "alpha", "unsigned", NULL};
 static char *(p_ff_values[]) = {FF_UNIX, FF_DOS, FF_MAC, NULL};
 #ifdef FEAT_CRYPT
 static char *(p_cm_values[]) = {"zip", "blowfish", "blowfish2", NULL};
index 31d3ef9a7010970ea931b1db7593a34bfd16dbf4..4a51b9cea634cb8e625351e20fe3e4ac07e80e6e 100644 (file)
@@ -1,4 +1,4 @@
-" Tests for using Ctrl-A/Ctrl-X on visual selections
+" Tests for using Ctrl-A/Ctrl-X
 
 func SetUp()
   new dummy
@@ -796,4 +796,48 @@ func Test_increment_special_char()
   call assert_beeps("normal \<C-X>")
 endfunc
 
+" Try incrementing/decrementing a number when nrformats contains unsigned
+func Test_increment_unsigned()
+  set nrformats+=unsigned
+
+  call setline(1, '0')
+  exec "norm! gg0\<C-X>"
+  call assert_equal('0', getline(1))
+
+  call setline(1, '3')
+  exec "norm! gg010\<C-X>"
+  call assert_equal('0', getline(1))
+
+  call setline(1, '-0')
+  exec "norm! gg0\<C-X>"
+  call assert_equal("-0", getline(1))
+
+  call setline(1, '-11')
+  exec "norm! gg08\<C-X>"
+  call assert_equal('-3', getline(1))
+
+  " NOTE: 18446744073709551615 == 2^64 - 1
+  call setline(1, '18446744073709551615')
+  exec "norm! gg0\<C-A>"
+  call assert_equal('18446744073709551615', getline(1))
+
+  call setline(1, '-18446744073709551615')
+  exec "norm! gg0\<C-A>"
+  call assert_equal('-18446744073709551615', getline(1))
+
+  call setline(1, '-18446744073709551614')
+  exec "norm! gg08\<C-A>"
+  call assert_equal('-18446744073709551615', getline(1))
+
+  call setline(1, '-1')
+  exec "norm! gg0\<C-A>"
+  call assert_equal('-2', getline(1))
+
+  call setline(1, '-3')
+  exec "norm! gg08\<C-A>"
+  call assert_equal('-11', getline(1))
+
+  set nrformats-=unsigned
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
index 88f6da85f8c4078e250d3fd61801c6e4524d8af9..f63cb0c1cf733a6bc6d2dd2063bf35dad444b8c8 100644 (file)
@@ -746,6 +746,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    860,
 /**/
     859,
 /**/