mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 11:28:22 +00:00
vim-patch:9.1.0537: signed number detection for CTRL-X/A can be improved (#29590)
Problem: signed number detection for CTRL-X/A can be improved
(Chris Patuzzo)
Solution: Add the new "blank" value for the 'nrformat' setting. This
will make Vim assume a signed number only if there is a blank
in front of the sign.
(distobs)
fixes: vim/vim#15033
closes: vim/vim#15110
25ac6d67d9
Co-authored-by: distobs <cuppotatocake@gmail.com>
This commit is contained in:
@@ -4430,6 +4430,20 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
(without "unsigned" it would become "9-2019").
|
(without "unsigned" it would become "9-2019").
|
||||||
Using CTRL-X on "0" or CTRL-A on "18446744073709551615"
|
Using CTRL-X on "0" or CTRL-A on "18446744073709551615"
|
||||||
(2^64 - 1) has no effect, overflow is prevented.
|
(2^64 - 1) has no effect, overflow is prevented.
|
||||||
|
blank If included, treat numbers as signed or unsigned based on
|
||||||
|
preceding whitespace. If a number with a leading dash has its
|
||||||
|
dash immediately preceded by a non-whitespace character (i.e.,
|
||||||
|
not a tab or a " "), the negative sign won't be considered as
|
||||||
|
part of the number. For example:
|
||||||
|
Using CTRL-A on "14" in "Carbon-14" results in "Carbon-15"
|
||||||
|
(without "blank" it would become "Carbon-13").
|
||||||
|
Using CTRL-X on "8" in "Carbon -8" results in "Carbon -9"
|
||||||
|
(because -8 is preceded by whitespace. If "unsigned" was
|
||||||
|
set, it would result in "Carbon -7").
|
||||||
|
If this format is included, overflow is prevented as if
|
||||||
|
"unsigned" were set. If both this format and "unsigned" are
|
||||||
|
included, "unsigned" will take precedence.
|
||||||
|
|
||||||
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.
|
||||||
|
14
runtime/lua/vim/_meta/options.lua
generated
14
runtime/lua/vim/_meta/options.lua
generated
@@ -4549,6 +4549,20 @@ vim.go.mouset = vim.go.mousetime
|
|||||||
--- (without "unsigned" it would become "9-2019").
|
--- (without "unsigned" it would become "9-2019").
|
||||||
--- Using CTRL-X on "0" or CTRL-A on "18446744073709551615"
|
--- Using CTRL-X on "0" or CTRL-A on "18446744073709551615"
|
||||||
--- (2^64 - 1) has no effect, overflow is prevented.
|
--- (2^64 - 1) has no effect, overflow is prevented.
|
||||||
|
--- blank If included, treat numbers as signed or unsigned based on
|
||||||
|
--- preceding whitespace. If a number with a leading dash has its
|
||||||
|
--- dash immediately preceded by a non-whitespace character (i.e.,
|
||||||
|
--- not a tab or a " "), the negative sign won't be considered as
|
||||||
|
--- part of the number. For example:
|
||||||
|
--- Using CTRL-A on "14" in "Carbon-14" results in "Carbon-15"
|
||||||
|
--- (without "blank" it would become "Carbon-13").
|
||||||
|
--- Using CTRL-X on "8" in "Carbon -8" results in "Carbon -9"
|
||||||
|
--- (because -8 is preceded by whitespace. If "unsigned" was
|
||||||
|
--- set, it would result in "Carbon -7").
|
||||||
|
--- If this format is included, overflow is prevented as if
|
||||||
|
--- "unsigned" were set. If both this format and "unsigned" are
|
||||||
|
--- included, "unsigned" will take precedence.
|
||||||
|
---
|
||||||
--- 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.
|
||||||
|
@@ -4420,6 +4420,7 @@ bool do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
|
|||||||
int pre; // 'X' or 'x': hex; '0': octal; 'B' or 'b': bin
|
int pre; // 'X' or 'x': hex; '0': octal; 'B' or 'b': bin
|
||||||
static bool hexupper = false; // 0xABC
|
static bool hexupper = false; // 0xABC
|
||||||
uvarnumber_T n;
|
uvarnumber_T n;
|
||||||
|
bool blank_unsigned = false; // blank: treat as unsigned?
|
||||||
bool negative = false;
|
bool negative = false;
|
||||||
bool was_positive = true;
|
bool was_positive = true;
|
||||||
bool visual = VIsual_active;
|
bool visual = VIsual_active;
|
||||||
@@ -4434,8 +4435,8 @@ bool do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
|
|||||||
const bool do_oct = vim_strchr(curbuf->b_p_nf, 'o') != NULL; // "Octal"
|
const bool do_oct = vim_strchr(curbuf->b_p_nf, 'o') != NULL; // "Octal"
|
||||||
const bool do_bin = vim_strchr(curbuf->b_p_nf, 'b') != NULL; // "Bin"
|
const bool do_bin = vim_strchr(curbuf->b_p_nf, 'b') != NULL; // "Bin"
|
||||||
const bool do_alpha = vim_strchr(curbuf->b_p_nf, 'p') != NULL; // "alPha"
|
const bool do_alpha = vim_strchr(curbuf->b_p_nf, 'p') != NULL; // "alPha"
|
||||||
// "Unsigned"
|
const bool do_unsigned = vim_strchr(curbuf->b_p_nf, 'u') != NULL; // "Unsigned"
|
||||||
const bool do_unsigned = vim_strchr(curbuf->b_p_nf, 'u') != NULL;
|
const bool do_blank = vim_strchr(curbuf->b_p_nf, 'k') != NULL; // "blanK"
|
||||||
|
|
||||||
if (virtual_active(curwin)) {
|
if (virtual_active(curwin)) {
|
||||||
save_coladd = pos->coladd;
|
save_coladd = pos->coladd;
|
||||||
@@ -4532,10 +4533,14 @@ bool do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
|
|||||||
if (col > pos->col && ptr[col - 1] == '-'
|
if (col > pos->col && ptr[col - 1] == '-'
|
||||||
&& !utf_head_off(ptr, ptr + col - 1)
|
&& !utf_head_off(ptr, ptr + col - 1)
|
||||||
&& !do_unsigned) {
|
&& !do_unsigned) {
|
||||||
|
if (do_blank && col >= 2 && !ascii_iswhite(ptr[col - 2])) {
|
||||||
|
blank_unsigned = true;
|
||||||
|
} else {
|
||||||
negative = true;
|
negative = true;
|
||||||
was_positive = false;
|
was_positive = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
int firstdigit = (uint8_t)ptr[col];
|
int firstdigit = (uint8_t)ptr[col];
|
||||||
@@ -4579,10 +4584,14 @@ bool do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
|
|||||||
&& !utf_head_off(ptr, ptr + col - 1)
|
&& !utf_head_off(ptr, ptr + col - 1)
|
||||||
&& !visual
|
&& !visual
|
||||||
&& !do_unsigned) {
|
&& !do_unsigned) {
|
||||||
|
if (do_blank && col >= 2 && !ascii_iswhite(ptr[col - 2])) {
|
||||||
|
blank_unsigned = true;
|
||||||
|
} else {
|
||||||
// negative number
|
// negative number
|
||||||
col--;
|
col--;
|
||||||
negative = true;
|
negative = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// get the number value (unsigned)
|
// get the number value (unsigned)
|
||||||
if (visual && VIsual_mode != 'V') {
|
if (visual && VIsual_mode != 'V') {
|
||||||
@@ -4638,7 +4647,7 @@ bool do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_unsigned && negative) {
|
if ((do_unsigned || blank_unsigned) && negative) {
|
||||||
if (subtract) {
|
if (subtract) {
|
||||||
// sticking at zero.
|
// sticking at zero.
|
||||||
n = 0;
|
n = 0;
|
||||||
|
@@ -5717,6 +5717,20 @@ return {
|
|||||||
(without "unsigned" it would become "9-2019").
|
(without "unsigned" it would become "9-2019").
|
||||||
Using CTRL-X on "0" or CTRL-A on "18446744073709551615"
|
Using CTRL-X on "0" or CTRL-A on "18446744073709551615"
|
||||||
(2^64 - 1) has no effect, overflow is prevented.
|
(2^64 - 1) has no effect, overflow is prevented.
|
||||||
|
blank If included, treat numbers as signed or unsigned based on
|
||||||
|
preceding whitespace. If a number with a leading dash has its
|
||||||
|
dash immediately preceded by a non-whitespace character (i.e.,
|
||||||
|
not a tab or a " "), the negative sign won't be considered as
|
||||||
|
part of the number. For example:
|
||||||
|
Using CTRL-A on "14" in "Carbon-14" results in "Carbon-15"
|
||||||
|
(without "blank" it would become "Carbon-13").
|
||||||
|
Using CTRL-X on "8" in "Carbon -8" results in "Carbon -9"
|
||||||
|
(because -8 is preceded by whitespace. If "unsigned" was
|
||||||
|
set, it would result in "Carbon -7").
|
||||||
|
If this format is included, overflow is prevented as if
|
||||||
|
"unsigned" were set. If both this format and "unsigned" are
|
||||||
|
included, "unsigned" will take precedence.
|
||||||
|
|
||||||
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.
|
||||||
|
@@ -82,7 +82,7 @@ static char *(p_dip_values[]) = { "filler", "context:", "iblank", "icase",
|
|||||||
"closeoff", "hiddenoff", "foldcolumn:", "followwrap", "internal",
|
"closeoff", "hiddenoff", "foldcolumn:", "followwrap", "internal",
|
||||||
"indent-heuristic", "linematch:", "algorithm:", NULL };
|
"indent-heuristic", "linematch:", "algorithm:", NULL };
|
||||||
static char *(p_dip_algorithm_values[]) = { "myers", "minimal", "patience", "histogram", NULL };
|
static char *(p_dip_algorithm_values[]) = { "myers", "minimal", "patience", "histogram", NULL };
|
||||||
static char *(p_nf_values[]) = { "bin", "octal", "hex", "alpha", "unsigned", NULL };
|
static char *(p_nf_values[]) = { "bin", "octal", "hex", "alpha", "unsigned", "blank", 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 };
|
||||||
static char *(p_cb_values[]) = { "unnamed", "unnamedplus", NULL };
|
static char *(p_cb_values[]) = { "unnamed", "unnamedplus", NULL };
|
||||||
static char *(p_cmp_values[]) = { "internal", "keepascii", NULL };
|
static char *(p_cmp_values[]) = { "internal", "keepascii", NULL };
|
||||||
|
@@ -841,6 +841,44 @@ func Test_increment_unsigned()
|
|||||||
set nrformats-=unsigned
|
set nrformats-=unsigned
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" Try incrementing/decrementing a number when nrformats contains blank
|
||||||
|
func Test_increment_blank()
|
||||||
|
set nrformats+=blank
|
||||||
|
|
||||||
|
" Signed
|
||||||
|
call setline(1, '0')
|
||||||
|
exec "norm! gg0\<C-X>"
|
||||||
|
call assert_equal('-1', getline(1))
|
||||||
|
|
||||||
|
call setline(1, '3')
|
||||||
|
exec "norm! gg010\<C-X>"
|
||||||
|
call assert_equal('-7', getline(1))
|
||||||
|
|
||||||
|
call setline(1, '-0')
|
||||||
|
exec "norm! gg0\<C-X>"
|
||||||
|
call assert_equal("-1", getline(1))
|
||||||
|
|
||||||
|
" Unsigned
|
||||||
|
" NOTE: 18446744073709551615 == 2^64 - 1
|
||||||
|
call setline(1, 'a-18446744073709551615')
|
||||||
|
exec "norm! gg0\<C-A>"
|
||||||
|
call assert_equal('a-18446744073709551615', getline(1))
|
||||||
|
|
||||||
|
call setline(1, 'a-18446744073709551615')
|
||||||
|
exec "norm! gg0\<C-A>"
|
||||||
|
call assert_equal('a-18446744073709551615', getline(1))
|
||||||
|
|
||||||
|
call setline(1, 'a-18446744073709551614')
|
||||||
|
exec "norm! gg08\<C-A>"
|
||||||
|
call assert_equal('a-18446744073709551615', getline(1))
|
||||||
|
|
||||||
|
call setline(1, 'a-1')
|
||||||
|
exec "norm! gg0\<C-A>"
|
||||||
|
call assert_equal('a-2', getline(1))
|
||||||
|
|
||||||
|
set nrformats-=blank
|
||||||
|
endfunc
|
||||||
|
|
||||||
func Test_in_decrement_large_number()
|
func Test_in_decrement_large_number()
|
||||||
" NOTE: 18446744073709551616 == 2^64
|
" NOTE: 18446744073709551616 == 2^64
|
||||||
call setline(1, '18446744073709551616')
|
call setline(1, '18446744073709551616')
|
||||||
|
Reference in New Issue
Block a user