# HG changeset patch # User Bram Moolenaar # Date 1590930904 -7200 # Node ID 9edb439adbea579b02eafdb1b5bb8d2b011093e2 # Parent b2ad048307ef5964f49d84075054e15bcaa3ba03 patch 8.2.0860: cannot use CTRL-A and CTRL-X on unsigned numbers Commit: https://github.com/vim/vim/commit/aaad995f8384a77a64efba6846c9c4ac99de0953 Author: Bram Moolenaar Date: Sun May 31 15:08:59 2020 +0200 patch 8.2.0860: cannot use CTRL-A and CTRL-X on unsigned numbers Problem: Cannot use CTRL-A and CTRL-X on unsigned numbers. Solution: Add "unsigned" to 'nrformats'. (Naruhiko Nishino, closes https://github.com/vim/vim/issues/6144) diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -5427,6 +5427,15 @@ A jump table for the options with a shor 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. diff --git a/src/ops.c b/src/ops.c --- 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; diff --git a/src/optionstr.c b/src/optionstr.c --- a/src/optionstr.c +++ b/src/optionstr.c @@ -21,7 +21,7 @@ static char *(p_bo_values[]) = {"all", " "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}; diff --git a/src/testdir/test_increment.vim b/src/testdir/test_increment.vim --- a/src/testdir/test_increment.vim +++ b/src/testdir/test_increment.vim @@ -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 \") endfunc +" Try incrementing/decrementing a number when nrformats contains unsigned +func Test_increment_unsigned() + set nrformats+=unsigned + + call setline(1, '0') + exec "norm! gg0\" + call assert_equal('0', getline(1)) + + call setline(1, '3') + exec "norm! gg010\" + call assert_equal('0', getline(1)) + + call setline(1, '-0') + exec "norm! gg0\" + call assert_equal("-0", getline(1)) + + call setline(1, '-11') + exec "norm! gg08\" + call assert_equal('-3', getline(1)) + + " NOTE: 18446744073709551615 == 2^64 - 1 + call setline(1, '18446744073709551615') + exec "norm! gg0\" + call assert_equal('18446744073709551615', getline(1)) + + call setline(1, '-18446744073709551615') + exec "norm! gg0\" + call assert_equal('-18446744073709551615', getline(1)) + + call setline(1, '-18446744073709551614') + exec "norm! gg08\" + call assert_equal('-18446744073709551615', getline(1)) + + call setline(1, '-1') + exec "norm! gg0\" + call assert_equal('-2', getline(1)) + + call setline(1, '-3') + exec "norm! gg08\" + call assert_equal('-11', getline(1)) + + set nrformats-=unsigned +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -747,6 +747,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 860, +/**/ 859, /**/ 858,