aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/options.txt14
-rw-r--r--runtime/lua/vim/_meta/options.lua14
-rw-r--r--src/nvim/ops.c33
-rw-r--r--src/nvim/options.lua14
-rw-r--r--src/nvim/optionstr.c2
-rw-r--r--test/old/testdir/test_increment.vim38
6 files changed, 102 insertions, 13 deletions
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 70d0bd4369..4bb589fb2c 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -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").
Using CTRL-X on "0" or CTRL-A on "18446744073709551615"
(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
considered decimal. This also happens for numbers that are not
recognized as octal or hex.
diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua
index fb04da14a5..40c12d94fd 100644
--- a/runtime/lua/vim/_meta/options.lua
+++ b/runtime/lua/vim/_meta/options.lua
@@ -4549,6 +4549,20 @@ vim.go.mouset = vim.go.mousetime
--- (without "unsigned" it would become "9-2019").
--- Using CTRL-X on "0" or CTRL-A on "18446744073709551615"
--- (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
--- considered decimal. This also happens for numbers that are not
--- recognized as octal or hex.
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 7bffb12412..f2f8708235 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -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
static bool hexupper = false; // 0xABC
uvarnumber_T n;
+ bool blank_unsigned = false; // blank: treat as unsigned?
bool negative = false;
bool was_positive = true;
bool visual = VIsual_active;
@@ -4430,12 +4431,12 @@ bool do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
pos_T endpos;
colnr_T save_coladd = 0;
- const bool do_hex = vim_strchr(curbuf->b_p_nf, 'x') != NULL; // "heX"
- 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_alpha = vim_strchr(curbuf->b_p_nf, 'p') != NULL; // "alPha"
- // "Unsigned"
- const bool do_unsigned = vim_strchr(curbuf->b_p_nf, 'u') != NULL;
+ const bool do_hex = vim_strchr(curbuf->b_p_nf, 'x') != NULL; // "heX"
+ 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_alpha = vim_strchr(curbuf->b_p_nf, 'p') != NULL; // "alPha"
+ const bool do_unsigned = vim_strchr(curbuf->b_p_nf, 'u') != NULL; // "Unsigned"
+ const bool do_blank = vim_strchr(curbuf->b_p_nf, 'k') != NULL; // "blanK"
if (virtual_active(curwin)) {
save_coladd = pos->coladd;
@@ -4532,8 +4533,12 @@ bool do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
if (col > pos->col && ptr[col - 1] == '-'
&& !utf_head_off(ptr, ptr + col - 1)
&& !do_unsigned) {
- negative = true;
- was_positive = false;
+ if (do_blank && col >= 2 && !ascii_iswhite(ptr[col - 2])) {
+ blank_unsigned = true;
+ } else {
+ negative = true;
+ was_positive = false;
+ }
}
}
@@ -4579,9 +4584,13 @@ bool do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
&& !utf_head_off(ptr, ptr + col - 1)
&& !visual
&& !do_unsigned) {
- // negative number
- col--;
- negative = true;
+ if (do_blank && col >= 2 && !ascii_iswhite(ptr[col - 2])) {
+ blank_unsigned = true;
+ } else {
+ // negative number
+ col--;
+ negative = true;
+ }
}
// get the number value (unsigned)
@@ -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) {
// sticking at zero.
n = 0;
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index 365679261c..6e317a426c 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -5717,6 +5717,20 @@ return {
(without "unsigned" it would become "9-2019").
Using CTRL-X on "0" or CTRL-A on "18446744073709551615"
(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
considered decimal. This also happens for numbers that are not
recognized as octal or hex.
diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c
index cdbb8c2d6d..1a4c142fdd 100644
--- a/src/nvim/optionstr.c
+++ b/src/nvim/optionstr.c
@@ -82,7 +82,7 @@ static char *(p_dip_values[]) = { "filler", "context:", "iblank", "icase",
"closeoff", "hiddenoff", "foldcolumn:", "followwrap", "internal",
"indent-heuristic", "linematch:", "algorithm:", 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_cb_values[]) = { "unnamed", "unnamedplus", NULL };
static char *(p_cmp_values[]) = { "internal", "keepascii", NULL };
diff --git a/test/old/testdir/test_increment.vim b/test/old/testdir/test_increment.vim
index 433b2b4471..cf6334747a 100644
--- a/test/old/testdir/test_increment.vim
+++ b/test/old/testdir/test_increment.vim
@@ -841,6 +841,44 @@ func Test_increment_unsigned()
set nrformats-=unsigned
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()
" NOTE: 18446744073709551616 == 2^64
call setline(1, '18446744073709551616')