diff options
author | zeertzjq <zeertzjq@outlook.com> | 2022-07-25 19:01:48 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-25 19:01:48 +0800 |
commit | 6e9a7e7db81b899553548b82b42bf5c162109e19 (patch) | |
tree | a313a1b2f01708f784d3af2a98c3444592c3ac3d /src | |
parent | 6c26d0b068a3aee4155f38bbf52e3568073ede8a (diff) | |
parent | aba3147cb62339714633b53f9ba114b08c5d6761 (diff) | |
download | rneovim-6e9a7e7db81b899553548b82b42bf5c162109e19.tar.gz rneovim-6e9a7e7db81b899553548b82b42bf5c162109e19.tar.bz2 rneovim-6e9a7e7db81b899553548b82b42bf5c162109e19.zip |
Merge pull request #19493 from zeertzjq/vim-8.2.1469
vim-patch:8.2.{1469,2254,2284,2285,2969,4228}: option fixes and refactorings
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/api/options.c | 20 | ||||
-rw-r--r-- | src/nvim/eval.c | 14 | ||||
-rw-r--r-- | src/nvim/eval/vars.c | 58 | ||||
-rw-r--r-- | src/nvim/normal.c | 3 | ||||
-rw-r--r-- | src/nvim/option.c | 45 | ||||
-rw-r--r-- | src/nvim/option.h | 11 | ||||
-rw-r--r-- | src/nvim/spell.c | 2 | ||||
-rw-r--r-- | src/nvim/testdir/test_diffmode.vim | 46 | ||||
-rw-r--r-- | src/nvim/testdir/test_normal.vim | 3 | ||||
-rw-r--r-- | src/nvim/testdir/test_vimscript.vim | 21 |
10 files changed, 159 insertions, 64 deletions
diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c index 4ed676e613..5c9eba163b 100644 --- a/src/nvim/api/options.c +++ b/src/nvim/api/options.c @@ -104,20 +104,20 @@ Object nvim_get_option_value(String name, Dict(option) *opts, Error *err) long numval = 0; char *stringval = NULL; - int result = access_option_value_for(name.data, &numval, &stringval, scope, opt_type, from, - true, err); + getoption_T result = access_option_value_for(name.data, &numval, &stringval, scope, opt_type, + from, true, err); if (ERROR_SET(err)) { return rv; } switch (result) { - case 0: + case gov_string: rv = STRING_OBJ(cstr_as_string(stringval)); break; - case 1: + case gov_number: rv = INTEGER_OBJ(numval); break; - case 2: + case gov_bool: switch (numval) { case 0: case 1: @@ -483,8 +483,8 @@ void set_option_to(uint64_t channel_id, void *to, int type, String name, Object }); } -static int access_option_value(char *key, long *numval, char **stringval, int opt_flags, bool get, - Error *err) +static getoption_T access_option_value(char *key, long *numval, char **stringval, int opt_flags, + bool get, Error *err) { if (get) { return get_option_value(key, numval, stringval, opt_flags); @@ -501,13 +501,13 @@ static int access_option_value(char *key, long *numval, char **stringval, int op } } -static int access_option_value_for(char *key, long *numval, char **stringval, int opt_flags, - int opt_type, void *from, bool get, Error *err) +static getoption_T access_option_value_for(char *key, long *numval, char **stringval, int opt_flags, + int opt_type, void *from, bool get, Error *err) { bool need_switch = false; switchwin_T switchwin; aco_save_T aco; - int result = 0; + getoption_T result = 0; try_start(); switch (opt_type) { diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 7b2a20e6fb..9c27ec16f3 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -3774,7 +3774,7 @@ int get_option_tv(const char **const arg, typval_T *const rettv, const bool eval { long numval; char *stringval; - int opt_type; + getoption_T opt_type; bool working = (**arg == '+'); // has("+option") int ret = OK; int opt_flags; @@ -3798,26 +3798,28 @@ int get_option_tv(const char **const arg, typval_T *const rettv, const bool eval opt_type = get_option_value(*arg, &numval, rettv == NULL ? NULL : &stringval, opt_flags); - if (opt_type == -3) { // invalid name + if (opt_type == gov_unknown) { if (rettv != NULL) { semsg(_("E113: Unknown option: %s"), *arg); } ret = FAIL; } else if (rettv != NULL) { - if (opt_type == -2) { // hidden string option + if (opt_type == gov_hidden_string) { rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; - } else if (opt_type == -1) { // hidden number option + } else if (opt_type == gov_hidden_bool || opt_type == gov_hidden_number) { rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; - } else if (opt_type == 1 || opt_type == 2) { // number or boolean option + } else if (opt_type == gov_bool || opt_type == gov_number) { rettv->v_type = VAR_NUMBER; rettv->vval.v_number = numval; } else { // string option rettv->v_type = VAR_STRING; rettv->vval.v_string = stringval; } - } else if (working && (opt_type == -2 || opt_type == -1)) { + } else if (working && (opt_type == gov_hidden_bool + || opt_type == gov_hidden_number + || opt_type == gov_hidden_string)) { ret = FAIL; } diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index e56ccef02b..152d1c3e00 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -619,26 +619,38 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo && vim_strchr(endchars, *skipwhite(p)) == NULL)) { emsg(_(e_letunexp)); } else { - int opt_type; + varnumber_T n = 0; + getoption_T opt_type; long numval; char *stringval = NULL; const char *s = NULL; + bool failed = false; const char c1 = *p; *p = NUL; - varnumber_T n = tv_get_number(tv); + opt_type = get_option_value(arg, &numval, &stringval, opt_flags); + if (opt_type == gov_bool + || opt_type == gov_number + || opt_type == gov_hidden_bool + || opt_type == gov_hidden_number) { + // number, possibly hidden + n = (long)tv_get_number(tv); + } + + // Avoid setting a string option to the text "v:false" or similar. if (tv->v_type != VAR_BOOL && tv->v_type != VAR_SPECIAL) { - s = tv_get_string_chk(tv); // != NULL if number or string. + s = tv_get_string_chk(tv); } - if (s != NULL && op != NULL && *op != '=') { - opt_type = get_option_value(arg, &numval, &stringval, opt_flags); - if ((opt_type == 1 && *op == '.') - || (opt_type == 0 && *op != '.')) { + + if (op != NULL && *op != '=') { + if (((opt_type == gov_bool || opt_type == gov_number) && *op == '.') + || (opt_type == gov_string && *op != '.')) { semsg(_(e_letwrong), op); - s = NULL; // don't set the value + failed = true; // don't set the value } else { - if (opt_type == 1) { // number + // number or bool + if (opt_type == gov_number || opt_type == gov_bool) { switch (*op) { case '+': n = numval + n; break; @@ -651,7 +663,9 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo case '%': n = num_modulus(numval, n); break; } - } else if (opt_type == 0 && stringval != NULL) { // string + s = NULL; + } else if (opt_type == gov_string && stringval != NULL && s != NULL) { + // string char *const oldstringval = stringval; stringval = (char *)concat_str((const char_u *)stringval, (const char_u *)s); @@ -660,10 +674,14 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo } } } - if (s != NULL || tv->v_type == VAR_BOOL - || tv->v_type == VAR_SPECIAL) { - set_option_value((const char *)arg, n, s, opt_flags); - arg_end = p; + + if (!failed) { + if (opt_type != gov_string || s != NULL) { + set_option_value(arg, n, s, opt_flags); + arg_end = p; + } else { + emsg(_(e_stringreq)); + } } *p = c1; xfree(stringval); @@ -1547,10 +1565,18 @@ static void getwinvar(typval_T *argvars, typval_T *rettv, int off) /// Set option "varname" to the value of "varp" for the current buffer/window. static void set_option_from_tv(const char *varname, typval_T *varp) { + long numval = 0; + const char *strval; bool error = false; char nbuf[NUMBUFLEN]; - const long numval = (long)tv_get_number_chk(varp, &error); - const char *const strval = tv_get_string_buf_chk(varp, nbuf); + + if (varp->v_type == VAR_BOOL) { + numval = (long)varp->vval.v_number; + strval = "0"; // avoid using "false" + } else { + numval = (long)tv_get_number_chk(varp, &error); + strval = tv_get_string_buf_chk(varp, nbuf); + } if (!error && strval != NULL) { set_option_value(varname, numval, strval, OPT_LOCAL); } diff --git a/src/nvim/normal.c b/src/nvim/normal.c index a842bb20a9..64bc868cb5 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -3485,7 +3485,8 @@ void scroll_redraw(int up, long count) redraw_later(curwin, VALID); } -/// Get the count specified after a 'z' command. +/// Get the count specified after a 'z' command. Only the 'z<CR>', 'zl', 'zh', +/// 'z<Left>', and 'z<Right>' commands accept a count after 'z'. /// @return true to process the 'z' command and false to skip it. static bool nv_z_get_count(cmdarg_T *cap, int *nchar_arg) { diff --git a/src/nvim/option.c b/src/nvim/option.c index bb3881b809..ea4c7080b7 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -5046,28 +5046,29 @@ static int findoption(const char *const arg) /// @param stringval NULL when only checking existence /// /// @returns: -/// Toggle option: 2, *numval gets value. -/// Number option: 1, *numval gets value. -/// String option: 0, *stringval gets allocated string. -/// Hidden Number or Toggle option: -1. -/// hidden String option: -2. -/// unknown option: -3. -int get_option_value(const char *name, long *numval, char **stringval, int opt_flags) +/// Number option: gov_number, *numval gets value. +/// Tottle option: gov_bool, *numval gets value. +/// String option: gov_string, *stringval gets allocated string. +/// Hidden Number option: gov_hidden_number. +/// Hidden Toggle option: gov_hidden_bool. +/// Hidden String option: gov_hidden_string. +/// Unknown option: gov_unknown. +getoption_T get_option_value(const char *name, long *numval, char **stringval, int opt_flags) { if (get_tty_option(name, stringval)) { - return 0; + return gov_string; } int opt_idx = findoption(name); - if (opt_idx < 0) { // Unknown option. - return -3; + if (opt_idx < 0) { // option not in the table + return gov_unknown; } char_u *varp = get_varp_scope(&(options[opt_idx]), opt_flags); if (options[opt_idx].flags & P_STRING) { if (varp == NULL) { // hidden option - return -2; + return gov_hidden_string; } if (stringval != NULL) { if ((char_u **)varp == &p_pt) { // 'pastetoggle' @@ -5076,26 +5077,24 @@ int get_option_value(const char *name, long *numval, char **stringval, int opt_f *stringval = xstrdup(*(char **)(varp)); } } - return 0; + return gov_string; } if (varp == NULL) { // hidden option - return -1; + return (options[opt_idx].flags & P_NUM) ? gov_hidden_number : gov_hidden_bool; } if (options[opt_idx].flags & P_NUM) { *numval = *(long *)varp; - return 1; - } - - // Special case: 'modified' is b_changed, but we also want to consider - // it set when 'ff' or 'fenc' changed. - if ((int *)varp == &curbuf->b_changed) { - *numval = curbufIsChanged(); } else { - *numval = (long)*(int *)varp; // NOLINT(whitespace/cast) + // Special case: 'modified' is b_changed, but we also want to consider + // it set when 'ff' or 'fenc' changed. + if ((int *)varp == &curbuf->b_changed) { + *numval = curbufIsChanged(); + } else { + *numval = (long)(*(int *)varp); + } } - - return 2; + return (options[opt_idx].flags & P_NUM) ? gov_number : gov_bool; } // Returns the option attributes and its value. Unlike the above function it diff --git a/src/nvim/option.h b/src/nvim/option.h index 9321dd5454..a5a57cc66d 100644 --- a/src/nvim/option.h +++ b/src/nvim/option.h @@ -3,6 +3,17 @@ #include "nvim/ex_cmds_defs.h" // for exarg_T +/// Returned by get_option_value(). +typedef enum { + gov_unknown, + gov_bool, + gov_number, + gov_string, + gov_hidden_bool, + gov_hidden_number, + gov_hidden_string, +} getoption_T; + // flags for buf_copy_options() #define BCO_ENTER 1 // going to enter the buffer #define BCO_ALWAYS 2 // always copy the options diff --git a/src/nvim/spell.c b/src/nvim/spell.c index 8bc9cda247..948e935907 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -6880,7 +6880,7 @@ void ex_spelldump(exarg_T *eap) if (no_spell_checking(curwin)) { return; } - get_option_value("spl", &dummy, &spl, OPT_LOCAL); + (void)get_option_value("spl", &dummy, &spl, OPT_LOCAL); // Create a new empty buffer in a new window. do_cmdline_cmd("new"); diff --git a/src/nvim/testdir/test_diffmode.vim b/src/nvim/testdir/test_diffmode.vim index 8c20c647f1..007b7e0f14 100644 --- a/src/nvim/testdir/test_diffmode.vim +++ b/src/nvim/testdir/test_diffmode.vim @@ -1332,4 +1332,50 @@ func Test_diff_binary() set diffopt&vim endfunc +" Test for using the 'zi' command to invert 'foldenable' in diff windows (test +" for the issue fixed by patch 6.2.317) +func Test_diff_foldinvert() + %bw! + edit Xfile1 + new Xfile2 + new Xfile3 + windo diffthis + " open a non-diff window + botright new + 1wincmd w + call assert_true(getwinvar(1, '&foldenable')) + call assert_true(getwinvar(2, '&foldenable')) + call assert_true(getwinvar(3, '&foldenable')) + normal zi + call assert_false(getwinvar(1, '&foldenable')) + call assert_false(getwinvar(2, '&foldenable')) + call assert_false(getwinvar(3, '&foldenable')) + normal zi + call assert_true(getwinvar(1, '&foldenable')) + call assert_true(getwinvar(2, '&foldenable')) + call assert_true(getwinvar(3, '&foldenable')) + + " If the current window has 'noscrollbind', then 'zi' should not change + " 'foldenable' in other windows. + 1wincmd w + set noscrollbind + normal zi + call assert_false(getwinvar(1, '&foldenable')) + call assert_true(getwinvar(2, '&foldenable')) + call assert_true(getwinvar(3, '&foldenable')) + + " 'zi' should not change the 'foldenable' for windows with 'noscrollbind' + 1wincmd w + set scrollbind + normal zi + call setwinvar(2, '&scrollbind', v:false) + normal zi + call assert_false(getwinvar(1, '&foldenable')) + call assert_true(getwinvar(2, '&foldenable')) + call assert_false(getwinvar(3, '&foldenable')) + + %bw! + set scrollbind& +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim index ffa0cd1807..f18ddb274c 100644 --- a/src/nvim/testdir/test_normal.vim +++ b/src/nvim/testdir/test_normal.vim @@ -580,6 +580,7 @@ endfunc func Test_normal_z_error() call assert_beeps('normal! z2p') call assert_beeps('normal! zq') + call assert_beeps('normal! cz1') endfunc func Test_normal15_z_scroll_vert() @@ -619,7 +620,7 @@ func Test_normal15_z_scroll_vert() call assert_equal(10, winheight(0)) exe "norm! z12\<cr>" call assert_equal(12, winheight(0)) - exe "norm! z10\<cr>" + exe "norm! z15\<Del>0\<cr>" call assert_equal(10, winheight(0)) " Test for z. diff --git a/src/nvim/testdir/test_vimscript.vim b/src/nvim/testdir/test_vimscript.vim index 1323288676..de4629451b 100644 --- a/src/nvim/testdir/test_vimscript.vim +++ b/src/nvim/testdir/test_vimscript.vim @@ -1661,16 +1661,25 @@ func Test_compound_assignment_operators() call assert_equal(6, &scrolljump) let &scrolljump %= 5 call assert_equal(1, &scrolljump) - call assert_fails('let &scrolljump .= "j"', 'E734') + call assert_fails('let &scrolljump .= "j"', 'E734:') set scrolljump&vim + let &foldlevelstart = 2 + let &foldlevelstart -= 1 + call assert_equal(1, &foldlevelstart) + let &foldlevelstart -= 1 + call assert_equal(0, &foldlevelstart) + let &foldlevelstart = 2 + let &foldlevelstart -= 2 + call assert_equal(0, &foldlevelstart) + " Test for register let @/ = 1 - call assert_fails('let @/ += 1', 'E734') - call assert_fails('let @/ -= 1', 'E734') - call assert_fails('let @/ *= 1', 'E734') - call assert_fails('let @/ /= 1', 'E734') - call assert_fails('let @/ %= 1', 'E734') + call assert_fails('let @/ += 1', 'E734:') + call assert_fails('let @/ -= 1', 'E734:') + call assert_fails('let @/ *= 1', 'E734:') + call assert_fails('let @/ /= 1', 'E734:') + call assert_fails('let @/ %= 1', 'E734:') let @/ .= 's' call assert_equal('1s', @/) let @/ = '' |