From 981fa11c91d3655828b4f70ccf7d079d917d5b6b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 3 Nov 2024 16:52:20 +0800 Subject: [PATCH 1/2] vim-patch:9.1.0832: :set doesn't work for 'cot' and 'bkc' after :setlocal Problem: :set doesn't work for 'cot' and 'bkc' after :setlocal. Solution: clear the local flags when using :set (zeertzjq). closes: vim/vim#15981 https://github.com/vim/vim/commit/46dcd84d242db6b053cb5b777c896cede9ad9b27 --- src/nvim/optionstr.c | 6 ++++ test/old/testdir/test_ins_complete.vim | 40 ++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 307c4ae79f..48423a1779 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -655,6 +655,9 @@ const char *did_set_backupcopy(optset_T *args) if (opt_flags & OPT_LOCAL) { bkc = buf->b_p_bkc; flags = &buf->b_bkc_flags; + } else if (!(opt_flags & OPT_GLOBAL)) { + // When using :set, clear the local flags. + buf->b_bkc_flags = 0; } if ((opt_flags & OPT_LOCAL) && *bkc == NUL) { @@ -1070,6 +1073,9 @@ const char *did_set_completeopt(optset_T *args FUNC_ATTR_UNUSED) if (args->os_flags & OPT_LOCAL) { cot = buf->b_p_cot; flags = &buf->b_cot_flags; + } else if (!(args->os_flags & OPT_GLOBAL)) { + // When using :set, clear the local flags. + buf->b_cot_flags = 0; } if (check_opt_strings(cot, p_cot_values, true) != OK) { diff --git a/test/old/testdir/test_ins_complete.vim b/test/old/testdir/test_ins_complete.vim index 8e2a7c4631..01695d5be5 100644 --- a/test/old/testdir/test_ins_complete.vim +++ b/test/old/testdir/test_ins_complete.vim @@ -950,6 +950,46 @@ func Test_completeopt_buffer_local() call assert_equal('menu', &completeopt) call assert_equal('menu', &g:completeopt) + new | only + call setline(1, ['foofoo', 'foobar', 'foobaz', '']) + set completeopt& + setlocal completeopt=menu,fuzzy,noinsert + setglobal completeopt=menu,longest + call assert_equal('menu,fuzzy,noinsert', &completeopt) + call assert_equal('menu,fuzzy,noinsert', &l:completeopt) + call assert_equal('menu,longest', &g:completeopt) + call feedkeys("Gccf\\bz\", 'tnix') + call assert_equal('foobaz', getline('.')) + setlocal bufhidden=wipe + new | only! + call setline(1, ['foofoo', 'foobar', 'foobaz', '']) + call assert_equal('menu,longest', &completeopt) + call assert_equal('menu,longest', &g:completeopt) + call assert_equal('', &l:completeopt) + call feedkeys("Gccf\\\\", 'tnix') + call assert_equal('foo', getline('.')) + bwipe! + + new | only + call setline(1, ['foofoo', 'foobar', 'foobaz', '']) + set completeopt& + setlocal completeopt=menu,fuzzy,noinsert + set completeopt=menu,longest + call assert_equal('menu,longest', &completeopt) + call assert_equal('menu,longest', &g:completeopt) + call assert_equal('', &l:completeopt) + call feedkeys("Gccf\\\\", 'tnix') + call assert_equal('foo', getline('.')) + setlocal bufhidden=wipe + new | only! + call setline(1, ['foofoo', 'foobar', 'foobaz', '']) + call assert_equal('menu,longest', &completeopt) + call assert_equal('menu,longest', &g:completeopt) + call assert_equal('', &l:completeopt) + call feedkeys("Gccf\\\\", 'tnix') + call assert_equal('foo', getline('.')) + bwipe! + set completeopt& endfunc From fe565ca382bb6cc4cd9f1c01de42d62c48922bf6 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 3 Nov 2024 16:54:25 +0800 Subject: [PATCH 2/2] vim-patch:9.1.0835: :setglobal doesn't work properly for 'ffu' and 'tsrfu' Problem: :setglobal doesn't work properly for 'ffu' and 'tsrfu' when the local value is set (after v9.1.0831) Solution: Check os_flags instead of buffer option variable (zeertzjq). closes: vim/vim#15980 https://github.com/vim/vim/commit/6eda269600b5ca952f28e808c662f67e581933d7 --- src/nvim/ex_docmd.c | 8 +++-- src/nvim/insexpand.c | 17 +++++++---- test/old/testdir/test_findfile.vim | 37 ++++++++++++++++++++++- test/old/testdir/test_ins_complete.vim | 41 ++++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 9 deletions(-) diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 1c215cd3e1..92695aa4de 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -5173,7 +5173,7 @@ static Callback *get_findfunc_callback(void) return *curbuf->b_p_ffu != NUL ? &curbuf->b_ffu_cb : &ffu_cb; } -/// Call 'findfunc' to obtain the list of file names. +/// Call 'findfunc' to obtain a list of file names. static list_T *call_findfunc(char *pat, BoolVarValue cmdcomplete) { const sctx_T saved_sctx = current_sctx; @@ -5294,12 +5294,16 @@ const char *did_set_findfunc(optset_T *args) buf_T *buf = (buf_T *)args->os_buf; int retval; - if (*buf->b_p_ffu != NUL) { + if (args->os_flags & OPT_LOCAL) { // buffer-local option set retval = option_set_callback_func(buf->b_p_ffu, &buf->b_ffu_cb); } else { // global option set retval = option_set_callback_func(p_ffu, &ffu_cb); + // when using :set, free the local callback + if (!(args->os_flags & OPT_GLOBAL)) { + callback_free(&buf->b_ffu_cb); + } } if (retval == FAIL) { diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c index 2482cef7a1..c8314d1bb2 100644 --- a/src/nvim/insexpand.c +++ b/src/nvim/insexpand.c @@ -2368,13 +2368,13 @@ static void copy_global_to_buflocal_cb(Callback *globcb, Callback *bufcb) /// Invoked when the 'completefunc' option is set. The option value can be a /// name of a function (string), or function() or funcref() or a /// lambda expression. -const char *did_set_completefunc(optset_T *args FUNC_ATTR_UNUSED) +const char *did_set_completefunc(optset_T *args) { - if (option_set_callback_func(curbuf->b_p_cfu, &cfu_cb) == FAIL) { + buf_T *buf = (buf_T *)args->os_buf; + if (option_set_callback_func(buf->b_p_cfu, &cfu_cb) == FAIL) { return e_invarg; } - - set_buflocal_cfu_callback(curbuf); + set_buflocal_cfu_callback(buf); return NULL; } @@ -2412,14 +2412,19 @@ void set_buflocal_ofu_callback(buf_T *buf) /// lambda expression. const char *did_set_thesaurusfunc(optset_T *args FUNC_ATTR_UNUSED) { + buf_T *buf = (buf_T *)args->os_buf; int retval; - if (*curbuf->b_p_tsrfu != NUL) { + if (args->os_flags & OPT_LOCAL) { // buffer-local option set - retval = option_set_callback_func(curbuf->b_p_tsrfu, &curbuf->b_tsrfu_cb); + retval = option_set_callback_func(buf->b_p_tsrfu, &buf->b_tsrfu_cb); } else { // global option set retval = option_set_callback_func(p_tsrfu, &tsrfu_cb); + // when using :set, free the local callback + if (!(args->os_flags & OPT_GLOBAL)) { + callback_free(&buf->b_tsrfu_cb); + } } return retval == FAIL ? e_invarg : NULL; diff --git a/test/old/testdir/test_findfile.vim b/test/old/testdir/test_findfile.vim index 2c049537f0..539c7a661a 100644 --- a/test/old/testdir/test_findfile.vim +++ b/test/old/testdir/test_findfile.vim @@ -364,7 +364,7 @@ func Test_findfunc() " Error cases - " Function that doesn't any argument + " Function that doesn't take any arguments func FindFuncNoArg() endfunc set findfunc=FindFuncNoArg @@ -484,6 +484,41 @@ func Test_findfunc_scriptlocal_func() call assert_equal('abc', g:FindFuncArg) bw! + new | only + set findfunc= + setlocal findfunc=NoSuchFunc + setglobal findfunc=s:FindFuncScript + call assert_equal('NoSuchFunc', &findfunc) + call assert_equal('NoSuchFunc', &l:findfunc) + call assert_equal(expand('') .. 'FindFuncScript', &g:findfunc) + new | only + call assert_equal(expand('') .. 'FindFuncScript', &findfunc) + call assert_equal(expand('') .. 'FindFuncScript', &g:findfunc) + call assert_equal('', &l:findfunc) + let g:FindFuncArg = '' + find abc + call assert_equal('abc', g:FindFuncArg) + bw! + + new | only + set findfunc= + setlocal findfunc=NoSuchFunc + set findfunc=s:FindFuncScript + call assert_equal(expand('') .. 'FindFuncScript', &findfunc) + call assert_equal(expand('') .. 'FindFuncScript', &g:findfunc) + call assert_equal('', &l:findfunc) + let g:FindFuncArg = '' + find abc + call assert_equal('abc', g:FindFuncArg) + new | only + call assert_equal(expand('') .. 'FindFuncScript', &findfunc) + call assert_equal(expand('') .. 'FindFuncScript', &g:findfunc) + call assert_equal('', &l:findfunc) + let g:FindFuncArg = '' + find abc + call assert_equal('abc', g:FindFuncArg) + bw! + set findfunc= delfunc s:FindFuncScript endfunc diff --git a/test/old/testdir/test_ins_complete.vim b/test/old/testdir/test_ins_complete.vim index 01695d5be5..c02aa1db62 100644 --- a/test/old/testdir/test_ins_complete.vim +++ b/test/old/testdir/test_ins_complete.vim @@ -2268,6 +2268,7 @@ func Test_thesaurusfunc_callback() call add(g:TsrFunc3Args, [a:findstart, a:base]) return a:findstart ? 0 : [] endfunc + set tsrfu=s:TsrFunc3 new call setline(1, 'script1') @@ -2283,6 +2284,46 @@ func Test_thesaurusfunc_callback() call feedkeys("A\\\", 'x') call assert_equal([[1, ''], [0, 'script2']], g:TsrFunc3Args) bw! + + new | only + set thesaurusfunc= + setlocal thesaurusfunc=NoSuchFunc + setglobal thesaurusfunc=s:TsrFunc3 + call assert_equal('NoSuchFunc', &thesaurusfunc) + call assert_equal('NoSuchFunc', &l:thesaurusfunc) + call assert_equal('s:TsrFunc3', &g:thesaurusfunc) + new | only + call assert_equal('s:TsrFunc3', &thesaurusfunc) + call assert_equal('s:TsrFunc3', &g:thesaurusfunc) + call assert_equal('', &l:thesaurusfunc) + call setline(1, 'script1') + let g:TsrFunc3Args = [] + call feedkeys("A\\\", 'x') + call assert_equal([[1, ''], [0, 'script1']], g:TsrFunc3Args) + bw! + + new | only + set thesaurusfunc= + setlocal thesaurusfunc=NoSuchFunc + set thesaurusfunc=s:TsrFunc3 + call assert_equal('s:TsrFunc3', &thesaurusfunc) + call assert_equal('s:TsrFunc3', &g:thesaurusfunc) + call assert_equal('', &l:thesaurusfunc) + call setline(1, 'script1') + let g:TsrFunc3Args = [] + call feedkeys("A\\\", 'x') + call assert_equal([[1, ''], [0, 'script1']], g:TsrFunc3Args) + setlocal bufhidden=wipe + new | only! + call assert_equal('s:TsrFunc3', &thesaurusfunc) + call assert_equal('s:TsrFunc3', &g:thesaurusfunc) + call assert_equal('', &l:thesaurusfunc) + call setline(1, 'script1') + let g:TsrFunc3Args = [] + call feedkeys("A\\\", 'x') + call assert_equal([[1, ''], [0, 'script1']], g:TsrFunc3Args) + bw! + delfunc s:TsrFunc3 " invalid return value