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:
@@ -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.
|
||||||
|
65
src/ops.c
65
src/ops.c
@@ -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;
|
||||||
|
@@ -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};
|
||||||
|
@@ -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
|
||||||
|
@@ -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,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user