1
0
forked from aniani/vim

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 #6144)
This commit is contained in:
Bram Moolenaar
2020-05-31 15:08:59 +02:00
parent f09715bc5c
commit aaad995f83
5 changed files with 97 additions and 27 deletions

View 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 bin If included, numbers starting with "0b" or "0B" will be
considered to be binary. Example: Using CTRL-X on considered to be binary. Example: Using CTRL-X on
"0b1000" subtracts one, resulting in "0b0111". "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 Numbers which simply begin with a digit in the range 1-9 are always
considered decimal. This also happens for numbers that are not considered decimal. This also happens for numbers that are not
recognized as octal or hex. recognized as octal or hex.

View File

@@ -2428,10 +2428,11 @@ do_addsub(
char_u *ptr; char_u *ptr;
int c; int c;
int todel; int todel;
int dohex; int do_hex;
int dooct; int do_oct;
int dobin; int do_bin;
int doalp; int do_alpha;
int do_unsigned;
int firstdigit; int firstdigit;
int subtract; int subtract;
int negative = FALSE; int negative = FALSE;
@@ -2443,10 +2444,11 @@ do_addsub(
pos_T startpos; pos_T startpos;
pos_T endpos; pos_T endpos;
dohex = (vim_strchr(curbuf->b_p_nf, 'x') != NULL); // "heX" do_hex = (vim_strchr(curbuf->b_p_nf, 'x') != NULL); // "heX"
dooct = (vim_strchr(curbuf->b_p_nf, 'o') != NULL); // "Octal" do_oct = (vim_strchr(curbuf->b_p_nf, 'o') != NULL); // "Octal"
dobin = (vim_strchr(curbuf->b_p_nf, 'b') != NULL); // "Bin" do_bin = (vim_strchr(curbuf->b_p_nf, 'b') != NULL); // "Bin"
doalp = (vim_strchr(curbuf->b_p_nf, 'p') != NULL); // "alPha" 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; curwin->w_cursor = *pos;
ptr = ml_get(pos->lnum); ptr = ml_get(pos->lnum);
@@ -2460,7 +2462,7 @@ do_addsub(
*/ */
if (!VIsual_active) if (!VIsual_active)
{ {
if (dobin) if (do_bin)
while (col > 0 && vim_isbdigit(ptr[col])) while (col > 0 && vim_isbdigit(ptr[col]))
{ {
--col; --col;
@@ -2468,7 +2470,7 @@ do_addsub(
col -= (*mb_head_off)(ptr, ptr + col); col -= (*mb_head_off)(ptr, ptr + col);
} }
if (dohex) if (do_hex)
while (col > 0 && vim_isxdigit(ptr[col])) while (col > 0 && vim_isxdigit(ptr[col]))
{ {
--col; --col;
@@ -2476,8 +2478,8 @@ do_addsub(
col -= (*mb_head_off)(ptr, ptr + col); col -= (*mb_head_off)(ptr, ptr + col);
} }
if ( dobin if ( do_bin
&& dohex && do_hex
&& ! ((col > 0 && ! ((col > 0
&& (ptr[col] == 'X' && (ptr[col] == 'X'
|| ptr[col] == 'x') || ptr[col] == 'x')
@@ -2499,7 +2501,7 @@ do_addsub(
} }
} }
if (( dohex if (( do_hex
&& col > 0 && col > 0
&& (ptr[col] == 'X' && (ptr[col] == 'X'
|| ptr[col] == 'x') || ptr[col] == 'x')
@@ -2507,7 +2509,7 @@ do_addsub(
&& (!has_mbyte || && (!has_mbyte ||
!(*mb_head_off)(ptr, ptr + col - 1)) !(*mb_head_off)(ptr, ptr + col - 1))
&& vim_isxdigit(ptr[col + 1])) || && vim_isxdigit(ptr[col + 1])) ||
( dobin ( do_bin
&& col > 0 && col > 0
&& (ptr[col] == 'B' && (ptr[col] == 'B'
|| ptr[col] == 'b') || ptr[col] == 'b')
@@ -2530,12 +2532,12 @@ do_addsub(
while (ptr[col] != NUL while (ptr[col] != NUL
&& !vim_isdigit(ptr[col]) && !vim_isdigit(ptr[col])
&& !(doalp && ASCII_ISALPHA(ptr[col]))) && !(do_alpha && ASCII_ISALPHA(ptr[col])))
col += mb_ptr2len(ptr + col); col += mb_ptr2len(ptr + col);
while (col > 0 while (col > 0
&& vim_isdigit(ptr[col - 1]) && vim_isdigit(ptr[col - 1])
&& !(doalp && ASCII_ISALPHA(ptr[col]))) && !(do_alpha && ASCII_ISALPHA(ptr[col])))
{ {
--col; --col;
if (has_mbyte) if (has_mbyte)
@@ -2548,7 +2550,7 @@ do_addsub(
{ {
while (ptr[col] != NUL && length > 0 while (ptr[col] != NUL && length > 0
&& !vim_isdigit(ptr[col]) && !vim_isdigit(ptr[col])
&& !(doalp && ASCII_ISALPHA(ptr[col]))) && !(do_alpha && ASCII_ISALPHA(ptr[col])))
{ {
int mb_len = mb_ptr2len(ptr + col); int mb_len = mb_ptr2len(ptr + col);
@@ -2560,7 +2562,8 @@ do_addsub(
goto theend; goto theend;
if (col > pos->col && ptr[col - 1] == '-' 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; negative = TRUE;
was_positive = FALSE; was_positive = FALSE;
@@ -2571,13 +2574,13 @@ do_addsub(
* If a number was found, and saving for undo works, replace the number. * If a number was found, and saving for undo works, replace the number.
*/ */
firstdigit = ptr[col]; firstdigit = ptr[col];
if (!VIM_ISDIGIT(firstdigit) && !(doalp && ASCII_ISALPHA(firstdigit))) if (!VIM_ISDIGIT(firstdigit) && !(do_alpha && ASCII_ISALPHA(firstdigit)))
{ {
beep_flush(); beep_flush();
goto theend; goto theend;
} }
if (doalp && ASCII_ISALPHA(firstdigit)) if (do_alpha && ASCII_ISALPHA(firstdigit))
{ {
// decrement or increment alphabetic character // decrement or increment alphabetic character
if (op_type == OP_NR_SUB) if (op_type == OP_NR_SUB)
@@ -2626,7 +2629,8 @@ do_addsub(
if (col > 0 && ptr[col - 1] == '-' if (col > 0 && ptr[col - 1] == '-'
&& (!has_mbyte || && (!has_mbyte ||
!(*mb_head_off)(ptr, ptr + col - 1)) !(*mb_head_off)(ptr, ptr + col - 1))
&& !visual) && !visual
&& !do_unsigned)
{ {
// negative number // negative number
--col; --col;
@@ -2639,9 +2643,9 @@ do_addsub(
: length); : length);
vim_str2nr(ptr + col, &pre, &length, vim_str2nr(ptr + col, &pre, &length,
0 + (dobin ? STR2NR_BIN : 0) 0 + (do_bin ? STR2NR_BIN : 0)
+ (dooct ? STR2NR_OCT : 0) + (do_oct ? STR2NR_OCT : 0)
+ (dohex ? STR2NR_HEX : 0), + (do_hex ? STR2NR_HEX : 0),
NULL, &n, maxlen, FALSE); NULL, &n, maxlen, FALSE);
// ignore leading '-' for hex and octal and bin numbers // ignore leading '-' for hex and octal and bin numbers
@@ -2687,6 +2691,17 @@ do_addsub(
negative = FALSE; 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) if (visual && !was_positive && !negative && col > 0)
{ {
// need to remove the '-' // need to remove the '-'
@@ -2780,7 +2795,7 @@ do_addsub(
* Don't do this when * Don't do this when
* the result may look like an octal number. * the result may look like an octal number.
*/ */
if (firstdigit == '0' && !(dooct && pre == 0)) if (firstdigit == '0' && !(do_oct && pre == 0))
while (length-- > 0) while (length-- > 0)
*ptr++ = '0'; *ptr++ = '0';
*ptr = NUL; *ptr = NUL;

View File

@@ -21,7 +21,7 @@ static char *(p_bo_values[]) = {"all", "backspace", "cursor", "complete",
"hangul", "insertmode", "lang", "mess", "hangul", "insertmode", "lang", "mess",
"showmatch", "operator", "register", "shell", "showmatch", "operator", "register", "shell",
"spell", "wildmode", NULL}; "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}; static char *(p_ff_values[]) = {FF_UNIX, FF_DOS, FF_MAC, NULL};
#ifdef FEAT_CRYPT #ifdef FEAT_CRYPT
static char *(p_cm_values[]) = {"zip", "blowfish", "blowfish2", NULL}; static char *(p_cm_values[]) = {"zip", "blowfish", "blowfish2", NULL};

View File

@@ -1,4 +1,4 @@
" Tests for using Ctrl-A/Ctrl-X on visual selections " Tests for using Ctrl-A/Ctrl-X
func SetUp() func SetUp()
new dummy new dummy
@@ -796,4 +796,48 @@ func Test_increment_special_char()
call assert_beeps("normal \<C-X>") call assert_beeps("normal \<C-X>")
endfunc 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 " vim: shiftwidth=2 sts=2 expandtab

View File

@@ -746,6 +746,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
860,
/**/ /**/
859, 859,
/**/ /**/