From af2b078258c029cb45eade52f229d9a31b7a7393 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 22 Aug 2022 09:28:32 +0800 Subject: vim-patch:8.2.2030: some tests fail on Mac Problem: Some tests fail on Mac. Solution: Avoid Mac test failures. Add additional test for wildmenu. (Yegappan Lakshmanan, closes vim/vim#7341) https://github.com/vim/vim/commit/4b2ce1297e6e991bf6a674f9465d26d28e648de7 --- src/nvim/testdir/runtest.vim | 7 +++++++ src/nvim/testdir/test_cmdline.vim | 30 ++++++++++++++++++++++++++++++ src/nvim/testdir/test_options.vim | 8 +++++++- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/nvim/testdir/runtest.vim b/src/nvim/testdir/runtest.vim index fcd3d5724c..206f335751 100644 --- a/src/nvim/testdir/runtest.vim +++ b/src/nvim/testdir/runtest.vim @@ -114,6 +114,13 @@ if has('win32') let $PROMPT = '$P$G' endif +if has('mac') + " In MacOS, when starting a shell in a terminal, a bash deprecation warning + " message is displayed. This breaks the terminal test. Disable the warning + " message. + let $BASH_SILENCE_DEPRECATION_WARNING = 1 +endif + " Prepare for calling test_garbagecollect_now(). let v:testing = 1 diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim index 35886d42c5..72d2dc9cbb 100644 --- a/src/nvim/testdir/test_cmdline.vim +++ b/src/nvim/testdir/test_cmdline.vim @@ -1809,6 +1809,36 @@ func Test_read_shellcmd() endif endfunc +" Test for going up and down the directory tree using 'wildmenu' +func Test_wildmenu_dirstack() + CheckUnix + %bw! + call mkdir('Xdir1/dir2/dir3', 'p') + call writefile([], 'Xdir1/file1_1.txt') + call writefile([], 'Xdir1/file1_2.txt') + call writefile([], 'Xdir1/dir2/file2_1.txt') + call writefile([], 'Xdir1/dir2/file2_2.txt') + call writefile([], 'Xdir1/dir2/dir3/file3_1.txt') + call writefile([], 'Xdir1/dir2/dir3/file3_2.txt') + cd Xdir1/dir2/dir3 + set wildmenu + + call feedkeys(":e \\\"\", 'xt') + call assert_equal('"e file3_1.txt', @:) + call feedkeys(":e \\\\"\", 'xt') + call assert_equal('"e ../dir3/', @:) + call feedkeys(":e \\\\\"\", 'xt') + call assert_equal('"e ../../dir2/', @:) + call feedkeys(":e \\\\\\"\", 'xt') + call assert_equal('"e ../../dir2/dir3/', @:) + call feedkeys(":e \\\\\\\"\", 'xt') + call assert_equal('"e ../../dir2/dir3/file3_1.txt', @:) + + cd - + call delete('Xdir1', 'rf') + set wildmenu& +endfunc + " Test for recalling newer or older cmdline from history with , , " , , , , , or . func Test_recalling_cmdline() diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim index fdfc1c0f89..e9a62d00a9 100644 --- a/src/nvim/testdir/test_options.vim +++ b/src/nvim/testdir/test_options.vim @@ -774,7 +774,13 @@ func Test_shell() CheckUnix let save_shell = &shell set shell= - call assert_fails('shell', 'E91:') + let caught_e91 = 0 + try + shell + catch /E91:/ + let caught_e91 = 1 + endtry + call assert_equal(1, caught_e91) let &shell = save_shell endfunc -- cgit From b94cfaf08056a43efa83a1911d9d44ce1ae73711 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 22 Aug 2022 09:48:11 +0800 Subject: vim-patch:8.2.2031: some tests fail when run under valgrind Problem: Some tests fail when run under valgrind. Solution: Avoid timing problems. https://github.com/vim/vim/commit/18dc355395f2eac72ab83d984cacd26ae61c791f --- src/nvim/testdir/test_clientserver.vim | 5 +++-- src/nvim/testdir/test_debugger.vim | 19 ++++++++++++------- src/nvim/testdir/test_quotestar.vim | 5 +++-- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/nvim/testdir/test_clientserver.vim b/src/nvim/testdir/test_clientserver.vim index edf36b413b..370d0cb190 100644 --- a/src/nvim/testdir/test_clientserver.vim +++ b/src/nvim/testdir/test_clientserver.vim @@ -66,8 +66,9 @@ func Test_client_server() call remote_send(name, ":gui -f\") endif " Wait for the server to be up and answering requests. - sleep 100m - call WaitForAssert({-> assert_true(name->remote_expr("v:version", "", 1) != "")}) + " When using valgrind this can be very, very slow. + sleep 1 + call WaitForAssert({-> assert_match('\d', name->remote_expr("v:version", "", 1))}, 10000) call remote_send(name, ":let testvar = 'maybe'\") call WaitForAssert({-> assert_equal('maybe', remote_expr(name, "testvar", "", 2))}) diff --git a/src/nvim/testdir/test_debugger.vim b/src/nvim/testdir/test_debugger.vim index e038c0096a..2be94409ca 100644 --- a/src/nvim/testdir/test_debugger.vim +++ b/src/nvim/testdir/test_debugger.vim @@ -15,14 +15,18 @@ func CheckCWD() endfunc command! -nargs=0 -bar CheckCWD call CheckCWD() +" "options" argument can contain: +" 'msec' - time to wait for a match +" 'match' - "pattern" to use "lines" as pattern instead of text func CheckDbgOutput(buf, lines, options = {}) " Verify the expected output let lnum = 20 - len(a:lines) + let msec = get(a:options, 'msec', 1000) for l in a:lines if get(a:options, 'match', 'equal') ==# 'pattern' - call WaitForAssert({-> assert_match(l, term_getline(a:buf, lnum))}, 200) + call WaitForAssert({-> assert_match(l, term_getline(a:buf, lnum))}, msec) else - call WaitForAssert({-> assert_equal(l, term_getline(a:buf, lnum))}, 200) + call WaitForAssert({-> assert_equal(l, term_getline(a:buf, lnum))}, msec) endif let lnum += 1 endfor @@ -198,7 +202,7 @@ func Test_Debugger() " Start a debug session, so that reading the last line from the terminal " works properly. - call RunDbgCmd(buf, ':debug echo Foo()') + call RunDbgCmd(buf, ':debug echo Foo()', ['cmd: echo Foo()']) " No breakpoints call RunDbgCmd(buf, 'breakl', ['No breakpoints defined']) @@ -814,9 +818,10 @@ func Test_Backtrace_CmdLine() \ '-S Xtest1.vim -c "debug call GlobalFunction()"', \ {'wait_for_ruler': 0}) - " Need to wait for the vim-in-terminal to be ready + " Need to wait for the vim-in-terminal to be ready. + " With valgrind this can take quite long. call CheckDbgOutput(buf, ['command line', - \ 'cmd: call GlobalFunction()']) + \ 'cmd: call GlobalFunction()'], #{msec: 5000}) " At this point the ontly thing in the stack is the cmdline call RunDbgCmd(buf, 'backtrace', [ @@ -967,14 +972,14 @@ func Test_debug_backtrace_level() " set a breakpoint and source file1.vim let buf = RunVimInTerminal( \ '-c "breakadd file 1 Xtest1.vim" -S Xtest1.vim', - \ #{ wait_for_ruler: 0 } ) + \ #{wait_for_ruler: 0}) call CheckDbgOutput(buf, [ \ 'Breakpoint in "' .. file1 .. '" line 1', \ 'Entering Debug mode. Type "cont" to continue.', \ 'command line..script ' .. file1, \ 'line 1: let s:file1_var = ''file1''' - \ ]) + \ ], #{msec: 5000}) " step through the initial declarations call RunDbgCmd(buf, 'step', [ 'line 2: let g:global_var = ''global''' ] ) diff --git a/src/nvim/testdir/test_quotestar.vim b/src/nvim/testdir/test_quotestar.vim index 93865869fa..e3ca141328 100644 --- a/src/nvim/testdir/test_quotestar.vim +++ b/src/nvim/testdir/test_quotestar.vim @@ -98,8 +98,6 @@ func Do_test_quotestar_for_x11() " Running in a terminal and the GUI is available: Tell the server to open " the GUI and check that the remote command still works. - " Need to wait for the GUI to start up, otherwise the send hangs in trying - " to send to the terminal window. if has('gui_athena') || has('gui_motif') " For those GUIs, ignore the 'failed to create input context' error. call remote_send(name, ":call test_ignore_error('E285') | gui -f\") @@ -107,7 +105,10 @@ func Do_test_quotestar_for_x11() call remote_send(name, ":gui -f\") endif " Wait for the server in the GUI to be up and answering requests. + " First need to wait for the GUI to start up, otherwise the send hangs in + " trying to send to the terminal window. " On some systems and with valgrind this can be very slow. + sleep 1 call WaitForAssert({-> assert_match("1", remote_expr(name, "has('gui_running')", "", 1))}, 10000) call remote_send(name, ":let @* = 'maybe'\") -- cgit From 4f6d0d6da971ee837864bf96aa28cc24c2d58b5a Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 22 Aug 2022 12:02:45 +0800 Subject: vim-patch:8.2.2289: Vim9: 'cpo' can become empty (#19887) Problem: Vim9: 'cpo' can become empty. Solution: Use empty_option instead of an empty string. Update quickfix buffer after restoring 'cpo'. (closes vim/vim#7608) https://github.com/vim/vim/commit/e5a2dc87fd9d63dfd0d9c379e363ee8b8c05b14c Omit test as it is Vim9 script. --- src/nvim/eval.c | 7 ++++++- src/nvim/eval/funcs.c | 11 ++++++++--- src/nvim/ex_eval.c | 2 +- src/nvim/quickfix.c | 15 +++++++++++++-- src/nvim/syntax.c | 4 ++-- 5 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/nvim/eval.c b/src/nvim/eval.c index cb46e26f82..a80d2e5fbb 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -2192,7 +2192,7 @@ int pattern_match(char *pat, char *text, bool ic) // avoid 'l' flag in 'cpoptions' char *save_cpo = p_cpo; - p_cpo = ""; + p_cpo = (char *)empty_option; regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING); if (regmatch.regprog != NULL) { regmatch.rm_ic = ic; @@ -8389,6 +8389,11 @@ char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, char *flags p_cpo = save_cpo; } else { // Darn, evaluating {sub} expression or {expr} changed the value. + // If it's still empty it was changed and restored, need to restore in + // the complicated way. + if (*p_cpo == NUL) { + set_option_value("cpo", 0L, save_cpo, 0); + } free_string_option((char_u *)save_cpo); } diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 9c3c859771..94bc2f5557 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -588,7 +588,7 @@ buf_T *tv_get_buf(typval_T *tv, int curtab_only) int save_magic = p_magic; p_magic = true; char *save_cpo = p_cpo; - p_cpo = ""; + p_cpo = (char *)empty_option; buf_T *buf = buflist_findnr(buflist_findpat((char *)name, (char *)name + STRLEN(name), true, false, curtab_only)); @@ -4893,7 +4893,7 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, // Make 'cpoptions' empty, the 'l' flag should not be used here. char *save_cpo = p_cpo; - p_cpo = ""; + p_cpo = (char *)empty_option; rettv->vval.v_number = -1; switch (type) { @@ -7413,6 +7413,11 @@ long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir p_cpo = save_cpo; } else { // Darn, evaluating the {skip} expression changed the value. + // If it's still empty it was changed and restored, need to restore in + // the complicated way. + if (*p_cpo == NUL) { + set_option_value("cpo", 0L, save_cpo, 0); + } free_string_option((char_u *)save_cpo); } @@ -8167,7 +8172,7 @@ static void f_split(typval_T *argvars, typval_T *rettv, FunPtr fptr) // Make 'cpoptions' empty, the 'l' flag should not be used here. char *save_cpo = p_cpo; - p_cpo = ""; + p_cpo = (char *)empty_option; const char *str = tv_get_string(&argvars[0]); const char *pat = NULL; diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c index 69d509abb7..82d6e66290 100644 --- a/src/nvim/ex_eval.c +++ b/src/nvim/ex_eval.c @@ -1376,7 +1376,7 @@ void ex_catch(exarg_T *eap) *end = NUL; } save_cpo = p_cpo; - p_cpo = ""; + p_cpo = (char *)empty_option; // Disable error messages, it will make current exception // invalid emsg_off++; diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 17fbbe17b8..86054b50c6 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -7062,6 +7062,7 @@ void ex_helpgrep(exarg_T *eap) } } + bool updated = false; // Make 'cpoptions' empty, the 'l' flag should not be used here. char *const save_cpo = p_cpo; p_cpo = (char *)empty_option; @@ -7092,16 +7093,26 @@ void ex_helpgrep(exarg_T *eap) qfl->qf_ptr = qfl->qf_start; qfl->qf_index = 1; qf_list_changed(qfl); - qf_update_buffer(qi, NULL); + updated = true; } if ((char_u *)p_cpo == empty_option) { p_cpo = save_cpo; } else { - // Darn, some plugin changed the value. + // Darn, some plugin changed the value. If it's still empty it was + // changed and restored, need to restore in the complicated way. + if (*p_cpo == NUL) { + set_option_value("cpo", 0L, save_cpo, 0); + } free_string_option((char_u *)save_cpo); } + if (updated) { + // This may open a window and source scripts, do this after 'cpo' was + // restored. + qf_update_buffer(qi, NULL); + } + if (au_name != NULL) { apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, curbuf->b_fname, true, curbuf); // When adding a location list to an existing location list stack, diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 2a3ec56451..005d7dc4e1 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -5070,7 +5070,7 @@ static char_u *get_syn_pattern(char_u *arg, synpat_T *ci) // Make 'cpoptions' empty, to avoid the 'l' flag cpo_save = p_cpo; - p_cpo = ""; + p_cpo = (char *)empty_option; ci->sp_prog = vim_regcomp((char *)ci->sp_pattern, RE_MAGIC); p_cpo = cpo_save; @@ -5231,7 +5231,7 @@ static void syn_cmd_sync(exarg_T *eap, int syncing) // Make 'cpoptions' empty, to avoid the 'l' flag cpo_save = p_cpo; - p_cpo = ""; + p_cpo = (char *)empty_option; curwin->w_s->b_syn_linecont_prog = vim_regcomp((char *)curwin->w_s->b_syn_linecont_pat, RE_MAGIC); p_cpo = cpo_save; -- cgit From d4d27c41b3298c25ae62bc067472bef37bc61c99 Mon Sep 17 00:00:00 2001 From: Axel Forsman Date: Mon, 22 Aug 2022 06:48:18 +0200 Subject: fix(edit.c): indentkeys double indent after "!" #12894 which is both unexpected and different from the Vim behaviour. Indent was triggered once by the '!' check in insert_execute(), and inserting the char was correctly skipped, but then triggered again in insert_check() (provided that cindent was not being ignored after manual indentation, i.e. `can_cindent == true`). While this is the smallest fix, another solution would be to remove VimState#check and instead move that to *_enter()/-_execute(), since the control flow is pretty unnecessarily convoluted as is. That would also have the benefit of differing less from the Vim source code. --- src/nvim/edit.c | 15 ++++++++------- test/functional/editor/mode_insert_spec.lua | 8 ++++++++ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 6583ac8584..dc856f01fe 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -624,16 +624,17 @@ static int insert_execute(VimState *state, int key) } if (cindent_on() && ctrl_x_mode_none()) { + s->line_is_white = inindent(0); // A key name preceded by a bang means this key is not to be // inserted. Skip ahead to the re-indenting below. - // A key name preceded by a star means that indenting has to be - // done before inserting the key. - s->line_is_white = inindent(0); - if (in_cinkeys(s->c, '!', s->line_is_white)) { - insert_do_cindent(s); + if (in_cinkeys(s->c, '!', s->line_is_white) + && stop_arrow() == OK) { + do_c_expr_indent(); return 1; // continue } + // A key name preceded by a star means that indenting has to be + // done before inserting the key. if (can_cindent && in_cinkeys(s->c, '*', s->line_is_white) && stop_arrow() == OK) { do_c_expr_indent(); @@ -3657,7 +3658,7 @@ void fix_indent(void) /// Check that "cinkeys" contains the key "keytyped", /// when == '*': Only if key is preceded with '*' (indent before insert) /// when == '!': Only if key is preceded with '!' (don't insert) -/// when == ' ': Only if key is not preceded with '*' (indent afterwards) +/// when == ' ': Only if key is not preceded with '*' or '!' (indent afterwards) /// /// "keytyped" can have a few special values: /// KEY_OPEN_FORW : @@ -3697,7 +3698,7 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty) case '!': try_match = (*look == '!'); break; default: - try_match = (*look != '*'); break; + try_match = (*look != '*') && (*look != '!'); break; } if (*look == '*' || *look == '!') { look++; diff --git a/test/functional/editor/mode_insert_spec.lua b/test/functional/editor/mode_insert_spec.lua index e3d3cdbd85..cd51a65be3 100644 --- a/test/functional/editor/mode_insert_spec.lua +++ b/test/functional/editor/mode_insert_spec.lua @@ -6,12 +6,20 @@ local expect = helpers.expect local command = helpers.command local eq = helpers.eq local eval = helpers.eval +local curbuf_contents = helpers.curbuf_contents describe('insert-mode', function() before_each(function() clear() end) + it('indents only once after "!" keys #12894', function() + command('let counter = []') + command('set indentexpr=len(add(counter,0))') + feed('ix') + eq(' x', curbuf_contents()) + end) + it('CTRL-@', function() -- Inserts last-inserted text, leaves insert-mode. insert('hello') -- cgit From 2bed0d1d978b42184564201088ea5fef12ec8581 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 22 Aug 2022 13:56:50 +0800 Subject: vim-patch:8.2.4753: error from setting an option is silently ignored (#19888) Problem: Error from setting an option is silently ignored. Solution: Handle option value errors better. Fix uses of N_(). https://github.com/vim/vim/commit/31e5c60a682840959cae6273ccadd9aae48c928d --- src/nvim/buffer.c | 6 ++--- src/nvim/diff.c | 2 +- src/nvim/eval.c | 2 +- src/nvim/eval/funcs.c | 2 +- src/nvim/eval/vars.c | 2 +- src/nvim/ex_cmds2.c | 12 +++++----- src/nvim/ex_docmd.c | 18 +++++++-------- src/nvim/ex_getln.c | 4 ++-- src/nvim/getchar.c | 2 +- src/nvim/help.c | 2 +- src/nvim/highlight_group.c | 2 +- src/nvim/main.c | 20 ++++++++-------- src/nvim/memline.c | 2 +- src/nvim/option.c | 57 ++++++++++++++++++++++++++++++++-------------- src/nvim/optionstr.c | 28 ++++++++++++++--------- src/nvim/popupmenu.c | 10 ++++---- src/nvim/quickfix.c | 12 +++++----- src/nvim/runtime.c | 2 +- src/nvim/spell.c | 8 +++---- src/nvim/spellfile.c | 2 +- 20 files changed, 112 insertions(+), 83 deletions(-) diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index ab5b32bf3e..15fdd977c1 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -4189,8 +4189,8 @@ void buf_open_scratch(handle_T bufnr, char *bufname) apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, false, curbuf); (void)setfname(curbuf, bufname, NULL, true); apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, false, curbuf); - set_option_value("bh", 0L, "hide", OPT_LOCAL); - set_option_value("bt", 0L, "nofile", OPT_LOCAL); - set_option_value("swf", 0L, NULL, OPT_LOCAL); + set_option_value_give_err("bh", 0L, "hide", OPT_LOCAL); + set_option_value_give_err("bt", 0L, "nofile", OPT_LOCAL); + set_option_value_give_err("swf", 0L, NULL, OPT_LOCAL); RESET_BINDING(curwin); } diff --git a/src/nvim/diff.c b/src/nvim/diff.c index 5485d528f7..bfafc3b4e0 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -1374,7 +1374,7 @@ static void set_diff_option(win_T *wp, int value) curwin = wp; curbuf = curwin->w_buffer; curbuf->b_ro_locked++; - set_option_value("diff", (long)value, NULL, OPT_LOCAL); + set_option_value_give_err("diff", (long)value, NULL, OPT_LOCAL); curbuf->b_ro_locked--; curwin = old_curwin; curbuf = curwin->w_buffer; diff --git a/src/nvim/eval.c b/src/nvim/eval.c index a80d2e5fbb..04f7347e1c 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -8392,7 +8392,7 @@ char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, char *flags // If it's still empty it was changed and restored, need to restore in // the complicated way. if (*p_cpo == NUL) { - set_option_value("cpo", 0L, save_cpo, 0); + set_option_value_give_err("cpo", 0L, save_cpo, 0); } free_string_option((char_u *)save_cpo); } diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 94bc2f5557..94fda654f3 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -7416,7 +7416,7 @@ long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir // If it's still empty it was changed and restored, need to restore in // the complicated way. if (*p_cpo == NUL) { - set_option_value("cpo", 0L, save_cpo, 0); + set_option_value_give_err("cpo", 0L, save_cpo, 0); } free_string_option((char_u *)save_cpo); } diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index b38849730a..23d77e0687 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1627,7 +1627,7 @@ static void set_option_from_tv(const char *varname, typval_T *varp) strval = tv_get_string_buf_chk(varp, nbuf); } if (!error && strval != NULL) { - set_option_value(varname, numval, strval, OPT_LOCAL); + set_option_value_give_err(varname, numval, strval, OPT_LOCAL); } } diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 54315a6417..2ed45f7ab8 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -544,9 +544,9 @@ void ex_listdo(exarg_T *eap) // Clear 'shm' to avoid that the file message overwrites // any output from the command. p_shm_save = (char *)vim_strsave(p_shm); - set_option_value("shm", 0L, "", 0); + set_option_value_give_err("shm", 0L, "", 0); do_argfile(eap, i); - set_option_value("shm", 0L, p_shm_save, 0); + set_option_value_give_err("shm", 0L, p_shm_save, 0); xfree(p_shm_save); } if (curwin->w_arg_idx != i) { @@ -613,9 +613,9 @@ void ex_listdo(exarg_T *eap) // Go to the next buffer. Clear 'shm' to avoid that the file // message overwrites any output from the command. p_shm_save = (char *)vim_strsave(p_shm); - set_option_value("shm", 0L, "", 0); + set_option_value_give_err("shm", 0L, "", 0); goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum); - set_option_value("shm", 0L, p_shm_save, 0); + set_option_value_give_err("shm", 0L, p_shm_save, 0); xfree(p_shm_save); // If autocommands took us elsewhere, quit here. @@ -636,9 +636,9 @@ void ex_listdo(exarg_T *eap) // Clear 'shm' to avoid that the file message overwrites // any output from the command. p_shm_save = (char *)vim_strsave(p_shm); - set_option_value("shm", 0L, "", 0); + set_option_value_give_err("shm", 0L, "", 0); ex_cnext(eap); - set_option_value("shm", 0L, p_shm_save, 0); + set_option_value_give_err("shm", 0L, p_shm_save, 0); xfree(p_shm_save); // If jumping to the next quickfix entry fails, quit here. diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 7bf272fbba..3b1b6e81e3 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -6945,15 +6945,15 @@ void dialog_msg(char *buff, char *format, char *fname) static void ex_behave(exarg_T *eap) { if (STRCMP(eap->arg, "mswin") == 0) { - set_option_value("selection", 0L, "exclusive", 0); - set_option_value("selectmode", 0L, "mouse,key", 0); - set_option_value("mousemodel", 0L, "popup", 0); - set_option_value("keymodel", 0L, "startsel,stopsel", 0); + set_option_value_give_err("selection", 0L, "exclusive", 0); + set_option_value_give_err("selectmode", 0L, "mouse,key", 0); + set_option_value_give_err("mousemodel", 0L, "popup", 0); + set_option_value_give_err("keymodel", 0L, "startsel,stopsel", 0); } else if (STRCMP(eap->arg, "xterm") == 0) { - set_option_value("selection", 0L, "inclusive", 0); - set_option_value("selectmode", 0L, "", 0); - set_option_value("mousemodel", 0L, "extend", 0); - set_option_value("keymodel", 0L, "", 0); + set_option_value_give_err("selection", 0L, "inclusive", 0); + set_option_value_give_err("selectmode", 0L, "", 0); + set_option_value_give_err("mousemodel", 0L, "extend", 0); + set_option_value_give_err("keymodel", 0L, "", 0); } else { semsg(_(e_invarg2), eap->arg); } @@ -7073,7 +7073,7 @@ static void ex_setfiletype(exarg_T *eap) arg += 9; } - set_option_value("filetype", 0L, arg, OPT_LOCAL); + set_option_value_give_err("filetype", 0L, arg, OPT_LOCAL); if (arg != eap->arg) { did_filetype = false; } diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index a0bcccb5be..9a7b093282 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -4074,7 +4074,7 @@ static int open_cmdwin(void) // Create empty command-line buffer. buf_open_scratch(0, _("[Command Line]")); // Command-line buffer has bufhidden=wipe, unlike a true "scratch" buffer. - set_option_value("bh", 0L, "wipe", OPT_LOCAL); + set_option_value_give_err("bh", 0L, "wipe", OPT_LOCAL); curwin->w_p_rl = cmdmsg_rl; cmdmsg_rl = false; curbuf->b_p_ma = true; @@ -4092,7 +4092,7 @@ static int open_cmdwin(void) add_map("", "", MODE_INSERT, true); add_map("", "a", MODE_NORMAL, true); } - set_option_value("ft", 0L, "vim", OPT_LOCAL); + set_option_value_give_err("ft", 0L, "vim", OPT_LOCAL); } curbuf->b_ro_locked--; diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 0f55158733..c8d4ef18ac 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -2112,7 +2112,7 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth) } del_typebuf(mlen, 0); // remove the chars - set_option_value("paste", !p_paste, NULL, 0); + set_option_value_give_err("paste", !p_paste, NULL, 0); if (!(State & MODE_INSERT)) { msg_col = 0; msg_row = Rows - 1; diff --git a/src/nvim/help.c b/src/nvim/help.c index 442f2e0b7b..5b2d3a17a3 100644 --- a/src/nvim/help.c +++ b/src/nvim/help.c @@ -652,7 +652,7 @@ void fix_help_buffer(void) // Set filetype to "help". if (STRCMP(curbuf->b_p_ft, "help") != 0) { curbuf->b_ro_locked++; - set_option_value("ft", 0L, "help", OPT_LOCAL); + set_option_value_give_err("ft", 0L, "help", OPT_LOCAL); curbuf->b_ro_locked--; } diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c index 77424de3b8..65a50df274 100644 --- a/src/nvim/highlight_group.c +++ b/src/nvim/highlight_group.c @@ -1156,7 +1156,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) if (dark != -1 && dark != (*p_bg == 'd') && !option_was_set("bg")) { - set_option_value("bg", 0L, (dark ? "dark" : "light"), 0); + set_option_value_give_err("bg", 0L, (dark ? "dark" : "light"), 0); reset_option_was_set("bg"); } } diff --git a/src/nvim/main.c b/src/nvim/main.c index d06b475934..3cd0a96116 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -1052,7 +1052,7 @@ static void command_line_scan(mparm_T *parmp) } else if (STRNICMP(argv[0] + argv_idx, "clean", 5) == 0) { parmp->use_vimrc = "NONE"; parmp->clean = true; - set_option_value("shadafile", 0L, "NONE", 0); + set_option_value_give_err("shadafile", 0L, "NONE", 0); } else if (STRNICMP(argv[0] + argv_idx, "luamod-dev", 9) == 0) { nlua_disable_preload = true; } else { @@ -1066,7 +1066,7 @@ static void command_line_scan(mparm_T *parmp) } break; case 'A': // "-A" start in Arabic mode. - set_option_value("arabic", 1L, NULL, 0); + set_option_value_give_err("arabic", 1L, NULL, 0); break; case 'b': // "-b" binary mode. // Needs to be effective before expanding file names, because @@ -1097,10 +1097,10 @@ static void command_line_scan(mparm_T *parmp) os_exit(0); case 'H': // "-H" start in Hebrew mode: rl + hkmap set. p_hkmap = true; - set_option_value("rl", 1L, NULL, 0); + set_option_value_give_err("rl", 1L, NULL, 0); break; case 'l': // "-l" lisp mode, 'lisp' and 'showmatch' on. - set_option_value("lisp", 1L, NULL, 0); + set_option_value_give_err("lisp", 1L, NULL, 0); p_sm = true; break; case 'M': // "-M" no changes or writing of files @@ -1181,7 +1181,7 @@ static void command_line_scan(mparm_T *parmp) // default is 10: a little bit verbose p_verbose = get_number_arg(argv[0], &argv_idx, 10); if (argv[0][argv_idx] != NUL) { - set_option_value("verbosefile", 0L, argv[0] + argv_idx, 0); + set_option_value_give_err("verbosefile", 0L, argv[0] + argv_idx, 0); argv_idx = (int)STRLEN(argv[0]); } break; @@ -1189,7 +1189,7 @@ static void command_line_scan(mparm_T *parmp) // "-w {scriptout}" write to script if (ascii_isdigit(((char_u *)argv[0])[argv_idx])) { n = get_number_arg(argv[0], &argv_idx, 10); - set_option_value("window", n, NULL, 0); + set_option_value_give_err("window", n, NULL, 0); break; } want_argument = true; @@ -1284,7 +1284,7 @@ static void command_line_scan(mparm_T *parmp) break; case 'i': // "-i {shada}" use for shada - set_option_value("shadafile", 0L, argv[0], 0); + set_option_value_give_err("shadafile", 0L, argv[0], 0); break; case 's': { // "-s {scriptin}" read from script file @@ -1334,7 +1334,7 @@ scripterror: if (ascii_isdigit(*((char_u *)argv[0]))) { argv_idx = 0; n = get_number_arg(argv[0], &argv_idx, 10); - set_option_value("window", n, NULL, 0); + set_option_value_give_err("window", n, NULL, 0); argv_idx = -1; break; } @@ -1735,7 +1735,7 @@ static void edit_buffers(mparm_T *parmp, char_u *cwd) p_shm_save = xstrdup((char *)p_shm); snprintf(buf, sizeof(buf), "F%s", p_shm); - set_option_value("shm", 0L, buf, 0); + set_option_value_give_err("shm", 0L, buf, 0); } } else { if (curwin->w_next == NULL) { // just checking @@ -1779,7 +1779,7 @@ static void edit_buffers(mparm_T *parmp, char_u *cwd) } if (p_shm_save != NULL) { - set_option_value("shm", 0L, p_shm_save, 0); + set_option_value_give_err("shm", 0L, p_shm_save, 0); xfree(p_shm_save); } diff --git a/src/nvim/memline.c b/src/nvim/memline.c index 23bc5d59c8..fd8b2c55b5 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -993,7 +993,7 @@ void ml_recover(bool checkext) set_fileformat(b0_ff - 1, OPT_LOCAL); } if (b0_fenc != NULL) { - set_option_value("fenc", 0L, (char *)b0_fenc, OPT_LOCAL); + set_option_value_give_err("fenc", 0L, (char *)b0_fenc, OPT_LOCAL); xfree(b0_fenc); } unchanged(curbuf, true, true); diff --git a/src/nvim/option.c b/src/nvim/option.c index 5c487a7c62..0cf5b4bddf 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -91,6 +91,19 @@ #include "nvim/os/input.h" #include "nvim/os/lang.h" +static char e_unknown_option[] + = N_("E518: Unknown option"); +static char e_not_allowed_in_modeline[] + = N_("E520: Not allowed in a modeline"); +static char e_not_allowed_in_modeline_when_modelineexpr_is_off[] + = N_("E992: Not allowed in a modeline when 'modelineexpr' is off"); +static char e_key_code_not_set[] + = N_("E846: Key code not set"); +static char e_number_required_after_equal[] + = N_("E521: Number required after ="); +static char e_preview_window_already_exists[] + = N_("E590: A preview window already exists"); + /* * The options that are local to a window or buffer have "indir" set to one of * these values. Special values: @@ -404,7 +417,7 @@ void set_init_1(bool clean_arg) // NOTE: mlterm's author is being asked to 'set' a variable // instead of an environment variable due to inheritance. if (os_env_exists("MLTERM")) { - set_option_value("tbidi", 1L, NULL, 0); + set_option_value_give_err("tbidi", 1L, NULL, 0); } didset_options2(); @@ -915,7 +928,7 @@ int do_set(char *arg, int opt_flags) nextchar = (uint8_t)arg[len]; if (opt_idx == -1 && key == 0) { // found a mismatch: skip - errmsg = N_("E518: Unknown option"); + errmsg = e_unknown_option; goto skip; } @@ -926,7 +939,7 @@ int do_set(char *arg, int opt_flags) if (vim_strchr("=:!&<", nextchar) == NULL && (!(options[opt_idx].flags & P_BOOL) || nextchar == '?')) { - errmsg = _(e_unsupportedoption); + errmsg = e_unsupportedoption; } goto skip; } @@ -953,11 +966,11 @@ int do_set(char *arg, int opt_flags) // Disallow changing some options from modelines. if (opt_flags & OPT_MODELINE) { if (flags & (P_SECURE | P_NO_ML)) { - errmsg = N_("E520: Not allowed in a modeline"); + errmsg = e_not_allowed_in_modeline; goto skip; } if ((flags & P_MLE) && !p_mle) { - errmsg = N_("E992: Not allowed in a modeline when 'modelineexpr' is off"); + errmsg = e_not_allowed_in_modeline_when_modelineexpr_is_off; goto skip; } // In diff mode some options are overruled. This avoids that @@ -1025,7 +1038,7 @@ int do_set(char *arg, int opt_flags) } } } else { - errmsg = N_("E846: Key code not set"); + errmsg = e_key_code_not_set; goto skip; } if (nextchar != '?' @@ -1118,11 +1131,11 @@ int do_set(char *arg, int opt_flags) // Allow negative, octal and hex numbers. vim_str2nr((char_u *)arg, NULL, &i, STR2NR_ALL, &value, NULL, 0, true); if (i == 0 || (arg[i] != NUL && !ascii_iswhite(arg[i]))) { - errmsg = N_("E521: Number required after ="); + errmsg = e_number_required_after_equal; goto skip; } } else { - errmsg = N_("E521: Number required after ="); + errmsg = e_number_required_after_equal; goto skip; } @@ -1971,6 +1984,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va { int old_value = *(int *)varp; int old_global_value = 0; + char *errmsg = NULL; // Disallow changing some options from secure mode if ((secure || sandbox != 0) @@ -2092,7 +2106,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va FOR_ALL_WINDOWS_IN_TAB(win, curtab) { if (win->w_p_pvw && win != curwin) { curwin->w_p_pvw = false; - return N_("E590: A preview window already exists"); + return e_preview_window_already_exists; } } } @@ -2151,10 +2165,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va } } else if ((int *)varp == &curwin->w_p_spell) { // 'spell' if (curwin->w_p_spell) { - char *errmsg = did_set_spelllang(curwin); - if (errmsg != NULL) { - emsg(_(errmsg)); - } + errmsg = did_set_spelllang(curwin); } } @@ -2191,7 +2202,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va p_deco = true; // Force-set the necessary keymap for arabic. - set_option_value("keymap", 0L, "arabic", OPT_LOCAL); + errmsg = set_option_value("keymap", 0L, "arabic", OPT_LOCAL); } else { /* * 'arabic' is reset, handle various sub-settings. @@ -2271,7 +2282,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va } check_redraw(options[opt_idx].flags); - return NULL; + return errmsg; } /// Set the value of a number option, taking care of side effects @@ -2898,7 +2909,7 @@ void set_tty_background(const char *value) ? "autocmd VimEnter * ++once ++nested set bg=light" : "autocmd VimEnter * ++once ++nested set bg=dark"); } else { - set_option_value("bg", 0L, value, 0); + set_option_value_give_err("bg", 0L, value, 0); reset_option_was_set("bg"); } } @@ -3147,7 +3158,7 @@ bool is_hidden_option(int opt_idx) /// is cleared (the exact semantics of this depend /// on the option). /// -/// @return NULL on success, error message on error. +/// @return NULL on success, an untranslated error message on error. char *set_option_value(const char *const name, const long number, const char *const string, const int opt_flags) FUNC_ATTR_NONNULL_ARG(1) @@ -3217,6 +3228,18 @@ char *set_option_value(const char *const name, const long number, const char *co return NULL; } +/// Call set_option_value() and when an error is returned report it. +/// +/// @param opt_flags OPT_LOCAL or 0 (both) +void set_option_value_give_err(const char *name, long number, const char *string, int opt_flags) +{ + char *errmsg = set_option_value(name, number, string, opt_flags); + + if (errmsg != NULL) { + emsg(_(errmsg)); + } +} + /// Return true if "name" is a string option. /// Returns false if option "name" does not exist. bool is_string_option(const char *name) diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index c50225dfdf..3287abdd9c 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -45,8 +45,14 @@ # include "optionstr.c.generated.h" #endif -static char e_unclosed_expression_sequence[] = N_("E540: Unclosed expression sequence"); -static char e_unbalanced_groups[] = N_("E542: unbalanced groups"); +static char e_unclosed_expression_sequence[] + = N_("E540: Unclosed expression sequence"); +static char e_unbalanced_groups[] + = N_("E542: unbalanced groups"); +static char e_backupext_and_patchmode_are_equal[] + = N_("E589: 'backupext' and 'patchmode' are equal"); +static char e_showbreak_contains_unprintable_or_wide_character[] + = N_("E595: 'showbreak' contains unprintable or wide character"); static char *(p_ambw_values[]) = { "single", "double", NULL }; static char *(p_bg_values[]) = { "light", "dark", NULL }; @@ -381,7 +387,7 @@ void set_string_option_direct_in_win(win_T *wp, const char *name, int opt_idx, c /// @param[in] opt_flags Option flags: expected to contain #OPT_LOCAL and/or /// #OPT_GLOBAL. /// -/// @return NULL on success, error message on error. +/// @return NULL on success, an untranslated error message on error. char *set_string_option(const int opt_idx, const char *const value, const int opt_flags) FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_WARN_UNUSED_RESULT { @@ -413,15 +419,15 @@ char *set_string_option(const int opt_idx, const char *const value, const int op char *const saved_newval = xstrdup(s); int value_checked = false; - char *const r = did_set_string_option(opt_idx, (char_u **)varp, (char_u *)oldval, - NULL, 0, - opt_flags, &value_checked); - if (r == NULL) { + char *const errmsg = did_set_string_option(opt_idx, (char_u **)varp, (char_u *)oldval, + NULL, 0, + opt_flags, &value_checked); + if (errmsg == NULL) { did_set_option(opt_idx, opt_flags, true, value_checked); } // call autocommand after handling side effects - if (r == NULL) { + if (errmsg == NULL) { if (!starting) { trigger_optionsset_string(opt_idx, opt_flags, saved_oldval, saved_oldval_l, saved_oldval_g, saved_newval); @@ -436,7 +442,7 @@ char *set_string_option(const int opt_idx, const char *const value, const int op xfree(saved_oldval_g); xfree(saved_newval); - return r; + return errmsg; } /// Return true if "val" is a valid 'filetype' name. @@ -679,7 +685,7 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er } else if (varp == &p_bex || varp == &p_pm) { // 'backupext' and 'patchmode' if (STRCMP(*p_bex == '.' ? p_bex + 1 : p_bex, *p_pm == '.' ? p_pm + 1 : p_pm) == 0) { - errmsg = N_("E589: 'backupext' and 'patchmode' are equal"); + errmsg = e_backupext_and_patchmode_are_equal; } } else if (varp == &curwin->w_p_briopt) { // 'breakindentopt' if (briopt_check(curwin) == FAIL) { @@ -1041,7 +1047,7 @@ char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *er } else if (gvarp == &p_sbr) { // 'showbreak' for (s = (char *)(*varp); *s;) { if (ptr2cells(s) != 1) { - errmsg = N_("E595: 'showbreak' contains unprintable or wide character"); + errmsg = e_showbreak_contains_unprintable_or_wide_character; } MB_PTR_ADV(s); } diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c index a4afe97ac8..d392bb5a2c 100644 --- a/src/nvim/popupmenu.c +++ b/src/nvim/popupmenu.c @@ -744,11 +744,11 @@ static bool pum_set_selected(int n, int repeat) if (res == OK) { // Edit a new, empty buffer. Set options for a "wipeout" // buffer. - set_option_value("swf", 0L, NULL, OPT_LOCAL); - set_option_value("bl", 0L, NULL, OPT_LOCAL); - set_option_value("bt", 0L, "nofile", OPT_LOCAL); - set_option_value("bh", 0L, "wipe", OPT_LOCAL); - set_option_value("diff", 0L, NULL, OPT_LOCAL); + set_option_value_give_err("swf", 0L, NULL, OPT_LOCAL); + set_option_value_give_err("bl", 0L, NULL, OPT_LOCAL); + set_option_value_give_err("bt", 0L, "nofile", OPT_LOCAL); + set_option_value_give_err("bh", 0L, "wipe", OPT_LOCAL); + set_option_value_give_err("diff", 0L, NULL, OPT_LOCAL); } } diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 86054b50c6..d5f4996f61 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -3558,12 +3558,12 @@ static int qf_goto_cwindow(const qf_info_T *qi, bool resize, int sz, bool vertsp static void qf_set_cwindow_options(void) { // switch off 'swapfile' - set_option_value("swf", 0L, NULL, OPT_LOCAL); - set_option_value("bt", 0L, "quickfix", OPT_LOCAL); - set_option_value("bh", 0L, "hide", OPT_LOCAL); + set_option_value_give_err("swf", 0L, NULL, OPT_LOCAL); + set_option_value_give_err("bt", 0L, "quickfix", OPT_LOCAL); + set_option_value_give_err("bh", 0L, "hide", OPT_LOCAL); RESET_BINDING(curwin); curwin->w_p_diff = false; - set_option_value("fdm", 0L, "manual", OPT_LOCAL); + set_option_value_give_err("fdm", 0L, "manual", OPT_LOCAL); } // Open a new quickfix or location list window, load the quickfix buffer and @@ -4108,7 +4108,7 @@ static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int q // resembles reading a file into a buffer, it's more logical when using // autocommands. curbuf->b_ro_locked++; - set_option_value("ft", 0L, "qf", OPT_LOCAL); + set_option_value_give_err("ft", 0L, "qf", OPT_LOCAL); curbuf->b_p_ma = false; keep_filetype = true; // don't detect 'filetype' @@ -7102,7 +7102,7 @@ void ex_helpgrep(exarg_T *eap) // Darn, some plugin changed the value. If it's still empty it was // changed and restored, need to restore in the complicated way. if (*p_cpo == NUL) { - set_option_value("cpo", 0L, save_cpo, 0); + set_option_value_give_err("cpo", 0L, save_cpo, 0); } free_string_option((char_u *)save_cpo); } diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index 914b21bb02..537c496ae2 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -923,7 +923,7 @@ static int add_pack_dir_to_rtp(char_u *fname, bool is_pack) xstrlcat(new_rtp, afterdir, new_rtp_capacity); } - set_option_value("rtp", 0L, new_rtp, 0); + set_option_value_give_err("rtp", 0L, new_rtp, 0); xfree(new_rtp); retval = OK; diff --git a/src/nvim/spell.c b/src/nvim/spell.c index 1e44d328b3..da712a5753 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -1828,8 +1828,8 @@ static int count_syllables(slang_T *slang, const char_u *word) return cnt; } -// Parse 'spelllang' and set w_s->b_langp accordingly. -// Returns NULL if it's OK, an error message otherwise. +/// Parse 'spelllang' and set w_s->b_langp accordingly. +/// @return NULL if it's OK, an untranslated error message otherwise. char *did_set_spelllang(win_T *wp) { garray_T ga; @@ -3155,8 +3155,8 @@ void ex_spelldump(exarg_T *eap) do_cmdline_cmd("new"); // enable spelling locally in the new window - set_option_value("spell", true, "", OPT_LOCAL); - set_option_value("spl", dummy, spl, OPT_LOCAL); + set_option_value_give_err("spell", true, "", OPT_LOCAL); + set_option_value_give_err("spl", dummy, spl, OPT_LOCAL); xfree(spl); if (!buf_is_empty(curbuf)) { diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index be1373f617..be19e1d655 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -5735,7 +5735,7 @@ static void init_spellfile(void) && strstr(path_tail((char *)fname), ".ascii.") != NULL) ? "ascii" : (const char *)spell_enc())); - set_option_value("spellfile", 0L, (const char *)buf, OPT_LOCAL); + set_option_value_give_err("spellfile", 0L, (const char *)buf, OPT_LOCAL); break; } aspath = false; -- cgit From 15a768eeb02e2af39eead1ea1eb4a5a60710d6fb Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 22 Aug 2022 18:06:18 +0800 Subject: fix(api): avoid side effects with nvim_parse_cmd (#19890) Save and restore the cursor and last search pattern and do not change search history. --- src/nvim/ex_docmd.c | 41 ++++++++++++++++++++------------- test/functional/api/vim_spec.lua | 49 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 16 deletions(-) diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 3b1b6e81e3..5e8c7dbdda 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -1361,6 +1361,13 @@ bool is_cmd_ni(cmdidx_T cmdidx) bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **errormsg) { char *after_modifier = NULL; + bool retval = false; + // parsing the command modifiers may set ex_pressedreturn + const bool save_ex_pressedreturn = ex_pressedreturn; + // parsing the command range may require moving the cursor + const pos_T save_cursor = curwin->w_cursor; + // parsing the command range may set the last search pattern + save_last_search_pattern(); // Initialize cmdinfo CLEAR_POINTER(cmdinfo); @@ -1375,13 +1382,10 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er .cookie = NULL, }; - const bool save_ex_pressedreturn = ex_pressedreturn; // Parse command modifiers if (parse_command_modifiers(eap, errormsg, &cmdinfo->cmdmod, false) == FAIL) { - ex_pressedreturn = save_ex_pressedreturn; - goto err; + goto end; } - ex_pressedreturn = save_ex_pressedreturn; after_modifier = eap->cmd; // Save location after command modifiers @@ -1394,21 +1398,21 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er char *p = find_ex_command(eap, NULL); if (p == NULL) { *errormsg = _(e_ambiguous_use_of_user_defined_command); - goto err; + goto end; } // Set command address type and parse command range set_cmd_addr_type(eap, p); eap->cmd = cmd; - if (parse_cmd_address(eap, errormsg, false) == FAIL) { - goto err; + if (parse_cmd_address(eap, errormsg, true) == FAIL) { + goto end; } // Skip colon and whitespace eap->cmd = skip_colon_white(eap->cmd, true); // Fail if command is a comment or if command doesn't exist if (*eap->cmd == NUL || *eap->cmd == '"') { - goto err; + goto end; } // Fail if command is invalid if (eap->cmdidx == CMD_SIZE) { @@ -1417,7 +1421,7 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er char *cmdname = after_modifier ? after_modifier : cmdline; append_command(cmdname); *errormsg = (char *)IObuff; - goto err; + goto end; } // Correctly set 'forceit' for commands @@ -1456,12 +1460,12 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er // Fail if command doesn't support bang but is used with a bang if (!(eap->argt & EX_BANG) && eap->forceit) { *errormsg = _(e_nobang); - goto err; + goto end; } // Fail if command doesn't support a range but it is given a range if (!(eap->argt & EX_RANGE) && eap->addr_count > 0) { *errormsg = _(e_norange); - goto err; + goto end; } // Set default range for command if required if ((eap->argt & EX_DFLALL) && eap->addr_count == 0) { @@ -1471,7 +1475,7 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er // Parse register and count parse_register(eap); if (parse_count(eap, errormsg, false) == FAIL) { - goto err; + goto end; } // Remove leading whitespace and colon from next command @@ -1487,10 +1491,15 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er cmdinfo->magic.bar = true; } - return true; -err: - undo_cmdmod(&cmdinfo->cmdmod); - return false; + retval = true; +end: + if (!retval) { + undo_cmdmod(&cmdinfo->cmdmod); + } + ex_pressedreturn = save_ex_pressedreturn; + curwin->w_cursor = save_cursor; + restore_last_search_pattern(); + return retval; } static int execute_cmd0(int *retv, exarg_T *eap, char **errormsg, bool preview) diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 72a03c409a..24d0b6da45 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -3668,6 +3668,55 @@ describe('API', function() :^ | ]]) end) + it('does not move cursor or change search history/pattern #19878 #19890', function() + meths.buf_set_lines(0, 0, -1, true, {'foo', 'bar', 'foo', 'bar'}) + eq({1, 0}, meths.win_get_cursor(0)) + eq('', funcs.getreg('/')) + eq('', funcs.histget('search')) + feed(':') -- call the API in cmdline mode to test whether it changes search history + eq({ + cmd = 'normal', + args = {'x'}, + bang = true, + range = {3, 4}, + count = -1, + reg = '', + addr = 'line', + magic = { + file = false, + bar = false, + }, + nargs = '+', + nextcmd = '', + mods = { + browse = false, + confirm = false, + emsg_silent = false, + filter = { + pattern = "", + force = false, + }, + hide = false, + keepalt = false, + keepjumps = false, + keepmarks = false, + keeppatterns = false, + lockmarks = false, + noautocmd = false, + noswapfile = false, + sandbox = false, + silent = false, + split = "", + tab = 0, + unsilent = false, + verbose = -1, + vertical = false, + } + }, meths.parse_cmd('+2;/bar/normal! x', {})) + eq({1, 0}, meths.win_get_cursor(0)) + eq('', funcs.getreg('/')) + eq('', funcs.histget('search')) + end) end) describe('nvim_cmd', function() it('works', function () -- cgit From 3c1d70f20b5d5bad3bec121e589187d15f325a9b Mon Sep 17 00:00:00 2001 From: Thomas Vigouroux Date: Mon, 25 Jul 2022 12:23:04 +0200 Subject: feat(treesitter): allow customizing language symbol name --- runtime/doc/treesitter.txt | 12 ++++++++---- runtime/lua/vim/treesitter/language.lua | 14 +++++++------- src/nvim/lua/treesitter.c | 16 ++++++++++++++-- test/functional/treesitter/language_spec.lua | 5 ++++- 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index 52531a1525..06409f9980 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -387,16 +387,20 @@ inspect_language({lang}) *inspect_language()* Parameters: ~ {lang} The language. -require_language({lang}, {path}, {silent}) *require_language()* + *require_language()* +require_language({lang}, {path}, {silent}, {symbol_name}) Asserts that the provided language is installed, and optionally provide a path for the parser Parsers are searched in the `parser` runtime directory. Parameters: ~ - {lang} The language the parser should parse - {path} Optional path the parser is located at - {silent} Don't throw an error if language not found + {lang} (string) The language the parser should parse + {path} (string|nil) Optional path the parser is located at + {silent} (boolean|nil) Don't throw an error if language not + found + {symbol_name} (string|nil) Internal symbol name for the language to + load ============================================================================== diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua index dfb6f5be84..d14b825603 100644 --- a/runtime/lua/vim/treesitter/language.lua +++ b/runtime/lua/vim/treesitter/language.lua @@ -6,10 +6,11 @@ local M = {} --- --- Parsers are searched in the `parser` runtime directory. --- ----@param lang The language the parser should parse ----@param path Optional path the parser is located at ----@param silent Don't throw an error if language not found -function M.require_language(lang, path, silent) +---@param lang string The language the parser should parse +---@param path string|nil Optional path the parser is located at +---@param silent boolean|nil Don't throw an error if language not found +---@param symbol_name string|nil Internal symbol name for the language to load +function M.require_language(lang, path, silent, symbol_name) if vim._ts_has_language(lang) then return true end @@ -21,7 +22,6 @@ function M.require_language(lang, path, silent) return false end - -- TODO(bfredl): help tag? error("no parser for '" .. lang .. "' language, see :help treesitter-parsers") end path = paths[1] @@ -29,10 +29,10 @@ function M.require_language(lang, path, silent) if silent then return pcall(function() - vim._ts_add_language(path, lang) + vim._ts_add_language(path, lang, symbol_name) end) else - vim._ts_add_language(path, lang) + vim._ts_add_language(path, lang, symbol_name) end return true diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c index f0d847e352..90b13181fb 100644 --- a/src/nvim/lua/treesitter.c +++ b/src/nvim/lua/treesitter.c @@ -14,10 +14,12 @@ #include #include #include +#include #include "nvim/api/private/helpers.h" #include "nvim/buffer.h" #include "nvim/lib/kvec.h" +#include "nvim/log.h" #include "nvim/lua/treesitter.h" #include "nvim/memline.h" #include "tree_sitter/api.h" @@ -145,18 +147,27 @@ int tslua_has_language(lua_State *L) return 1; } +// Creates the language into the internal language map. +// +// Returns true if the language is correctly loaded in the language map int tslua_add_language(lua_State *L) { const char *path = luaL_checkstring(L, 1); const char *lang_name = luaL_checkstring(L, 2); + const char *symbol_name = lang_name; + + if (lua_gettop(L) >= 3 && !lua_isnil(L, 3)) { + symbol_name = luaL_checkstring(L, 3); + } if (pmap_has(cstr_t)(&langs, lang_name)) { - return 0; + lua_pushboolean(L, true); + return 1; } #define BUFSIZE 128 char symbol_buf[BUFSIZE]; - snprintf(symbol_buf, BUFSIZE, "tree_sitter_%s", lang_name); + snprintf(symbol_buf, BUFSIZE, "tree_sitter_%s", symbol_name); #undef BUFSIZE uv_lib_t lib; @@ -179,6 +190,7 @@ int tslua_add_language(lua_State *L) TSLanguage *lang = lang_parser(); if (lang == NULL) { + uv_dlclose(&lib); return luaL_error(L, "Failed to load parser %s: internal error", path); } diff --git a/test/functional/treesitter/language_spec.lua b/test/functional/treesitter/language_spec.lua index 30585be328..5eb72471c3 100644 --- a/test/functional/treesitter/language_spec.lua +++ b/test/functional/treesitter/language_spec.lua @@ -10,7 +10,7 @@ local pending_c_parser = helpers.pending_c_parser before_each(clear) -describe('treesitter API', function() +describe('treesitter language API', function() -- error tests not requiring a parser library it('handles missing language', function() eq("Error executing lua: .../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers", @@ -26,6 +26,9 @@ describe('treesitter API', function() eq("Error executing lua: .../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers", pcall_err(exec_lua, "parser = vim.treesitter.inspect_language('borklang')")) + + matches("Error executing lua: Failed to load parser: uv_dlsym: .+", + pcall_err(exec_lua, "parser = vim.treesitter.require_language('c', nil, false, 'borklang')")) end) it('inspects language', function() -- cgit From baaaa1f2b3b6ae3a989d1362a27e55dc7b0b148a Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 22 Aug 2022 22:09:53 +0800 Subject: vim-patch:8.2.3421: a bit of code is not covered by tests (#19895) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: A bit of code is not covered by tests. Solution: Add a few more test cases. (Dominique PellĂ©, closes vim/vim#8857) https://github.com/vim/vim/commit/d176ca3dde47c11aae0376c31b7e1ba0939c8c6c Cherry-pick Test_trim() change from patch 8.2.0448. Cherry-pick Test_History() change from patch 8.2.1736. Cherry-pick charidx() and trim() type checks from patch 8.2.3135. --- src/nvim/eval/funcs.c | 8 +++++++- src/nvim/testdir/test_functions.vim | 9 ++++++--- src/nvim/testdir/test_history.vim | 17 +++++++++++++++++ src/nvim/testdir/test_startup.vim | 4 ++-- 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 94fda654f3..181b17f747 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -874,7 +874,8 @@ static void f_charidx(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[0].v_type != VAR_STRING || argvars[1].v_type != VAR_NUMBER || (argvars[2].v_type != VAR_UNKNOWN - && argvars[2].v_type != VAR_NUMBER)) { + && argvars[2].v_type != VAR_NUMBER + && argvars[2].v_type != VAR_BOOL)) { emsg(_(e_invarg)); return; } @@ -9460,6 +9461,11 @@ static void f_trim(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } + if (argvars[1].v_type != VAR_UNKNOWN && argvars[1].v_type != VAR_STRING) { + semsg(_(e_invarg2), tv_get_string(&argvars[1])); + return; + } + if (argvars[1].v_type == VAR_STRING) { mask = (const char_u *)tv_get_string_buf_chk(&argvars[1], buf2); if (argvars[2].v_type != VAR_UNKNOWN) { diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim index 44b6f0373e..ee63c0e1bd 100644 --- a/src/nvim/testdir/test_functions.vim +++ b/src/nvim/testdir/test_functions.vim @@ -1420,12 +1420,15 @@ func Test_trim() call assert_equal("vim", trim(" vim ", " ", 0)) call assert_equal("vim ", trim(" vim ", " ", 1)) call assert_equal(" vim", trim(" vim ", " ", 2)) - call assert_fails('call trim(" vim ", " ", [])', 'E745:') - call assert_fails('call trim(" vim ", " ", -1)', 'E475:') - call assert_fails('call trim(" vim ", " ", 3)', 'E475:') + call assert_fails('eval trim(" vim ", " ", [])', 'E745:') + call assert_fails('eval trim(" vim ", " ", -1)', 'E475:') + call assert_fails('eval trim(" vim ", " ", 3)', 'E475:') + call assert_fails('eval trim(" vim ", 0)', 'E475:') let chars = join(map(range(1, 0x20) + [0xa0], {n -> n->nr2char()}), '') call assert_equal("x", trim(chars . "x" . chars)) + + call assert_fails('let c=trim([])', 'E730:') endfunc " Test for reg_recording() and reg_executing() diff --git a/src/nvim/testdir/test_history.vim b/src/nvim/testdir/test_history.vim index feb521e232..f1c31dee04 100644 --- a/src/nvim/testdir/test_history.vim +++ b/src/nvim/testdir/test_history.vim @@ -95,6 +95,23 @@ function Test_History() call assert_fails('call histnr([])', 'E730:') call assert_fails('history xyz', 'E488:') call assert_fails('history ,abc', 'E488:') + call assert_fails('call histdel(":", "\\%(")', 'E53:') +endfunction + +function Test_history_truncates_long_entry() + " History entry short enough to fit on the screen should not be truncated. + call histadd(':', 'echo x' .. repeat('y', &columns - 17) .. 'z') + let a = execute('history : -1') + + call assert_match("^\n # cmd history\n" + \ .. "> *\\d\\+ echo x" .. repeat('y', &columns - 17) .. 'z$', a) + + " Long history entry should be truncated to fit on the screen, with, '...' + " inserted in the string to indicate the that there is truncation. + call histadd(':', 'echo x' .. repeat('y', &columns - 16) .. 'z') + let a = execute('history : -1') + call assert_match("^\n # cmd history\n" + \ .. "> *\\d\\+ echo xy\\+\.\.\.y\\+z$", a) endfunction function Test_Search_history_window() diff --git a/src/nvim/testdir/test_startup.vim b/src/nvim/testdir/test_startup.vim index 39fafbf7b4..880ca62685 100644 --- a/src/nvim/testdir/test_startup.vim +++ b/src/nvim/testdir/test_startup.vim @@ -603,7 +603,7 @@ func Test_invalid_args() call assert_equal(0, v:shell_error) if has('quickfix') - " Detect invalid repeated arguments '-t foo -t foo", '-q foo -q foo'. + " Detect invalid repeated arguments '-t foo -t foo', '-q foo -q foo'. for opt in ['-t', '-q'] let out = split(system(GetVimCommand() .. repeat(' ' .. opt .. ' foo', 2)), "\n") call assert_equal(1, v:shell_error) @@ -855,7 +855,7 @@ func Test_t_arg() call writefile([' first', ' second', ' third'], 'Xfile1') for t_arg in ['-t second', '-tsecond'] - if RunVim(before, after, '-t second') + if RunVim(before, after, t_arg) call assert_equal(['Xfile1:L2C5'], readfile('Xtestout'), t_arg) call delete('Xtestout') endif -- cgit From 2fd25fb909fd4472c46c8c3c652b21d70bac9e77 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 23 Aug 2022 07:20:23 +0800 Subject: vim-patch:8.1.0832: confirm() is not tested (#19896) Problem: confirm() is not tested. Solution: Add a test. (Dominique Pelle, closes vim/vim#3868) https://github.com/vim/vim/commit/2e0500921891e4fec57e97d3c0021aa2d2b4d7ae --- src/nvim/testdir/test_filechanged.vim | 6 ++- src/nvim/testdir/test_functions.vim | 57 +++++++++++++++++++++++ test/functional/vimscript/input_spec.lua | 77 +++++++++++++++++++++++++++++++- 3 files changed, 136 insertions(+), 4 deletions(-) diff --git a/src/nvim/testdir/test_filechanged.vim b/src/nvim/testdir/test_filechanged.vim index b77f02afd1..fef0eb732f 100644 --- a/src/nvim/testdir/test_filechanged.vim +++ b/src/nvim/testdir/test_filechanged.vim @@ -140,7 +140,8 @@ func Test_FileChangedShell_edit() endfunc func Test_FileChangedShell_edit_dialog() - throw 'Skipped: requires a UI to be active' + " requires a UI to be active + throw 'Skipped: use test/functional/legacy/filechanged_spec.lua' CheckNotGui CheckUnix " Using low level feedkeys() does not work on MS-Windows. @@ -190,7 +191,8 @@ func Test_FileChangedShell_edit_dialog() endfunc func Test_file_changed_dialog() - throw 'Skipped: requires a UI to be active' + " requires a UI to be active + throw 'Skipped: use test/functional/legacy/filechanged_spec.lua' CheckUnix CheckNotGui au! FileChangedShell diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim index ee63c0e1bd..05636199a4 100644 --- a/src/nvim/testdir/test_functions.vim +++ b/src/nvim/testdir/test_functions.vim @@ -1700,6 +1700,63 @@ func Test_platform_name() endif endfunc +" Test confirm({msg} [, {choices} [, {default} [, {type}]]]) +func Test_confirm() + " requires a UI to be active + throw 'Skipped: use test/functional/vimscript/input_spec.lua' + if !has('unix') || has('gui_running') + return + endif + + call feedkeys('o', 'L') + let a = confirm('Press O to proceed') + call assert_equal(1, a) + + call feedkeys('y', 'L') + let a = confirm('Are you sure?', "&Yes\n&No") + call assert_equal(1, a) + + call feedkeys('n', 'L') + let a = confirm('Are you sure?', "&Yes\n&No") + call assert_equal(2, a) + + " confirm() should return 0 when pressing CTRL-C. + call feedkeys("\", 'L') + let a = confirm('Are you sure?', "&Yes\n&No") + call assert_equal(0, a) + + " requires another character to avoid it being seen as the start of an + " escape sequence. Zero should be harmless. + call feedkeys("\0", 'L') + let a = confirm('Are you sure?', "&Yes\n&No") + call assert_equal(0, a) + + " Default choice is returned when pressing . + call feedkeys("\", 'L') + let a = confirm('Are you sure?', "&Yes\n&No") + call assert_equal(1, a) + + call feedkeys("\", 'L') + let a = confirm('Are you sure?', "&Yes\n&No", 2) + call assert_equal(2, a) + + call feedkeys("\", 'L') + let a = confirm('Are you sure?', "&Yes\n&No", 0) + call assert_equal(0, a) + + " Test with the {type} 4th argument + for type in ['Error', 'Question', 'Info', 'Warning', 'Generic'] + call feedkeys('y', 'L') + let a = confirm('Are you sure?', "&Yes\n&No\n", 1, type) + call assert_equal(1, a) + endfor + + call assert_fails('call confirm([])', 'E730:') + call assert_fails('call confirm("Are you sure?", [])', 'E730:') + call assert_fails('call confirm("Are you sure?", "&Yes\n&No\n", [])', 'E745:') + call assert_fails('call confirm("Are you sure?", "&Yes\n&No\n", 0, [])', 'E730:') +endfunc + func Test_readdir() call mkdir('Xdir') call writefile([], 'Xdir/foo.txt') diff --git a/test/functional/vimscript/input_spec.lua b/test/functional/vimscript/input_spec.lua index 554d15e550..d6ab71b7d5 100644 --- a/test/functional/vimscript/input_spec.lua +++ b/test/functional/vimscript/input_spec.lua @@ -8,7 +8,8 @@ local clear = helpers.clear local source = helpers.source local command = helpers.command local exc_exec = helpers.exc_exec -local nvim_async = helpers.nvim_async +local pcall_err = helpers.pcall_err +local async_meths = helpers.async_meths local NIL = helpers.NIL local screen @@ -449,6 +450,78 @@ describe('inputdialog()', function() end) describe('confirm()', function() + -- oldtest: Test_confirm() + it('works', function() + meths.set_option('more', false) -- Avoid hit-enter prompt + meths.set_option('laststatus', 2) + -- screen:expect() calls are needed to avoid feeding input too early + screen:expect({any = 'No Name'}) + + async_meths.command([[let a = confirm('Press O to proceed')]]) + screen:expect({any = '{CONFIRM:.+: }'}) + feed('o') + screen:expect({any = 'No Name'}) + eq(1, meths.get_var('a')) + + async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No")]]) + screen:expect({any = '{CONFIRM:.+: }'}) + feed('y') + screen:expect({any = 'No Name'}) + eq(1, meths.get_var('a')) + + async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No")]]) + screen:expect({any = '{CONFIRM:.+: }'}) + feed('n') + screen:expect({any = 'No Name'}) + eq(2, meths.get_var('a')) + + -- Not possible to match Vim's CTRL-C test here as CTRL-C always sets got_int in Nvim. + + -- confirm() should return 0 when pressing ESC. + async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No")]]) + screen:expect({any = '{CONFIRM:.+: }'}) + feed('') + screen:expect({any = 'No Name'}) + eq(0, meths.get_var('a')) + + -- Default choice is returned when pressing . + async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No")]]) + screen:expect({any = '{CONFIRM:.+: }'}) + feed('') + screen:expect({any = 'No Name'}) + eq(1, meths.get_var('a')) + + async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No", 2)]]) + screen:expect({any = '{CONFIRM:.+: }'}) + feed('') + screen:expect({any = 'No Name'}) + eq(2, meths.get_var('a')) + + async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No", 0)]]) + screen:expect({any = '{CONFIRM:.+: }'}) + feed('') + screen:expect({any = 'No Name'}) + eq(0, meths.get_var('a')) + + -- Test with the {type} 4th argument + for _, type in ipairs({'Error', 'Question', 'Info', 'Warning', 'Generic'}) do + async_meths.command(([[let a = confirm('Are you sure?', "&Yes\n&No", 1, '%s')]]):format(type)) + screen:expect({any = '{CONFIRM:.+: }'}) + feed('y') + screen:expect({any = 'No Name'}) + eq(1, meths.get_var('a')) + end + + eq('Vim(call):E730: using List as a String', + pcall_err(command, 'call confirm([])')) + eq('Vim(call):E730: using List as a String', + pcall_err(command, 'call confirm("Are you sure?", [])')) + eq('Vim(call):E745: Using a List as a Number', + pcall_err(command, 'call confirm("Are you sure?", "&Yes\n&No\n", [])')) + eq('Vim(call):E730: using List as a String', + pcall_err(command, 'call confirm("Are you sure?", "&Yes\n&No\n", 0, [])')) + end) + it("shows dialog even if :silent #8788", function() command("autocmd BufNewFile * call confirm('test')") @@ -483,7 +556,7 @@ describe('confirm()', function() feed(':call nvim_command("edit x")') check_and_clear(':call nvim_command("edit |\n') - nvim_async('command', 'edit x') + async_meths.command('edit x') check_and_clear(' |\n') end) end) -- cgit From 48a4657aee76e41d097b0730c91bcca78b5bc9c7 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 23 Aug 2022 08:36:22 +0800 Subject: vim-patch:8.1.{1915,1921,1953} (#19900) vim-patch:8.1.1915: more functions can be used as methods Problem: More functions can be used as methods. Solution: Make various functions usable as a method. https://github.com/vim/vim/commit/1a3a89168d61c2fed91cbca812cf1c6983901b79 Move debugbreak() to the right place. vim-patch:8.1.1921: more functions can be used as methods Problem: More functions can be used as methods. Solution: Make various functions usable as a method. https://github.com/vim/vim/commit/a4208966fb289a505ebdef62bbc37c214069bab4 vim-patch:8.1.1953: more functions can be used as a method Problem: More functions can be used as a method. Solution: Allow more functions to be used as a method. https://github.com/vim/vim/commit/f9f24ce7a0e5988fedf2e2ff751818f9b07510a6 Omit test_termcodes.vim: cannot be used and superseded by later patches. Cherry-pick test_bufline.vim change from patch 8.1.1993. --- runtime/doc/builtin.txt | 27 +++++++++++++++------------ src/nvim/testdir/test_blob.vim | 2 +- src/nvim/testdir/test_bufline.vim | 2 +- src/nvim/testdir/test_cd.vim | 2 +- src/nvim/testdir/test_cursor_func.vim | 2 +- src/nvim/testdir/test_diffmode.vim | 6 +----- src/nvim/testdir/test_functions.vim | 7 ++++--- 7 files changed, 24 insertions(+), 24 deletions(-) diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 0be9e9b9d1..a47eae8274 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -1136,6 +1136,9 @@ chdir({dir}) *chdir()* " ... do some work call chdir(save_dir) endif + +< Can also be used as a |method|: > + GetDir()->chdir() < cindent({lnum}) *cindent()* Get the amount of indent for line {lnum} according the C @@ -1526,6 +1529,18 @@ cursor({list}) Can also be used as a |method|: > GetCursorPos()->cursor() +debugbreak({pid}) *debugbreak()* + Specifically used to interrupt a program being debugged. It + will cause process {pid} to get a SIGTRAP. Behavior for other + processes is undefined. See |terminal-debugger|. + {Sends a SIGINT to a process {pid} other than MS-Windows} + + Returns |TRUE| if successfully interrupted the program. + Otherwise returns |FALSE|. + + Can also be used as a |method|: > + GetPid()->debugbreak() + deepcopy({expr} [, {noref}]) *deepcopy()* *E698* Make a copy of {expr}. For Numbers and Strings this isn't different from using {expr} directly. @@ -1967,18 +1982,6 @@ exp({expr}) *exp()* Can also be used as a |method|: > Compute()->exp() -debugbreak({pid}) *debugbreak()* - Specifically used to interrupt a program being debugged. It - will cause process {pid} to get a SIGTRAP. Behavior for other - processes is undefined. See |terminal-debugger|. - {Sends a SIGINT to a process {pid} other than MS-Windows} - - Returns |TRUE| if successfully interrupted the program. - Otherwise returns |FALSE|. - - Can also be used as a |method|: > - GetPid()->debugbreak() - expand({string} [, {nosuf} [, {list}]]) *expand()* Expand wildcards and the following special keywords in {string}. 'wildignorecase' applies. diff --git a/src/nvim/testdir/test_blob.vim b/src/nvim/testdir/test_blob.vim index af42b3857d..70529c14d5 100644 --- a/src/nvim/testdir/test_blob.vim +++ b/src/nvim/testdir/test_blob.vim @@ -294,7 +294,7 @@ func Test_blob_index() call assert_equal(2, index(0zDEADBEEF, 0xBE)) call assert_equal(-1, index(0zDEADBEEF, 0)) call assert_equal(2, index(0z11111111, 0x11, 2)) - call assert_equal(3, index(0z11110111, 0x11, 2)) + call assert_equal(3, 0z11110111->index(0x11, 2)) call assert_equal(2, index(0z11111111, 0x11, -2)) call assert_equal(3, index(0z11110111, 0x11, -2)) diff --git a/src/nvim/testdir/test_bufline.vim b/src/nvim/testdir/test_bufline.vim index 579d3a5eb5..939147b83b 100644 --- a/src/nvim/testdir/test_bufline.vim +++ b/src/nvim/testdir/test_bufline.vim @@ -19,7 +19,7 @@ func Test_setbufline_getbufline() let b = bufnr('%') wincmd w call assert_equal(1, setbufline(b, 5, ['x'])) - call assert_equal(1, setbufline(bufnr('$') + 1, 1, ['x'])) + call assert_equal(1, ['x']->setbufline(bufnr('$') + 1, 1)) call assert_equal(0, setbufline(b, 4, ['d', 'e'])) call assert_equal(['c'], b->getbufline(3)) call assert_equal(['d'], getbufline(b, 4)) diff --git a/src/nvim/testdir/test_cd.vim b/src/nvim/testdir/test_cd.vim index a1e53df774..d6d44d1901 100644 --- a/src/nvim/testdir/test_cd.vim +++ b/src/nvim/testdir/test_cd.vim @@ -113,7 +113,7 @@ func Test_chdir_func() call assert_equal('z', fnamemodify(3->getcwd(2), ':t')) tabnext | wincmd t call assert_match('^\[tabpage\] .*/y$', trim(execute('verbose pwd'))) - call chdir('..') + eval '..'->chdir() call assert_equal('Xdir', fnamemodify(getcwd(1, 2), ':t')) call assert_equal('Xdir', fnamemodify(getcwd(2, 2), ':t')) call assert_equal('z', fnamemodify(getcwd(3, 2), ':t')) diff --git a/src/nvim/testdir/test_cursor_func.vim b/src/nvim/testdir/test_cursor_func.vim index 3b8a5f27ad..f13842edc8 100644 --- a/src/nvim/testdir/test_cursor_func.vim +++ b/src/nvim/testdir/test_cursor_func.vim @@ -22,7 +22,7 @@ func Test_move_cursor() call cursor(3, 0) call assert_equal([3, 1, 0, 1], getcurpos()[1:]) " below last line goes to last line - call cursor(9, 1) + eval [9, 1]->cursor() call assert_equal([4, 1, 0, 1], getcurpos()[1:]) " pass string arguments call cursor('3', '3') diff --git a/src/nvim/testdir/test_diffmode.vim b/src/nvim/testdir/test_diffmode.vim index ea453b7174..1cb71664bd 100644 --- a/src/nvim/testdir/test_diffmode.vim +++ b/src/nvim/testdir/test_diffmode.vim @@ -744,17 +744,13 @@ func Test_diff_hlID() call diff_hlID(-1, 1)->synIDattr("name")->assert_equal("") - call assert_equal(diff_hlID(1, 1), hlID("DiffChange")) call diff_hlID(1, 1)->synIDattr("name")->assert_equal("DiffChange") - call assert_equal(diff_hlID(1, 2), hlID("DiffText")) call diff_hlID(1, 2)->synIDattr("name")->assert_equal("DiffText") call diff_hlID(2, 1)->synIDattr("name")->assert_equal("") - call assert_equal(diff_hlID(3, 1), hlID("DiffAdd")) call diff_hlID(3, 1)->synIDattr("name")->assert_equal("DiffAdd") - call diff_hlID(4, 1)->synIDattr("name")->assert_equal("") + eval 4->diff_hlID(1)->synIDattr("name")->assert_equal("") wincmd w - call assert_equal(diff_hlID(1, 1), hlID("DiffChange")) call assert_equal(synIDattr(diff_hlID(1, 1), "name"), "DiffChange") call assert_equal(synIDattr(diff_hlID(2, 1), "name"), "") call assert_equal(synIDattr(diff_hlID(3, 1), "name"), "") diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim index 05636199a4..b024df5a45 100644 --- a/src/nvim/testdir/test_functions.vim +++ b/src/nvim/testdir/test_functions.vim @@ -1713,7 +1713,7 @@ func Test_confirm() call assert_equal(1, a) call feedkeys('y', 'L') - let a = confirm('Are you sure?', "&Yes\n&No") + let a = 'Are you sure?'->confirm("&Yes\n&No") call assert_equal(1, a) call feedkeys('n', 'L') @@ -1727,7 +1727,7 @@ func Test_confirm() " requires another character to avoid it being seen as the start of an " escape sequence. Zero should be harmless. - call feedkeys("\0", 'L') + eval "\0"->feedkeys('L') let a = confirm('Are you sure?', "&Yes\n&No") call assert_equal(0, a) @@ -1784,7 +1784,7 @@ func Test_readdir() let files = readdir('Xdir', {x -> len(add(l, x)) == 2 ? -1 : 1}) call assert_equal(1, len(files)) - call delete('Xdir', 'rf') + eval 'Xdir'->delete('rf') endfunc func Test_delete_rf() @@ -1827,6 +1827,7 @@ endfunc func Test_char2nr() call assert_equal(12354, char2nr('ă‚', 1)) + call assert_equal(120, 'x'->char2nr()) endfunc func Test_charclass() -- cgit From d5328ea408d93d53b46417a65ca3b2fc99ab64b6 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 23 Aug 2022 10:38:53 +0800 Subject: vim-patch:8.2.0522: several errors are not tested for (#19901) Problem: Several errors are not tested for. Solution: Add tests. (Yegappan Lakshmanan, closes vim/vim#5892) https://github.com/vim/vim/commit/ee4e0c1e9a81cb5d96e0060203a9033c2f28588e Omit Test_range() change: reverted in patch 8.2.0615. Cherry-pick Test_z_no_space_before_xxx() from patch 8.2.0195. Cherry-pick Test_reverse_sort_uniq() change from patch 8.2.0183. Make uniq() error behavior consistent with sort(). Cherry-pick Test_set_ttytype() change from patch 8.1.1826. Cherry-pick quickfix checks from patch 8.1.2373 to test_preview.vim. Test_viminfo_error() is applicable. Cherry-pick E1058 from patch 8.2.0149 and port Test_deep_nest() to Lua. --- src/nvim/eval/typval.c | 8 ++-- src/nvim/eval/userfunc.c | 10 ++++- src/nvim/testdir/test_autocmd.vim | 24 ++++++++++ src/nvim/testdir/test_clientserver.vim | 6 +++ src/nvim/testdir/test_digraph.vim | 13 ++++++ src/nvim/testdir/test_expr.vim | 1 + src/nvim/testdir/test_highlight.vim | 5 ++- src/nvim/testdir/test_lambda.vim | 18 ++++++++ src/nvim/testdir/test_listdict.vim | 27 +++++++----- src/nvim/testdir/test_options.vim | 58 +++++++++++++----------- src/nvim/testdir/test_preview.vim | 7 +++ src/nvim/testdir/test_user_func.vim | 7 +++ src/nvim/testdir/test_viminfo.vim | 21 +++++++++ src/nvim/testdir/test_vimscript.vim | 23 ++++++++++ test/functional/vimscript/eval_spec.lua | 75 ++++++++++++++++++++++++++++++++ test/functional/vimscript/input_spec.lua | 20 ++++----- 16 files changed, 267 insertions(+), 56 deletions(-) create mode 100644 src/nvim/testdir/test_viminfo.vim diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 8822bb0491..7efbb1c793 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -1247,15 +1247,15 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) ; li != NULL;) { listitem_T *const prev_li = TV_LIST_ITEM_PREV(l, li); if (item_compare_func_ptr(&prev_li, &li) == 0) { - if (info.item_compare_func_err) { // -V547 - emsg(_("E882: Uniq compare function failed")); - break; - } li = tv_list_item_remove(l, li); } else { idx++; li = TV_LIST_ITEM_NEXT(l, li); } + if (info.item_compare_func_err) { + emsg(_("E882: Uniq compare function failed")); + break; + } } } diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index c46cb6ba5d..2542a5aeb0 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -1885,6 +1885,8 @@ theend: return name; } +#define MAX_FUNC_NESTING 50 + /// ":function" void ex_function(exarg_T *eap) { @@ -2304,8 +2306,12 @@ void ex_function(exarg_T *eap) p += eval_fname_script((const char *)p); xfree(trans_function_name((char **)&p, true, 0, NULL, NULL)); if (*skipwhite((char *)p) == '(') { - nesting++; - indent += 2; + if (nesting == MAX_FUNC_NESTING - 1) { + emsg(_("E1058: function nesting too deep")); + } else { + nesting++; + indent += 2; + } } } diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim index 716511210d..5451dcf241 100644 --- a/src/nvim/testdir/test_autocmd.vim +++ b/src/nvim/testdir/test_autocmd.vim @@ -2724,6 +2724,30 @@ func Test_autocmd_FileReadCmd() delfunc ReadFileCmd endfunc +" Test for passing invalid arguments to autocmd +func Test_autocmd_invalid_args() + " Additional character after * for event + call assert_fails('autocmd *a Xfile set ff=unix', 'E215:') + augroup Test + augroup END + " Invalid autocmd event + call assert_fails('autocmd Bufabc Xfile set ft=vim', 'E216:') + " Invalid autocmd event in a autocmd group + call assert_fails('autocmd Test Bufabc Xfile set ft=vim', 'E216:') + augroup! Test + " Execute all autocmds + call assert_fails('doautocmd * BufEnter', 'E217:') + call assert_fails('augroup! x1a2b3', 'E367:') + call assert_fails('autocmd BufNew pwd', 'E680:') +endfunc + +" Test for deep nesting of autocmds +func Test_autocmd_deep_nesting() + autocmd BufEnter Xfile doautocmd BufEnter Xfile + call assert_fails('doautocmd BufEnter Xfile', 'E218:') + autocmd! BufEnter Xfile +endfunc + " Tests for SigUSR1 autocmd event, which is only available on posix systems. func Test_autocmd_sigusr1() CheckUnix diff --git a/src/nvim/testdir/test_clientserver.vim b/src/nvim/testdir/test_clientserver.vim index 370d0cb190..66ee776a90 100644 --- a/src/nvim/testdir/test_clientserver.vim +++ b/src/nvim/testdir/test_clientserver.vim @@ -2,6 +2,11 @@ source check.vim CheckFeature job + +if !has('clientserver') + call assert_fails('call remote_startserver("local")', 'E942:') +endif + CheckFeature clientserver source shared.vim @@ -179,6 +184,7 @@ func Test_client_server() call assert_fails("let x = remote_peek([])", 'E730:') call assert_fails("let x = remote_read('vim10')", 'E277:') + call assert_fails("call server2client('abc', 'xyz')", 'E258:') endfunc " Uncomment this line to get a debugging log diff --git a/src/nvim/testdir/test_digraph.vim b/src/nvim/testdir/test_digraph.vim index acc34e5e7c..f08dff8605 100644 --- a/src/nvim/testdir/test_digraph.vim +++ b/src/nvim/testdir/test_digraph.vim @@ -211,6 +211,8 @@ func Test_digraphs() call Put_Dig("00") call Put_Dig("el") call assert_equal(['â€', 'ĂĽ', 'âž', 'l'], getline(line('.')-3,line('.'))) + call assert_fails('exe "digraph a\ 100"', 'E104:') + call assert_fails('exe "digraph \a 100"', 'E104:') call assert_fails('digraph xy z', 'E39:') call assert_fails('digraph x', 'E1214:') bw! @@ -491,6 +493,17 @@ func Test_show_digraph_cp1251() bwipe! endfunc +" Test for error in a keymap file +func Test_loadkeymap_error() + if !has('keymap') + return + endif + call assert_fails('loadkeymap', 'E105:') + call writefile(['loadkeymap', 'a'], 'Xkeymap') + call assert_fails('source Xkeymap', 'E791:') + call delete('Xkeymap') +endfunc + " Test for the characters displayed on the screen when entering a digraph func Test_entering_digraph() CheckRunVimInTerminal diff --git a/src/nvim/testdir/test_expr.vim b/src/nvim/testdir/test_expr.vim index 5b10e691e5..15622cd6fe 100644 --- a/src/nvim/testdir/test_expr.vim +++ b/src/nvim/testdir/test_expr.vim @@ -547,6 +547,7 @@ func Test_funcref() call assert_fails('echo funcref("{")', 'E475:') let OneByRef = funcref("One", repeat(["foo"], 20)) call assert_fails('let OneByRef = funcref("One", repeat(["foo"], 21))', 'E118:') + call assert_fails('echo function("min") =~ function("min")', 'E694:') endfunc func Test_setmatches() diff --git a/src/nvim/testdir/test_highlight.vim b/src/nvim/testdir/test_highlight.vim index efdf44a0d6..8e808a00d0 100644 --- a/src/nvim/testdir/test_highlight.vim +++ b/src/nvim/testdir/test_highlight.vim @@ -731,7 +731,8 @@ func Test_1_highlight_Normalgroup_exists() endif endfunc -function Test_no_space_before_xxx() +" Do this test last, sometimes restoring the columns doesn't work +func Test_z_no_space_before_xxx() " Note: we need to create this highlight group in the test because it does not exist in Neovim execute('hi StatusLineTermNC ctermfg=green') let l:org_columns = &columns @@ -739,7 +740,7 @@ function Test_no_space_before_xxx() let l:hi_StatusLineTermNC = join(split(execute('hi StatusLineTermNC'))) call assert_match('StatusLineTermNC xxx', l:hi_StatusLineTermNC) let &columns = l:org_columns -endfunction +endfunc " Test for :highlight command errors func Test_highlight_cmd_errors() diff --git a/src/nvim/testdir/test_lambda.vim b/src/nvim/testdir/test_lambda.vim index c1fe47d1c9..c178c87d3e 100644 --- a/src/nvim/testdir/test_lambda.vim +++ b/src/nvim/testdir/test_lambda.vim @@ -308,3 +308,21 @@ func Test_lambda_error() " This was causing a crash call assert_fails('ec{@{->{d->()()', 'E15') endfunc + +func Test_closure_error() + let l =<< trim END + func F1() closure + return 1 + endfunc + END + call writefile(l, 'Xscript') + let caught_932 = 0 + try + source Xscript + catch /E932:/ + let caught_932 = 1 + endtry + call assert_equal(1, caught_932) +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_listdict.vim b/src/nvim/testdir/test_listdict.vim index 2f4e1db4a1..08c415a069 100644 --- a/src/nvim/testdir/test_listdict.vim +++ b/src/nvim/testdir/test_listdict.vim @@ -604,20 +604,23 @@ func Test_reverse_sort_uniq() call assert_equal(['-0', 'A11', 2, 'xaaa', 4, 'foo', 'foo6', 'foo', [0, 1, 2], 'x8', [0, 1, 2], 1.5], uniq(copy(l))) call assert_equal([1.5, [0, 1, 2], 'x8', [0, 1, 2], 'foo', 'foo6', 'foo', 4, 'xaaa', 2, 2, 'A11', '-0'], reverse(l)) call assert_equal([1.5, [0, 1, 2], 'x8', [0, 1, 2], 'foo', 'foo6', 'foo', 4, 'xaaa', 2, 2, 'A11', '-0'], reverse(reverse(l))) - call assert_equal(['-0', 'A11', 'foo', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 2, 4, [0, 1, 2], [0, 1, 2]], sort(l)) - call assert_equal([[0, 1, 2], [0, 1, 2], 4, 2, 2, 1.5, 'xaaa', 'x8', 'foo6', 'foo', 'foo', 'A11', '-0'], reverse(sort(l))) - call assert_equal(['-0', 'A11', 'foo', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 2, 4, [0, 1, 2], [0, 1, 2]], sort(reverse(sort(l)))) - call assert_equal(['-0', 'A11', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 4, [0, 1, 2]], uniq(sort(l))) - - let l=[7, 9, 'one', 18, 12, 22, 'two', 10.0e-16, -1, 'three', 0xff, 0.22, 'four'] - call assert_equal([-1, 'one', 'two', 'three', 'four', 1.0e-15, 0.22, 7, 9, 12, 18, 22, 255], sort(copy(l), 'n')) - - let l=[7, 9, 18, 12, 22, 10.0e-16, -1, 0xff, 0, -0, 0.22, 'bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', {}, []] - call assert_equal(['bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}], sort(copy(l), 1)) - call assert_equal(['bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}], sort(copy(l), 'i')) - call assert_equal(['BAR', 'Bar', 'FOO', 'FOOBAR', 'Foo', 'bar', 'foo', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}], sort(copy(l))) + if has('float') + call assert_equal(['-0', 'A11', 'foo', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 2, 4, [0, 1, 2], [0, 1, 2]], sort(l)) + call assert_equal([[0, 1, 2], [0, 1, 2], 4, 2, 2, 1.5, 'xaaa', 'x8', 'foo6', 'foo', 'foo', 'A11', '-0'], reverse(sort(l))) + call assert_equal(['-0', 'A11', 'foo', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 2, 4, [0, 1, 2], [0, 1, 2]], sort(reverse(sort(l)))) + call assert_equal(['-0', 'A11', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 4, [0, 1, 2]], uniq(sort(l))) + + let l = [7, 9, 'one', 18, 12, 22, 'two', 10.0e-16, -1, 'three', 0xff, 0.22, 'four'] + call assert_equal([-1, 'one', 'two', 'three', 'four', 1.0e-15, 0.22, 7, 9, 12, 18, 22, 255], sort(copy(l), 'n')) + + let l = [7, 9, 18, 12, 22, 10.0e-16, -1, 0xff, 0, -0, 0.22, 'bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', {}, []] + call assert_equal(['bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}], sort(copy(l), 1)) + call assert_equal(['bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}], sort(copy(l), 'i')) + call assert_equal(['BAR', 'Bar', 'FOO', 'FOOBAR', 'Foo', 'bar', 'foo', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}], sort(copy(l))) + endif call assert_fails('call reverse("")', 'E899:') + call assert_fails('call uniq([1, 2], {x, y -> []})', 'E882:') endfunc " reduce a list or a blob diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim index e9a62d00a9..655d537336 100644 --- a/src/nvim/testdir/test_options.vim +++ b/src/nvim/testdir/test_options.vim @@ -234,6 +234,7 @@ func Test_complete() new call feedkeys("i\\", 'xt') bwipe! + call assert_fails('set complete=ix', 'E535:') set complete& endfun @@ -431,32 +432,37 @@ func Test_copy_context() endfunc func Test_set_ttytype() - " Nvim does not support 'ttytype'. - if !has('nvim') && !has('gui_running') && has('unix') - " Setting 'ttytype' used to cause a double-free when exiting vim and - " when vim is compiled with -DEXITFREE. - set ttytype=ansi - call assert_equal('ansi', &ttytype) - call assert_equal(&ttytype, &term) - set ttytype=xterm - call assert_equal('xterm', &ttytype) - call assert_equal(&ttytype, &term) - try - set ttytype= - call assert_report('set ttytype= did not fail') - catch /E529/ - endtry - - " Some systems accept any terminal name and return dumb settings, - " check for failure of finding the entry and for missing 'cm' entry. - try - set ttytype=xxx - call assert_report('set ttytype=xxx did not fail') - catch /E522\|E437/ - endtry - - set ttytype& - call assert_equal(&ttytype, &term) + throw "Skipped: Nvim does not support 'ttytype'" + CheckUnix + CheckNotGui + + " Setting 'ttytype' used to cause a double-free when exiting vim and + " when vim is compiled with -DEXITFREE. + set ttytype=ansi + call assert_equal('ansi', &ttytype) + call assert_equal(&ttytype, &term) + set ttytype=xterm + call assert_equal('xterm', &ttytype) + call assert_equal(&ttytype, &term) + try + set ttytype= + call assert_report('set ttytype= did not fail') + catch /E529/ + endtry + + " Some systems accept any terminal name and return dumb settings, + " check for failure of finding the entry and for missing 'cm' entry. + try + set ttytype=xxx + call assert_report('set ttytype=xxx did not fail') + catch /E522\|E437/ + endtry + + set ttytype& + call assert_equal(&ttytype, &term) + + if has('gui') && !has('gui_running') + call assert_fails('set term=gui', 'E531:') endif endfunc diff --git a/src/nvim/testdir/test_preview.vim b/src/nvim/testdir/test_preview.vim index 6c4ae414d3..b7b908e761 100644 --- a/src/nvim/testdir/test_preview.vim +++ b/src/nvim/testdir/test_preview.vim @@ -1,5 +1,8 @@ " Tests for the preview window +source check.vim +CheckFeature quickfix + func Test_Psearch() " this used to cause ml_get errors help @@ -13,6 +16,8 @@ func Test_Psearch() endfunc func Test_window_preview() + CheckFeature quickfix + " Open a preview window pedit Xa call assert_equal(2, winnr('$')) @@ -32,6 +37,8 @@ func Test_window_preview() endfunc func Test_window_preview_from_help() + CheckFeature quickfix + filetype on call writefile(['/* some C code */'], 'Xpreview.c') help diff --git a/src/nvim/testdir/test_user_func.vim b/src/nvim/testdir/test_user_func.vim index 5231ef7b4f..c14624f5b4 100644 --- a/src/nvim/testdir/test_user_func.vim +++ b/src/nvim/testdir/test_user_func.vim @@ -169,3 +169,10 @@ endfunc func Test_failed_call_in_try() try | call UnknownFunc() | catch | endtry endfunc + +" Test for listing user-defined functions +func Test_function_list() + call assert_fails("function Xabc", 'E123:') +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_viminfo.vim b/src/nvim/testdir/test_viminfo.vim new file mode 100644 index 0000000000..2d6d598011 --- /dev/null +++ b/src/nvim/testdir/test_viminfo.vim @@ -0,0 +1,21 @@ + +" Test for errors in setting 'viminfo' +func Test_viminfo_option_error() + " Missing number + call assert_fails('set viminfo=\"', 'E526:') + for c in split("'/:<@s", '\zs') + call assert_fails('set viminfo=' .. c, 'E526:') + endfor + + " Missing comma + call assert_fails('set viminfo=%10!', 'E527:') + call assert_fails('set viminfo=!%10', 'E527:') + call assert_fails('set viminfo=h%10', 'E527:') + call assert_fails('set viminfo=c%10', 'E527:') + call assert_fails('set viminfo=:10%10', 'E527:') + + " Missing ' setting + call assert_fails('set viminfo=%10', 'E528:') +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_vimscript.vim b/src/nvim/testdir/test_vimscript.vim index 0f204cdd0c..97e879c9ef 100644 --- a/src/nvim/testdir/test_vimscript.vim +++ b/src/nvim/testdir/test_vimscript.vim @@ -1829,6 +1829,9 @@ func Test_missing_end() endtry call assert_equal(1, caught_e733) + " Using endfunc with :if + call assert_fails('exe "if 1 | endfunc | endif"', 'E193:') + " Missing 'in' in a :for statement call assert_fails('for i range(1) | endfor', 'E690:') endfunc @@ -1875,6 +1878,15 @@ func Test_deep_nest() @a let @a = '' endfunc + + " Deep nesting of function ... endfunction + func Test5() + let @a = join(repeat(['function X()'], 51), "\n") + let @a ..= "\necho v:true\n" + let @a ..= join(repeat(['endfunction'], 51), "\n") + @a + let @a = '' + endfunc [SCRIPT] call writefile(lines, 'Xscript') @@ -1882,20 +1894,31 @@ func Test_deep_nest() " Deep nesting of if ... endif call term_sendkeys(buf, ":call Test1()\n") + call term_wait(buf) call WaitForAssert({-> assert_match('^E579:', term_getline(buf, 5))}) " Deep nesting of for ... endfor call term_sendkeys(buf, ":call Test2()\n") + call term_wait(buf) call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))}) " Deep nesting of while ... endwhile call term_sendkeys(buf, ":call Test3()\n") + call term_wait(buf) call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))}) " Deep nesting of try ... endtry call term_sendkeys(buf, ":call Test4()\n") + call term_wait(buf) call WaitForAssert({-> assert_match('^E601:', term_getline(buf, 5))}) + " Deep nesting of function ... endfunction + call term_sendkeys(buf, ":call Test5()\n") + call term_wait(buf) + call WaitForAssert({-> assert_match('^E1058:', term_getline(buf, 4))}) + call term_sendkeys(buf, "\\n") + call term_wait(buf) + "let l = '' "for i in range(1, 6) " let l ..= term_getline(buf, i) . "\n" diff --git a/test/functional/vimscript/eval_spec.lua b/test/functional/vimscript/eval_spec.lua index 0c2ca8de78..65ac5b8c80 100644 --- a/test/functional/vimscript/eval_spec.lua +++ b/test/functional/vimscript/eval_spec.lua @@ -10,11 +10,13 @@ -- test/functional/vimscript/functions_spec.lua local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') local lfs = require('lfs') local clear = helpers.clear local eq = helpers.eq local exc_exec = helpers.exc_exec +local exec = helpers.exec local eval = helpers.eval local command = helpers.command local write_file = helpers.write_file @@ -144,3 +146,76 @@ describe('List support code', function() end end) end) + +-- oldtest: Test_deep_nest() +it('Error when if/for/while/try/function is nested too deep',function() + clear() + local screen = Screen.new(80, 24) + screen:attach() + meths.set_option('laststatus', 2) + exec([[ + " Deep nesting of if ... endif + func Test1() + let @a = join(repeat(['if v:true'], 51), "\n") + let @a ..= "\n" + let @a ..= join(repeat(['endif'], 51), "\n") + @a + let @a = '' + endfunc + + " Deep nesting of for ... endfor + func Test2() + let @a = join(repeat(['for i in [1]'], 51), "\n") + let @a ..= "\n" + let @a ..= join(repeat(['endfor'], 51), "\n") + @a + let @a = '' + endfunc + + " Deep nesting of while ... endwhile + func Test3() + let @a = join(repeat(['while v:true'], 51), "\n") + let @a ..= "\n" + let @a ..= join(repeat(['endwhile'], 51), "\n") + @a + let @a = '' + endfunc + + " Deep nesting of try ... endtry + func Test4() + let @a = join(repeat(['try'], 51), "\n") + let @a ..= "\necho v:true\n" + let @a ..= join(repeat(['endtry'], 51), "\n") + @a + let @a = '' + endfunc + + " Deep nesting of function ... endfunction + func Test5() + let @a = join(repeat(['function X()'], 51), "\n") + let @a ..= "\necho v:true\n" + let @a ..= join(repeat(['endfunction'], 51), "\n") + @a + let @a = '' + endfunc + ]]) + screen:expect({any = '%[No Name%]'}) + feed(':call Test1()') + screen:expect({any = 'E579: '}) + feed('') + screen:expect({any = '%[No Name%]'}) + feed(':call Test2()') + screen:expect({any = 'E585: '}) + feed('') + screen:expect({any = '%[No Name%]'}) + feed(':call Test3()') + screen:expect({any = 'E585: '}) + feed('') + screen:expect({any = '%[No Name%]'}) + feed(':call Test4()') + screen:expect({any = 'E601: '}) + feed('') + screen:expect({any = '%[No Name%]'}) + feed(':call Test5()') + screen:expect({any = 'E1058: '}) +end) diff --git a/test/functional/vimscript/input_spec.lua b/test/functional/vimscript/input_spec.lua index d6ab71b7d5..f50b39c2c5 100644 --- a/test/functional/vimscript/input_spec.lua +++ b/test/functional/vimscript/input_spec.lua @@ -455,24 +455,24 @@ describe('confirm()', function() meths.set_option('more', false) -- Avoid hit-enter prompt meths.set_option('laststatus', 2) -- screen:expect() calls are needed to avoid feeding input too early - screen:expect({any = 'No Name'}) + screen:expect({any = '%[No Name%]'}) async_meths.command([[let a = confirm('Press O to proceed')]]) screen:expect({any = '{CONFIRM:.+: }'}) feed('o') - screen:expect({any = 'No Name'}) + screen:expect({any = '%[No Name%]'}) eq(1, meths.get_var('a')) - async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No")]]) + async_meths.command([[let a = 'Are you sure?'->confirm("&Yes\n&No")]]) screen:expect({any = '{CONFIRM:.+: }'}) feed('y') - screen:expect({any = 'No Name'}) + screen:expect({any = '%[No Name%]'}) eq(1, meths.get_var('a')) async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No")]]) screen:expect({any = '{CONFIRM:.+: }'}) feed('n') - screen:expect({any = 'No Name'}) + screen:expect({any = '%[No Name%]'}) eq(2, meths.get_var('a')) -- Not possible to match Vim's CTRL-C test here as CTRL-C always sets got_int in Nvim. @@ -481,26 +481,26 @@ describe('confirm()', function() async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No")]]) screen:expect({any = '{CONFIRM:.+: }'}) feed('') - screen:expect({any = 'No Name'}) + screen:expect({any = '%[No Name%]'}) eq(0, meths.get_var('a')) -- Default choice is returned when pressing . async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No")]]) screen:expect({any = '{CONFIRM:.+: }'}) feed('') - screen:expect({any = 'No Name'}) + screen:expect({any = '%[No Name%]'}) eq(1, meths.get_var('a')) async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No", 2)]]) screen:expect({any = '{CONFIRM:.+: }'}) feed('') - screen:expect({any = 'No Name'}) + screen:expect({any = '%[No Name%]'}) eq(2, meths.get_var('a')) async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No", 0)]]) screen:expect({any = '{CONFIRM:.+: }'}) feed('') - screen:expect({any = 'No Name'}) + screen:expect({any = '%[No Name%]'}) eq(0, meths.get_var('a')) -- Test with the {type} 4th argument @@ -508,7 +508,7 @@ describe('confirm()', function() async_meths.command(([[let a = confirm('Are you sure?', "&Yes\n&No", 1, '%s')]]):format(type)) screen:expect({any = '{CONFIRM:.+: }'}) feed('y') - screen:expect({any = 'No Name'}) + screen:expect({any = '%[No Name%]'}) eq(1, meths.get_var('a')) end -- cgit From 63df91c10a7ec492adae91c78cb51eb231c77d89 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 23 Aug 2022 11:24:46 +0800 Subject: vim-patch:8.2.1046: insufficient tests for src/buffer.c (#19903) Problem: Insufficient tests for src/buffer.c. Solution: Add more tests. Move comments related tests to a separate file. (Yegappan Lakshmanan, closes vim/vim#6325) https://github.com/vim/vim/commit/b7e2483655d9b68df0c7349918027d800051a28a --- src/nvim/testdir/test_buffer.vim | 206 ++++++++++++++++++++++++ src/nvim/testdir/test_cmdline.vim | 1 + src/nvim/testdir/test_comments.vim | 277 +++++++++++++++++++++++++++++++++ src/nvim/testdir/test_normal.vim | 1 + src/nvim/testdir/test_textformat.vim | 272 -------------------------------- test/functional/legacy/buffer_spec.lua | 59 +++++++ 6 files changed, 544 insertions(+), 272 deletions(-) create mode 100644 src/nvim/testdir/test_comments.vim create mode 100644 test/functional/legacy/buffer_spec.lua diff --git a/src/nvim/testdir/test_buffer.vim b/src/nvim/testdir/test_buffer.vim index 67be3e6747..4def3b5df9 100644 --- a/src/nvim/testdir/test_buffer.vim +++ b/src/nvim/testdir/test_buffer.vim @@ -154,6 +154,24 @@ func Test_bdelete_cmd() set nobuflisted enew call assert_fails('bdelete ' .. bnr, 'E516:') + + " Deleting more than one buffer + new Xbuf1 + new Xbuf2 + exe 'bdel ' .. bufnr('Xbuf2') .. ' ' .. bufnr('Xbuf1') + call assert_equal(1, winnr('$')) + call assert_equal(0, getbufinfo('Xbuf1')[0].loaded) + call assert_equal(0, getbufinfo('Xbuf2')[0].loaded) + + " Deleting more than one buffer and an invalid buffer + new Xbuf1 + new Xbuf2 + let cmd = "exe 'bdel ' .. bufnr('Xbuf2') .. ' xxx ' .. bufnr('Xbuf1')" + call assert_fails(cmd, 'E94:') + call assert_equal(2, winnr('$')) + call assert_equal(1, getbufinfo('Xbuf1')[0].loaded) + call assert_equal(0, getbufinfo('Xbuf2')[0].loaded) + %bwipe! endfunc @@ -168,6 +186,194 @@ func Test_buffer_error() %bwipe endfunc +" Test for the status messages displayed when unloading, deleting or wiping +" out buffers +func Test_buffer_statusmsg() + CheckEnglish + set report=1 + new Xbuf1 + new Xbuf2 + let bnr = bufnr() + exe "normal 2\" + call assert_match('buf ' .. bnr .. ':', v:statusmsg) + bunload Xbuf1 Xbuf2 + call assert_equal('2 buffers unloaded', v:statusmsg) + bdel Xbuf1 Xbuf2 + call assert_equal('2 buffers deleted', v:statusmsg) + bwipe Xbuf1 Xbuf2 + call assert_equal('2 buffers wiped out', v:statusmsg) + set report& +endfunc + +" Test for quitting the 'swapfile exists' dialog with the split buffer +" command. +func Test_buffer_sbuf_cleanup() + call writefile([], 'Xfile') + " first open the file in a buffer + new Xfile + let bnr = bufnr() + close + " create the swap file + call writefile([], '.Xfile.swp') + " Remove the catch-all that runtest.vim adds + au! SwapExists + augroup BufTest + au! + autocmd SwapExists Xfile let v:swapchoice='q' + augroup END + exe 'sbuf ' . bnr + call assert_equal(1, winnr('$')) + call assert_equal(0, getbufinfo('Xfile')[0].loaded) + + " test for :sball + sball + call assert_equal(1, winnr('$')) + call assert_equal(0, getbufinfo('Xfile')[0].loaded) + + %bw! + set shortmess+=F + let v:statusmsg = '' + edit Xfile + call assert_equal('', v:statusmsg) + call assert_equal(1, winnr('$')) + call assert_equal(0, getbufinfo('Xfile')[0].loaded) + set shortmess& + + call delete('Xfile') + call delete('.Xfile.swp') + augroup BufTest + au! + augroup END + augroup! BufTest +endfunc + +" Test for deleting a modified buffer with :confirm +func Test_bdel_with_confirm() + " requires a UI to be active + throw 'Skipped: use test/functional/legacy/buffer_spec.lua' + CheckUnix + CheckNotGui + CheckFeature dialog_con + new + call setline(1, 'test') + call assert_fails('bdel', 'E89:') + call feedkeys('c', 'L') + confirm bdel + call assert_equal(2, winnr('$')) + call assert_equal(1, &modified) + call feedkeys('n', 'L') + confirm bdel + call assert_equal(1, winnr('$')) +endfunc + +" Test for editing another buffer from a modified buffer with :confirm +func Test_goto_buf_with_confirm() + " requires a UI to be active + throw 'Skipped: use test/functional/legacy/buffer_spec.lua' + CheckUnix + CheckNotGui + CheckFeature dialog_con + new Xfile + enew + call setline(1, 'test') + call assert_fails('b Xfile', 'E37:') + call feedkeys('c', 'L') + call assert_fails('confirm b Xfile', 'E37:') + call assert_equal(1, &modified) + call assert_equal('', @%) + call feedkeys('y', 'L') + call assert_fails('confirm b Xfile', 'E37:') + call assert_equal(1, &modified) + call assert_equal('', @%) + call feedkeys('n', 'L') + confirm b Xfile + call assert_equal('Xfile', @%) + close! +endfunc + +" Test for splitting buffer with 'switchbuf' +func Test_buffer_switchbuf() + new Xfile + wincmd w + set switchbuf=useopen + sbuf Xfile + call assert_equal(1, winnr()) + call assert_equal(2, winnr('$')) + set switchbuf=usetab + tabnew + sbuf Xfile + call assert_equal(1, tabpagenr()) + call assert_equal(2, tabpagenr('$')) + set switchbuf& + %bw +endfunc + +" Test for BufAdd autocommand wiping out the buffer +func Test_bufadd_autocmd_bwipe() + %bw! + augroup BufAdd_Wipe + au! + autocmd BufAdd Xfile %bw! + augroup END + edit Xfile + call assert_equal('', @%) + call assert_equal(0, bufexists('Xfile')) + augroup BufAdd_Wipe + au! + augroup END + augroup! BufAdd_Wipe +endfunc + +" Test for trying to load a buffer with text locked +" e in the command line is used to lock the text +func Test_load_buf_with_text_locked() + new Xfile1 + edit Xfile2 + let cmd = ":\eexecute(\"normal \\")\\" + call assert_fails("call feedkeys(cmd, 'xt')", 'E565:') + %bw! +endfunc + +" Test for using CTRL-^ to edit the alternative file keeping the cursor +" position with 'nostartofline'. Also test using the 'buf' command. +func Test_buffer_edit_altfile() + call writefile(repeat(['one two'], 50), 'Xfile1') + call writefile(repeat(['five six'], 50), 'Xfile2') + set nosol + edit Xfile1 + call cursor(25, 5) + edit Xfile2 + call cursor(30, 4) + exe "normal \" + call assert_equal([0, 25, 5, 0], getpos('.')) + exe "normal \" + call assert_equal([0, 30, 4, 0], getpos('.')) + buf Xfile1 + call assert_equal([0, 25, 5, 0], getpos('.')) + buf Xfile2 + call assert_equal([0, 30, 4, 0], getpos('.')) + set sol& + call delete('Xfile1') + call delete('Xfile2') +endfunc + +" Test for running the :sball command with a maximum window count and a +" modified buffer +func Test_sball_with_count() + %bw! + edit Xfile1 + call setline(1, ['abc']) + new Xfile2 + new Xfile3 + new Xfile4 + 2sball + call assert_equal(bufnr('Xfile4'), winbufnr(1)) + call assert_equal(bufnr('Xfile1'), winbufnr(2)) + call assert_equal(0, getbufinfo('Xfile2')[0].loaded) + call assert_equal(0, getbufinfo('Xfile3')[0].loaded) + %bw! +endfunc + func Test_badd_options() new SomeNewBuffer setlocal numberwidth=3 diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim index 72d2dc9cbb..b7c6c1e4d1 100644 --- a/src/nvim/testdir/test_cmdline.vim +++ b/src/nvim/testdir/test_cmdline.vim @@ -514,6 +514,7 @@ func Test_getcompletion() call delete('Xtags') set tags& + call assert_fails("call getcompletion('\\\\@!\\\\@=', 'buffer')", 'E871:') call assert_fails('call getcompletion("", "burp")', 'E475:') call assert_fails('call getcompletion("abc", [])', 'E475:') endfunc diff --git a/src/nvim/testdir/test_comments.vim b/src/nvim/testdir/test_comments.vim new file mode 100644 index 0000000000..c34b85c42d --- /dev/null +++ b/src/nvim/testdir/test_comments.vim @@ -0,0 +1,277 @@ +" Tests for the various flags in the 'comments' option + +" Test for the 'n' flag in 'comments' +func Test_comment_nested() + new + setlocal comments=n:> fo+=ro + exe "normal i> B\nD\ggOA\joC\Go\>>> F\nH" + exe "normal 5GOE\6GoG" + let expected =<< trim END + > A + > B + > C + > D + >>>> E + >>>> F + >>>> G + >>>> H + END + call assert_equal(expected, getline(1, '$')) + close! +endfunc + +" Test for the 'b' flag in 'comments' +func Test_comment_blank() + new + setlocal comments=b:* fo+=ro + exe "normal i* E\nF\n\G\nH\ggOC\O\B\OA\2joD" + let expected =<< trim END + A + *B + * C + * D + * E + * F + *G + H + END + call assert_equal(expected, getline(1, '$')) + close! +endfunc + +" Test for the 'f' flag in 'comments' (only the first line has a comment +" string) +func Test_comment_firstline() + new + setlocal comments=f:- fo+=ro + exe "normal i- B\nD\ggoC\ggOA\" + call assert_equal(['A', '- B', ' C', ' D'], getline(1, '$')) + %d + setlocal comments=:- + exe "normal i- B\nD\ggoC\ggOA\" + call assert_equal(['- A', '- B', '- C', '- D'], getline(1, '$')) + close! +endfunc + +" Test for the 's', 'm' and 'e' flags in 'comments' +" Test for automatically adding comment leaders in insert mode +func Test_comment_threepiece() + new + setlocal expandtab + call setline(1, ["\t/*"]) + setlocal formatoptions=croql + call cursor(1, 3) + call feedkeys("A\\/", 'tnix') + call assert_equal(["\t/*", " *", " */"], getline(1, '$')) + + " If a comment ends in a single line, then don't add it in the next line + %d + call setline(1, '/* line1 */') + call feedkeys("A\next line", 'xt') + call assert_equal(['/* line1 */', 'next line'], getline(1, '$')) + + %d + " Copy the trailing indentation from the leader comment to a new line + setlocal autoindent noexpandtab + call feedkeys("a\t/*\tone\ntwo\n/", 'xt') + call assert_equal(["\t/*\tone", "\t *\ttwo", "\t */"], getline(1, '$')) + close! +endfunc + +" Test for the 'r' flag in 'comments' (right align comment) +func Test_comment_rightalign() + new + setlocal comments=sr:/***,m:**,ex-2:******/ fo+=ro + exe "normal i=\o\t /***\nD\n/" + exe "normal 2GOA\joB\jOC\joE\GOF\joG" + let expected =<< trim END + = + A + /*** + ** B + ** C + ** D + ** E + ** F + ******/ + G + END + call assert_equal(expected, getline(1, '$')) + close! +endfunc + +" Test for the 'O' flag in 'comments' +func Test_comment_O() + new + setlocal comments=Ob:* fo+=ro + exe "normal i* B\nD\kOA\joC" + let expected =<< trim END + A + * B + * C + * D + END + call assert_equal(expected, getline(1, '$')) + close! +endfunc + +" Test for using a multibyte character as a comment leader +func Test_comment_multibyte_leader() + new + let t =<< trim END + { + X + Xa + XaY + XY + XYZ + X Y + X YZ + XX + XXa + XXY + } + END + call setline(1, t) + call cursor(2, 1) + + set tw=2 fo=cqm comments=n:X + exe "normal gqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgq" + let t =<< trim END + X + Xa + XaY + XY + XYZ + X Y + X YZ + XX + XXa + XXY + END + exe "normal o\n" . join(t, "\n") + + let expected =<< trim END + { + X + Xa + Xa + XY + XY + XY + XZ + X Y + X Y + X Z + XX + XXa + XXY + + X + Xa + Xa + XY + XY + XY + XZ + X Y + X Y + X Z + XX + XXa + XXY + } + END + call assert_equal(expected, getline(1, '$')) + + set tw& fo& comments& + close! +endfunc + +" Test for a space character in 'comments' setting +func Test_comment_space() + new + setlocal comments=b:\ > fo+=ro + exe "normal i> B\nD\ggOA\joC" + exe "normal Go > F\nH\kOE\joG" + let expected =<< trim END + A + > B + C + D + > E + > F + > G + > H + END + call assert_equal(expected, getline(1, '$')) + close! +endfunc + +" Test for formatting lines with and without comments +func Test_comment_format_lines() + new + call setline(1, ['one', '/* two */', 'three']) + normal gggqG + call assert_equal(['one', '/* two */', 'three'], getline(1, '$')) + close! +endfunc + +" Test for using 'a' in 'formatoptions' with comments +func Test_comment_autoformat() + new + setlocal formatoptions+=a + call feedkeys("a- one\n- two\n", 'xt') + call assert_equal(['- one', '- two', ''], getline(1, '$')) + + %d + call feedkeys("a\none\n", 'xt') + call assert_equal(['', 'one', ''], getline(1, '$')) + + setlocal formatoptions+=aw + %d + call feedkeys("aone \ntwo\n", 'xt') + call assert_equal(['one two', ''], getline(1, '$')) + + %d + call feedkeys("aone\ntwo\n", 'xt') + call assert_equal(['one', 'two', ''], getline(1, '$')) + + close! +endfunc + +" Test for joining lines with comments ('j' flag in 'formatoptions') +func Test_comment_join_lines_fo_j() + new + setlocal fo+=j comments=:// + call setline(1, ['i++; // comment1', ' // comment2']) + normal J + call assert_equal('i++; // comment1 comment2', getline(1)) + setlocal fo-=j + call setline(1, ['i++; // comment1', ' // comment2']) + normal J + call assert_equal('i++; // comment1 // comment2', getline(1)) + " Test with nested comments + setlocal fo+=j comments=n:>,n:) + call setline(1, ['i++; > ) > ) comment1', ' > ) comment2']) + normal J + call assert_equal('i++; > ) > ) comment1 comment2', getline(1)) + close! +endfunc + +" Test for formatting lines where only the first line has a comment. +func Test_comment_format_firstline_comment() + new + setlocal formatoptions=tcq + call setline(1, ['- one two', 'three']) + normal gggqG + call assert_equal(['- one two three'], getline(1, '$')) + + %d + call setline(1, ['- one', '- two']) + normal gggqG + call assert_equal(['- one', '- two'], getline(1, '$')) + close! +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim index 2092b508ea..4f842189b6 100644 --- a/src/nvim/testdir/test_normal.vim +++ b/src/nvim/testdir/test_normal.vim @@ -1455,6 +1455,7 @@ func Test_normal21_nv_hat() edit Xfoo | %bw call assert_fails(':buffer #', 'E86') call assert_fails(':execute "normal! \"', 'E23') + call assert_fails("normal i\#", 'E23:') " Test for the expected behavior when switching between two named buffers. edit Xfoo | edit Xbar diff --git a/src/nvim/testdir/test_textformat.vim b/src/nvim/testdir/test_textformat.vim index 0fc56083aa..4eb6e69adf 100644 --- a/src/nvim/testdir/test_textformat.vim +++ b/src/nvim/testdir/test_textformat.vim @@ -962,78 +962,6 @@ func Test_tw_2_fo_tm_noai() bwipe! endfunc -func Test_tw_2_fo_cqm_com() - new - let t =<< trim END - { - X - Xa - XaY - XY - XYZ - X Y - X YZ - XX - XXa - XXY - } - END - call setline(1, t) - call cursor(2, 1) - - set tw=2 fo=cqm comments=n:X - exe "normal gqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgq" - let t =<< trim END - X - Xa - XaY - XY - XYZ - X Y - X YZ - XX - XXa - XXY - END - exe "normal o\n" . join(t, "\n") - - let expected =<< trim END - { - X - Xa - Xa - XY - XY - XY - XZ - X Y - X Y - X Z - XX - XXa - XXY - - X - Xa - Xa - XY - XY - XY - XZ - X Y - X Y - X Z - XX - XXa - XXY - } - END - call assert_equal(expected, getline(1, '$')) - - set tw& fo& comments& - bwipe! -endfunc - func Test_tw_2_fo_tm_replace() new let t =<< trim END @@ -1161,140 +1089,6 @@ func Test_whichwrap_multi_byte() bwipe! endfunc -" Test for automatically adding comment leaders in insert mode -func Test_threepiece_comment() - new - setlocal expandtab - call setline(1, ["\t/*"]) - setlocal formatoptions=croql - call cursor(1, 3) - call feedkeys("A\\/", 'tnix') - call assert_equal(["\t/*", " *", " */"], getline(1, '$')) - - " If a comment ends in a single line, then don't add it in the next line - %d - call setline(1, '/* line1 */') - call feedkeys("A\next line", 'xt') - call assert_equal(['/* line1 */', 'next line'], getline(1, '$')) - - %d - " Copy the trailing indentation from the leader comment to a new line - setlocal autoindent noexpandtab - call feedkeys("a\t/*\tone\ntwo\n/", 'xt') - call assert_equal(["\t/*\tone", "\t *\ttwo", "\t */"], getline(1, '$')) - close! -endfunc - -" Test for the 'f' flag in 'comments' (only the first line has the comment -" string) -func Test_firstline_comment() - new - setlocal comments=f:- fo+=ro - exe "normal i- B\nD\ggoC\ggOA\" - call assert_equal(['A', '- B', ' C', ' D'], getline(1, '$')) - %d - setlocal comments=:- - exe "normal i- B\nD\ggoC\ggOA\" - call assert_equal(['- A', '- B', '- C', '- D'], getline(1, '$')) - %bw! -endfunc - -" Test for the 'r' flag in 'comments' (right align comment) -func Test_comment_rightalign() - new - setlocal comments=sr:/***,m:**,ex-2:******/ fo+=ro - exe "normal i=\o\t /***\nD\n/" - exe "normal 2GOA\joB\jOC\joE\GOF\joG" - let expected =<< trim END - = - A - /*** - ** B - ** C - ** D - ** E - ** F - ******/ - G - END - call assert_equal(expected, getline(1, '$')) - %bw! -endfunc - -" Test for the 'b' flag in 'comments' -func Test_comment_blank() - new - setlocal comments=b:* fo+=ro - exe "normal i* E\nF\n\G\nH\ggOC\O\B\OA\2joD" - let expected =<< trim END - A - *B - * C - * D - * E - * F - *G - H - END - call assert_equal(expected, getline(1, '$')) - %bw! -endfunc - -" Test for the 'n' flag in comments -func Test_comment_nested() - new - setlocal comments=n:> fo+=ro - exe "normal i> B\nD\ggOA\joC\Go\>>> F\nH" - exe "normal 5GOE\6GoG" - let expected =<< trim END - > A - > B - > C - > D - >>>> E - >>>> F - >>>> G - >>>> H - END - call assert_equal(expected, getline(1, '$')) - %bw! -endfunc - -" Test for a space character in 'comments' setting -func Test_comment_space() - new - setlocal comments=b:\ > fo+=ro - exe "normal i> B\nD\ggOA\joC" - exe "normal Go > F\nH\kOE\joG" - let expected =<< trim END - A - > B - C - D - > E - > F - > G - > H - END - call assert_equal(expected, getline(1, '$')) - %bw! -endfunc - -" Test for the 'O' flag in 'comments' -func Test_comment_O() - new - setlocal comments=Ob:* fo+=ro - exe "normal i* B\nD\kOA\joC" - let expected =<< trim END - A - * B - * C - * D - END - call assert_equal(expected, getline(1, '$')) - %bw! -endfunc - " Test for 'a' and 'w' flags in 'formatoptions' func Test_fo_a_w() new @@ -1334,25 +1128,6 @@ func Test_fo_a_w() %bw! endfunc -" Test for 'j' flag in 'formatoptions' -func Test_fo_j() - new - setlocal fo+=j comments=:// - call setline(1, ['i++; // comment1', ' // comment2']) - normal J - call assert_equal('i++; // comment1 comment2', getline(1)) - setlocal fo-=j - call setline(1, ['i++; // comment1', ' // comment2']) - normal J - call assert_equal('i++; // comment1 // comment2', getline(1)) - " Test with nested comments - setlocal fo+=j comments=n:>,n:) - call setline(1, ['i++; > ) > ) comment1', ' > ) comment2']) - normal J - call assert_equal('i++; > ) > ) comment1 comment2', getline(1)) - %bw! -endfunc - " Test for formatting lines using gq in visual mode func Test_visual_gq_format() new @@ -1487,53 +1262,6 @@ func Test_fo_2() close! endfunc -" Test for formatting lines where only the first line has a comment. -func Test_fo_gq_with_firstline_comment() - new - setlocal formatoptions=tcq - call setline(1, ['- one two', 'three']) - normal gggqG - call assert_equal(['- one two three'], getline(1, '$')) - - %d - call setline(1, ['- one', '- two']) - normal gggqG - call assert_equal(['- one', '- two'], getline(1, '$')) - close! -endfunc - -" Test for trying to join a comment line with a non-comment line -func Test_join_comments() - new - call setline(1, ['one', '/* two */', 'three']) - normal gggqG - call assert_equal(['one', '/* two */', 'three'], getline(1, '$')) - close! -endfunc - -" Test for using 'a' in 'formatoptions' with comments -func Test_autoformat_comments() - new - setlocal formatoptions+=a - call feedkeys("a- one\n- two\n", 'xt') - call assert_equal(['- one', '- two', ''], getline(1, '$')) - - %d - call feedkeys("a\none\n", 'xt') - call assert_equal(['', 'one', ''], getline(1, '$')) - - setlocal formatoptions+=aw - %d - call feedkeys("aone \ntwo\n", 'xt') - call assert_equal(['one two', ''], getline(1, '$')) - - %d - call feedkeys("aone\ntwo\n", 'xt') - call assert_equal(['one', 'two', ''], getline(1, '$')) - - close! -endfunc - " This was leaving the cursor after the end of a line. Complicated way to " have the problem show up with valgrind. func Test_correct_cursor_position() diff --git a/test/functional/legacy/buffer_spec.lua b/test/functional/legacy/buffer_spec.lua new file mode 100644 index 0000000000..acaa9a51f1 --- /dev/null +++ b/test/functional/legacy/buffer_spec.lua @@ -0,0 +1,59 @@ +local helpers = require('test.functional.helpers')(after_each) +local clear, source = helpers.clear, helpers.source +local call, eq, meths = helpers.call, helpers.eq, helpers.meths + +local function expected_empty() + eq({}, meths.get_vvar('errors')) +end + +describe('buffer', function() + before_each(function() + clear() + meths.ui_attach(80, 24, {}) + meths.set_option('hidden', false) + end) + + it('deleting a modified buffer with :confirm', function() + source([[ + func Test_bdel_with_confirm() + new + call setline(1, 'test') + call assert_fails('bdel', 'E89:') + call nvim_input('c') + confirm bdel + call assert_equal(2, winnr('$')) + call assert_equal(1, &modified) + call nvim_input('n') + confirm bdel + call assert_equal(1, winnr('$')) + endfunc + ]]) + call('Test_bdel_with_confirm') + expected_empty() + end) + + it('editing another buffer from a modified buffer with :confirm', function() + source([[ + func Test_goto_buf_with_confirm() + new Xfile + enew + call setline(1, 'test') + call assert_fails('b Xfile', 'E37:') + call nvim_input('c') + call assert_fails('confirm b Xfile', 'E37:') + call assert_equal(1, &modified) + call assert_equal('', @%) + call nvim_input('y') + call assert_fails('confirm b Xfile', 'E37:') + call assert_equal(1, &modified) + call assert_equal('', @%) + call nvim_input('n') + confirm b Xfile + call assert_equal('Xfile', @%) + close! + endfunc + ]]) + call('Test_goto_buf_with_confirm') + expected_empty() + end) +end) -- cgit From 42e9fe7d958e0ba025034c330d8e29293d828b60 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 23 Aug 2022 11:39:25 +0800 Subject: test: add test for using :normal to stop Visual mode in cmdwin (#19904) --- test/functional/ex_cmds/normal_spec.lua | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/test/functional/ex_cmds/normal_spec.lua b/test/functional/ex_cmds/normal_spec.lua index f6e7dd2b3a..009f1d6516 100644 --- a/test/functional/ex_cmds/normal_spec.lua +++ b/test/functional/ex_cmds/normal_spec.lua @@ -1,6 +1,7 @@ local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local command = helpers.command +local funcs = helpers.funcs local feed = helpers.feed local expect = helpers.expect local eq = helpers.eq @@ -8,20 +9,30 @@ local eval = helpers.eval before_each(clear) -describe(':normal', function() +describe(':normal!', function() it('can get out of Insert mode if called from Ex mode #17924', function() feed('gQnormal! Ifoo') expect('foo') end) - it('normal! does not execute command in Ex mode when running out of characters', function() + it('does not execute command in Ex mode when running out of characters', function() command('let g:var = 0') command('normal! gQlet g:var = 1') eq(0, eval('g:var')) end) - it('normal! gQinsert does not hang #17980', function() + it('gQinsert does not hang #17980', function() command('normal! gQinsert') expect('') end) + + it('can stop Visual mode without closing cmdwin vim-patch:9.0.0234', function() + feed('q:') + feed('v') + eq('v', funcs.mode(1)) + eq(':', funcs.getcmdwintype()) + command('normal! \027') + eq('n', funcs.mode(1)) + eq(':', funcs.getcmdwintype()) + end) end) -- cgit From ffa1335047047ac00280ac742bcc6dfcc7fa3589 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 20 Aug 2022 07:54:14 +0800 Subject: vim-patch:8.2.4726: cannot use expand() to get the script name Problem: Cannot use expand() to get the script name. Solution: Support expand(' - -$treeview -$search -$mathjax - -$extrastylesheet - - - -
- - - - - diff --git a/contrib/doxygen/logo-devdoc.png b/contrib/doxygen/logo-devdoc.png deleted file mode 100644 index a25ef2b9d7..0000000000 Binary files a/contrib/doxygen/logo-devdoc.png and /dev/null differ -- cgit From ede66a0b85fcff44890cb34d71e22995eb621006 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Fri, 23 Sep 2022 12:02:16 -0400 Subject: fix: cleanup contrib/ #20304 - YouCompleteMe is unnecessary since Nvim LSP works well. - vim-addon-local-vimrc is not needed since we added `.editorconfig`. - Inline flake8 arguments. Eventually we will remove all python code, don't need a top-level `.flake8` file meanwhile. --- .flake8 | 2 - CMakeLists.txt | 1 + contrib/YouCompleteMe/README.md | 31 ---------------- contrib/YouCompleteMe/ycm_extra_conf.py | 65 --------------------------------- contrib/vim-addon-local-vimrc/README.md | 18 --------- contrib/vim-addon-local-vimrc/vimrc | 11 ------ 6 files changed, 1 insertion(+), 127 deletions(-) delete mode 100644 .flake8 delete mode 100644 contrib/YouCompleteMe/README.md delete mode 100644 contrib/YouCompleteMe/ycm_extra_conf.py delete mode 100644 contrib/vim-addon-local-vimrc/README.md delete mode 100644 contrib/vim-addon-local-vimrc/vimrc diff --git a/.flake8 b/.flake8 deleted file mode 100644 index 2bcd70e390..0000000000 --- a/.flake8 +++ /dev/null @@ -1,2 +0,0 @@ -[flake8] -max-line-length = 88 diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a1b0c6391..81a0a2f667 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -639,6 +639,7 @@ include(InstallHelpers) add_glob_targets( TARGET lintpy COMMAND ${FLAKE8_PRG} + FLAGS --max-line-length 88 GLOB_DIRS contrib scripts src test GLOB_PAT *.py TOUCH_STRATEGY SINGLE diff --git a/contrib/YouCompleteMe/README.md b/contrib/YouCompleteMe/README.md deleted file mode 100644 index 345a9d8d12..0000000000 --- a/contrib/YouCompleteMe/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# YouCompleteMe Integration - -## What is this? - -This provides the code necessary to configure vim's YCM plugin to provide C -semantic support (completion, go-to-definition, etc) for developers working on -the Neovim project. - -## Installation - -### Step 1 - -Install [YouCompleteMe](https://github.com/Valloric/YouCompleteMe). - -### Step 2 - -```bash -cp contrib/YouCompleteMe/ycm_extra_conf.py .ycm_extra_conf.py -echo .ycm_extra_conf.py >> .git/info/exclude -make -``` - -Tip: to improve source code navigation, add something like this to your nvim -configuration: - -```vim -au FileType c,cpp nnoremap :YcmCompleter GoTo -``` - -And use `ctrl+]` when the cursor is positioned in a symbol to quickly jump to a -definition or declaration. diff --git a/contrib/YouCompleteMe/ycm_extra_conf.py b/contrib/YouCompleteMe/ycm_extra_conf.py deleted file mode 100644 index e436609ce2..0000000000 --- a/contrib/YouCompleteMe/ycm_extra_conf.py +++ /dev/null @@ -1,65 +0,0 @@ -# .ycm_extra_conf.py for nvim source code. -import os -import ycm_core - - -def DirectoryOfThisScript(): - return os.path.dirname(os.path.abspath(__file__)) - - -def GetDatabase(): - compilation_database_folder = os.path.join(DirectoryOfThisScript(), - 'build') - if os.path.exists(compilation_database_folder): - return ycm_core.CompilationDatabase(compilation_database_folder) - return None - - -def GetCompilationInfoForFile(filename): - database = GetDatabase() - if not database: - return None - return database.GetCompilationInfoForFile(filename) - - -# It seems YCM does not resolve directories correctly. This function will -# adjust paths in the compiler flags to be absolute -def FixDirectories(args, compiler_working_dir): - def adjust_path(path): - return os.path.abspath(os.path.join(compiler_working_dir, path)) - - adjust_next_arg = False - new_args = [] - for arg in args: - if adjust_next_arg: - arg = adjust_path(arg) - adjust_next_arg = False - else: - for dir_flag in ['-I', '-isystem', '-o', '-c']: - if arg.startswith(dir_flag): - if arg != dir_flag: - # flag and path are concatenated in same arg - path = arg[len(dir_flag):] - new_path = adjust_path(path) - arg = '{0}{1}'.format(dir_flag, new_path) - else: - # path is specified in next argument - adjust_next_arg = True - new_args.append(arg) - return new_args - - -def FlagsForFile(filename): - compilation_info = GetCompilationInfoForFile(filename) - if not compilation_info: - return None - # Add flags not needed for clang-the-binary, - # but needed for libclang-the-library (YCM uses this last one). - flags = FixDirectories((list(compilation_info.compiler_flags_) - if compilation_info.compiler_flags_ - else []), compilation_info.compiler_working_dir_) - extra_flags = ['-Wno-newline-eof'] - return { - 'flags': flags + extra_flags, - 'do_cache': True - } diff --git a/contrib/vim-addon-local-vimrc/README.md b/contrib/vim-addon-local-vimrc/README.md deleted file mode 100644 index 2ff9f0d627..0000000000 --- a/contrib/vim-addon-local-vimrc/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# vim-addon-local-vimrc - -## Installation - -### Step 1 - -Install [vim-addon-local-vimrc](https://github.com/MarcWeber/vim-addon-local-vimrc). -For example with [Vundle](https://github.com/MarcWeber/vim-addon-local-vimrc): -```vim -Bundle 'MarcWeber/vim-addon-local-vimrc' -``` - -### Step 2 - -```bash -cp vimrc ../../.vimrc -echo .vimrc >> ../../.git/info/exclude -``` diff --git a/contrib/vim-addon-local-vimrc/vimrc b/contrib/vim-addon-local-vimrc/vimrc deleted file mode 100644 index cd8a2896ed..0000000000 --- a/contrib/vim-addon-local-vimrc/vimrc +++ /dev/null @@ -1,11 +0,0 @@ -set modelines=0 - -augroup LOCAL_SETUP - autocmd! - autocmd BufRead,BufNewFile *.h set filetype=c - autocmd FileType c setlocal expandtab - autocmd FileType c setlocal shiftwidth=2 - autocmd FileType c setlocal softtabstop=2 - autocmd FileType c setlocal textwidth=80 - autocmd FileType c setlocal comments=:///,:// -augroup end -- cgit From f3c842058ebc0ac475910726581a738d834955f6 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 24 Sep 2022 08:10:49 +0800 Subject: vim-patch:9.0.0559: timer test may get stuck at hit-enter prompt (#20312) Problem: Timer test may get stuck at hit-enter prompt. Solution: Feed some more characters. https://github.com/vim/vim/commit/4ecf16bbf951f10fd32c918c9d8bc004b7f8f7c9 --- src/nvim/testdir/test_timers.vim | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/nvim/testdir/test_timers.vim b/src/nvim/testdir/test_timers.vim index 6adf503f14..b3a22614b0 100644 --- a/src/nvim/testdir/test_timers.vim +++ b/src/nvim/testdir/test_timers.vim @@ -349,11 +349,13 @@ func Test_nocatch_timer_garbage_collect() let a = {'foo', 'bar'} endfunc func FeedChar(id) - call feedkeys('x', 't') + call feedkeys(":\", 't') endfunc call timer_start(300, 'FeedChar') call timer_start(100, 'CauseAnError') - let x = getchar() + let x = getchar() " wait for error in timer + let x = getchar(0) " read any remaining chars + let x = getchar(0) set ut& call test_override('no_wait_return', 1) -- cgit From 14610332b2e851f9464a2d32a0ef3869dcff9834 Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 23 Sep 2022 20:20:56 -0500 Subject: fix(lsp): use correct function name in deprecated message (#20308) fix: use correct function name in deprecated message --- runtime/lua/vim/lsp/buf.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index 2ce565e1d9..8567619228 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -404,7 +404,7 @@ end ---@param end_pos ({number, number}, optional) mark-indexed position. ---Defaults to the end of the last visual selection. function M.range_formatting(options, start_pos, end_pos) - vim.deprecate('vim.lsp.buf.range_formatting', 'vim.lsp.formatexpr or vim.lsp.format', '0.9.0') + vim.deprecate('vim.lsp.buf.range_formatting', 'vim.lsp.formatexpr or vim.lsp.buf.format', '0.9.0') local params = util.make_given_range_params(start_pos, end_pos) params.options = util.make_formatting_params(options).options select_client('textDocument/rangeFormatting', function(client) -- cgit From 24b5449b3d9b39a436bb8fe935116afa15a9473e Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Sat, 24 Sep 2022 10:16:30 +0200 Subject: vim-patch:9.0.0562: HSL playlist files are not recognized (#20307) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: HSL playlist files are not recognized. Solution: Add a pattern to recognize HSL palylist files. (BenoĂ®t Ryder, closes vim/vim#11204) https://github.com/vim/vim/commit/35fdd9a67d73d4750152c419d4193ebb6b6d6eee --- runtime/filetype.vim | 3 +++ runtime/lua/vim/filetype.lua | 1 + src/nvim/testdir/test_filetype.vim | 1 + 3 files changed, 5 insertions(+) diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 4de1720c75..e2efaaa0ce 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -845,6 +845,9 @@ au BufNewFile,BufRead *.hex,*.h32 setf hex " Hjson au BufNewFile,BufRead *.hjson setf hjson +" HLS Playlist +au BufNewFile,BufRead *.m3u8 setf hlsplaylist + " Hollywood au BufRead,BufNewFile *.hws setf hollywood diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 5f58da7a34..c96ead323b 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -473,6 +473,7 @@ local extension = { hex = 'hex', ['h32'] = 'hex', hjson = 'hjson', + m3u8 = 'hlsplaylist', hog = 'hog', hws = 'hollywood', hoon = 'hoon', diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index e3e698aa60..2d71d9b1a6 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -255,6 +255,7 @@ let s:filename_checks = { \ 'hex': ['file.hex', 'file.h32'], \ 'hgcommit': ['hg-editor-file.txt'], \ 'hjson': ['file.hjson'], + \ 'hlsplaylist': ['file.m3u8'], \ 'hog': ['file.hog', 'snort.conf', 'vision.conf'], \ 'hollywood': ['file.hws'], \ 'hoon': ['file.hoon'], -- cgit From caf5738fa9cc12fd448a9c0787a3ebf0c8e696e9 Mon Sep 17 00:00:00 2001 From: shaunsingh Date: Sat, 24 Sep 2022 06:46:21 -0400 Subject: fix(lsp): create missing directory before creating file (#19835) Co-authored-by: Mathias Fussenegger --- runtime/lua/vim/lsp/util.lua | 5 ++++- test/functional/plugin/lsp_spec.lua | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 1909dbd4d1..64512a9739 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -772,8 +772,11 @@ local function create_file(change) -- from spec: Overwrite wins over `ignoreIfExists` local fname = vim.uri_to_fname(change.uri) if not opts.ignoreIfExists or opts.overwrite then + vim.fn.mkdir(vim.fs.dirname(fname), 'p') local file = io.open(fname, 'w') - file:close() + if file then + file:close() + end end vim.fn.bufadd(fname) end diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index e032f3bc2b..bcae9b4084 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -1977,6 +1977,22 @@ describe('LSP', function() exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16') eq(true, exec_lua('return vim.loop.fs_stat(...) ~= nil', tmpfile)) end) + it('Supports file creation in folder that needs to be created with CreateFile payload', function() + local tmpfile = helpers.tmpname() + os.remove(tmpfile) -- Should not exist, only interested in a tmpname + tmpfile = tmpfile .. '/dummy/x/' + local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile) + local edit = { + documentChanges = { + { + kind = 'create', + uri = uri, + }, + } + } + exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16') + eq(true, exec_lua('return vim.loop.fs_stat(...) ~= nil', tmpfile)) + end) it('createFile does not touch file if it exists and ignoreIfExists is set', function() local tmpfile = helpers.tmpname() write_file(tmpfile, 'Dummy content') -- cgit From f8b656c582c6f0d9cb35523ac2d2f3d0edbcd52b Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Sat, 24 Sep 2022 12:59:37 +0200 Subject: vim-patch:9.0.0566: Nim files are not recognized (#20317) Problem: Nim files are not recognized. Solution: Add patterns for Nim files. (Nbiba Bedis, closes vim/vim#11205) https://github.com/vim/vim/commit/9fd1583c839c5e43b0d48ec815a79005a2364776 --- runtime/filetype.vim | 3 +++ runtime/lua/vim/filetype.lua | 3 +++ src/nvim/testdir/test_filetype.vim | 1 + 3 files changed, 7 insertions(+) diff --git a/runtime/filetype.vim b/runtime/filetype.vim index e2efaaa0ce..a78478ec9e 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1279,6 +1279,9 @@ au BufNewFile,BufRead .netrc setf netrc " Nginx au BufNewFile,BufRead *.nginx,nginx*.conf,*nginx.conf,*/etc/nginx/*,*/usr/local/nginx/conf/*,*/nginx/*.conf setf nginx +" Nim file +au BufNewFile,BufRead *.nim,*.nims,*.nimble setf nim + " Ninja file au BufNewFile,BufRead *.ninja setf ninja diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index c96ead323b..d8ede33dfa 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -704,6 +704,9 @@ local extension = { nanorc = 'nanorc', ncf = 'ncf', nginx = 'nginx', + nim = 'nim', + nims = 'nim', + nimble = 'nim', ninja = 'ninja', nix = 'nix', nqc = 'nqc', diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index 2d71d9b1a6..3067fa439c 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -386,6 +386,7 @@ let s:filename_checks = { \ 'neomuttrc': ['Neomuttrc', '.neomuttrc', '.neomuttrc-file', '/.neomutt/neomuttrc', '/.neomutt/neomuttrc-file', 'Neomuttrc', 'Neomuttrc-file', 'any/.neomutt/neomuttrc', 'any/.neomutt/neomuttrc-file', 'neomuttrc', 'neomuttrc-file'], \ 'netrc': ['.netrc'], \ 'nginx': ['file.nginx', 'nginxfile.conf', 'filenginx.conf', 'any/etc/nginx/file', 'any/usr/local/nginx/conf/file', 'any/nginx/file.conf'], + \ 'nim': ['file.nim', 'file.nims', 'file.nimble'], \ 'ninja': ['file.ninja'], \ 'nix': ['file.nix'], \ 'nqc': ['file.nqc'], -- cgit From db056de29ad2d57ee8e1ba841d969560f9bc6714 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 24 Sep 2022 19:20:03 +0800 Subject: vim-patch:9.0.0568: autocmd code is indented more than needed (#20318) Problem: Autocmd code is indented more than needed. Solution: Break out sooner. (Yegappan Lakshmanan, closes vim/vim#11208) Also in user function code. https://github.com/vim/vim/commit/e9dcf13a3007d4f603e007e0526b0005fd026bc5 --- src/nvim/autocmd.c | 61 ++++++++++++++++++++++++++---------------------- src/nvim/eval/userfunc.c | 47 ++++++++++++++++++------------------- 2 files changed, 56 insertions(+), 52 deletions(-) diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index 644f892f3c..1f23e7ab79 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -478,34 +478,37 @@ void augroup_del(char *name, bool stupid_legacy_mode) int i = augroup_find(name); if (i == AUGROUP_ERROR) { // the group doesn't exist semsg(_("E367: No such group: \"%s\""), name); - } else if (i == current_augroup) { + return; + } + if (i == current_augroup) { emsg(_("E936: Cannot delete the current group")); - } else { - if (stupid_legacy_mode) { - FOR_ALL_AUEVENTS(event) { - FOR_ALL_AUPATS_IN_EVENT(event, ap) { - if (ap->group == i && ap->pat != NULL) { - give_warning(_("W19: Deleting augroup that is still in use"), true); - map_put(String, int)(&map_augroup_name_to_id, cstr_as_string(name), AUGROUP_DELETED); - augroup_map_del(ap->group, NULL); - return; - } + return; + } + + if (stupid_legacy_mode) { + FOR_ALL_AUEVENTS(event) { + FOR_ALL_AUPATS_IN_EVENT(event, ap) { + if (ap->group == i && ap->pat != NULL) { + give_warning(_("W19: Deleting augroup that is still in use"), true); + map_put(String, int)(&map_augroup_name_to_id, cstr_as_string(name), AUGROUP_DELETED); + augroup_map_del(ap->group, NULL); + return; } } - } else { - FOR_ALL_AUEVENTS(event) { - FOR_ALL_AUPATS_IN_EVENT(event, ap) { - if (ap->group == i) { - aupat_del(ap); - } + } + } else { + FOR_ALL_AUEVENTS(event) { + FOR_ALL_AUPATS_IN_EVENT(event, ap) { + if (ap->group == i) { + aupat_del(ap); } } } - - // Remove the group because it's not currently in use. - augroup_map_del(i, name); - au_cleanup(); } + + // Remove the group because it's not currently in use. + augroup_map_del(i, name); + au_cleanup(); } /// Find the ID of an autocmd group name. @@ -733,7 +736,6 @@ char *au_event_disable(char *what) } set_string_option_direct("ei", -1, new_ei, OPT_FREE, SID_NONE); xfree(new_ei); - return save_ei; } @@ -837,13 +839,15 @@ void do_autocmd(char *arg_in, int forceit) bool invalid_flags = false; for (size_t i = 0; i < 2; i++) { - if (*cmd != NUL) { - invalid_flags |= arg_autocmd_flag_get(&once, &cmd, "++once", 6); - invalid_flags |= arg_autocmd_flag_get(&nested, &cmd, "++nested", 8); - - // Check the deprecated "nested" flag. - invalid_flags |= arg_autocmd_flag_get(&nested, &cmd, "nested", 6); + if (*cmd == NUL) { + continue; } + + invalid_flags |= arg_autocmd_flag_get(&once, &cmd, "++once", 6); + invalid_flags |= arg_autocmd_flag_get(&nested, &cmd, "++nested", 8); + + // Check the deprecated "nested" flag. + invalid_flags |= arg_autocmd_flag_get(&nested, &cmd, "nested", 6); } if (invalid_flags) { @@ -1275,6 +1279,7 @@ void ex_doautoall(exarg_T *eap) if (buf->b_ml.ml_mfp == NULL || buf == curbuf) { continue; } + // Find a window for this buffer and save some values. aucmd_prepbuf(&aco, buf); set_bufref(&bufref, buf); diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index f28af5a6cc..72d6a1394e 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -515,35 +515,34 @@ static char *fname_trans_sid(const char *const name, char *const fname_buf, char int *const error) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { - char *fname; const int llen = eval_fname_script(name); - if (llen > 0) { - fname_buf[0] = (char)K_SPECIAL; - fname_buf[1] = (char)KS_EXTRA; - fname_buf[2] = KE_SNR; - int i = 3; - if (eval_fname_sid(name)) { // "" or "s:" - if (current_sctx.sc_sid <= 0) { - *error = FCERR_SCRIPT; - } else { - snprintf(fname_buf + i, (size_t)(FLEN_FIXED + 1 - i), "%" PRId64 "_", - (int64_t)current_sctx.sc_sid); - i = (int)strlen(fname_buf); - } - } - if ((size_t)i + strlen(name + llen) < FLEN_FIXED) { - STRCPY(fname_buf + i, name + llen); - fname = fname_buf; + if (llen == 0) { + return (char *)name; // no prefix + } + + fname_buf[0] = (char)K_SPECIAL; + fname_buf[1] = (char)KS_EXTRA; + fname_buf[2] = KE_SNR; + int i = 3; + if (eval_fname_sid(name)) { // "" or "s:" + if (current_sctx.sc_sid <= 0) { + *error = FCERR_SCRIPT; } else { - fname = xmalloc((size_t)i + strlen(name + llen) + 1); - *tofree = fname; - memmove(fname, fname_buf, (size_t)i); - STRCPY(fname + i, name + llen); + snprintf(fname_buf + i, (size_t)(FLEN_FIXED + 1 - i), "%" PRId64 "_", + (int64_t)current_sctx.sc_sid); + i = (int)strlen(fname_buf); } + } + char *fname; + if ((size_t)i + strlen(name + llen) < FLEN_FIXED) { + STRCPY(fname_buf + i, name + llen); + fname = fname_buf; } else { - fname = (char *)name; + fname = xmalloc((size_t)i + strlen(name + llen) + 1); + *tofree = fname; + memmove(fname, fname_buf, (size_t)i); + STRCPY(fname + i, name + llen); } - return fname; } -- cgit From 291a6496327e90056ea68085ad52ab74ca1df752 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 24 Sep 2022 21:07:18 +0800 Subject: fix(mapset): remove existing abbreviation of same lhs (#20320) --- src/nvim/mapping.c | 2 +- test/functional/vimscript/map_functions_spec.lua | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c index a10146c110..6267e1c875 100644 --- a/src/nvim/mapping.c +++ b/src/nvim/mapping.c @@ -2199,7 +2199,7 @@ void f_mapset(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) MapArguments unmap_args = MAP_ARGUMENTS_INIT; set_maparg_lhs_rhs(lhs, strlen(lhs), "", 0, LUA_NOREF, 0, &unmap_args); unmap_args.buffer = buffer; - buf_do_map(MAPTYPE_UNMAP, &unmap_args, mode, false, curbuf); + buf_do_map(MAPTYPE_UNMAP, &unmap_args, mode, is_abbr, curbuf); xfree(unmap_args.rhs); xfree(unmap_args.orig_rhs); diff --git a/test/functional/vimscript/map_functions_spec.lua b/test/functional/vimscript/map_functions_spec.lua index 96b86d053e..ed1863754a 100644 --- a/test/functional/vimscript/map_functions_spec.lua +++ b/test/functional/vimscript/map_functions_spec.lua @@ -12,6 +12,7 @@ local meths = helpers.meths local nvim = helpers.nvim local source = helpers.source local command = helpers.command +local exec_capture = helpers.exec_capture local pcall_err = helpers.pcall_err describe('maparg()', function() @@ -178,8 +179,9 @@ describe('mapset()', function() eq('\nn lhs rhs\n map description', helpers.exec_capture("nmap lhs")) local mapargs = funcs.maparg('lhs', 'n', false, true) - meths.del_keymap('n', 'lhs') - eq('\nNo mapping found', helpers.exec_capture("nmap lhs")) + meths.set_keymap('n', 'lhs', 'rhs', {desc = 'MAP DESCRIPTION'}) + eq('\nn lhs rhs\n MAP DESCRIPTION', + helpers.exec_capture("nmap lhs")) funcs.mapset('n', false, mapargs) eq('\nn lhs rhs\n map description', helpers.exec_capture("nmap lhs")) @@ -198,6 +200,22 @@ describe('mapset()', function() expect('<<') end) + it('replaces an abbreviation of the same lhs #20320', function() + command('inoreabbr foo bar') + eq('\ni foo * bar', exec_capture('iabbr foo')) + feed('ifoo ') + expect('bar ') + local mapargs = funcs.maparg('foo', 'i', true, true) + command('inoreabbr foo BAR') + eq('\ni foo * BAR', exec_capture('iabbr foo')) + feed('foo ') + expect('bar BAR ') + funcs.mapset('i', true, mapargs) + eq('\ni foo * bar', exec_capture('iabbr foo')) + feed('foo') + expect('bar BAR bar') + end) + it('can restore Lua callback from the dict returned by maparg()', function() eq(0, exec_lua([[ GlobalCount = 0 -- cgit From 57b731818d3d54dacdace081f6db4a8ce813173d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 24 Sep 2022 21:13:32 +0800 Subject: vim-patch:9.0.0567: 'completeopt' "longest" is not used for complete() Problem: 'completeopt' "longest" is not used for complete(). Solution: Also use "longest" for complete(). (Bjorn Linse, closes vim/vim#11206) https://github.com/vim/vim/commit/87af60c91503e37c9144f8e48022b12994ce2c85 --- src/nvim/insexpand.c | 14 +++++++++++--- src/nvim/testdir/test_ins_complete.vim | 20 ++++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c index a4b0d68ffe..1426f28453 100644 --- a/src/nvim/insexpand.c +++ b/src/nvim/insexpand.c @@ -199,6 +199,8 @@ static bool compl_no_insert = false; ///< false: select & insert ///< true: noinsert static bool compl_no_select = false; ///< false: select & insert ///< true: noselect +static bool compl_longest = false; ///< false: insert full match + ///< true: insert longest prefix /// Selected one of the matches. When false the match was edited or using the /// longest common string. @@ -1006,12 +1008,16 @@ void completeopt_was_set(void) { compl_no_insert = false; compl_no_select = false; + compl_longest = false; if (strstr(p_cot, "noselect") != NULL) { compl_no_select = true; } if (strstr(p_cot, "noinsert") != NULL) { compl_no_insert = true; } + if (strstr(p_cot, "longest") != NULL) { + compl_longest = true; + } } /// "compl_match_array" points the currently displayed list of entries in the @@ -2103,7 +2109,7 @@ bool ins_compl_prep(int c) // Set "compl_get_longest" when finding the first matches. if (ctrl_x_mode_not_defined_yet() || (ctrl_x_mode_normal() && !compl_started)) { - compl_get_longest = (strstr(p_cot, "longest") != NULL); + compl_get_longest = compl_longest; compl_used_match = true; } @@ -2420,6 +2426,7 @@ static void set_completion(colnr_T startcol, list_T *list) } ins_compl_clear(); ins_compl_free(); + compl_get_longest = compl_longest; compl_direction = FORWARD; if (startcol > curwin->w_cursor.col) { @@ -2449,9 +2456,10 @@ static void set_completion(colnr_T startcol, list_T *list) int save_w_leftcol = curwin->w_leftcol; compl_curr_match = compl_first_match; - if (compl_no_insert || compl_no_select) { + bool no_select = compl_no_select || compl_longest; + if (compl_no_insert || no_select) { ins_complete(K_DOWN, false); - if (compl_no_select) { + if (no_select) { ins_complete(K_UP, false); } } else { diff --git a/src/nvim/testdir/test_ins_complete.vim b/src/nvim/testdir/test_ins_complete.vim index 3e563f29f9..0810bd4adc 100644 --- a/src/nvim/testdir/test_ins_complete.vim +++ b/src/nvim/testdir/test_ins_complete.vim @@ -702,6 +702,26 @@ func Test_recursive_complete_func() bw! endfunc +" Test for using complete() with completeopt+=longest +func Test_complete_with_longest() + inoremap call complete(1, ["iaax", "iaay", "iaaz"]) + new + + " default: insert first match + set completeopt& + call setline(1, ['i']) + exe "normal Aa\\" + call assert_equal('iaax', getline(1)) + + " with longest: insert longest prefix + set completeopt+=longest + call setline(1, ['i']) + exe "normal Aa\\" + call assert_equal('iaa', getline(1)) + set completeopt& +endfunc + + " Test for completing words following a completed word in a line func Test_complete_wrapscan() " complete words from another buffer -- cgit From 0c77dba9a46765c7a769090ae21433efea5bda00 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 24 Sep 2022 21:16:50 +0800 Subject: vim-patch:9.0.0572: insert complete tests leave a mapping behind Problem: Insert complete tests leave a mapping behind. Solution: Use a buffer-local mapping. (closes vim/vim#11211) https://github.com/vim/vim/commit/75f4bafabdcc6bce5cf3e09fee29c634bf102c17 --- src/nvim/testdir/test_ins_complete.vim | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/nvim/testdir/test_ins_complete.vim b/src/nvim/testdir/test_ins_complete.vim index 0810bd4adc..f706322a85 100644 --- a/src/nvim/testdir/test_ins_complete.vim +++ b/src/nvim/testdir/test_ins_complete.vim @@ -704,8 +704,8 @@ endfunc " Test for using complete() with completeopt+=longest func Test_complete_with_longest() - inoremap call complete(1, ["iaax", "iaay", "iaaz"]) new + inoremap call complete(1, ["iaax", "iaay", "iaaz"]) " default: insert first match set completeopt& @@ -719,6 +719,7 @@ func Test_complete_with_longest() exe "normal Aa\\" call assert_equal('iaa', getline(1)) set completeopt& + bwipe! endfunc @@ -1276,7 +1277,7 @@ endfunc " A mapping is not used for the key after CTRL-X. func Test_no_mapping_for_ctrl_x_key() new - inoremap let was_mapped = 'yes' + inoremap let was_mapped = 'yes' setlocal dictionary=README.txt call feedkeys("aexam\\ ", 'xt') call assert_equal('example ', getline(1)) -- cgit From 8317b9199edc6936fec829f4908f9c74dc874ce4 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 24 Sep 2022 22:28:41 +0800 Subject: fix(input): use click number of last click for mouse drag (#20300) --- src/nvim/os/input.c | 48 ++++++++++---------- test/functional/ui/mouse_spec.lua | 96 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 113 insertions(+), 31 deletions(-) diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c index fc7390a303..cb0dba8cac 100644 --- a/src/nvim/os/input.c +++ b/src/nvim/os/input.c @@ -306,37 +306,35 @@ static uint8_t check_multiclick(int code, int grid, int row, int col) static int orig_mouse_row = 0; static uint64_t orig_mouse_time = 0; // time of previous mouse click - if (code == KE_LEFTRELEASE - || code == KE_RIGHTRELEASE - || code == KE_MIDDLERELEASE - || code == KE_MOUSEDOWN - || code == KE_MOUSEUP - || code == KE_MOUSELEFT - || code == KE_MOUSERIGHT - || code == KE_MOUSEMOVE) { + if ((code >= KE_MOUSEDOWN && code <= KE_MOUSERIGHT) || code == KE_MOUSEMOVE) { return 0; } - uint64_t mouse_time = os_hrtime(); // time of current mouse click (ns) - - // compute the time elapsed since the previous mouse click and - // convert p_mouse from ms to ns - uint64_t timediff = mouse_time - orig_mouse_time; - uint64_t mouset = (uint64_t)p_mouset * 1000000; - if (code == orig_mouse_code - && timediff < mouset - && orig_num_clicks != 4 - && orig_mouse_grid == grid - && orig_mouse_col == col - && orig_mouse_row == row) { - orig_num_clicks++; - } else { - orig_num_clicks = 1; + + // For click events the number of clicks is updated. + if (code == KE_LEFTMOUSE || code == KE_RIGHTMOUSE || code == KE_MIDDLEMOUSE) { + uint64_t mouse_time = os_hrtime(); // time of current mouse click (ns) + // compute the time elapsed since the previous mouse click and + // convert p_mouse from ms to ns + uint64_t timediff = mouse_time - orig_mouse_time; + uint64_t mouset = (uint64_t)p_mouset * 1000000; + if (code == orig_mouse_code + && timediff < mouset + && orig_num_clicks != 4 + && orig_mouse_grid == grid + && orig_mouse_col == col + && orig_mouse_row == row) { + orig_num_clicks++; + } else { + orig_num_clicks = 1; + } + orig_mouse_code = code; + orig_mouse_time = mouse_time; } - orig_mouse_code = code; + // For drag and release events the number of clicks is kept. + orig_mouse_grid = grid; orig_mouse_col = col; orig_mouse_row = row; - orig_mouse_time = mouse_time; uint8_t modifiers = 0; if (orig_num_clicks == 2) { diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua index 8c5475ecce..cb8dfdb8e1 100644 --- a/test/functional/ui/mouse_spec.lua +++ b/test/functional/ui/mouse_spec.lua @@ -648,8 +648,10 @@ describe('ui/mouse/input', function() ]]} end) - it('two clicks will select the word and enter VISUAL', function() - feed('<2,2><2,2>') + it('two clicks will enter VISUAL and dragging selects words', function() + feed('<2,2>') + feed('<2,2>') + feed('<2,2>') screen:expect([[ testing | mouse | @@ -657,10 +659,38 @@ describe('ui/mouse/input', function() {0:~ }| {2:-- VISUAL --} | ]]) + feed('<0,1>') + screen:expect([[ + testing | + ^m{1:ouse} | + {1:support} and selection | + {0:~ }| + {2:-- VISUAL --} | + ]]) + feed('<4,0>') + screen:expect([[ + ^t{1:esting} | + {1:mouse} | + {1:support} and selection | + {0:~ }| + {2:-- VISUAL --} | + ]]) + feed('<14,2>') + screen:expect([[ + testing | + mouse | + {1:support and selectio}^n | + {0:~ }| + {2:-- VISUAL --} | + ]]) end) - it('three clicks will select the line and enter VISUAL LINE', function() - feed('<2,2><2,2><2,2>') + it('three clicks will enter VISUAL LINE and dragging selects lines', function() + feed('<2,2>') + feed('<2,2>') + feed('<2,2>') + feed('<2,2>') + feed('<2,2>') screen:expect([[ testing | mouse | @@ -668,10 +698,40 @@ describe('ui/mouse/input', function() {0:~ }| {2:-- VISUAL LINE --} | ]]) + feed('<0,1>') + screen:expect([[ + testing | + ^m{1:ouse} | + {1:support and selection} | + {0:~ }| + {2:-- VISUAL LINE --} | + ]]) + feed('<4,0>') + screen:expect([[ + {1:test}^i{1:ng} | + {1:mouse} | + {1:support and selection} | + {0:~ }| + {2:-- VISUAL LINE --} | + ]]) + feed('<14,2>') + screen:expect([[ + testing | + mouse | + {1:support and se}^l{1:ection} | + {0:~ }| + {2:-- VISUAL LINE --} | + ]]) end) - it('four clicks will enter VISUAL BLOCK', function() - feed('<2,2><2,2><2,2><2,2>') + it('four clicks will enter VISUAL BLOCK and dragging selects blockwise', function() + feed('<2,2>') + feed('<2,2>') + feed('<2,2>') + feed('<2,2>') + feed('<2,2>') + feed('<2,2>') + feed('<2,2>') screen:expect([[ testing | mouse | @@ -679,6 +739,30 @@ describe('ui/mouse/input', function() {0:~ }| {2:-- VISUAL BLOCK --} | ]]) + feed('<0,1>') + screen:expect([[ + testing | + ^m{1:ou}se | + {1:sup}port and selection | + {0:~ }| + {2:-- VISUAL BLOCK --} | + ]]) + feed('<4,0>') + screen:expect([[ + te{1:st}^ing | + mo{1:use} | + su{1:ppo}rt and selection | + {0:~ }| + {2:-- VISUAL BLOCK --} | + ]]) + feed('<14,2>') + screen:expect([[ + testing | + mouse | + su{1:pport and se}^lection | + {0:~ }| + {2:-- VISUAL BLOCK --} | + ]]) end) it('right click extends visual selection to the clicked location', function() -- cgit From b0fcdf9f099b17198630025a700e87f05b4e3a84 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sun, 25 Sep 2022 00:07:59 +0200 Subject: vim-patch:9.0.0576: unused loop variables (#20326) Problem: Unused loop variables. Solution: Use a while loop instead. (closes vim/vim#11214) https://github.com/vim/vim/commit/b2209f213e2931cf3313b24868a9165bbb717cc4 --- src/nvim/digraph.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/nvim/digraph.c b/src/nvim/digraph.c index c0e7a6250e..1267d49ad1 100644 --- a/src/nvim/digraph.c +++ b/src/nvim/digraph.c @@ -1578,7 +1578,7 @@ static int getexactdigraph(int char1, int char2, bool meta_char) if (retval == 0) { dp = digraphdefault; - for (int i = 0; dp->char1 != 0; i++) { + while (dp->char1 != 0) { if (((int)dp->char1 == char1) && ((int)dp->char2 == char2)) { retval = dp->result; break; @@ -1707,7 +1707,7 @@ void listdigraphs(bool use_headers) const digr_T *dp = digraphdefault; - for (int i = 0; dp->char1 != NUL && !got_int; i++) { + while (dp->char1 != NUL && !got_int) { digr_T tmp; // May need to convert the result to 'encoding'. @@ -1759,7 +1759,7 @@ void digraph_getlist_common(bool list_all, typval_T *rettv) if (list_all) { dp = digraphdefault; - for (int i = 0; dp->char1 != NUL && !got_int; i++) { + while (dp->char1 != NUL && !got_int) { digr_T tmp; tmp.char1 = dp->char1; tmp.char2 = dp->char2; -- cgit From c7cf1232a71b0db700b818e2ae8e8ebaf40133f2 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 25 Sep 2022 09:49:21 +0800 Subject: vim-patch:8.2.4467: running filetype test leaves file behind (#20335) Problem: Running filetype test leaves file behind. Solution: Delete the file. https://github.com/vim/vim/commit/0e71b7d4ce3e1210150ce772e1af6956057a71ed vim-patch:8.2.4466: MS-Windows: illegal memory access in installer Problem: MS-Windows: illegal memory access in installer when using "create-directories" as the final argument. Solution: Check the argument count. (Cam Sinclair, closes vim/vim#9844) https://github.com/vim/vim/commit/5c6edf41f9beffea21ce45d658822cc4c0745fdb --- src/nvim/testdir/test_filetype.vim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index 3067fa439c..516a764f45 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -932,7 +932,9 @@ func Test_d_file() call assert_equal('d', &filetype) bwipe! + " clean up filetype off + call delete('Xfile.d') endfunc func Test_dat_file() -- cgit From 2a3cb0893b03aeff4d8c0b2116cbddda53bba5a2 Mon Sep 17 00:00:00 2001 From: Louis Sven Goulet <31444858+lorlouis@users.noreply.github.com> Date: Sat, 24 Sep 2022 21:57:10 -0400 Subject: feat: ":write!" skips "file changed" warning #18665 Problem: Cannot opt-out of "WARNING: The file has been changed since reading it!!!", even with ":write!". Solution: Change ":write!" to skip the warning. closes #7270 --- runtime/doc/editing.txt | 6 ++-- runtime/doc/vim_diff.txt | 1 + src/nvim/fileio.c | 4 +-- test/functional/core/fileio_spec.lua | 58 ++++++++++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 5 deletions(-) diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt index dcb0bf8a2e..21a30ca429 100644 --- a/runtime/doc/editing.txt +++ b/runtime/doc/editing.txt @@ -941,7 +941,7 @@ WRITING WITH MULTIPLE BUFFERS *buffer-write* Vim will warn you if you try to overwrite a file that has been changed -elsewhere. See |timestamp|. +elsewhere (unless "!" was used). See |timestamp|. *backup* *E207* *E506* *E507* *E508* *E509* *E510* If you write to an existing file (but do not append) while the 'backup', @@ -1481,8 +1481,8 @@ doing something there and closing it should be OK (if there are no side effects from other autocommands). Closing unrelated windows and buffers will get you into trouble. -Before writing a file the timestamp is checked. If it has changed, Vim will -ask if you really want to overwrite the file: +Before writing a file, the timestamp is checked (unless "!" was used). +If it has changed, Vim will ask if you really want to overwrite the file: WARNING: The file has been changed since reading it!!! Do you really want to write to it (y/n)? diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index b013e00fe8..e254e5edd0 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -372,6 +372,7 @@ Lua interface (|lua.txt|): Commands: |:doautocmd| does not warn about "No matching autocommands". |:wincmd| accepts a count. + `:write!` does not show a prompt if the file was updated externally. Command line completion: The meanings of arrow keys do not change depending on 'wildoptions'. diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index d391e19964..76317298dc 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -2536,8 +2536,8 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en goto fail; } - // Check if the timestamp hasn't changed since reading the file. - if (overwriting) { + // If 'forceit' is false, check if the timestamp hasn't changed since reading the file. + if (overwriting && !forceit) { retval = check_mtime(buf, &file_info_old); if (retval == FAIL) { goto fail; diff --git a/test/functional/core/fileio_spec.lua b/test/functional/core/fileio_spec.lua index e71131dcf8..a589d088a4 100644 --- a/test/functional/core/fileio_spec.lua +++ b/test/functional/core/fileio_spec.lua @@ -23,6 +23,8 @@ local iswin = helpers.iswin local assert_alive = helpers.assert_alive local expect_exit = helpers.expect_exit local write_file = helpers.write_file +local Screen = require('test.functional.ui.screen') +local feed_command = helpers.feed_command local uname = helpers.uname describe('fileio', function() @@ -36,6 +38,7 @@ describe('fileio', function() os.remove('Xtest_startup_file2') os.remove('Xtest_теŃŃ‚.md') os.remove('Xtest-u8-int-max') + os.remove('Xtest-overwrite-forced') rmdir('Xtest_startup_swapdir') rmdir('Xtest_backupdir') end) @@ -151,6 +154,61 @@ describe('fileio', function() command('edit ++enc=utf32 Xtest-u8-int-max') assert_alive() end) + + it(':w! does not show "file has been changed" warning', function() + clear() + write_file("Xtest-overwrite-forced", 'foobar') + command('set nofixendofline') + local screen = Screen.new(40,4) + screen:set_default_attr_ids({ + [1] = {bold = true, foreground = Screen.colors.Blue1}, + [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red}, + [3] = {bold = true, foreground = Screen.colors.SeaGreen4} + }) + screen:attach() + command("set display-=msgsep shortmess-=F") + + command("e Xtest-overwrite-forced") + screen:expect([[ + ^foobar | + {1:~ }| + {1:~ }| + "Xtest-overwrite-forced" [noeol] 1L, 6B | + ]]) + + -- Get current unix time. + local cur_unix_time = os.time(os.date("!*t")) + local future_time = cur_unix_time + 999999 + -- Set the file's access/update time to be + -- greater than the time at which it was created. + local uv = require("luv") + uv.fs_utime('Xtest-overwrite-forced', future_time, future_time) + -- use async feed_command because nvim basically hangs on the prompt + feed_command("w") + screen:expect([[ + {2:WARNING: The file has been changed since}| + {2: reading it!!!} | + {3:Do you really want to write to it (y/n)^?}| + | + ]]) + + feed("n") + feed("") + screen:expect([[ + ^foobar | + {1:~ }| + {1:~ }| + | + ]]) + -- Use a screen test because the warning does not set v:errmsg. + command("w!") + screen:expect([[ + ^foobar | + {1:~ }| + {1:~ }| + Date: Sun, 25 Sep 2022 00:45:15 +0200 Subject: refactor(treesitter): rename x_position => x_pos "pos" has a long precedent as "position" in vim, and there is no reason to use a verbose name here. --- runtime/doc/develop.txt | 6 ++++++ runtime/doc/treesitter.txt | 6 ++---- runtime/lua/vim/treesitter.lua | 9 ++++----- test/functional/treesitter/highlight_spec.lua | 2 +- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/runtime/doc/develop.txt b/runtime/doc/develop.txt index b31ac47bda..4f17e7d34a 100644 --- a/runtime/doc/develop.txt +++ b/runtime/doc/develop.txt @@ -251,6 +251,12 @@ Use existing common {action} names if possible: list Get all things set Set a thing (or group of things) +Use existing common {thing} names if possible: + buf Buffer + pos Position + tab Tabpage + win Window + Use consistent names for {thing} in all API functions. E.g. a buffer is called "buf" everywhere, not "buffer" in some places and "buf" in others. diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index eda1a5e496..3102c6da9a 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -434,8 +434,7 @@ get_captures_at_cursor({winnr}) *get_captures_at_cursor()* Return: ~ string[] List of capture names - *get_captures_at_position()* -get_captures_at_position({bufnr}, {row}, {col}) +get_captures_at_pos({bufnr}, {row}, {col}) *get_captures_at_pos()* Returns a list of highlight captures at the given position Each capture is represented by a table containing the capture name as a @@ -460,8 +459,7 @@ get_node_at_cursor({winnr}) *get_node_at_cursor()* Return: ~ (string) Name of node under the cursor - *get_node_at_position()* -get_node_at_position({bufnr}, {row}, {col}, {opts}) +get_node_at_pos({bufnr}, {row}, {col}, {opts}) *get_node_at_pos()* Returns the smallest named node at the given position Parameters: ~ diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 04e12cbe0b..6cd00516bf 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -202,7 +202,7 @@ end ---@param col number Position column --- ---@return table[] List of captures `{ capture = "capture name", metadata = { ... } }` -function M.get_captures_at_position(bufnr, row, col) +function M.get_captures_at_pos(bufnr, row, col) if bufnr == 0 then bufnr = a.nvim_get_current_buf() end @@ -258,7 +258,7 @@ function M.get_captures_at_cursor(winnr) local bufnr = a.nvim_win_get_buf(winnr) local cursor = a.nvim_win_get_cursor(winnr) - local data = M.get_captures_at_position(bufnr, cursor[1] - 1, cursor[2]) + local data = M.get_captures_at_pos(bufnr, cursor[1] - 1, cursor[2]) local captures = {} @@ -278,7 +278,7 @@ end --- - ignore_injections boolean Ignore injected languages (default true) --- ---@return userdata |tsnode| under the cursor -function M.get_node_at_position(bufnr, row, col, opts) +function M.get_node_at_pos(bufnr, row, col, opts) if bufnr == 0 then bufnr = a.nvim_get_current_buf() end @@ -302,8 +302,7 @@ function M.get_node_at_cursor(winnr) local bufnr = a.nvim_win_get_buf(winnr) local cursor = a.nvim_win_get_cursor(winnr) - return M.get_node_at_position(bufnr, cursor[1] - 1, cursor[2], { ignore_injections = false }) - :type() + return M.get_node_at_pos(bufnr, cursor[1] - 1, cursor[2], { ignore_injections = false }):type() end --- Starts treesitter highlighting for a buffer diff --git a/test/functional/treesitter/highlight_spec.lua b/test/functional/treesitter/highlight_spec.lua index 1684337c3c..ae3f42ff0a 100644 --- a/test/functional/treesitter/highlight_spec.lua +++ b/test/functional/treesitter/highlight_spec.lua @@ -607,7 +607,7 @@ describe('treesitter highlighting', function() eq({ {capture='Error', metadata = { priority='101' }}; {capture='type', metadata = { } }; - }, exec_lua [[ return vim.treesitter.get_captures_at_position(0, 0, 2) ]]) + }, exec_lua [[ return vim.treesitter.get_captures_at_pos(0, 0, 2) ]]) end) it("allows to use captures with dots (don't use fallback when specialization of foo exists)", function() -- cgit From 2a5692c64628ee0af3ef4931a774a2eb0a7e046f Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Sun, 25 Sep 2022 13:59:11 +0200 Subject: vim-patch:9.0.0583: only recognizing .m3u8 files is inconsistent (#20342) Problem: Only recognizing .m3u8 files is inconsistent. Solution: Also matc .m3u files. (issue vim/vim#11204) https://github.com/vim/vim/commit/b9725bc7f6427654eb4e35874034b0ec1b6b96b3 --- runtime/filetype.vim | 4 ++-- runtime/lua/vim/filetype.lua | 1 + src/nvim/testdir/test_filetype.vim | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/runtime/filetype.vim b/runtime/filetype.vim index a78478ec9e..11536adf69 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -845,8 +845,8 @@ au BufNewFile,BufRead *.hex,*.h32 setf hex " Hjson au BufNewFile,BufRead *.hjson setf hjson -" HLS Playlist -au BufNewFile,BufRead *.m3u8 setf hlsplaylist +" HLS Playlist (or another form of playlist) +au BufNewFile,BufRead *.m3u,*.m3u8 setf hlsplaylist " Hollywood au BufRead,BufNewFile *.hws setf hollywood diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index d8ede33dfa..bd317baae9 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -473,6 +473,7 @@ local extension = { hex = 'hex', ['h32'] = 'hex', hjson = 'hjson', + m3u = 'hlsplaylist', m3u8 = 'hlsplaylist', hog = 'hog', hws = 'hollywood', diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index 516a764f45..4755d39cd3 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -255,7 +255,7 @@ let s:filename_checks = { \ 'hex': ['file.hex', 'file.h32'], \ 'hgcommit': ['hg-editor-file.txt'], \ 'hjson': ['file.hjson'], - \ 'hlsplaylist': ['file.m3u8'], + \ 'hlsplaylist': ['file.m3u', 'file.m3u8'], \ 'hog': ['file.hog', 'snort.conf', 'vision.conf'], \ 'hollywood': ['file.hws'], \ 'hoon': ['file.hoon'], -- cgit From 1b60b5ec94001f18b70dbebf6c232c33209f11b5 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 25 Sep 2022 13:45:41 +0200 Subject: fix(gen_vimdoc.py): handle missing luajit --- scripts/gen_vimdoc.py | 14 ++++++++++---- scripts/lua2dox_filter | 7 ++++++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index 766c420c7d..306857ca6c 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -295,14 +295,16 @@ annotation_map = { # or if `cond()` is callable and returns True. def debug_this(o, cond=True): name = '' + if cond is False: + return if not isinstance(o, str): try: name = o.nodeName o = o.toprettyxml(indent=' ', newl='\n') except Exception: pass - if ((callable(cond) and cond()) - or (not callable(cond) and cond) + if (cond is True + or (callable(cond) and cond()) or (not callable(cond) and cond in o)): raise RuntimeError('xxx: {}\n{}'.format(name, o)) @@ -887,7 +889,7 @@ def extract_from_xml(filename, target, width, fmt_vimhelp): def fmt_doxygen_xml_as_vimhelp(filename, target): """Entrypoint for generating Vim :help from from Doxygen XML. - Returns 3 items: + Returns 2 items: 1. Vim help text for functions found in `filename`. 2. Vim help text for deprecated functions. """ @@ -1094,7 +1096,11 @@ def main(config, args): fn_map_full.update(fn_map) if len(sections) == 0: - fail(f'no sections for target: {target}') + if target == 'lua': + fail(f'no sections for target: {target} (this usually means' + + ' "luajit" was not found by scripts/lua2dox_filter)') + else: + fail(f'no sections for target: {target}') if len(sections) > len(CONFIG[target]['section_order']): raise RuntimeError( 'found new modules "{}"; update the "section_order" map'.format( diff --git a/scripts/lua2dox_filter b/scripts/lua2dox_filter index 22484a807f..0b9f59b6ac 100755 --- a/scripts/lua2dox_filter +++ b/scripts/lua2dox_filter @@ -36,6 +36,10 @@ test_executable(){ ##! \brief sets the lua interpreter set_lua(){ + if test -z "${EXE}"; then + test_executable '.deps/usr/bin/luajit' + fi + if test -z "${EXE}"; then test_executable 'luajit' fi @@ -73,7 +77,8 @@ do_readlink(){ set_lua if test -z "${EXE}" then - echo "no lua interpreter available" + echo "no lua interpreter found" + exit 1 else BASENAME=`basename "$0"` do_readlink "$0" -- cgit From 91e912f8d40284c74d4a997c8c95961eebb35d91 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sun, 25 Sep 2022 15:26:37 +0200 Subject: refactor: move klib out of src/nvim/ #20341 It's confusing to mix vendored dependencies with neovim source code. A clean separation is simpler to keep track of and simpler to document. --- src/klib/kbtree.h | 477 ++++++++++++++++++++++++ src/klib/khash.h | 730 +++++++++++++++++++++++++++++++++++++ src/klib/klist.h | 144 ++++++++ src/klib/kvec.h | 236 ++++++++++++ src/nvim/CMakeLists.txt | 4 +- src/nvim/api/private/defs.h | 2 +- src/nvim/api/private/helpers.c | 2 +- src/nvim/api/private/helpers.h | 2 +- src/nvim/buffer_defs.h | 2 +- src/nvim/context.h | 2 +- src/nvim/decoration_provider.c | 2 +- src/nvim/eval/decode.c | 2 +- src/nvim/eval/encode.c | 2 +- src/nvim/eval/typval_encode.c.h | 2 +- src/nvim/eval/typval_encode.h | 2 +- src/nvim/event/loop.h | 2 +- src/nvim/ex_getln.c | 2 +- src/nvim/extmark.c | 2 +- src/nvim/extmark_defs.h | 2 +- src/nvim/lib/kbtree.h | 477 ------------------------ src/nvim/lib/khash.h | 730 ------------------------------------- src/nvim/lib/klist.h | 144 -------- src/nvim/lib/kvec.h | 236 ------------ src/nvim/lua/converter.c | 2 +- src/nvim/lua/treesitter.c | 2 +- src/nvim/map.c | 2 +- src/nvim/map_defs.h | 2 +- src/nvim/marktree.c | 2 +- src/nvim/message.h | 2 +- src/nvim/msgpack_rpc/channel.c | 2 +- src/nvim/msgpack_rpc/helpers.c | 2 +- src/nvim/ops.c | 2 +- src/nvim/os/pty_conpty_win.h | 2 +- src/nvim/os/pty_process_unix.c | 2 +- src/nvim/os/shell.c | 2 +- src/nvim/shada.c | 4 +- src/nvim/state.c | 2 +- src/nvim/strings.h | 2 +- src/nvim/tui/tui.c | 2 +- src/nvim/ui_compositor.c | 2 +- src/nvim/undo.c | 2 +- src/nvim/viml/parser/expressions.c | 2 +- src/nvim/viml/parser/parser.h | 2 +- 43 files changed, 1624 insertions(+), 1624 deletions(-) create mode 100644 src/klib/kbtree.h create mode 100644 src/klib/khash.h create mode 100644 src/klib/klist.h create mode 100644 src/klib/kvec.h delete mode 100644 src/nvim/lib/kbtree.h delete mode 100644 src/nvim/lib/khash.h delete mode 100644 src/nvim/lib/klist.h delete mode 100644 src/nvim/lib/kvec.h diff --git a/src/klib/kbtree.h b/src/klib/kbtree.h new file mode 100644 index 0000000000..99f79952d7 --- /dev/null +++ b/src/klib/kbtree.h @@ -0,0 +1,477 @@ +/*- + * Copyright 1997-1999, 2001, John-Mark Gurney. + * 2008-2009, Attractive Chaos + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +// Gotchas +// ------- +// +// if you delete from a kbtree while iterating over it you must use +// kb_del_itr and not kb_del otherwise the iterator might point to freed memory. + +#ifndef NVIM_LIB_KBTREE_H +#define NVIM_LIB_KBTREE_H + +#include +#include +#include +#include + +#include "nvim/memory.h" + +#define KB_MAX_DEPTH 64 + +#define __KB_KEY(type, x) (x->key) +#define __KB_PTR(btr, x) (x->ptr) + +#define __KB_TREE_T(name, key_t, T) \ + typedef struct kbnode_##name##_s kbnode_##name##_t; \ + struct kbnode_##name##_s { \ + int32_t n; \ + bool is_internal; \ + key_t key[2*T - 1]; \ + kbnode_##name##_t *ptr[]; \ + }; \ + typedef struct { \ + kbnode_##name##_t *root; \ + int n_keys, n_nodes; \ + } kbtree_##name##_t; \ + typedef struct { \ + kbnode_##name##_t *x; \ + int i; \ + } kbpos_##name##_t; \ + typedef struct { \ + kbpos_##name##_t stack[KB_MAX_DEPTH], *p; \ + } kbitr_##name##_t; \ + + +#define __kb_destroy(kbnode_t, b) do { \ + int i; \ + unsigned int max = 8; \ + kbnode_t *x, **top, **stack = 0; \ + if (b->root) { \ + top = stack = (kbnode_t **)xcalloc(max, sizeof(kbnode_t *)); \ + *top++ = (b)->root; \ + while (top != stack) { \ + x = *--top; \ + if (x->is_internal == 0) { XFREE_CLEAR(x); continue; } \ + for (i = 0; i <= x->n; ++i) \ + if (__KB_PTR(b, x)[i]) { \ + if (top - stack == (int)max) { \ + max <<= 1; \ + stack = (kbnode_t **)xrealloc(stack, max * sizeof(kbnode_t *)); \ + top = stack + (max>>1); \ + } \ + *top++ = __KB_PTR(b, x)[i]; \ + } \ + XFREE_CLEAR(x); \ + } \ + } \ + XFREE_CLEAR(stack); \ +} while (0) + +#define __KB_GET_AUX1(name, key_t, kbnode_t, __cmp) \ + static inline int __kb_getp_aux_##name(const kbnode_t * __restrict x, key_t * __restrict k, \ + int *r) \ + { \ + int tr, *rr, begin = 0, end = x->n; \ + if (x->n == 0) return -1; \ + rr = r? r : &tr; \ + while (begin < end) { \ + int mid = (begin + end) >> 1; \ + if (__cmp(__KB_KEY(key_t, x)[mid], *k) < 0) begin = mid + 1; \ + else end = mid; \ + } \ + if (begin == x->n) { *rr = 1; return x->n - 1; } \ + if ((*rr = __cmp(*k, __KB_KEY(key_t, x)[begin])) < 0) --begin; \ + return begin; \ + } + +#define __KB_GET(name, key_t, kbnode_t) \ + static key_t *kb_getp_##name(kbtree_##name##_t *b, key_t * __restrict k) \ + { \ + if (!b->root) { \ + return 0; \ + } \ + int i, r = 0; \ + kbnode_t *x = b->root; \ + while (x) { \ + i = __kb_getp_aux_##name(x, k, &r); \ + if (i >= 0 && r == 0) return &__KB_KEY(key_t, x)[i]; \ + if (x->is_internal == 0) return 0; \ + x = __KB_PTR(b, x)[i + 1]; \ + } \ + return 0; \ + } \ + static inline key_t *kb_get_##name(kbtree_##name##_t *b, key_t k) \ + { \ + return kb_getp_##name(b, &k); \ + } + +#define __KB_INTERVAL(name, key_t, kbnode_t) \ + static inline void kb_intervalp_##name(kbtree_##name##_t *b, key_t * __restrict k, key_t **lower, \ + key_t **upper) \ + { \ + if (!b->root) { \ + return; \ + } \ + int i, r = 0; \ + kbnode_t *x = b->root; \ + *lower = *upper = 0; \ + while (x) { \ + i = __kb_getp_aux_##name(x, k, &r); \ + if (i >= 0 && r == 0) { \ + *lower = *upper = &__KB_KEY(key_t, x)[i]; \ + return; \ + } \ + if (i >= 0) *lower = &__KB_KEY(key_t, x)[i]; \ + if (i < x->n - 1) *upper = &__KB_KEY(key_t, x)[i + 1]; \ + if (x->is_internal == 0) return; \ + x = __KB_PTR(b, x)[i + 1]; \ + } \ + } \ + static inline void kb_interval_##name(kbtree_##name##_t *b, key_t k, key_t **lower, key_t **upper) \ + { \ + kb_intervalp_##name(b, &k, lower, upper); \ + } + +#define __KB_PUT(name, key_t, kbnode_t, __cmp, T, ILEN) \ + /* x must be an internal node */ \ + static inline void __kb_split_##name(kbtree_##name##_t *b, kbnode_t *x, int i, kbnode_t *y) \ + { \ + kbnode_t *z; \ + z = (kbnode_t *)xcalloc(1, y->is_internal? ILEN : sizeof(kbnode_##name##_t)); \ + ++b->n_nodes; \ + z->is_internal = y->is_internal; \ + z->n = T - 1; \ + memcpy(__KB_KEY(key_t, z), &__KB_KEY(key_t, y)[T], sizeof(key_t) * (T - 1)); \ + if (y->is_internal) memcpy(__KB_PTR(b, z), &__KB_PTR(b, y)[T], sizeof(void *) * T); \ + y->n = T - 1; \ + memmove(&__KB_PTR(b, x)[i + 2], &__KB_PTR(b, \ + x)[i + 1], sizeof(void *) * (unsigned int)(x->n - i)); \ + __KB_PTR(b, x)[i + 1] = z; \ + memmove(&__KB_KEY(key_t, x)[i + 1], &__KB_KEY(key_t, x)[i], \ + sizeof(key_t) * (unsigned int)(x->n - i)); \ + __KB_KEY(key_t, x)[i] = __KB_KEY(key_t, y)[T - 1]; \ + ++x->n; \ + } \ + static inline key_t *__kb_putp_aux_##name(kbtree_##name##_t *b, kbnode_t *x, key_t * __restrict k) \ + { \ + int i = x->n - 1; \ + key_t *ret; \ + if (x->is_internal == 0) { \ + i = __kb_getp_aux_##name(x, k, 0); \ + if (i != x->n - 1) \ + memmove(&__KB_KEY(key_t, x)[i + 2], &__KB_KEY(key_t, \ + x)[i + 1], \ + (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ + ret = &__KB_KEY(key_t, x)[i + 1]; \ + *ret = *k; \ + ++x->n; \ + } else { \ + i = __kb_getp_aux_##name(x, k, 0) + 1; \ + if (__KB_PTR(b, x)[i]->n == 2 * T - 1) { \ + __kb_split_##name(b, x, i, __KB_PTR(b, x)[i]); \ + if (__cmp(*k, __KB_KEY(key_t, x)[i]) > 0) ++i; \ + } \ + ret = __kb_putp_aux_##name(b, __KB_PTR(b, x)[i], k); \ + } \ + return ret; \ + } \ + static inline key_t *kb_putp_##name(kbtree_##name##_t *b, key_t * __restrict k) \ + { \ + if (!b->root) { \ + b->root = (kbnode_t *)xcalloc(1, ILEN); \ + ++b->n_nodes; \ + } \ + kbnode_t *r, *s; \ + ++b->n_keys; \ + r = b->root; \ + if (r->n == 2 * T - 1) { \ + ++b->n_nodes; \ + s = (kbnode_t *)xcalloc(1, ILEN); \ + b->root = s; s->is_internal = 1; s->n = 0; \ + __KB_PTR(b, s)[0] = r; \ + __kb_split_##name(b, s, 0, r); \ + r = s; \ + } \ + return __kb_putp_aux_##name(b, r, k); \ + } \ + static inline void kb_put_##name(kbtree_##name##_t *b, key_t k) \ + { \ + kb_putp_##name(b, &k); \ + } + +#define __KB_DEL(name, key_t, kbnode_t, T) \ + static inline key_t __kb_delp_aux_##name(kbtree_##name##_t *b, kbnode_t *x, key_t * __restrict k, \ + int s) \ + { \ + int yn, zn, i, r = 0; \ + kbnode_t *xp, *y, *z; \ + key_t kp; \ + if (x == 0) return *k; \ + if (s) { /* s can only be 0, 1 or 2 */ \ + r = x->is_internal == 0? 0 : s == 1? 1 : -1; \ + i = s == 1? x->n - 1 : -1; \ + } else i = __kb_getp_aux_##name(x, k, &r); \ + if (x->is_internal == 0) { \ + if (s == 2) ++i; \ + kp = __KB_KEY(key_t, x)[i]; \ + memmove(&__KB_KEY(key_t, x)[i], &__KB_KEY(key_t, \ + x)[i + 1], \ + (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ + --x->n; \ + return kp; \ + } \ + if (r == 0) { \ + if ((yn = __KB_PTR(b, x)[i]->n) >= T) { \ + xp = __KB_PTR(b, x)[i]; \ + kp = __KB_KEY(key_t, x)[i]; \ + __KB_KEY(key_t, x)[i] = __kb_delp_aux_##name(b, xp, 0, 1); \ + return kp; \ + } else if ((zn = __KB_PTR(b, x)[i + 1]->n) >= T) { \ + xp = __KB_PTR(b, x)[i + 1]; \ + kp = __KB_KEY(key_t, x)[i]; \ + __KB_KEY(key_t, x)[i] = __kb_delp_aux_##name(b, xp, 0, 2); \ + return kp; \ + } else if (yn == T - 1 && zn == T - 1) { \ + y = __KB_PTR(b, x)[i]; z = __KB_PTR(b, x)[i + 1]; \ + __KB_KEY(key_t, y)[y->n++] = *k; \ + memmove(&__KB_KEY(key_t, y)[y->n], __KB_KEY(key_t, z), (unsigned int)z->n * sizeof(key_t)); \ + if (y->is_internal) memmove(&__KB_PTR(b, y)[y->n], __KB_PTR(b, \ + z), \ + (unsigned int)(z->n + 1) * sizeof(void *)); \ + y->n += z->n; \ + memmove(&__KB_KEY(key_t, x)[i], &__KB_KEY(key_t, \ + x)[i + 1], \ + (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ + memmove(&__KB_PTR(b, x)[i + 1], &__KB_PTR(b, \ + x)[i + 2], \ + (unsigned int)(x->n - i - 1) * sizeof(void *)); \ + --x->n; \ + XFREE_CLEAR(z); \ + return __kb_delp_aux_##name(b, y, k, s); \ + } \ + } \ + ++i; \ + if ((xp = __KB_PTR(b, x)[i])->n == T - 1) { \ + if (i > 0 && (y = __KB_PTR(b, x)[i - 1])->n >= T) { \ + memmove(&__KB_KEY(key_t, xp)[1], __KB_KEY(key_t, xp), (unsigned int)xp->n * sizeof(key_t)); \ + if (xp->is_internal) memmove(&__KB_PTR(b, xp)[1], __KB_PTR(b, \ + xp), \ + (unsigned int)(xp->n + 1) * sizeof(void *)); \ + __KB_KEY(key_t, xp)[0] = __KB_KEY(key_t, x)[i - 1]; \ + __KB_KEY(key_t, x)[i - 1] = __KB_KEY(key_t, y)[y->n - 1]; \ + if (xp->is_internal) __KB_PTR(b, xp)[0] = __KB_PTR(b, y)[y->n]; \ + --y->n; ++xp->n; \ + } else if (i < x->n && (y = __KB_PTR(b, x)[i + 1])->n >= T) { \ + __KB_KEY(key_t, xp)[xp->n++] = __KB_KEY(key_t, x)[i]; \ + __KB_KEY(key_t, x)[i] = __KB_KEY(key_t, y)[0]; \ + if (xp->is_internal) __KB_PTR(b, xp)[xp->n] = __KB_PTR(b, y)[0]; \ + --y->n; \ + memmove(__KB_KEY(key_t, y), &__KB_KEY(key_t, y)[1], (unsigned int)y->n * sizeof(key_t)); \ + if (y->is_internal) memmove(__KB_PTR(b, y), &__KB_PTR(b, \ + y)[1], \ + (unsigned int)(y->n + 1) * sizeof(void *)); \ + } else if (i > 0 && (y = __KB_PTR(b, x)[i - 1])->n == T - 1) { \ + __KB_KEY(key_t, y)[y->n++] = __KB_KEY(key_t, x)[i - 1]; \ + memmove(&__KB_KEY(key_t, y)[y->n], __KB_KEY(key_t, xp), \ + (unsigned int)xp->n * sizeof(key_t)); \ + if (y->is_internal) memmove(&__KB_PTR(b, y)[y->n], __KB_PTR(b, \ + xp), \ + (unsigned int)(xp->n + 1) * sizeof(void *)); \ + y->n += xp->n; \ + memmove(&__KB_KEY(key_t, x)[i - 1], &__KB_KEY(key_t, \ + x)[i], \ + (unsigned int)(x->n - i) * sizeof(key_t)); \ + memmove(&__KB_PTR(b, x)[i], &__KB_PTR(b, \ + x)[i + 1], (unsigned int)(x->n - i) * sizeof(void *)); \ + --x->n; \ + XFREE_CLEAR(xp); \ + xp = y; \ + } else if (i < x->n && (y = __KB_PTR(b, x)[i + 1])->n == T - 1) { \ + __KB_KEY(key_t, xp)[xp->n++] = __KB_KEY(key_t, x)[i]; \ + memmove(&__KB_KEY(key_t, xp)[xp->n], __KB_KEY(key_t, y), \ + (unsigned int)y->n * sizeof(key_t)); \ + if (xp->is_internal) memmove(&__KB_PTR(b, xp)[xp->n], __KB_PTR(b, y), \ + (unsigned int)(y->n + 1) * sizeof(void *)); \ + xp->n += y->n; \ + memmove(&__KB_KEY(key_t, x)[i], &__KB_KEY(key_t, \ + x)[i + 1], \ + (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ + memmove(&__KB_PTR(b, x)[i + 1], &__KB_PTR(b, \ + x)[i + 2], \ + (unsigned int)(x->n - i - 1) * sizeof(void *)); \ + --x->n; \ + XFREE_CLEAR(y); \ + } \ + } \ + return __kb_delp_aux_##name(b, xp, k, s); \ + } \ + static inline key_t kb_delp_##name(kbtree_##name##_t *b, key_t * __restrict k) \ + { \ + kbnode_t *x; \ + key_t ret; \ + ret = __kb_delp_aux_##name(b, b->root, k, 0); \ + --b->n_keys; \ + if (b->root->n == 0 && b->root->is_internal) { \ + --b->n_nodes; \ + x = b->root; \ + b->root = __KB_PTR(b, x)[0]; \ + XFREE_CLEAR(x); \ + } \ + return ret; \ + } \ + static inline key_t kb_del_##name(kbtree_##name##_t *b, key_t k) \ + { \ + return kb_delp_##name(b, &k); \ + } + +#define __KB_ITR(name, key_t, kbnode_t) \ + static inline void kb_itr_first_##name(kbtree_##name##_t *b, kbitr_##name##_t *itr) \ + { \ + itr->p = NULL; \ + if (b->n_keys == 0) return; \ + itr->p = itr->stack; \ + itr->p->x = b->root; itr->p->i = 0; \ + while (itr->p->x->is_internal && __KB_PTR(b, itr->p->x)[0] != 0) { \ + kbnode_t *x = itr->p->x; \ + ++itr->p; \ + itr->p->x = __KB_PTR(b, x)[0]; itr->p->i = 0; \ + } \ + } \ + static inline int kb_itr_next_##name(kbtree_##name##_t *b, kbitr_##name##_t *itr) \ + { \ + if (itr->p == NULL) return 0; \ + for (;;) { \ + ++itr->p->i; \ + assert(itr->p->i <= 21); \ + while (itr->p->x && itr->p->i <= itr->p->x->n) { \ + itr->p[1].i = 0; \ + itr->p[1].x = itr->p->x->is_internal? __KB_PTR(b, itr->p->x)[itr->p->i] : 0; \ + ++itr->p; \ + } \ + if (itr->p == itr->stack) { \ + itr->p = NULL; \ + return 0; \ + } \ + --itr->p; \ + if (itr->p->x && itr->p->i < itr->p->x->n) return 1; \ + } \ + } \ + static inline int kb_itr_prev_##name(kbtree_##name##_t *b, kbitr_##name##_t *itr) \ + { \ + if (itr->p == NULL) return 0; \ + for (;;) { \ + while (itr->p->x && itr->p->i >= 0) { \ + itr->p[1].x = itr->p->x->is_internal? __KB_PTR(b, itr->p->x)[itr->p->i] : 0; \ + itr->p[1].i = itr->p[1].x ? itr->p[1].x->n : -1; \ + ++itr->p; \ + } \ + if (itr->p == itr->stack) { \ + itr->p = NULL; \ + return 0; \ + } \ + --itr->p; \ + --itr->p->i; \ + if (itr->p->x && itr->p->i >= 0) return 1; \ + } \ + } \ + static inline int kb_itr_getp_##name(kbtree_##name##_t *b, key_t * __restrict k, \ + kbitr_##name##_t *itr) \ + { \ + if (b->n_keys == 0) { \ + itr->p = NULL; \ + return 0; \ + } \ + int i, r = 0; \ + itr->p = itr->stack; \ + itr->p->x = b->root; \ + while (itr->p->x) { \ + i = __kb_getp_aux_##name(itr->p->x, k, &r); \ + itr->p->i = i; \ + if (i >= 0 && r == 0) return 1; \ + ++itr->p->i; \ + assert(itr->p->i <= 21); \ + itr->p[1].x = itr->p->x->is_internal? __KB_PTR(b, itr->p->x)[i + 1] : 0; \ + ++itr->p; \ + } \ + itr->p->i = 0; \ + return 0; \ + } \ + static inline int kb_itr_get_##name(kbtree_##name##_t *b, key_t k, kbitr_##name##_t *itr) \ + { \ + return kb_itr_getp_##name(b, &k, itr); \ + } \ + static inline void kb_del_itr_##name(kbtree_##name##_t *b, kbitr_##name##_t *itr) \ + { \ + key_t k = kb_itr_key(itr); \ + kb_delp_##name(b, &k); \ + kb_itr_getp_##name(b, &k, itr); \ + } + +#define KBTREE_INIT(name, key_t, __cmp, T) \ + KBTREE_INIT_IMPL(name, key_t, kbnode_##name##_t, __cmp, T, \ + (sizeof(kbnode_##name##_t) + (2*T)*sizeof(void *))) + +#define KBTREE_INIT_IMPL(name, key_t, kbnode_t, __cmp, T, ILEN) \ + __KB_TREE_T(name, key_t, T) \ + __KB_GET_AUX1(name, key_t, kbnode_t, __cmp) \ + __KB_GET(name, key_t, kbnode_t) \ + __KB_INTERVAL(name, key_t, kbnode_t) \ + __KB_PUT(name, key_t, kbnode_t, __cmp, T, ILEN) \ + __KB_DEL(name, key_t, kbnode_t, T) \ + __KB_ITR(name, key_t, kbnode_t) + +#define KB_DEFAULT_SIZE 512 + +#define kbtree_t(name) kbtree_##name##_t +#define kbitr_t(name) kbitr_##name##_t +#define kb_init(b) ((b)->n_keys = (b)->n_nodes = 0, (b)->root = 0) +#define kb_destroy(name, b) __kb_destroy(kbnode_##name##_t, b) +#define kb_get(name, b, k) kb_get_##name(b, k) +#define kb_put(name, b, k) kb_put_##name(b, k) +#define kb_del(name, b, k) kb_del_##name(b, k) +#define kb_interval(name, b, k, l, u) kb_interval_##name(b, k, l, u) +#define kb_getp(name, b, k) kb_getp_##name(b, k) +#define kb_putp(name, b, k) kb_putp_##name(b, k) +#define kb_delp(name, b, k) kb_delp_##name(b, k) +#define kb_intervalp(name, b, k, l, u) kb_intervalp_##name(b, k, l, u) + +#define kb_itr_first(name, b, i) kb_itr_first_##name(b, i) +#define kb_itr_get(name, b, k, i) kb_itr_get_##name(b, k, i) +#define kb_itr_getp(name, b, k, i) kb_itr_getp_##name(b, k, i) +#define kb_itr_next(name, b, i) kb_itr_next_##name(b, i) +#define kb_itr_prev(name, b, i) kb_itr_prev_##name(b, i) +#define kb_del_itr(name, b, i) kb_del_itr_##name(b, i) +#define kb_itr_key(itr) __KB_KEY(dummy, (itr)->p->x)[(itr)->p->i] +#define kb_itr_valid(itr) ((itr)->p >= (itr)->stack) + +#define kb_size(b) ((b)->n_keys) + +#define kb_generic_cmp(a, b) (((b) < (a)) - ((a) < (b))) +#define kb_str_cmp(a, b) strcmp(a, b) + +#endif // NVIM_LIB_KBTREE_H diff --git a/src/klib/khash.h b/src/klib/khash.h new file mode 100644 index 0000000000..57a41f9c13 --- /dev/null +++ b/src/klib/khash.h @@ -0,0 +1,730 @@ +/* The MIT License + + Copyright (c) 2008, 2009, 2011 by Attractive Chaos + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + */ + +/* + Example: + + #include "nvim/khash.h" + KHASH_MAP_INIT_INT(32, char) + int main() { + int ret, is_missing; + khiter_t k; + khash_t(32) *h = kh_init(32); + k = kh_put(32, h, 5, &ret); + kh_value(h, k) = 10; + k = kh_get(32, h, 10); + is_missing = (k == kh_end(h)); + k = kh_get(32, h, 5); + kh_del(32, h, k); + for (k = kh_begin(h); k != kh_end(h); ++k) + if (kh_exist(h, k)) kh_value(h, k) = 1; + kh_destroy(32, h); + return 0; + } + */ + +/* + 2013-05-02 (0.2.8): + + * Use quadratic probing. When the capacity is power of 2, stepping function + i*(i+1)/2 guarantees to traverse each bucket. It is better than double + hashing on cache performance and is more robust than linear probing. + + In theory, double hashing should be more robust than quadratic probing. + However, my implementation is probably not for large hash tables, because + the second hash function is closely tied to the first hash function, + which reduce the effectiveness of double hashing. + + Reference: http://research.cs.vt.edu/AVresearch/hashing/quadratic.php + + 2011-12-29 (0.2.7): + + * Minor code clean up; no actual effect. + + 2011-09-16 (0.2.6): + + * The capacity is a power of 2. This seems to dramatically improve the + speed for simple keys. Thank Zilong Tan for the suggestion. Reference: + + - http://code.google.com/p/ulib/ + - http://nothings.org/computer/judy/ + + * Allow to optionally use linear probing which usually has better + performance for random input. Double hashing is still the default as it + is more robust to certain non-random input. + + * Added Wang's integer hash function (not used by default). This hash + function is more robust to certain non-random input. + + 2011-02-14 (0.2.5): + + * Allow to declare global functions. + + 2009-09-26 (0.2.4): + + * Improve portability + + 2008-09-19 (0.2.3): + + * Corrected the example + * Improved interfaces + + 2008-09-11 (0.2.2): + + * Improved speed a little in kh_put() + + 2008-09-10 (0.2.1): + + * Added kh_clear() + * Fixed a compiling error + + 2008-09-02 (0.2.0): + + * Changed to token concatenation which increases flexibility. + + 2008-08-31 (0.1.2): + + * Fixed a bug in kh_get(), which has not been tested previously. + + 2008-08-31 (0.1.1): + + * Added destructor + */ + +#ifndef NVIM_LIB_KHASH_H +#define NVIM_LIB_KHASH_H + +/*! + @header + + Generic hash table library. + */ + +#define AC_VERSION_KHASH_H "0.2.8" + +#include +#include +#include +#include + +#include "nvim/func_attr.h" +#include "nvim/memory.h" + +// compiler specific configuration + +#if UINT_MAX == 0xffffffffu +typedef unsigned int khint32_t; +#elif ULONG_MAX == 0xffffffffu +typedef unsigned long khint32_t; +#endif + +#if ULONG_MAX == ULLONG_MAX +typedef unsigned long khint64_t; +#else +typedef unsigned long long khint64_t; +#endif + +#ifdef _MSC_VER +# define kh_inline __inline +#else +# define kh_inline inline +#endif + +typedef khint32_t khint_t; +typedef khint_t khiter_t; + +#define __ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2) +#define __ac_isdel(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&1) +#define __ac_iseither(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&3) +#define __ac_set_isdel_false(flag, i) (flag[i>>4]&=~(khint_t)(1ul<<((i&0xfU)<<1))) +#define __ac_set_isempty_false(flag, i) (flag[i>>4]&=~(khint_t)(2ul<<((i&0xfU)<<1))) +#define __ac_set_isboth_false(flag, i) (flag[i>>4]&=~(khint_t)(3ul<<((i&0xfU)<<1))) +#define __ac_set_isdel_true(flag, i) (flag[i>>4]|=(khint_t)1ul<<((i&0xfU)<<1)) + +#define __ac_fsize(m) ((m) < 16? 1 : (m)>>4) + +#ifndef kroundup32 +# define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, \ + ++(x)) +#endif + +#ifndef kcalloc +# define kcalloc(N, Z) xcalloc(N, Z) +#endif +#ifndef kmalloc +# define kmalloc(Z) xmalloc(Z) +#endif +#ifndef krealloc +# define krealloc(P, Z) xrealloc(P, Z) +#endif +#ifndef kfree +# define kfree(P) XFREE_CLEAR(P) +#endif + +#define __ac_HASH_UPPER 0.77 + +#define __KHASH_TYPE(name, khkey_t, khval_t) \ + typedef struct { \ + khint_t n_buckets, size, n_occupied, upper_bound; \ + khint32_t *flags; \ + khkey_t *keys; \ + khval_t *vals; \ + } kh_##name##_t; + +#define __KHASH_PROTOTYPES(name, khkey_t, khval_t) \ + extern kh_##name##_t *kh_init_##name(void); \ + extern void kh_dealloc_##name(kh_##name##_t *h); \ + extern void kh_destroy_##name(kh_##name##_t *h); \ + extern void kh_clear_##name(kh_##name##_t *h); \ + extern khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); \ + extern void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \ + extern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \ + extern void kh_del_##name(kh_##name##_t *h, khint_t x); + +#define __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, \ + __hash_equal) \ + SCOPE kh_##name##_t *kh_init_##name(void) \ + REAL_FATTR_UNUSED; \ + SCOPE kh_##name##_t *kh_init_##name(void) { \ + return (kh_##name##_t *)kcalloc(1, sizeof(kh_##name##_t)); \ + } \ + SCOPE void kh_dealloc_##name(kh_##name##_t *h) \ + REAL_FATTR_UNUSED; \ + SCOPE void kh_dealloc_##name(kh_##name##_t *h) \ + { \ + kfree(h->keys); \ + kfree(h->flags); \ + kfree(h->vals); \ + } \ + SCOPE void kh_destroy_##name(kh_##name##_t *h) \ + REAL_FATTR_UNUSED; \ + SCOPE void kh_destroy_##name(kh_##name##_t *h) \ + { \ + if (h) { \ + kh_dealloc_##name(h); \ + kfree(h); \ + } \ + } \ + SCOPE void kh_clear_##name(kh_##name##_t *h) \ + REAL_FATTR_UNUSED; \ + SCOPE void kh_clear_##name(kh_##name##_t *h) \ + { \ + if (h && h->flags) { \ + memset(h->flags, 0xaa, __ac_fsize(h->n_buckets) * sizeof(khint32_t)); \ + h->size = h->n_occupied = 0; \ + } \ + } \ + SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \ + REAL_FATTR_UNUSED; \ + SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \ + { \ + if (h->n_buckets) { \ + khint_t k, i, last, mask, step = 0; \ + mask = h->n_buckets - 1; \ + k = __hash_func(key); i = k & mask; \ + last = i; \ + while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || \ + !__hash_equal(h->keys[i], key))) { \ + i = (i + (++step)) & mask; \ + if (i == last) { \ + return h->n_buckets; \ + } \ + } \ + return __ac_iseither(h->flags, i) ? h->n_buckets : i; \ + } else { \ + return 0; \ + } \ + } \ + SCOPE void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \ + REAL_FATTR_UNUSED; \ + SCOPE void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \ + { /* This function uses 0.25*n_buckets bytes of working space instead of */ \ + /* [sizeof(key_t+val_t)+.25]*n_buckets. */ \ + khint32_t *new_flags = 0; \ + khint_t j = 1; \ + { \ + kroundup32(new_n_buckets); \ + if (new_n_buckets < 4) { \ + new_n_buckets = 4; \ + } \ + /* requested size is too small */ \ + if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) { \ + j = 0; \ + } else { /* hash table size to be changed (shrink or expand); rehash */ \ + new_flags = (khint32_t *)kmalloc(__ac_fsize(new_n_buckets) \ + * sizeof(khint32_t)); \ + memset(new_flags, 0xaa, \ + __ac_fsize(new_n_buckets) * sizeof(khint32_t)); \ + if (h->n_buckets < new_n_buckets) { /* expand */ \ + khkey_t *new_keys = (khkey_t *)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \ + h->keys = new_keys; \ + if (kh_is_map) { \ + khval_t *new_vals = \ + (khval_t *)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \ + h->vals = new_vals; \ + } \ + } /* otherwise shrink */ \ + } \ + } \ + if (j) { /* rehashing is needed */ \ + for (j = 0; j != h->n_buckets; ++j) { \ + if (__ac_iseither(h->flags, j) == 0) { \ + khkey_t key = h->keys[j]; \ + khval_t val; \ + khint_t new_mask; \ + new_mask = new_n_buckets - 1; \ + if (kh_is_map) { \ + val = h->vals[j]; \ + } \ + __ac_set_isdel_true(h->flags, j); \ + /* kick-out process; sort of like in Cuckoo hashing */ \ + while (1) { \ + khint_t k, i, step = 0; \ + k = __hash_func(key); \ + i = k & new_mask; \ + while (!__ac_isempty(new_flags, i)) { \ + i = (i + (++step)) & new_mask; \ + } \ + __ac_set_isempty_false(new_flags, i); \ + /* kick out the existing element */ \ + if (i < h->n_buckets && __ac_iseither(h->flags, i) == 0) { \ + { \ + khkey_t tmp = h->keys[i]; \ + h->keys[i] = key; \ + key = tmp; \ + } \ + if (kh_is_map) { \ + khval_t tmp = h->vals[i]; \ + h->vals[i] = val; \ + val = tmp; \ + } \ + /* mark it as deleted in the old hash table */ \ + __ac_set_isdel_true(h->flags, i); \ + } else { /* write the element and jump out of the loop */ \ + h->keys[i] = key; \ + if (kh_is_map) { \ + h->vals[i] = val; \ + } \ + break; \ + } \ + } \ + } \ + } \ + if (h->n_buckets > new_n_buckets) { /* shrink the hash table */ \ + h->keys = (khkey_t *)krealloc((void *)h->keys, \ + new_n_buckets * sizeof(khkey_t)); \ + if (kh_is_map) { \ + h->vals = (khval_t *)krealloc((void *)h->vals, \ + new_n_buckets * sizeof(khval_t)); \ + } \ + } \ + kfree(h->flags); /* free the working space */ \ + h->flags = new_flags; \ + h->n_buckets = new_n_buckets; \ + h->n_occupied = h->size; \ + h->upper_bound = (khint_t)(h->n_buckets * __ac_HASH_UPPER + 0.5); \ + } \ + } \ + SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \ + REAL_FATTR_UNUSED; \ + SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \ + { \ + khint_t x; \ + if (h->n_occupied >= h->upper_bound) { /* update the hash table */ \ + if (h->n_buckets > (h->size << 1)) { \ + kh_resize_##name(h, h->n_buckets - 1); /* clear "deleted" elements */ \ + } else { \ + kh_resize_##name(h, h->n_buckets + 1); /* expand the hash table */ \ + } \ + } /* TODO: implement automatically shrinking; */ \ + /* resize() already support shrinking */ \ + { \ + khint_t k, i, site, last, mask = h->n_buckets - 1, step = 0; \ + x = site = h->n_buckets; \ + k = __hash_func(key); \ + i = k & mask; \ + if (__ac_isempty(h->flags, i)) { \ + x = i; /* for speed up */ \ + } else { \ + last = i; \ + while (!__ac_isempty(h->flags, i) \ + && (__ac_isdel(h->flags, i) \ + || !__hash_equal(h->keys[i], key))) { \ + if (__ac_isdel(h->flags, i)) { \ + site = i; \ + } \ + i = (i + (++step)) & mask; \ + if (i == last) { \ + x = site; \ + break; \ + } \ + } \ + if (x == h->n_buckets) { \ + if (__ac_isempty(h->flags, i) && site != h->n_buckets) { \ + x = site; \ + } else { \ + x = i; \ + } \ + } \ + } \ + } \ + if (__ac_isempty(h->flags, x)) { /* not present at all */ \ + h->keys[x] = key; \ + __ac_set_isboth_false(h->flags, x); \ + h->size++; \ + h->n_occupied++; \ + *ret = 1; \ + } else if (__ac_isdel(h->flags, x)) { /* deleted */ \ + h->keys[x] = key; \ + __ac_set_isboth_false(h->flags, x); \ + h->size++; \ + *ret = 2; \ + } else { \ + *ret = 0; /* Don't touch h->keys[x] if present and not deleted */ \ + } \ + return x; \ + } \ + SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \ + REAL_FATTR_UNUSED; \ + SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \ + { \ + if (x != h->n_buckets && !__ac_iseither(h->flags, x)) { \ + __ac_set_isdel_true(h->flags, x); \ + --h->size; \ + } \ + } + +#define KHASH_DECLARE(name, khkey_t, khval_t) \ + __KHASH_TYPE(name, khkey_t, khval_t) \ + __KHASH_PROTOTYPES(name, khkey_t, khval_t) + +#define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ + __KHASH_TYPE(name, khkey_t, khval_t) \ + __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) + +#define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ + KHASH_INIT2(name, static kh_inline, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) + +// --- BEGIN OF HASH FUNCTIONS --- + +/*! @function + @abstract Integer hash function + @param key The integer [khint32_t] + @return The hash value [khint_t] + */ +#define kh_int_hash_func(key) (khint32_t)(key) +/*! @function + @abstract Integer comparison function + */ +#define kh_int_hash_equal(a, b) ((a) == (b)) +/*! @function + @abstract 64-bit integer hash function + @param key The integer [khint64_t] + @return The hash value [khint_t] + */ +#define kh_int64_hash_func(key) (khint32_t)((key)>>33^(key)^(key)<<11) +/*! @function + @abstract 64-bit integer comparison function + */ +#define kh_int64_hash_equal(a, b) ((a) == (b)) +/*! @function + @abstract const char* hash function + @param s Pointer to a null terminated string + @return The hash value + */ +static kh_inline khint_t __ac_X31_hash_string(const char *s) +{ + khint_t h = (khint_t)*s; + if (h) { + for (++s; *s; ++s) { h = (h << 5) - h + (uint8_t)*s; } + } + return h; +} +/*! @function + @abstract Another interface to const char* hash function + @param key Pointer to a null terminated string [const char*] + @return The hash value [khint_t] + */ +#define kh_str_hash_func(key) __ac_X31_hash_string(key) +/*! @function + @abstract Const char* comparison function + */ +#define kh_str_hash_equal(a, b) (strcmp(a, b) == 0) + +static kh_inline khint_t __ac_Wang_hash(khint_t key) +{ + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + return key; +} +#define kh_int_hash_func2(k) __ac_Wang_hash((khint_t)key) + +// --- END OF HASH FUNCTIONS --- + +// Other convenient macros... + +/*! + @abstract Type of the hash table. + @param name Name of the hash table [symbol] + */ +#define khash_t(name) kh_##name##_t + +/*! @function + @abstract Initiate a hash table. + @param name Name of the hash table [symbol] + @return Pointer to the hash table [khash_t(name)*] + */ +#define kh_init(name) kh_init_##name() + +/*! @function + @abstract Destroy a hash table. + @param name Name of the hash table [symbol] + @param h Pointer to the hash table [khash_t(name)*] + */ +#define kh_destroy(name, h) kh_destroy_##name(h) + +/*! @function + @abstract Free memory referenced directly inside a hash table. + @param name Name of the hash table [symbol] + @param h Pointer to the hash table [khash_t(name)*] + */ +#define kh_dealloc(name, h) kh_dealloc_##name(h) + +/*! @function + @abstract Reset a hash table without deallocating memory. + @param name Name of the hash table [symbol] + @param h Pointer to the hash table [khash_t(name)*] + */ +#define kh_clear(name, h) kh_clear_##name(h) + +/*! @function + @abstract Resize a hash table. + @param name Name of the hash table [symbol] + @param h Pointer to the hash table [khash_t(name)*] + @param s New size [khint_t] + */ +#define kh_resize(name, h, s) kh_resize_##name(h, s) + +/*! @function + @abstract Insert a key to the hash table. + @param name Name of the hash table [symbol] + @param h Pointer to the hash table [khash_t(name)*] + @param k Key [type of keys] + @param r Extra return code: -1 if the operation failed; + 0 if the key is present in the hash table; + 1 if the bucket is empty (never used); 2 if the element in + the bucket has been deleted [int*] + @return Iterator to the inserted element [khint_t] + */ +#define kh_put(name, h, k, r) kh_put_##name(h, k, r) + +/*! @function + @abstract Retrieve a key from the hash table. + @param name Name of the hash table [symbol] + @param h Pointer to the hash table [khash_t(name)*] + @param k Key [type of keys] + @return Iterator to the found element, or kh_end(h) if the element is absent [khint_t] + */ +#define kh_get(name, h, k) kh_get_##name(h, k) + +/*! @function + @abstract Remove a key from the hash table. + @param name Name of the hash table [symbol] + @param h Pointer to the hash table [khash_t(name)*] + @param k Iterator to the element to be deleted [khint_t] + */ +#define kh_del(name, h, k) kh_del_##name(h, k) + +/*! @function + @abstract Test whether a bucket contains data. + @param h Pointer to the hash table [khash_t(name)*] + @param x Iterator to the bucket [khint_t] + @return 1 if containing data; 0 otherwise [int] + */ +#define kh_exist(h, x) (!__ac_iseither((h)->flags, (x))) + +/*! @function + @abstract Get key given an iterator + @param h Pointer to the hash table [khash_t(name)*] + @param x Iterator to the bucket [khint_t] + @return Key [type of keys] + */ +#define kh_key(h, x) ((h)->keys[x]) + +/*! @function + @abstract Get value given an iterator + @param h Pointer to the hash table [khash_t(name)*] + @param x Iterator to the bucket [khint_t] + @return Value [type of values] + @discussion For hash sets, calling this results in segfault. + */ +#define kh_val(h, x) ((h)->vals[x]) + +/*! @function + @abstract Alias of kh_val() + */ +#define kh_value(h, x) ((h)->vals[x]) + +/*! @function + @abstract Get the start iterator + @param h Pointer to the hash table [khash_t(name)*] + @return The start iterator [khint_t] + */ +#define kh_begin(h) (khint_t)(0) + +/*! @function + @abstract Get the end iterator + @param h Pointer to the hash table [khash_t(name)*] + @return The end iterator [khint_t] + */ +#define kh_end(h) ((h)->n_buckets) + +/*! @function + @abstract Get the number of elements in the hash table + @param h Pointer to the hash table [khash_t(name)*] + @return Number of elements in the hash table [khint_t] + */ +#define kh_size(h) ((h)->size) + +/*! @function + @abstract Get the number of buckets in the hash table + @param h Pointer to the hash table [khash_t(name)*] + @return Number of buckets in the hash table [khint_t] + */ +#define kh_n_buckets(h) ((h)->n_buckets) + +/*! @function + @abstract Iterate over the entries in the hash table + @param h Pointer to the hash table [khash_t(name)*] + @param kvar Variable to which key will be assigned + @param vvar Variable to which value will be assigned + @param code Block of code to execute + */ +#define kh_foreach(h, kvar, vvar, code) { khint_t __i; \ + for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \ + if (!kh_exist(h, __i)) continue; \ + (kvar) = kh_key(h, __i); \ + (vvar) = kh_val(h, __i); \ + code; \ + } } + +/*! @function + @abstract Iterate over the values in the hash table + @param h Pointer to the hash table [khash_t(name)*] + @param vvar Variable to which value will be assigned + @param code Block of code to execute + */ +#define kh_foreach_value(h, vvar, code) { khint_t __i; \ + for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \ + if (!kh_exist(h, __i)) continue; \ + (vvar) = kh_val(h, __i); \ + code; \ + } } + +/*! @function + @abstract Iterate over the keys in the hash table + @param h Pointer to the hash table [khash_t(name)*] + @param kvar Variable to which value will be assigned + @param code Block of code to execute + */ +#define kh_foreach_key(h, kvar, code) \ + { \ + khint_t __i; \ + for (__i = kh_begin(h); __i != kh_end(h); __i++) { \ + if (!kh_exist(h, __i)) { \ + continue; \ + } \ + (kvar) = kh_key(h, __i); \ + code; \ + } \ + } + +// More convenient interfaces + +/*! @function + @abstract Instantiate a hash set containing integer keys + @param name Name of the hash table [symbol] + */ +#define KHASH_SET_INIT_INT(name) \ + KHASH_INIT(name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal) + +/*! @function + @abstract Instantiate a hash map containing integer keys + @param name Name of the hash table [symbol] + @param khval_t Type of values [type] + */ +#define KHASH_MAP_INIT_INT(name, khval_t) \ + KHASH_INIT(name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal) + +/*! @function + @abstract Instantiate a hash map containing 64-bit integer keys + @param name Name of the hash table [symbol] + */ +#define KHASH_SET_INIT_INT64(name) \ + KHASH_INIT(name, khint64_t, char, 0, kh_int64_hash_func, kh_int64_hash_equal) + +/*! @function + @abstract Instantiate a hash map containing 64-bit integer keys + @param name Name of the hash table [symbol] + @param khval_t Type of values [type] + */ +#define KHASH_MAP_INIT_INT64(name, khval_t) \ + KHASH_INIT(name, khint64_t, khval_t, 1, kh_int64_hash_func, kh_int64_hash_equal) + +typedef const char *kh_cstr_t; +/*! @function + @abstract Instantiate a hash map containing const char* keys + @param name Name of the hash table [symbol] + */ +#define KHASH_SET_INIT_STR(name) \ + KHASH_INIT(name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal) + +/*! @function + @abstract Instantiate a hash map containing const char* keys + @param name Name of the hash table [symbol] + @param khval_t Type of values [type] + */ +#define KHASH_MAP_INIT_STR(name, khval_t) \ + KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal) + +/*! @function + @abstract Return a literal for an empty hash table. + @param name Name of the hash table [symbol] + */ +#define KHASH_EMPTY_TABLE(name) \ + ((kh_##name##_t) { \ + .n_buckets = 0, \ + .size = 0, \ + .n_occupied = 0, \ + .upper_bound = 0, \ + .flags = NULL, \ + .keys = NULL, \ + .vals = NULL, \ + }) +#endif // NVIM_LIB_KHASH_H diff --git a/src/klib/klist.h b/src/klib/klist.h new file mode 100644 index 0000000000..a9abbc6dc2 --- /dev/null +++ b/src/klib/klist.h @@ -0,0 +1,144 @@ +/* The MIT License + + Copyright (c) 2008-2009, by Attractive Chaos + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + */ + +#ifndef _AC_KLIST_H +#define _AC_KLIST_H + +#include +#include + +#include "nvim/func_attr.h" +#include "nvim/memory.h" + +#define KMEMPOOL_INIT(name, kmptype_t, kmpfree_f) \ + typedef struct { \ + size_t cnt, n, max; \ + kmptype_t **buf; \ + } kmp_##name##_t; \ + static inline kmp_##name##_t *kmp_init_##name(void) { \ + return xcalloc(1, sizeof(kmp_##name##_t)); \ + } \ + static inline void kmp_destroy_##name(kmp_##name##_t *mp) \ + REAL_FATTR_UNUSED; \ + static inline void kmp_destroy_##name(kmp_##name##_t *mp) { \ + size_t k; \ + for (k = 0; k < mp->n; k++) { \ + kmpfree_f(mp->buf[k]); XFREE_CLEAR(mp->buf[k]); \ + } \ + XFREE_CLEAR(mp->buf); XFREE_CLEAR(mp); \ + } \ + static inline kmptype_t *kmp_alloc_##name(kmp_##name##_t *mp) { \ + mp->cnt++; \ + if (mp->n == 0) { \ + return xcalloc(1, sizeof(kmptype_t)); \ + } \ + return mp->buf[--mp->n]; \ + } \ + static inline void kmp_free_##name(kmp_##name##_t *mp, kmptype_t *p) { \ + mp->cnt--; \ + if (mp->n == mp->max) { \ + mp->max = mp->max ? (mp->max << 1) : 16; \ + mp->buf = xrealloc(mp->buf, sizeof(kmptype_t *) * mp->max); \ + } \ + mp->buf[mp->n++] = p; \ + } + +#define kmempool_t(name) kmp_##name##_t +#define kmp_init(name) kmp_init_##name() +#define kmp_destroy(name, mp) kmp_destroy_##name(mp) +#define kmp_alloc(name, mp) kmp_alloc_##name(mp) +#define kmp_free(name, mp, p) kmp_free_##name(mp, p) + +#define KLIST_INIT(name, kltype_t, kmpfree_t) \ + struct __kl1_##name { \ + kltype_t data; \ + struct __kl1_##name *next; \ + }; \ + typedef struct __kl1_##name kl1_##name; \ + KMEMPOOL_INIT(name, kl1_##name, kmpfree_t) \ + typedef struct { \ + kl1_##name *head, *tail; \ + kmp_##name##_t *mp; \ + size_t size; \ + } kl_##name##_t; \ + static inline kl_##name##_t *kl_init_##name(void) { \ + kl_##name##_t *kl = xcalloc(1, sizeof(kl_##name##_t)); \ + kl->mp = kmp_init(name); \ + kl->head = kl->tail = kmp_alloc(name, kl->mp); \ + kl->head->next = 0; \ + return kl; \ + } \ + static inline void kl_destroy_##name(kl_##name##_t *kl) \ + REAL_FATTR_UNUSED; \ + static inline void kl_destroy_##name(kl_##name##_t *kl) { \ + kl1_##name *p; \ + for (p = kl->head; p != kl->tail; p = p->next) { \ + kmp_free(name, kl->mp, p); \ + } \ + kmp_free(name, kl->mp, p); \ + kmp_destroy(name, kl->mp); \ + XFREE_CLEAR(kl); \ + } \ + static inline void kl_push_##name(kl_##name##_t *kl, kltype_t d) { \ + kl1_##name *q, *p = kmp_alloc(name, kl->mp); \ + q = kl->tail; p->next = 0; kl->tail->next = p; kl->tail = p; \ + kl->size++; \ + q->data = d; \ + } \ + static inline kltype_t kl_shift_at_##name(kl_##name##_t *kl, \ + kl1_##name **n) { \ + assert((*n)->next); \ + kl1_##name *p; \ + kl->size--; \ + p = *n; \ + *n = (*n)->next; \ + if (p == kl->head) { \ + kl->head = *n; \ + } \ + kltype_t d = p->data; \ + kmp_free(name, kl->mp, p); \ + return d; \ + } + +#define kliter_t(name) kl1_##name +#define klist_t(name) kl_##name##_t +#define kl_val(iter) ((iter)->data) +#define kl_next(iter) ((iter)->next) +#define kl_begin(kl) ((kl)->head) +#define kl_end(kl) ((kl)->tail) + +#define kl_init(name) kl_init_##name() +#define kl_destroy(name, kl) kl_destroy_##name(kl) +#define kl_push(name, kl, d) kl_push_##name(kl, d) +#define kl_shift_at(name, kl, node) kl_shift_at_##name(kl, node) +#define kl_shift(name, kl) kl_shift_at(name, kl, &kl->head) +#define kl_empty(kl) ((kl)->size == 0) +// Iteration macros. It's ok to modify the list while iterating as long as a +// `break` statement is executed before the next iteration. +#define kl_iter(name, kl, p) kl_iter_at(name, kl, p, NULL) +#define kl_iter_at(name, kl, p, h) \ + for (kl1_##name **p = h ? h : &kl->head; *p != kl->tail; p = &(*p)->next) + +#endif diff --git a/src/klib/kvec.h b/src/klib/kvec.h new file mode 100644 index 0000000000..b5b3adf7d2 --- /dev/null +++ b/src/klib/kvec.h @@ -0,0 +1,236 @@ +// The MIT License +// +// Copyright (c) 2008, by Attractive Chaos +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +// An example: +// +// #include "kvec.h" +// int main() { +// kvec_t(int) array = KV_INITIAL_VALUE; +// kv_push(array, 10); // append +// kv_a(array, 20) = 5; // dynamic +// kv_A(array, 20) = 4; // static +// kv_destroy(array); +// return 0; +// } + +#ifndef NVIM_LIB_KVEC_H +#define NVIM_LIB_KVEC_H + +#include +#include + +#include "nvim/memory.h" +#include "nvim/os/os_defs.h" + +#define kv_roundup32(x) \ + ((--(x)), \ + ((x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16), \ + (++(x))) + +#define KV_INITIAL_VALUE { .size = 0, .capacity = 0, .items = NULL } + +#define kvec_t(type) \ + struct { \ + size_t size; \ + size_t capacity; \ + type *items; \ + } + +#define kv_init(v) ((v).size = (v).capacity = 0, (v).items = 0) +#define kv_destroy(v) \ + do { \ + xfree((v).items); \ + kv_init(v); \ + } while (0) +#define kv_A(v, i) ((v).items[(i)]) +#define kv_pop(v) ((v).items[--(v).size]) +#define kv_size(v) ((v).size) +#define kv_max(v) ((v).capacity) +#define kv_Z(v, i) kv_A(v, kv_size(v) - (i) - 1) +#define kv_last(v) kv_Z(v, 0) + +/// Drop last n items from kvec without resizing +/// +/// Previously spelled as `(void)kv_pop(v)`, repeated n times. +/// +/// @param[out] v Kvec to drop items from. +/// @param[in] n Number of elements to drop. +#define kv_drop(v, n) ((v).size -= (n)) + +#define kv_resize(v, s) \ + ((v).capacity = (s), \ + (v).items = xrealloc((v).items, sizeof((v).items[0]) * (v).capacity)) + +#define kv_resize_full(v) \ + kv_resize(v, (v).capacity ? (v).capacity << 1 : 8) + +#define kv_copy(v1, v0) \ + do { \ + if ((v1).capacity < (v0).size) { \ + kv_resize(v1, (v0).size); \ + } \ + (v1).size = (v0).size; \ + memcpy((v1).items, (v0).items, sizeof((v1).items[0]) * (v0).size); \ + } while (0) + +/// fit at least "len" more items +#define kv_ensure_space(v, len) \ + do { \ + if ((v).capacity < (v).size + len) { \ + (v).capacity = (v).size + len; \ + kv_roundup32((v).capacity); \ + kv_resize((v), (v).capacity); \ + } \ + } while (0) + +#define kv_concat_len(v, data, len) \ + do { \ + kv_ensure_space(v, len); \ + memcpy((v).items + (v).size, data, sizeof((v).items[0]) * len); \ + (v).size = (v).size + len; \ + } while (0) + +#define kv_concat(v, str) kv_concat_len(v, str, STRLEN(str)) +#define kv_splice(v1, v0) kv_concat_len(v1, (v0).items, (v0).size) + +#define kv_pushp(v) \ + ((((v).size == (v).capacity) ? (kv_resize_full(v), 0) : 0), \ + ((v).items + ((v).size++))) + +#define kv_push(v, x) \ + (*kv_pushp(v) = (x)) + +#define kv_pushp_c(v) ((v).items + ((v).size++)) +#define kv_push_c(v, x) (*kv_pushp_c(v) = (x)) + +#define kv_a(v, i) \ + (*(((v).capacity <= (size_t)(i) \ + ? ((v).capacity = (v).size = (i) + 1, \ + kv_roundup32((v).capacity), \ + kv_resize((v), (v).capacity), 0UL) \ + : ((v).size <= (size_t)(i) \ + ? (v).size = (i) + 1 \ + : 0UL)), \ + &(v).items[(i)])) + +#define kv_printf(v, ...) kv_do_printf(&(v), __VA_ARGS__) + +/// Type of a vector with a few first members allocated on stack +/// +/// Is compatible with #kv_A, #kv_pop, #kv_size, #kv_max, #kv_last. +/// Is not compatible with #kv_resize, #kv_resize_full, #kv_copy, #kv_push, +/// #kv_pushp, #kv_a, #kv_destroy. +/// +/// @param[in] type Type of vector elements. +/// @param[in] init_size Number of the elements in the initial array. +#define kvec_withinit_t(type, INIT_SIZE) \ + struct { \ + size_t size; \ + size_t capacity; \ + type *items; \ + type init_array[INIT_SIZE]; \ + } + +/// Initialize vector with preallocated array +/// +/// @param[out] v Vector to initialize. +#define kvi_init(v) \ + ((v).capacity = ARRAY_SIZE((v).init_array), \ + (v).size = 0, \ + (v).items = (v).init_array) + +/// Move data to a new destination and free source +static inline void *_memcpy_free(void *const restrict dest, void *const restrict src, + const size_t size) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET FUNC_ATTR_ALWAYS_INLINE +{ + memcpy(dest, src, size); + XFREE_CLEAR(src); + return dest; +} + +// -V:kvi_push:512 + +/// Resize vector with preallocated array +/// +/// @note May not resize to an array smaller then init_array: if requested, +/// init_array will be used. +/// +/// @param[out] v Vector to resize. +/// @param[in] s New size. +#define kvi_resize(v, s) \ + ((v).capacity = ((s) > ARRAY_SIZE((v).init_array) \ + ? (s) \ + : ARRAY_SIZE((v).init_array)), \ + (v).items = ((v).capacity == ARRAY_SIZE((v).init_array) \ + ? ((v).items == (v).init_array \ + ? (v).items \ + : _memcpy_free((v).init_array, (v).items, \ + (v).size * sizeof((v).items[0]))) \ + : ((v).items == (v).init_array \ + ? memcpy(xmalloc((v).capacity * sizeof((v).items[0])), \ + (v).items, \ + (v).size * sizeof((v).items[0])) \ + : xrealloc((v).items, \ + (v).capacity * sizeof((v).items[0]))))) + +/// Resize vector with preallocated array when it is full +/// +/// @param[out] v Vector to resize. +#define kvi_resize_full(v) \ + /* ARRAY_SIZE((v).init_array) is the minimal capacity of this vector. */ \ + /* Thus when vector is full capacity may not be zero and it is safe */ \ + /* not to bother with checking whether (v).capacity is 0. But now */ \ + /* capacity is not guaranteed to have size that is a power of 2, it is */ \ + /* hard to fix this here and is not very necessary if users will use */ \ + /* 2^x initial array size. */ \ + kvi_resize(v, (v).capacity << 1) + +/// Get location where to store new element to a vector with preallocated array +/// +/// @param[in,out] v Vector to push to. +/// +/// @return Pointer to the place where new value should be stored. +#define kvi_pushp(v) \ + ((((v).size == (v).capacity) ? (kvi_resize_full(v), 0) : 0), \ + ((v).items + ((v).size++))) + +/// Push value to a vector with preallocated array +/// +/// @param[out] v Vector to push to. +/// @param[in] x Value to push. +#define kvi_push(v, x) \ + (*kvi_pushp(v) = (x)) + +/// Free array of elements of a vector with preallocated array if needed +/// +/// @param[out] v Vector to free. +#define kvi_destroy(v) \ + do { \ + if ((v).items != (v).init_array) { \ + XFREE_CLEAR((v).items); \ + } \ + } while (0) + +#endif // NVIM_LIB_KVEC_H diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index a1b57f927e..f28b7a7e28 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -96,8 +96,8 @@ file(MAKE_DIRECTORY ${LINT_SUPPRESSES_ROOT}/src) glob_wrapper(NVIM_SOURCES *.c) glob_wrapper(NVIM_HEADERS *.h) -glob_wrapper(EXTERNAL_SOURCES ../xdiff/*.c ../mpack/*.c ../cjson/*.c) -glob_wrapper(EXTERNAL_HEADERS ../xdiff/*.h ../mpack/*.h ../cjson/*.h) +glob_wrapper(EXTERNAL_SOURCES ../xdiff/*.c ../mpack/*.c ../cjson/*.c ../klib/*.c) +glob_wrapper(EXTERNAL_HEADERS ../xdiff/*.h ../mpack/*.h ../cjson/*.h ../klib/*.h) foreach(subdir os diff --git a/src/nvim/api/private/defs.h b/src/nvim/api/private/defs.h index 9c7e59e4b3..2ae3ee6c7c 100644 --- a/src/nvim/api/private/defs.h +++ b/src/nvim/api/private/defs.h @@ -5,8 +5,8 @@ #include #include +#include "klib/kvec.h" #include "nvim/func_attr.h" -#include "nvim/lib/kvec.h" #include "nvim/types.h" #define ARRAY_DICT_INIT KV_INITIAL_VALUE diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 22d2ffbaf1..b888d09343 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -8,6 +8,7 @@ #include #include +#include "klib/kvec.h" #include "nvim/api/private/converter.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" @@ -22,7 +23,6 @@ #include "nvim/ex_eval.h" #include "nvim/extmark.h" #include "nvim/highlight_group.h" -#include "nvim/lib/kvec.h" #include "nvim/lua/executor.h" #include "nvim/map.h" #include "nvim/map_defs.h" diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h index 2157ad0ec2..65215fa8c8 100644 --- a/src/nvim/api/private/helpers.h +++ b/src/nvim/api/private/helpers.h @@ -1,11 +1,11 @@ #ifndef NVIM_API_PRIVATE_HELPERS_H #define NVIM_API_PRIVATE_HELPERS_H +#include "klib/kvec.h" #include "nvim/api/private/defs.h" #include "nvim/decoration.h" #include "nvim/ex_eval_defs.h" #include "nvim/getchar.h" -#include "nvim/lib/kvec.h" #include "nvim/memory.h" #include "nvim/vim.h" diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 3019a1323c..c18a8209cf 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -41,7 +41,7 @@ typedef struct { // for Map(K, V) #include "nvim/map.h" // for kvec -#include "nvim/lib/kvec.h" +#include "klib/kvec.h" // for marktree #include "nvim/marktree.h" diff --git a/src/nvim/context.h b/src/nvim/context.h index c2deca12c9..ae77e66516 100644 --- a/src/nvim/context.h +++ b/src/nvim/context.h @@ -3,8 +3,8 @@ #include +#include "klib/kvec.h" #include "nvim/api/private/defs.h" -#include "nvim/lib/kvec.h" typedef struct { msgpack_sbuffer regs; ///< Registers. diff --git a/src/nvim/decoration_provider.c b/src/nvim/decoration_provider.c index a11a4d2b04..48664421a3 100644 --- a/src/nvim/decoration_provider.c +++ b/src/nvim/decoration_provider.c @@ -1,13 +1,13 @@ // This is an open source non-commercial project. Dear PVS-Studio, please check // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com +#include "klib/kvec.h" #include "nvim/api/extmark.h" #include "nvim/api/private/helpers.h" #include "nvim/buffer.h" #include "nvim/decoration.h" #include "nvim/decoration_provider.h" #include "nvim/highlight.h" -#include "nvim/lib/kvec.h" #include "nvim/lua/executor.h" static kvec_t(DecorProvider) decor_providers = KV_INITIAL_VALUE; diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index d585509df4..94ef419bed 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -4,6 +4,7 @@ #include #include +#include "klib/kvec.h" #include "nvim/ascii.h" #include "nvim/charset.h" // vim_str2nr #include "nvim/eval.h" @@ -11,7 +12,6 @@ #include "nvim/eval/encode.h" #include "nvim/eval/typval.h" #include "nvim/globals.h" -#include "nvim/lib/kvec.h" #include "nvim/macros.h" #include "nvim/message.h" #include "nvim/vim.h" // OK, FAIL diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index 599bbae0f5..27d35ea24f 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -13,6 +13,7 @@ #include #include +#include "klib/kvec.h" #include "nvim/ascii.h" #include "nvim/buffer_defs.h" #include "nvim/charset.h" // vim_isprintc() @@ -21,7 +22,6 @@ #include "nvim/eval/typval.h" #include "nvim/eval/typval_encode.h" #include "nvim/garray.h" -#include "nvim/lib/kvec.h" #include "nvim/macros.h" #include "nvim/math.h" #include "nvim/mbyte.h" diff --git a/src/nvim/eval/typval_encode.c.h b/src/nvim/eval/typval_encode.c.h index 73b36b8611..ff4f92e40b 100644 --- a/src/nvim/eval/typval_encode.c.h +++ b/src/nvim/eval/typval_encode.c.h @@ -250,7 +250,7 @@ #include "nvim/eval/typval.h" #include "nvim/eval/typval_encode.h" #include "nvim/func_attr.h" -#include "nvim/lib/kvec.h" +#include "klib/kvec.h" // -V::1063 diff --git a/src/nvim/eval/typval_encode.h b/src/nvim/eval/typval_encode.h index ed70ba87ec..33e19c531c 100644 --- a/src/nvim/eval/typval_encode.h +++ b/src/nvim/eval/typval_encode.h @@ -10,9 +10,9 @@ #include #include +#include "klib/kvec.h" #include "nvim/eval/typval.h" #include "nvim/func_attr.h" -#include "nvim/lib/kvec.h" /// Type of the stack entry typedef enum { diff --git a/src/nvim/event/loop.h b/src/nvim/event/loop.h index 65980c6c05..c0bcda40ce 100644 --- a/src/nvim/event/loop.h +++ b/src/nvim/event/loop.h @@ -4,8 +4,8 @@ #include #include +#include "klib/klist.h" #include "nvim/event/multiqueue.h" -#include "nvim/lib/klist.h" #include "nvim/os/time.h" typedef void *WatcherPtr; diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 2a91e9c672..2d39ced582 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -9,6 +9,7 @@ #include #include +#include "klib/kvec.h" #include "nvim/api/extmark.h" #include "nvim/api/vim.h" #include "nvim/arabic.h" @@ -40,7 +41,6 @@ #include "nvim/highlight_group.h" #include "nvim/indent.h" #include "nvim/keycodes.h" -#include "nvim/lib/kvec.h" #include "nvim/log.h" #include "nvim/main.h" #include "nvim/mapping.h" diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c index 290d20b749..176ad0d5c8 100644 --- a/src/nvim/extmark.c +++ b/src/nvim/extmark.c @@ -30,6 +30,7 @@ #include +#include "klib/kbtree.h" #include "nvim/api/extmark.h" #include "nvim/buffer.h" #include "nvim/buffer_updates.h" @@ -37,7 +38,6 @@ #include "nvim/decoration.h" #include "nvim/extmark.h" #include "nvim/globals.h" -#include "nvim/lib/kbtree.h" #include "nvim/map.h" #include "nvim/memline.h" #include "nvim/pos.h" diff --git a/src/nvim/extmark_defs.h b/src/nvim/extmark_defs.h index 5570b5c71e..9ef4ec23e5 100644 --- a/src/nvim/extmark_defs.h +++ b/src/nvim/extmark_defs.h @@ -1,7 +1,7 @@ #ifndef NVIM_EXTMARK_DEFS_H #define NVIM_EXTMARK_DEFS_H -#include "nvim/lib/kvec.h" +#include "klib/kvec.h" #include "nvim/types.h" typedef struct { diff --git a/src/nvim/lib/kbtree.h b/src/nvim/lib/kbtree.h deleted file mode 100644 index 99f79952d7..0000000000 --- a/src/nvim/lib/kbtree.h +++ /dev/null @@ -1,477 +0,0 @@ -/*- - * Copyright 1997-1999, 2001, John-Mark Gurney. - * 2008-2009, Attractive Chaos - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -// Gotchas -// ------- -// -// if you delete from a kbtree while iterating over it you must use -// kb_del_itr and not kb_del otherwise the iterator might point to freed memory. - -#ifndef NVIM_LIB_KBTREE_H -#define NVIM_LIB_KBTREE_H - -#include -#include -#include -#include - -#include "nvim/memory.h" - -#define KB_MAX_DEPTH 64 - -#define __KB_KEY(type, x) (x->key) -#define __KB_PTR(btr, x) (x->ptr) - -#define __KB_TREE_T(name, key_t, T) \ - typedef struct kbnode_##name##_s kbnode_##name##_t; \ - struct kbnode_##name##_s { \ - int32_t n; \ - bool is_internal; \ - key_t key[2*T - 1]; \ - kbnode_##name##_t *ptr[]; \ - }; \ - typedef struct { \ - kbnode_##name##_t *root; \ - int n_keys, n_nodes; \ - } kbtree_##name##_t; \ - typedef struct { \ - kbnode_##name##_t *x; \ - int i; \ - } kbpos_##name##_t; \ - typedef struct { \ - kbpos_##name##_t stack[KB_MAX_DEPTH], *p; \ - } kbitr_##name##_t; \ - - -#define __kb_destroy(kbnode_t, b) do { \ - int i; \ - unsigned int max = 8; \ - kbnode_t *x, **top, **stack = 0; \ - if (b->root) { \ - top = stack = (kbnode_t **)xcalloc(max, sizeof(kbnode_t *)); \ - *top++ = (b)->root; \ - while (top != stack) { \ - x = *--top; \ - if (x->is_internal == 0) { XFREE_CLEAR(x); continue; } \ - for (i = 0; i <= x->n; ++i) \ - if (__KB_PTR(b, x)[i]) { \ - if (top - stack == (int)max) { \ - max <<= 1; \ - stack = (kbnode_t **)xrealloc(stack, max * sizeof(kbnode_t *)); \ - top = stack + (max>>1); \ - } \ - *top++ = __KB_PTR(b, x)[i]; \ - } \ - XFREE_CLEAR(x); \ - } \ - } \ - XFREE_CLEAR(stack); \ -} while (0) - -#define __KB_GET_AUX1(name, key_t, kbnode_t, __cmp) \ - static inline int __kb_getp_aux_##name(const kbnode_t * __restrict x, key_t * __restrict k, \ - int *r) \ - { \ - int tr, *rr, begin = 0, end = x->n; \ - if (x->n == 0) return -1; \ - rr = r? r : &tr; \ - while (begin < end) { \ - int mid = (begin + end) >> 1; \ - if (__cmp(__KB_KEY(key_t, x)[mid], *k) < 0) begin = mid + 1; \ - else end = mid; \ - } \ - if (begin == x->n) { *rr = 1; return x->n - 1; } \ - if ((*rr = __cmp(*k, __KB_KEY(key_t, x)[begin])) < 0) --begin; \ - return begin; \ - } - -#define __KB_GET(name, key_t, kbnode_t) \ - static key_t *kb_getp_##name(kbtree_##name##_t *b, key_t * __restrict k) \ - { \ - if (!b->root) { \ - return 0; \ - } \ - int i, r = 0; \ - kbnode_t *x = b->root; \ - while (x) { \ - i = __kb_getp_aux_##name(x, k, &r); \ - if (i >= 0 && r == 0) return &__KB_KEY(key_t, x)[i]; \ - if (x->is_internal == 0) return 0; \ - x = __KB_PTR(b, x)[i + 1]; \ - } \ - return 0; \ - } \ - static inline key_t *kb_get_##name(kbtree_##name##_t *b, key_t k) \ - { \ - return kb_getp_##name(b, &k); \ - } - -#define __KB_INTERVAL(name, key_t, kbnode_t) \ - static inline void kb_intervalp_##name(kbtree_##name##_t *b, key_t * __restrict k, key_t **lower, \ - key_t **upper) \ - { \ - if (!b->root) { \ - return; \ - } \ - int i, r = 0; \ - kbnode_t *x = b->root; \ - *lower = *upper = 0; \ - while (x) { \ - i = __kb_getp_aux_##name(x, k, &r); \ - if (i >= 0 && r == 0) { \ - *lower = *upper = &__KB_KEY(key_t, x)[i]; \ - return; \ - } \ - if (i >= 0) *lower = &__KB_KEY(key_t, x)[i]; \ - if (i < x->n - 1) *upper = &__KB_KEY(key_t, x)[i + 1]; \ - if (x->is_internal == 0) return; \ - x = __KB_PTR(b, x)[i + 1]; \ - } \ - } \ - static inline void kb_interval_##name(kbtree_##name##_t *b, key_t k, key_t **lower, key_t **upper) \ - { \ - kb_intervalp_##name(b, &k, lower, upper); \ - } - -#define __KB_PUT(name, key_t, kbnode_t, __cmp, T, ILEN) \ - /* x must be an internal node */ \ - static inline void __kb_split_##name(kbtree_##name##_t *b, kbnode_t *x, int i, kbnode_t *y) \ - { \ - kbnode_t *z; \ - z = (kbnode_t *)xcalloc(1, y->is_internal? ILEN : sizeof(kbnode_##name##_t)); \ - ++b->n_nodes; \ - z->is_internal = y->is_internal; \ - z->n = T - 1; \ - memcpy(__KB_KEY(key_t, z), &__KB_KEY(key_t, y)[T], sizeof(key_t) * (T - 1)); \ - if (y->is_internal) memcpy(__KB_PTR(b, z), &__KB_PTR(b, y)[T], sizeof(void *) * T); \ - y->n = T - 1; \ - memmove(&__KB_PTR(b, x)[i + 2], &__KB_PTR(b, \ - x)[i + 1], sizeof(void *) * (unsigned int)(x->n - i)); \ - __KB_PTR(b, x)[i + 1] = z; \ - memmove(&__KB_KEY(key_t, x)[i + 1], &__KB_KEY(key_t, x)[i], \ - sizeof(key_t) * (unsigned int)(x->n - i)); \ - __KB_KEY(key_t, x)[i] = __KB_KEY(key_t, y)[T - 1]; \ - ++x->n; \ - } \ - static inline key_t *__kb_putp_aux_##name(kbtree_##name##_t *b, kbnode_t *x, key_t * __restrict k) \ - { \ - int i = x->n - 1; \ - key_t *ret; \ - if (x->is_internal == 0) { \ - i = __kb_getp_aux_##name(x, k, 0); \ - if (i != x->n - 1) \ - memmove(&__KB_KEY(key_t, x)[i + 2], &__KB_KEY(key_t, \ - x)[i + 1], \ - (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ - ret = &__KB_KEY(key_t, x)[i + 1]; \ - *ret = *k; \ - ++x->n; \ - } else { \ - i = __kb_getp_aux_##name(x, k, 0) + 1; \ - if (__KB_PTR(b, x)[i]->n == 2 * T - 1) { \ - __kb_split_##name(b, x, i, __KB_PTR(b, x)[i]); \ - if (__cmp(*k, __KB_KEY(key_t, x)[i]) > 0) ++i; \ - } \ - ret = __kb_putp_aux_##name(b, __KB_PTR(b, x)[i], k); \ - } \ - return ret; \ - } \ - static inline key_t *kb_putp_##name(kbtree_##name##_t *b, key_t * __restrict k) \ - { \ - if (!b->root) { \ - b->root = (kbnode_t *)xcalloc(1, ILEN); \ - ++b->n_nodes; \ - } \ - kbnode_t *r, *s; \ - ++b->n_keys; \ - r = b->root; \ - if (r->n == 2 * T - 1) { \ - ++b->n_nodes; \ - s = (kbnode_t *)xcalloc(1, ILEN); \ - b->root = s; s->is_internal = 1; s->n = 0; \ - __KB_PTR(b, s)[0] = r; \ - __kb_split_##name(b, s, 0, r); \ - r = s; \ - } \ - return __kb_putp_aux_##name(b, r, k); \ - } \ - static inline void kb_put_##name(kbtree_##name##_t *b, key_t k) \ - { \ - kb_putp_##name(b, &k); \ - } - -#define __KB_DEL(name, key_t, kbnode_t, T) \ - static inline key_t __kb_delp_aux_##name(kbtree_##name##_t *b, kbnode_t *x, key_t * __restrict k, \ - int s) \ - { \ - int yn, zn, i, r = 0; \ - kbnode_t *xp, *y, *z; \ - key_t kp; \ - if (x == 0) return *k; \ - if (s) { /* s can only be 0, 1 or 2 */ \ - r = x->is_internal == 0? 0 : s == 1? 1 : -1; \ - i = s == 1? x->n - 1 : -1; \ - } else i = __kb_getp_aux_##name(x, k, &r); \ - if (x->is_internal == 0) { \ - if (s == 2) ++i; \ - kp = __KB_KEY(key_t, x)[i]; \ - memmove(&__KB_KEY(key_t, x)[i], &__KB_KEY(key_t, \ - x)[i + 1], \ - (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ - --x->n; \ - return kp; \ - } \ - if (r == 0) { \ - if ((yn = __KB_PTR(b, x)[i]->n) >= T) { \ - xp = __KB_PTR(b, x)[i]; \ - kp = __KB_KEY(key_t, x)[i]; \ - __KB_KEY(key_t, x)[i] = __kb_delp_aux_##name(b, xp, 0, 1); \ - return kp; \ - } else if ((zn = __KB_PTR(b, x)[i + 1]->n) >= T) { \ - xp = __KB_PTR(b, x)[i + 1]; \ - kp = __KB_KEY(key_t, x)[i]; \ - __KB_KEY(key_t, x)[i] = __kb_delp_aux_##name(b, xp, 0, 2); \ - return kp; \ - } else if (yn == T - 1 && zn == T - 1) { \ - y = __KB_PTR(b, x)[i]; z = __KB_PTR(b, x)[i + 1]; \ - __KB_KEY(key_t, y)[y->n++] = *k; \ - memmove(&__KB_KEY(key_t, y)[y->n], __KB_KEY(key_t, z), (unsigned int)z->n * sizeof(key_t)); \ - if (y->is_internal) memmove(&__KB_PTR(b, y)[y->n], __KB_PTR(b, \ - z), \ - (unsigned int)(z->n + 1) * sizeof(void *)); \ - y->n += z->n; \ - memmove(&__KB_KEY(key_t, x)[i], &__KB_KEY(key_t, \ - x)[i + 1], \ - (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ - memmove(&__KB_PTR(b, x)[i + 1], &__KB_PTR(b, \ - x)[i + 2], \ - (unsigned int)(x->n - i - 1) * sizeof(void *)); \ - --x->n; \ - XFREE_CLEAR(z); \ - return __kb_delp_aux_##name(b, y, k, s); \ - } \ - } \ - ++i; \ - if ((xp = __KB_PTR(b, x)[i])->n == T - 1) { \ - if (i > 0 && (y = __KB_PTR(b, x)[i - 1])->n >= T) { \ - memmove(&__KB_KEY(key_t, xp)[1], __KB_KEY(key_t, xp), (unsigned int)xp->n * sizeof(key_t)); \ - if (xp->is_internal) memmove(&__KB_PTR(b, xp)[1], __KB_PTR(b, \ - xp), \ - (unsigned int)(xp->n + 1) * sizeof(void *)); \ - __KB_KEY(key_t, xp)[0] = __KB_KEY(key_t, x)[i - 1]; \ - __KB_KEY(key_t, x)[i - 1] = __KB_KEY(key_t, y)[y->n - 1]; \ - if (xp->is_internal) __KB_PTR(b, xp)[0] = __KB_PTR(b, y)[y->n]; \ - --y->n; ++xp->n; \ - } else if (i < x->n && (y = __KB_PTR(b, x)[i + 1])->n >= T) { \ - __KB_KEY(key_t, xp)[xp->n++] = __KB_KEY(key_t, x)[i]; \ - __KB_KEY(key_t, x)[i] = __KB_KEY(key_t, y)[0]; \ - if (xp->is_internal) __KB_PTR(b, xp)[xp->n] = __KB_PTR(b, y)[0]; \ - --y->n; \ - memmove(__KB_KEY(key_t, y), &__KB_KEY(key_t, y)[1], (unsigned int)y->n * sizeof(key_t)); \ - if (y->is_internal) memmove(__KB_PTR(b, y), &__KB_PTR(b, \ - y)[1], \ - (unsigned int)(y->n + 1) * sizeof(void *)); \ - } else if (i > 0 && (y = __KB_PTR(b, x)[i - 1])->n == T - 1) { \ - __KB_KEY(key_t, y)[y->n++] = __KB_KEY(key_t, x)[i - 1]; \ - memmove(&__KB_KEY(key_t, y)[y->n], __KB_KEY(key_t, xp), \ - (unsigned int)xp->n * sizeof(key_t)); \ - if (y->is_internal) memmove(&__KB_PTR(b, y)[y->n], __KB_PTR(b, \ - xp), \ - (unsigned int)(xp->n + 1) * sizeof(void *)); \ - y->n += xp->n; \ - memmove(&__KB_KEY(key_t, x)[i - 1], &__KB_KEY(key_t, \ - x)[i], \ - (unsigned int)(x->n - i) * sizeof(key_t)); \ - memmove(&__KB_PTR(b, x)[i], &__KB_PTR(b, \ - x)[i + 1], (unsigned int)(x->n - i) * sizeof(void *)); \ - --x->n; \ - XFREE_CLEAR(xp); \ - xp = y; \ - } else if (i < x->n && (y = __KB_PTR(b, x)[i + 1])->n == T - 1) { \ - __KB_KEY(key_t, xp)[xp->n++] = __KB_KEY(key_t, x)[i]; \ - memmove(&__KB_KEY(key_t, xp)[xp->n], __KB_KEY(key_t, y), \ - (unsigned int)y->n * sizeof(key_t)); \ - if (xp->is_internal) memmove(&__KB_PTR(b, xp)[xp->n], __KB_PTR(b, y), \ - (unsigned int)(y->n + 1) * sizeof(void *)); \ - xp->n += y->n; \ - memmove(&__KB_KEY(key_t, x)[i], &__KB_KEY(key_t, \ - x)[i + 1], \ - (unsigned int)(x->n - i - 1) * sizeof(key_t)); \ - memmove(&__KB_PTR(b, x)[i + 1], &__KB_PTR(b, \ - x)[i + 2], \ - (unsigned int)(x->n - i - 1) * sizeof(void *)); \ - --x->n; \ - XFREE_CLEAR(y); \ - } \ - } \ - return __kb_delp_aux_##name(b, xp, k, s); \ - } \ - static inline key_t kb_delp_##name(kbtree_##name##_t *b, key_t * __restrict k) \ - { \ - kbnode_t *x; \ - key_t ret; \ - ret = __kb_delp_aux_##name(b, b->root, k, 0); \ - --b->n_keys; \ - if (b->root->n == 0 && b->root->is_internal) { \ - --b->n_nodes; \ - x = b->root; \ - b->root = __KB_PTR(b, x)[0]; \ - XFREE_CLEAR(x); \ - } \ - return ret; \ - } \ - static inline key_t kb_del_##name(kbtree_##name##_t *b, key_t k) \ - { \ - return kb_delp_##name(b, &k); \ - } - -#define __KB_ITR(name, key_t, kbnode_t) \ - static inline void kb_itr_first_##name(kbtree_##name##_t *b, kbitr_##name##_t *itr) \ - { \ - itr->p = NULL; \ - if (b->n_keys == 0) return; \ - itr->p = itr->stack; \ - itr->p->x = b->root; itr->p->i = 0; \ - while (itr->p->x->is_internal && __KB_PTR(b, itr->p->x)[0] != 0) { \ - kbnode_t *x = itr->p->x; \ - ++itr->p; \ - itr->p->x = __KB_PTR(b, x)[0]; itr->p->i = 0; \ - } \ - } \ - static inline int kb_itr_next_##name(kbtree_##name##_t *b, kbitr_##name##_t *itr) \ - { \ - if (itr->p == NULL) return 0; \ - for (;;) { \ - ++itr->p->i; \ - assert(itr->p->i <= 21); \ - while (itr->p->x && itr->p->i <= itr->p->x->n) { \ - itr->p[1].i = 0; \ - itr->p[1].x = itr->p->x->is_internal? __KB_PTR(b, itr->p->x)[itr->p->i] : 0; \ - ++itr->p; \ - } \ - if (itr->p == itr->stack) { \ - itr->p = NULL; \ - return 0; \ - } \ - --itr->p; \ - if (itr->p->x && itr->p->i < itr->p->x->n) return 1; \ - } \ - } \ - static inline int kb_itr_prev_##name(kbtree_##name##_t *b, kbitr_##name##_t *itr) \ - { \ - if (itr->p == NULL) return 0; \ - for (;;) { \ - while (itr->p->x && itr->p->i >= 0) { \ - itr->p[1].x = itr->p->x->is_internal? __KB_PTR(b, itr->p->x)[itr->p->i] : 0; \ - itr->p[1].i = itr->p[1].x ? itr->p[1].x->n : -1; \ - ++itr->p; \ - } \ - if (itr->p == itr->stack) { \ - itr->p = NULL; \ - return 0; \ - } \ - --itr->p; \ - --itr->p->i; \ - if (itr->p->x && itr->p->i >= 0) return 1; \ - } \ - } \ - static inline int kb_itr_getp_##name(kbtree_##name##_t *b, key_t * __restrict k, \ - kbitr_##name##_t *itr) \ - { \ - if (b->n_keys == 0) { \ - itr->p = NULL; \ - return 0; \ - } \ - int i, r = 0; \ - itr->p = itr->stack; \ - itr->p->x = b->root; \ - while (itr->p->x) { \ - i = __kb_getp_aux_##name(itr->p->x, k, &r); \ - itr->p->i = i; \ - if (i >= 0 && r == 0) return 1; \ - ++itr->p->i; \ - assert(itr->p->i <= 21); \ - itr->p[1].x = itr->p->x->is_internal? __KB_PTR(b, itr->p->x)[i + 1] : 0; \ - ++itr->p; \ - } \ - itr->p->i = 0; \ - return 0; \ - } \ - static inline int kb_itr_get_##name(kbtree_##name##_t *b, key_t k, kbitr_##name##_t *itr) \ - { \ - return kb_itr_getp_##name(b, &k, itr); \ - } \ - static inline void kb_del_itr_##name(kbtree_##name##_t *b, kbitr_##name##_t *itr) \ - { \ - key_t k = kb_itr_key(itr); \ - kb_delp_##name(b, &k); \ - kb_itr_getp_##name(b, &k, itr); \ - } - -#define KBTREE_INIT(name, key_t, __cmp, T) \ - KBTREE_INIT_IMPL(name, key_t, kbnode_##name##_t, __cmp, T, \ - (sizeof(kbnode_##name##_t) + (2*T)*sizeof(void *))) - -#define KBTREE_INIT_IMPL(name, key_t, kbnode_t, __cmp, T, ILEN) \ - __KB_TREE_T(name, key_t, T) \ - __KB_GET_AUX1(name, key_t, kbnode_t, __cmp) \ - __KB_GET(name, key_t, kbnode_t) \ - __KB_INTERVAL(name, key_t, kbnode_t) \ - __KB_PUT(name, key_t, kbnode_t, __cmp, T, ILEN) \ - __KB_DEL(name, key_t, kbnode_t, T) \ - __KB_ITR(name, key_t, kbnode_t) - -#define KB_DEFAULT_SIZE 512 - -#define kbtree_t(name) kbtree_##name##_t -#define kbitr_t(name) kbitr_##name##_t -#define kb_init(b) ((b)->n_keys = (b)->n_nodes = 0, (b)->root = 0) -#define kb_destroy(name, b) __kb_destroy(kbnode_##name##_t, b) -#define kb_get(name, b, k) kb_get_##name(b, k) -#define kb_put(name, b, k) kb_put_##name(b, k) -#define kb_del(name, b, k) kb_del_##name(b, k) -#define kb_interval(name, b, k, l, u) kb_interval_##name(b, k, l, u) -#define kb_getp(name, b, k) kb_getp_##name(b, k) -#define kb_putp(name, b, k) kb_putp_##name(b, k) -#define kb_delp(name, b, k) kb_delp_##name(b, k) -#define kb_intervalp(name, b, k, l, u) kb_intervalp_##name(b, k, l, u) - -#define kb_itr_first(name, b, i) kb_itr_first_##name(b, i) -#define kb_itr_get(name, b, k, i) kb_itr_get_##name(b, k, i) -#define kb_itr_getp(name, b, k, i) kb_itr_getp_##name(b, k, i) -#define kb_itr_next(name, b, i) kb_itr_next_##name(b, i) -#define kb_itr_prev(name, b, i) kb_itr_prev_##name(b, i) -#define kb_del_itr(name, b, i) kb_del_itr_##name(b, i) -#define kb_itr_key(itr) __KB_KEY(dummy, (itr)->p->x)[(itr)->p->i] -#define kb_itr_valid(itr) ((itr)->p >= (itr)->stack) - -#define kb_size(b) ((b)->n_keys) - -#define kb_generic_cmp(a, b) (((b) < (a)) - ((a) < (b))) -#define kb_str_cmp(a, b) strcmp(a, b) - -#endif // NVIM_LIB_KBTREE_H diff --git a/src/nvim/lib/khash.h b/src/nvim/lib/khash.h deleted file mode 100644 index 57a41f9c13..0000000000 --- a/src/nvim/lib/khash.h +++ /dev/null @@ -1,730 +0,0 @@ -/* The MIT License - - Copyright (c) 2008, 2009, 2011 by Attractive Chaos - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - */ - -/* - Example: - - #include "nvim/khash.h" - KHASH_MAP_INIT_INT(32, char) - int main() { - int ret, is_missing; - khiter_t k; - khash_t(32) *h = kh_init(32); - k = kh_put(32, h, 5, &ret); - kh_value(h, k) = 10; - k = kh_get(32, h, 10); - is_missing = (k == kh_end(h)); - k = kh_get(32, h, 5); - kh_del(32, h, k); - for (k = kh_begin(h); k != kh_end(h); ++k) - if (kh_exist(h, k)) kh_value(h, k) = 1; - kh_destroy(32, h); - return 0; - } - */ - -/* - 2013-05-02 (0.2.8): - - * Use quadratic probing. When the capacity is power of 2, stepping function - i*(i+1)/2 guarantees to traverse each bucket. It is better than double - hashing on cache performance and is more robust than linear probing. - - In theory, double hashing should be more robust than quadratic probing. - However, my implementation is probably not for large hash tables, because - the second hash function is closely tied to the first hash function, - which reduce the effectiveness of double hashing. - - Reference: http://research.cs.vt.edu/AVresearch/hashing/quadratic.php - - 2011-12-29 (0.2.7): - - * Minor code clean up; no actual effect. - - 2011-09-16 (0.2.6): - - * The capacity is a power of 2. This seems to dramatically improve the - speed for simple keys. Thank Zilong Tan for the suggestion. Reference: - - - http://code.google.com/p/ulib/ - - http://nothings.org/computer/judy/ - - * Allow to optionally use linear probing which usually has better - performance for random input. Double hashing is still the default as it - is more robust to certain non-random input. - - * Added Wang's integer hash function (not used by default). This hash - function is more robust to certain non-random input. - - 2011-02-14 (0.2.5): - - * Allow to declare global functions. - - 2009-09-26 (0.2.4): - - * Improve portability - - 2008-09-19 (0.2.3): - - * Corrected the example - * Improved interfaces - - 2008-09-11 (0.2.2): - - * Improved speed a little in kh_put() - - 2008-09-10 (0.2.1): - - * Added kh_clear() - * Fixed a compiling error - - 2008-09-02 (0.2.0): - - * Changed to token concatenation which increases flexibility. - - 2008-08-31 (0.1.2): - - * Fixed a bug in kh_get(), which has not been tested previously. - - 2008-08-31 (0.1.1): - - * Added destructor - */ - -#ifndef NVIM_LIB_KHASH_H -#define NVIM_LIB_KHASH_H - -/*! - @header - - Generic hash table library. - */ - -#define AC_VERSION_KHASH_H "0.2.8" - -#include -#include -#include -#include - -#include "nvim/func_attr.h" -#include "nvim/memory.h" - -// compiler specific configuration - -#if UINT_MAX == 0xffffffffu -typedef unsigned int khint32_t; -#elif ULONG_MAX == 0xffffffffu -typedef unsigned long khint32_t; -#endif - -#if ULONG_MAX == ULLONG_MAX -typedef unsigned long khint64_t; -#else -typedef unsigned long long khint64_t; -#endif - -#ifdef _MSC_VER -# define kh_inline __inline -#else -# define kh_inline inline -#endif - -typedef khint32_t khint_t; -typedef khint_t khiter_t; - -#define __ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2) -#define __ac_isdel(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&1) -#define __ac_iseither(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&3) -#define __ac_set_isdel_false(flag, i) (flag[i>>4]&=~(khint_t)(1ul<<((i&0xfU)<<1))) -#define __ac_set_isempty_false(flag, i) (flag[i>>4]&=~(khint_t)(2ul<<((i&0xfU)<<1))) -#define __ac_set_isboth_false(flag, i) (flag[i>>4]&=~(khint_t)(3ul<<((i&0xfU)<<1))) -#define __ac_set_isdel_true(flag, i) (flag[i>>4]|=(khint_t)1ul<<((i&0xfU)<<1)) - -#define __ac_fsize(m) ((m) < 16? 1 : (m)>>4) - -#ifndef kroundup32 -# define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, \ - ++(x)) -#endif - -#ifndef kcalloc -# define kcalloc(N, Z) xcalloc(N, Z) -#endif -#ifndef kmalloc -# define kmalloc(Z) xmalloc(Z) -#endif -#ifndef krealloc -# define krealloc(P, Z) xrealloc(P, Z) -#endif -#ifndef kfree -# define kfree(P) XFREE_CLEAR(P) -#endif - -#define __ac_HASH_UPPER 0.77 - -#define __KHASH_TYPE(name, khkey_t, khval_t) \ - typedef struct { \ - khint_t n_buckets, size, n_occupied, upper_bound; \ - khint32_t *flags; \ - khkey_t *keys; \ - khval_t *vals; \ - } kh_##name##_t; - -#define __KHASH_PROTOTYPES(name, khkey_t, khval_t) \ - extern kh_##name##_t *kh_init_##name(void); \ - extern void kh_dealloc_##name(kh_##name##_t *h); \ - extern void kh_destroy_##name(kh_##name##_t *h); \ - extern void kh_clear_##name(kh_##name##_t *h); \ - extern khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); \ - extern void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \ - extern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \ - extern void kh_del_##name(kh_##name##_t *h, khint_t x); - -#define __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, \ - __hash_equal) \ - SCOPE kh_##name##_t *kh_init_##name(void) \ - REAL_FATTR_UNUSED; \ - SCOPE kh_##name##_t *kh_init_##name(void) { \ - return (kh_##name##_t *)kcalloc(1, sizeof(kh_##name##_t)); \ - } \ - SCOPE void kh_dealloc_##name(kh_##name##_t *h) \ - REAL_FATTR_UNUSED; \ - SCOPE void kh_dealloc_##name(kh_##name##_t *h) \ - { \ - kfree(h->keys); \ - kfree(h->flags); \ - kfree(h->vals); \ - } \ - SCOPE void kh_destroy_##name(kh_##name##_t *h) \ - REAL_FATTR_UNUSED; \ - SCOPE void kh_destroy_##name(kh_##name##_t *h) \ - { \ - if (h) { \ - kh_dealloc_##name(h); \ - kfree(h); \ - } \ - } \ - SCOPE void kh_clear_##name(kh_##name##_t *h) \ - REAL_FATTR_UNUSED; \ - SCOPE void kh_clear_##name(kh_##name##_t *h) \ - { \ - if (h && h->flags) { \ - memset(h->flags, 0xaa, __ac_fsize(h->n_buckets) * sizeof(khint32_t)); \ - h->size = h->n_occupied = 0; \ - } \ - } \ - SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \ - REAL_FATTR_UNUSED; \ - SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \ - { \ - if (h->n_buckets) { \ - khint_t k, i, last, mask, step = 0; \ - mask = h->n_buckets - 1; \ - k = __hash_func(key); i = k & mask; \ - last = i; \ - while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || \ - !__hash_equal(h->keys[i], key))) { \ - i = (i + (++step)) & mask; \ - if (i == last) { \ - return h->n_buckets; \ - } \ - } \ - return __ac_iseither(h->flags, i) ? h->n_buckets : i; \ - } else { \ - return 0; \ - } \ - } \ - SCOPE void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \ - REAL_FATTR_UNUSED; \ - SCOPE void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \ - { /* This function uses 0.25*n_buckets bytes of working space instead of */ \ - /* [sizeof(key_t+val_t)+.25]*n_buckets. */ \ - khint32_t *new_flags = 0; \ - khint_t j = 1; \ - { \ - kroundup32(new_n_buckets); \ - if (new_n_buckets < 4) { \ - new_n_buckets = 4; \ - } \ - /* requested size is too small */ \ - if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) { \ - j = 0; \ - } else { /* hash table size to be changed (shrink or expand); rehash */ \ - new_flags = (khint32_t *)kmalloc(__ac_fsize(new_n_buckets) \ - * sizeof(khint32_t)); \ - memset(new_flags, 0xaa, \ - __ac_fsize(new_n_buckets) * sizeof(khint32_t)); \ - if (h->n_buckets < new_n_buckets) { /* expand */ \ - khkey_t *new_keys = (khkey_t *)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \ - h->keys = new_keys; \ - if (kh_is_map) { \ - khval_t *new_vals = \ - (khval_t *)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \ - h->vals = new_vals; \ - } \ - } /* otherwise shrink */ \ - } \ - } \ - if (j) { /* rehashing is needed */ \ - for (j = 0; j != h->n_buckets; ++j) { \ - if (__ac_iseither(h->flags, j) == 0) { \ - khkey_t key = h->keys[j]; \ - khval_t val; \ - khint_t new_mask; \ - new_mask = new_n_buckets - 1; \ - if (kh_is_map) { \ - val = h->vals[j]; \ - } \ - __ac_set_isdel_true(h->flags, j); \ - /* kick-out process; sort of like in Cuckoo hashing */ \ - while (1) { \ - khint_t k, i, step = 0; \ - k = __hash_func(key); \ - i = k & new_mask; \ - while (!__ac_isempty(new_flags, i)) { \ - i = (i + (++step)) & new_mask; \ - } \ - __ac_set_isempty_false(new_flags, i); \ - /* kick out the existing element */ \ - if (i < h->n_buckets && __ac_iseither(h->flags, i) == 0) { \ - { \ - khkey_t tmp = h->keys[i]; \ - h->keys[i] = key; \ - key = tmp; \ - } \ - if (kh_is_map) { \ - khval_t tmp = h->vals[i]; \ - h->vals[i] = val; \ - val = tmp; \ - } \ - /* mark it as deleted in the old hash table */ \ - __ac_set_isdel_true(h->flags, i); \ - } else { /* write the element and jump out of the loop */ \ - h->keys[i] = key; \ - if (kh_is_map) { \ - h->vals[i] = val; \ - } \ - break; \ - } \ - } \ - } \ - } \ - if (h->n_buckets > new_n_buckets) { /* shrink the hash table */ \ - h->keys = (khkey_t *)krealloc((void *)h->keys, \ - new_n_buckets * sizeof(khkey_t)); \ - if (kh_is_map) { \ - h->vals = (khval_t *)krealloc((void *)h->vals, \ - new_n_buckets * sizeof(khval_t)); \ - } \ - } \ - kfree(h->flags); /* free the working space */ \ - h->flags = new_flags; \ - h->n_buckets = new_n_buckets; \ - h->n_occupied = h->size; \ - h->upper_bound = (khint_t)(h->n_buckets * __ac_HASH_UPPER + 0.5); \ - } \ - } \ - SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \ - REAL_FATTR_UNUSED; \ - SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \ - { \ - khint_t x; \ - if (h->n_occupied >= h->upper_bound) { /* update the hash table */ \ - if (h->n_buckets > (h->size << 1)) { \ - kh_resize_##name(h, h->n_buckets - 1); /* clear "deleted" elements */ \ - } else { \ - kh_resize_##name(h, h->n_buckets + 1); /* expand the hash table */ \ - } \ - } /* TODO: implement automatically shrinking; */ \ - /* resize() already support shrinking */ \ - { \ - khint_t k, i, site, last, mask = h->n_buckets - 1, step = 0; \ - x = site = h->n_buckets; \ - k = __hash_func(key); \ - i = k & mask; \ - if (__ac_isempty(h->flags, i)) { \ - x = i; /* for speed up */ \ - } else { \ - last = i; \ - while (!__ac_isempty(h->flags, i) \ - && (__ac_isdel(h->flags, i) \ - || !__hash_equal(h->keys[i], key))) { \ - if (__ac_isdel(h->flags, i)) { \ - site = i; \ - } \ - i = (i + (++step)) & mask; \ - if (i == last) { \ - x = site; \ - break; \ - } \ - } \ - if (x == h->n_buckets) { \ - if (__ac_isempty(h->flags, i) && site != h->n_buckets) { \ - x = site; \ - } else { \ - x = i; \ - } \ - } \ - } \ - } \ - if (__ac_isempty(h->flags, x)) { /* not present at all */ \ - h->keys[x] = key; \ - __ac_set_isboth_false(h->flags, x); \ - h->size++; \ - h->n_occupied++; \ - *ret = 1; \ - } else if (__ac_isdel(h->flags, x)) { /* deleted */ \ - h->keys[x] = key; \ - __ac_set_isboth_false(h->flags, x); \ - h->size++; \ - *ret = 2; \ - } else { \ - *ret = 0; /* Don't touch h->keys[x] if present and not deleted */ \ - } \ - return x; \ - } \ - SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \ - REAL_FATTR_UNUSED; \ - SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \ - { \ - if (x != h->n_buckets && !__ac_iseither(h->flags, x)) { \ - __ac_set_isdel_true(h->flags, x); \ - --h->size; \ - } \ - } - -#define KHASH_DECLARE(name, khkey_t, khval_t) \ - __KHASH_TYPE(name, khkey_t, khval_t) \ - __KHASH_PROTOTYPES(name, khkey_t, khval_t) - -#define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ - __KHASH_TYPE(name, khkey_t, khval_t) \ - __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) - -#define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ - KHASH_INIT2(name, static kh_inline, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) - -// --- BEGIN OF HASH FUNCTIONS --- - -/*! @function - @abstract Integer hash function - @param key The integer [khint32_t] - @return The hash value [khint_t] - */ -#define kh_int_hash_func(key) (khint32_t)(key) -/*! @function - @abstract Integer comparison function - */ -#define kh_int_hash_equal(a, b) ((a) == (b)) -/*! @function - @abstract 64-bit integer hash function - @param key The integer [khint64_t] - @return The hash value [khint_t] - */ -#define kh_int64_hash_func(key) (khint32_t)((key)>>33^(key)^(key)<<11) -/*! @function - @abstract 64-bit integer comparison function - */ -#define kh_int64_hash_equal(a, b) ((a) == (b)) -/*! @function - @abstract const char* hash function - @param s Pointer to a null terminated string - @return The hash value - */ -static kh_inline khint_t __ac_X31_hash_string(const char *s) -{ - khint_t h = (khint_t)*s; - if (h) { - for (++s; *s; ++s) { h = (h << 5) - h + (uint8_t)*s; } - } - return h; -} -/*! @function - @abstract Another interface to const char* hash function - @param key Pointer to a null terminated string [const char*] - @return The hash value [khint_t] - */ -#define kh_str_hash_func(key) __ac_X31_hash_string(key) -/*! @function - @abstract Const char* comparison function - */ -#define kh_str_hash_equal(a, b) (strcmp(a, b) == 0) - -static kh_inline khint_t __ac_Wang_hash(khint_t key) -{ - key += ~(key << 15); - key ^= (key >> 10); - key += (key << 3); - key ^= (key >> 6); - key += ~(key << 11); - key ^= (key >> 16); - return key; -} -#define kh_int_hash_func2(k) __ac_Wang_hash((khint_t)key) - -// --- END OF HASH FUNCTIONS --- - -// Other convenient macros... - -/*! - @abstract Type of the hash table. - @param name Name of the hash table [symbol] - */ -#define khash_t(name) kh_##name##_t - -/*! @function - @abstract Initiate a hash table. - @param name Name of the hash table [symbol] - @return Pointer to the hash table [khash_t(name)*] - */ -#define kh_init(name) kh_init_##name() - -/*! @function - @abstract Destroy a hash table. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - */ -#define kh_destroy(name, h) kh_destroy_##name(h) - -/*! @function - @abstract Free memory referenced directly inside a hash table. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - */ -#define kh_dealloc(name, h) kh_dealloc_##name(h) - -/*! @function - @abstract Reset a hash table without deallocating memory. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - */ -#define kh_clear(name, h) kh_clear_##name(h) - -/*! @function - @abstract Resize a hash table. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - @param s New size [khint_t] - */ -#define kh_resize(name, h, s) kh_resize_##name(h, s) - -/*! @function - @abstract Insert a key to the hash table. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - @param k Key [type of keys] - @param r Extra return code: -1 if the operation failed; - 0 if the key is present in the hash table; - 1 if the bucket is empty (never used); 2 if the element in - the bucket has been deleted [int*] - @return Iterator to the inserted element [khint_t] - */ -#define kh_put(name, h, k, r) kh_put_##name(h, k, r) - -/*! @function - @abstract Retrieve a key from the hash table. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - @param k Key [type of keys] - @return Iterator to the found element, or kh_end(h) if the element is absent [khint_t] - */ -#define kh_get(name, h, k) kh_get_##name(h, k) - -/*! @function - @abstract Remove a key from the hash table. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - @param k Iterator to the element to be deleted [khint_t] - */ -#define kh_del(name, h, k) kh_del_##name(h, k) - -/*! @function - @abstract Test whether a bucket contains data. - @param h Pointer to the hash table [khash_t(name)*] - @param x Iterator to the bucket [khint_t] - @return 1 if containing data; 0 otherwise [int] - */ -#define kh_exist(h, x) (!__ac_iseither((h)->flags, (x))) - -/*! @function - @abstract Get key given an iterator - @param h Pointer to the hash table [khash_t(name)*] - @param x Iterator to the bucket [khint_t] - @return Key [type of keys] - */ -#define kh_key(h, x) ((h)->keys[x]) - -/*! @function - @abstract Get value given an iterator - @param h Pointer to the hash table [khash_t(name)*] - @param x Iterator to the bucket [khint_t] - @return Value [type of values] - @discussion For hash sets, calling this results in segfault. - */ -#define kh_val(h, x) ((h)->vals[x]) - -/*! @function - @abstract Alias of kh_val() - */ -#define kh_value(h, x) ((h)->vals[x]) - -/*! @function - @abstract Get the start iterator - @param h Pointer to the hash table [khash_t(name)*] - @return The start iterator [khint_t] - */ -#define kh_begin(h) (khint_t)(0) - -/*! @function - @abstract Get the end iterator - @param h Pointer to the hash table [khash_t(name)*] - @return The end iterator [khint_t] - */ -#define kh_end(h) ((h)->n_buckets) - -/*! @function - @abstract Get the number of elements in the hash table - @param h Pointer to the hash table [khash_t(name)*] - @return Number of elements in the hash table [khint_t] - */ -#define kh_size(h) ((h)->size) - -/*! @function - @abstract Get the number of buckets in the hash table - @param h Pointer to the hash table [khash_t(name)*] - @return Number of buckets in the hash table [khint_t] - */ -#define kh_n_buckets(h) ((h)->n_buckets) - -/*! @function - @abstract Iterate over the entries in the hash table - @param h Pointer to the hash table [khash_t(name)*] - @param kvar Variable to which key will be assigned - @param vvar Variable to which value will be assigned - @param code Block of code to execute - */ -#define kh_foreach(h, kvar, vvar, code) { khint_t __i; \ - for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \ - if (!kh_exist(h, __i)) continue; \ - (kvar) = kh_key(h, __i); \ - (vvar) = kh_val(h, __i); \ - code; \ - } } - -/*! @function - @abstract Iterate over the values in the hash table - @param h Pointer to the hash table [khash_t(name)*] - @param vvar Variable to which value will be assigned - @param code Block of code to execute - */ -#define kh_foreach_value(h, vvar, code) { khint_t __i; \ - for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \ - if (!kh_exist(h, __i)) continue; \ - (vvar) = kh_val(h, __i); \ - code; \ - } } - -/*! @function - @abstract Iterate over the keys in the hash table - @param h Pointer to the hash table [khash_t(name)*] - @param kvar Variable to which value will be assigned - @param code Block of code to execute - */ -#define kh_foreach_key(h, kvar, code) \ - { \ - khint_t __i; \ - for (__i = kh_begin(h); __i != kh_end(h); __i++) { \ - if (!kh_exist(h, __i)) { \ - continue; \ - } \ - (kvar) = kh_key(h, __i); \ - code; \ - } \ - } - -// More convenient interfaces - -/*! @function - @abstract Instantiate a hash set containing integer keys - @param name Name of the hash table [symbol] - */ -#define KHASH_SET_INIT_INT(name) \ - KHASH_INIT(name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal) - -/*! @function - @abstract Instantiate a hash map containing integer keys - @param name Name of the hash table [symbol] - @param khval_t Type of values [type] - */ -#define KHASH_MAP_INIT_INT(name, khval_t) \ - KHASH_INIT(name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal) - -/*! @function - @abstract Instantiate a hash map containing 64-bit integer keys - @param name Name of the hash table [symbol] - */ -#define KHASH_SET_INIT_INT64(name) \ - KHASH_INIT(name, khint64_t, char, 0, kh_int64_hash_func, kh_int64_hash_equal) - -/*! @function - @abstract Instantiate a hash map containing 64-bit integer keys - @param name Name of the hash table [symbol] - @param khval_t Type of values [type] - */ -#define KHASH_MAP_INIT_INT64(name, khval_t) \ - KHASH_INIT(name, khint64_t, khval_t, 1, kh_int64_hash_func, kh_int64_hash_equal) - -typedef const char *kh_cstr_t; -/*! @function - @abstract Instantiate a hash map containing const char* keys - @param name Name of the hash table [symbol] - */ -#define KHASH_SET_INIT_STR(name) \ - KHASH_INIT(name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal) - -/*! @function - @abstract Instantiate a hash map containing const char* keys - @param name Name of the hash table [symbol] - @param khval_t Type of values [type] - */ -#define KHASH_MAP_INIT_STR(name, khval_t) \ - KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal) - -/*! @function - @abstract Return a literal for an empty hash table. - @param name Name of the hash table [symbol] - */ -#define KHASH_EMPTY_TABLE(name) \ - ((kh_##name##_t) { \ - .n_buckets = 0, \ - .size = 0, \ - .n_occupied = 0, \ - .upper_bound = 0, \ - .flags = NULL, \ - .keys = NULL, \ - .vals = NULL, \ - }) -#endif // NVIM_LIB_KHASH_H diff --git a/src/nvim/lib/klist.h b/src/nvim/lib/klist.h deleted file mode 100644 index a9abbc6dc2..0000000000 --- a/src/nvim/lib/klist.h +++ /dev/null @@ -1,144 +0,0 @@ -/* The MIT License - - Copyright (c) 2008-2009, by Attractive Chaos - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - */ - -#ifndef _AC_KLIST_H -#define _AC_KLIST_H - -#include -#include - -#include "nvim/func_attr.h" -#include "nvim/memory.h" - -#define KMEMPOOL_INIT(name, kmptype_t, kmpfree_f) \ - typedef struct { \ - size_t cnt, n, max; \ - kmptype_t **buf; \ - } kmp_##name##_t; \ - static inline kmp_##name##_t *kmp_init_##name(void) { \ - return xcalloc(1, sizeof(kmp_##name##_t)); \ - } \ - static inline void kmp_destroy_##name(kmp_##name##_t *mp) \ - REAL_FATTR_UNUSED; \ - static inline void kmp_destroy_##name(kmp_##name##_t *mp) { \ - size_t k; \ - for (k = 0; k < mp->n; k++) { \ - kmpfree_f(mp->buf[k]); XFREE_CLEAR(mp->buf[k]); \ - } \ - XFREE_CLEAR(mp->buf); XFREE_CLEAR(mp); \ - } \ - static inline kmptype_t *kmp_alloc_##name(kmp_##name##_t *mp) { \ - mp->cnt++; \ - if (mp->n == 0) { \ - return xcalloc(1, sizeof(kmptype_t)); \ - } \ - return mp->buf[--mp->n]; \ - } \ - static inline void kmp_free_##name(kmp_##name##_t *mp, kmptype_t *p) { \ - mp->cnt--; \ - if (mp->n == mp->max) { \ - mp->max = mp->max ? (mp->max << 1) : 16; \ - mp->buf = xrealloc(mp->buf, sizeof(kmptype_t *) * mp->max); \ - } \ - mp->buf[mp->n++] = p; \ - } - -#define kmempool_t(name) kmp_##name##_t -#define kmp_init(name) kmp_init_##name() -#define kmp_destroy(name, mp) kmp_destroy_##name(mp) -#define kmp_alloc(name, mp) kmp_alloc_##name(mp) -#define kmp_free(name, mp, p) kmp_free_##name(mp, p) - -#define KLIST_INIT(name, kltype_t, kmpfree_t) \ - struct __kl1_##name { \ - kltype_t data; \ - struct __kl1_##name *next; \ - }; \ - typedef struct __kl1_##name kl1_##name; \ - KMEMPOOL_INIT(name, kl1_##name, kmpfree_t) \ - typedef struct { \ - kl1_##name *head, *tail; \ - kmp_##name##_t *mp; \ - size_t size; \ - } kl_##name##_t; \ - static inline kl_##name##_t *kl_init_##name(void) { \ - kl_##name##_t *kl = xcalloc(1, sizeof(kl_##name##_t)); \ - kl->mp = kmp_init(name); \ - kl->head = kl->tail = kmp_alloc(name, kl->mp); \ - kl->head->next = 0; \ - return kl; \ - } \ - static inline void kl_destroy_##name(kl_##name##_t *kl) \ - REAL_FATTR_UNUSED; \ - static inline void kl_destroy_##name(kl_##name##_t *kl) { \ - kl1_##name *p; \ - for (p = kl->head; p != kl->tail; p = p->next) { \ - kmp_free(name, kl->mp, p); \ - } \ - kmp_free(name, kl->mp, p); \ - kmp_destroy(name, kl->mp); \ - XFREE_CLEAR(kl); \ - } \ - static inline void kl_push_##name(kl_##name##_t *kl, kltype_t d) { \ - kl1_##name *q, *p = kmp_alloc(name, kl->mp); \ - q = kl->tail; p->next = 0; kl->tail->next = p; kl->tail = p; \ - kl->size++; \ - q->data = d; \ - } \ - static inline kltype_t kl_shift_at_##name(kl_##name##_t *kl, \ - kl1_##name **n) { \ - assert((*n)->next); \ - kl1_##name *p; \ - kl->size--; \ - p = *n; \ - *n = (*n)->next; \ - if (p == kl->head) { \ - kl->head = *n; \ - } \ - kltype_t d = p->data; \ - kmp_free(name, kl->mp, p); \ - return d; \ - } - -#define kliter_t(name) kl1_##name -#define klist_t(name) kl_##name##_t -#define kl_val(iter) ((iter)->data) -#define kl_next(iter) ((iter)->next) -#define kl_begin(kl) ((kl)->head) -#define kl_end(kl) ((kl)->tail) - -#define kl_init(name) kl_init_##name() -#define kl_destroy(name, kl) kl_destroy_##name(kl) -#define kl_push(name, kl, d) kl_push_##name(kl, d) -#define kl_shift_at(name, kl, node) kl_shift_at_##name(kl, node) -#define kl_shift(name, kl) kl_shift_at(name, kl, &kl->head) -#define kl_empty(kl) ((kl)->size == 0) -// Iteration macros. It's ok to modify the list while iterating as long as a -// `break` statement is executed before the next iteration. -#define kl_iter(name, kl, p) kl_iter_at(name, kl, p, NULL) -#define kl_iter_at(name, kl, p, h) \ - for (kl1_##name **p = h ? h : &kl->head; *p != kl->tail; p = &(*p)->next) - -#endif diff --git a/src/nvim/lib/kvec.h b/src/nvim/lib/kvec.h deleted file mode 100644 index b5b3adf7d2..0000000000 --- a/src/nvim/lib/kvec.h +++ /dev/null @@ -1,236 +0,0 @@ -// The MIT License -// -// Copyright (c) 2008, by Attractive Chaos -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -// An example: -// -// #include "kvec.h" -// int main() { -// kvec_t(int) array = KV_INITIAL_VALUE; -// kv_push(array, 10); // append -// kv_a(array, 20) = 5; // dynamic -// kv_A(array, 20) = 4; // static -// kv_destroy(array); -// return 0; -// } - -#ifndef NVIM_LIB_KVEC_H -#define NVIM_LIB_KVEC_H - -#include -#include - -#include "nvim/memory.h" -#include "nvim/os/os_defs.h" - -#define kv_roundup32(x) \ - ((--(x)), \ - ((x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16), \ - (++(x))) - -#define KV_INITIAL_VALUE { .size = 0, .capacity = 0, .items = NULL } - -#define kvec_t(type) \ - struct { \ - size_t size; \ - size_t capacity; \ - type *items; \ - } - -#define kv_init(v) ((v).size = (v).capacity = 0, (v).items = 0) -#define kv_destroy(v) \ - do { \ - xfree((v).items); \ - kv_init(v); \ - } while (0) -#define kv_A(v, i) ((v).items[(i)]) -#define kv_pop(v) ((v).items[--(v).size]) -#define kv_size(v) ((v).size) -#define kv_max(v) ((v).capacity) -#define kv_Z(v, i) kv_A(v, kv_size(v) - (i) - 1) -#define kv_last(v) kv_Z(v, 0) - -/// Drop last n items from kvec without resizing -/// -/// Previously spelled as `(void)kv_pop(v)`, repeated n times. -/// -/// @param[out] v Kvec to drop items from. -/// @param[in] n Number of elements to drop. -#define kv_drop(v, n) ((v).size -= (n)) - -#define kv_resize(v, s) \ - ((v).capacity = (s), \ - (v).items = xrealloc((v).items, sizeof((v).items[0]) * (v).capacity)) - -#define kv_resize_full(v) \ - kv_resize(v, (v).capacity ? (v).capacity << 1 : 8) - -#define kv_copy(v1, v0) \ - do { \ - if ((v1).capacity < (v0).size) { \ - kv_resize(v1, (v0).size); \ - } \ - (v1).size = (v0).size; \ - memcpy((v1).items, (v0).items, sizeof((v1).items[0]) * (v0).size); \ - } while (0) - -/// fit at least "len" more items -#define kv_ensure_space(v, len) \ - do { \ - if ((v).capacity < (v).size + len) { \ - (v).capacity = (v).size + len; \ - kv_roundup32((v).capacity); \ - kv_resize((v), (v).capacity); \ - } \ - } while (0) - -#define kv_concat_len(v, data, len) \ - do { \ - kv_ensure_space(v, len); \ - memcpy((v).items + (v).size, data, sizeof((v).items[0]) * len); \ - (v).size = (v).size + len; \ - } while (0) - -#define kv_concat(v, str) kv_concat_len(v, str, STRLEN(str)) -#define kv_splice(v1, v0) kv_concat_len(v1, (v0).items, (v0).size) - -#define kv_pushp(v) \ - ((((v).size == (v).capacity) ? (kv_resize_full(v), 0) : 0), \ - ((v).items + ((v).size++))) - -#define kv_push(v, x) \ - (*kv_pushp(v) = (x)) - -#define kv_pushp_c(v) ((v).items + ((v).size++)) -#define kv_push_c(v, x) (*kv_pushp_c(v) = (x)) - -#define kv_a(v, i) \ - (*(((v).capacity <= (size_t)(i) \ - ? ((v).capacity = (v).size = (i) + 1, \ - kv_roundup32((v).capacity), \ - kv_resize((v), (v).capacity), 0UL) \ - : ((v).size <= (size_t)(i) \ - ? (v).size = (i) + 1 \ - : 0UL)), \ - &(v).items[(i)])) - -#define kv_printf(v, ...) kv_do_printf(&(v), __VA_ARGS__) - -/// Type of a vector with a few first members allocated on stack -/// -/// Is compatible with #kv_A, #kv_pop, #kv_size, #kv_max, #kv_last. -/// Is not compatible with #kv_resize, #kv_resize_full, #kv_copy, #kv_push, -/// #kv_pushp, #kv_a, #kv_destroy. -/// -/// @param[in] type Type of vector elements. -/// @param[in] init_size Number of the elements in the initial array. -#define kvec_withinit_t(type, INIT_SIZE) \ - struct { \ - size_t size; \ - size_t capacity; \ - type *items; \ - type init_array[INIT_SIZE]; \ - } - -/// Initialize vector with preallocated array -/// -/// @param[out] v Vector to initialize. -#define kvi_init(v) \ - ((v).capacity = ARRAY_SIZE((v).init_array), \ - (v).size = 0, \ - (v).items = (v).init_array) - -/// Move data to a new destination and free source -static inline void *_memcpy_free(void *const restrict dest, void *const restrict src, - const size_t size) - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET FUNC_ATTR_ALWAYS_INLINE -{ - memcpy(dest, src, size); - XFREE_CLEAR(src); - return dest; -} - -// -V:kvi_push:512 - -/// Resize vector with preallocated array -/// -/// @note May not resize to an array smaller then init_array: if requested, -/// init_array will be used. -/// -/// @param[out] v Vector to resize. -/// @param[in] s New size. -#define kvi_resize(v, s) \ - ((v).capacity = ((s) > ARRAY_SIZE((v).init_array) \ - ? (s) \ - : ARRAY_SIZE((v).init_array)), \ - (v).items = ((v).capacity == ARRAY_SIZE((v).init_array) \ - ? ((v).items == (v).init_array \ - ? (v).items \ - : _memcpy_free((v).init_array, (v).items, \ - (v).size * sizeof((v).items[0]))) \ - : ((v).items == (v).init_array \ - ? memcpy(xmalloc((v).capacity * sizeof((v).items[0])), \ - (v).items, \ - (v).size * sizeof((v).items[0])) \ - : xrealloc((v).items, \ - (v).capacity * sizeof((v).items[0]))))) - -/// Resize vector with preallocated array when it is full -/// -/// @param[out] v Vector to resize. -#define kvi_resize_full(v) \ - /* ARRAY_SIZE((v).init_array) is the minimal capacity of this vector. */ \ - /* Thus when vector is full capacity may not be zero and it is safe */ \ - /* not to bother with checking whether (v).capacity is 0. But now */ \ - /* capacity is not guaranteed to have size that is a power of 2, it is */ \ - /* hard to fix this here and is not very necessary if users will use */ \ - /* 2^x initial array size. */ \ - kvi_resize(v, (v).capacity << 1) - -/// Get location where to store new element to a vector with preallocated array -/// -/// @param[in,out] v Vector to push to. -/// -/// @return Pointer to the place where new value should be stored. -#define kvi_pushp(v) \ - ((((v).size == (v).capacity) ? (kvi_resize_full(v), 0) : 0), \ - ((v).items + ((v).size++))) - -/// Push value to a vector with preallocated array -/// -/// @param[out] v Vector to push to. -/// @param[in] x Value to push. -#define kvi_push(v, x) \ - (*kvi_pushp(v) = (x)) - -/// Free array of elements of a vector with preallocated array if needed -/// -/// @param[out] v Vector to free. -#define kvi_destroy(v) \ - do { \ - if ((v).items != (v).init_array) { \ - XFREE_CLEAR((v).items); \ - } \ - } while (0) - -#endif // NVIM_LIB_KVEC_H diff --git a/src/nvim/lua/converter.c b/src/nvim/lua/converter.c index 735a75a6f1..bdb0719809 100644 --- a/src/nvim/lua/converter.c +++ b/src/nvim/lua/converter.c @@ -15,12 +15,12 @@ #include "nvim/memory.h" // FIXME: vim.h is not actually needed, but otherwise it states MAXPATHL is // redefined +#include "klib/kvec.h" #include "nvim/ascii.h" #include "nvim/eval/decode.h" #include "nvim/eval/typval.h" #include "nvim/eval/userfunc.h" #include "nvim/globals.h" -#include "nvim/lib/kvec.h" #include "nvim/lua/converter.h" #include "nvim/lua/executor.h" #include "nvim/macros.h" diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c index f3c67e265f..64cace9ab4 100644 --- a/src/nvim/lua/treesitter.c +++ b/src/nvim/lua/treesitter.c @@ -16,9 +16,9 @@ #include #include +#include "klib/kvec.h" #include "nvim/api/private/helpers.h" #include "nvim/buffer.h" -#include "nvim/lib/kvec.h" #include "nvim/log.h" #include "nvim/lua/treesitter.h" #include "nvim/map.h" diff --git a/src/nvim/map.c b/src/nvim/map.c index 1561b089a7..24478c6091 100644 --- a/src/nvim/map.c +++ b/src/nvim/map.c @@ -14,7 +14,7 @@ #include #include -#include "nvim/lib/khash.h" +#include "klib/khash.h" #include "nvim/map.h" #include "nvim/map_defs.h" #include "nvim/memory.h" diff --git a/src/nvim/map_defs.h b/src/nvim/map_defs.h index 7b4596ce2e..61afedbe50 100644 --- a/src/nvim/map_defs.h +++ b/src/nvim/map_defs.h @@ -1,7 +1,7 @@ #ifndef NVIM_MAP_DEFS_H #define NVIM_MAP_DEFS_H -#include "nvim/lib/khash.h" +#include "klib/khash.h" typedef const char *cstr_t; typedef void *ptr_t; diff --git a/src/nvim/marktree.c b/src/nvim/marktree.c index 03340a99d6..ad1680322c 100644 --- a/src/nvim/marktree.c +++ b/src/nvim/marktree.c @@ -49,8 +49,8 @@ #include +#include "klib/kvec.h" #include "nvim/garray.h" -#include "nvim/lib/kvec.h" #include "nvim/marktree.h" #define T MT_BRANCH_FACTOR diff --git a/src/nvim/message.h b/src/nvim/message.h index 811e621c11..31cd54f18c 100644 --- a/src/nvim/message.h +++ b/src/nvim/message.h @@ -5,9 +5,9 @@ #include #include +#include "klib/kvec.h" #include "nvim/api/private/defs.h" #include "nvim/grid_defs.h" -#include "nvim/lib/kvec.h" #include "nvim/macros.h" #include "nvim/types.h" diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index d22bcb29d5..71ed5ccf81 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -7,6 +7,7 @@ #include #include +#include "klib/kvec.h" #include "nvim/api/private/helpers.h" #include "nvim/api/ui.h" #include "nvim/api/vim.h" @@ -18,7 +19,6 @@ #include "nvim/event/rstream.h" #include "nvim/event/socket.h" #include "nvim/event/wstream.h" -#include "nvim/lib/kvec.h" #include "nvim/log.h" #include "nvim/main.h" #include "nvim/map.h" diff --git a/src/nvim/msgpack_rpc/helpers.c b/src/nvim/msgpack_rpc/helpers.c index 488321be42..ddca9afad0 100644 --- a/src/nvim/msgpack_rpc/helpers.c +++ b/src/nvim/msgpack_rpc/helpers.c @@ -5,10 +5,10 @@ #include #include +#include "klib/kvec.h" #include "nvim/api/private/dispatch.h" #include "nvim/api/private/helpers.h" #include "nvim/assert.h" -#include "nvim/lib/kvec.h" #include "nvim/log.h" #include "nvim/memory.h" #include "nvim/msgpack_rpc/helpers.h" diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 6391644f83..dee23e9193 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -9,6 +9,7 @@ #include #include +#include "klib/kvec.h" #include "nvim/ascii.h" #include "nvim/assert.h" #include "nvim/buffer.h" @@ -28,7 +29,6 @@ #include "nvim/globals.h" #include "nvim/indent.h" #include "nvim/indent_c.h" -#include "nvim/lib/kvec.h" #include "nvim/log.h" #include "nvim/macros.h" #include "nvim/mark.h" diff --git a/src/nvim/os/pty_conpty_win.h b/src/nvim/os/pty_conpty_win.h index 15e7c3da0c..0c25a5970e 100644 --- a/src/nvim/os/pty_conpty_win.h +++ b/src/nvim/os/pty_conpty_win.h @@ -1,7 +1,7 @@ #ifndef NVIM_OS_PTY_CONPTY_WIN_H #define NVIM_OS_PTY_CONPTY_WIN_H -#include "nvim/lib/kvec.h" +#include "klib/kvec.h" #include "nvim/os/input.h" #ifndef HPCON diff --git a/src/nvim/os/pty_process_unix.c b/src/nvim/os/pty_process_unix.c index c5d6af0ff6..0b7af87267 100644 --- a/src/nvim/os/pty_process_unix.c +++ b/src/nvim/os/pty_process_unix.c @@ -31,11 +31,11 @@ #include +#include "klib/klist.h" #include "nvim/event/loop.h" #include "nvim/event/process.h" #include "nvim/event/rstream.h" #include "nvim/event/wstream.h" -#include "nvim/lib/klist.h" #include "nvim/log.h" #include "nvim/os/os.h" #include "nvim/os/pty_process_unix.h" diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index ca3e32e871..9766c8f3d9 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -7,6 +7,7 @@ #include #include +#include "klib/kvec.h" #include "nvim/ascii.h" #include "nvim/charset.h" #include "nvim/eval.h" @@ -15,7 +16,6 @@ #include "nvim/event/rstream.h" #include "nvim/ex_cmds.h" #include "nvim/fileio.h" -#include "nvim/lib/kvec.h" #include "nvim/log.h" #include "nvim/main.h" #include "nvim/memline.h" diff --git a/src/nvim/shada.c b/src/nvim/shada.c index f735829030..7580cc8897 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -11,6 +11,8 @@ #include #include +#include "klib/khash.h" +#include "klib/kvec.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" #include "nvim/ascii.h" @@ -25,8 +27,6 @@ #include "nvim/fileio.h" #include "nvim/garray.h" #include "nvim/globals.h" -#include "nvim/lib/khash.h" -#include "nvim/lib/kvec.h" #include "nvim/macros.h" #include "nvim/mark.h" #include "nvim/memory.h" diff --git a/src/nvim/state.c b/src/nvim/state.c index 8b07c484e6..0353e61742 100644 --- a/src/nvim/state.c +++ b/src/nvim/state.c @@ -3,6 +3,7 @@ #include +#include "klib/kvec.h" #include "nvim/ascii.h" #include "nvim/autocmd.h" #include "nvim/drawscreen.h" @@ -10,7 +11,6 @@ #include "nvim/ex_docmd.h" #include "nvim/getchar.h" #include "nvim/insexpand.h" -#include "nvim/lib/kvec.h" #include "nvim/log.h" #include "nvim/main.h" #include "nvim/option.h" diff --git a/src/nvim/strings.h b/src/nvim/strings.h index 9ef1eb5816..6ad9daf5bf 100644 --- a/src/nvim/strings.h +++ b/src/nvim/strings.h @@ -5,8 +5,8 @@ #include #include +#include "klib/kvec.h" #include "nvim/eval/typval.h" -#include "nvim/lib/kvec.h" #include "nvim/types.h" /// Append string to string and return pointer to the next byte diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 5a331463e3..4eabecb74a 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -13,13 +13,13 @@ # include #endif +#include "klib/kvec.h" #include "nvim/api/private/helpers.h" #include "nvim/api/vim.h" #include "nvim/ascii.h" #include "nvim/event/loop.h" #include "nvim/event/signal.h" #include "nvim/highlight.h" -#include "nvim/lib/kvec.h" #include "nvim/log.h" #include "nvim/main.h" #include "nvim/map.h" diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c index f23615180e..8ef24b484e 100644 --- a/src/nvim/ui_compositor.c +++ b/src/nvim/ui_compositor.c @@ -11,12 +11,12 @@ #include #include +#include "klib/kvec.h" #include "nvim/api/private/helpers.h" #include "nvim/ascii.h" #include "nvim/grid.h" #include "nvim/highlight.h" #include "nvim/highlight_group.h" -#include "nvim/lib/kvec.h" #include "nvim/log.h" #include "nvim/lua/executor.h" #include "nvim/main.h" diff --git a/src/nvim/undo.c b/src/nvim/undo.c index 0a5a3133df..d67863f84f 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -81,6 +81,7 @@ #include #include "auto/config.h" +#include "klib/kvec.h" #include "nvim/ascii.h" #include "nvim/buffer.h" #include "nvim/buffer_updates.h" @@ -94,7 +95,6 @@ #include "nvim/fold.h" #include "nvim/garray.h" #include "nvim/getchar.h" -#include "nvim/lib/kvec.h" #include "nvim/mark.h" #include "nvim/memline.h" #include "nvim/memory.h" diff --git a/src/nvim/viml/parser/expressions.c b/src/nvim/viml/parser/expressions.c index d12a690b83..4564831824 100644 --- a/src/nvim/viml/parser/expressions.c +++ b/src/nvim/viml/parser/expressions.c @@ -55,11 +55,11 @@ #include #include +#include "klib/kvec.h" #include "nvim/ascii.h" #include "nvim/assert.h" #include "nvim/charset.h" #include "nvim/eval/typval.h" -#include "nvim/lib/kvec.h" #include "nvim/memory.h" #include "nvim/types.h" #include "nvim/vim.h" diff --git a/src/nvim/viml/parser/parser.h b/src/nvim/viml/parser/parser.h index 55f54cedbe..404dc5a0d1 100644 --- a/src/nvim/viml/parser/parser.h +++ b/src/nvim/viml/parser/parser.h @@ -5,8 +5,8 @@ #include #include +#include "klib/kvec.h" #include "nvim/func_attr.h" -#include "nvim/lib/kvec.h" #include "nvim/mbyte.h" #include "nvim/memory.h" -- cgit From fded344f38f0814256b3acd01d94d5942a22f7fc Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 25 Sep 2022 21:38:46 +0800 Subject: fix(extmarks): make virt_lines always start at 0 virtcol --- src/nvim/drawline.c | 2 +- test/functional/ui/decorations_spec.lua | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 5c3fa3d3b0..10e1d95730 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -2607,7 +2607,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, assert(i >= 0); int offset = kv_A(virt_lines, i).left_col ? 0 : win_col_offset; draw_virt_text_item(buf, offset, kv_A(virt_lines, i).line, - kHlModeReplace, grid->cols, offset); + kHlModeReplace, grid->cols, 0); } } else { draw_virt_text(wp, buf, win_col_offset, &draw_col, grid->cols, row); diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua index eff6fe6d23..44b88d702f 100644 --- a/test/functional/ui/decorations_spec.lua +++ b/test/functional/ui/decorations_spec.lua @@ -1550,6 +1550,38 @@ if (h->n_buckets < new_n_buckets) { // expand } | | ]]} + + command 'set number' + screen:expect{grid=[[ + {9: 1 }^if (h->n_buckets < new_n_buckets) { // expand | + {9: 2 } khkey_t *new_keys = (khkey_t *)krealloc((voi| + {9: }d *)h->keys, new_n_buckets * sizeof(khkey_t));| + {9: }{1:>>}{2: very tabby}text with tabs | + {9: 3 } h->keys = new_keys; | + {9: 4 } if (kh_is_map && val_size) { | + {9: 5 } char *new_vals = krealloc( h->vals_buf, ne| + {9: }w_n_buckets * val_size); | + {9: 6 } h->vals_buf = new_vals; | + {9: 7 } } | + {9: 8 }} | + | + ]]} + + command 'set tabstop&' + screen:expect{grid=[[ + {9: 1 }^if (h->n_buckets < new_n_buckets) { // expand | + {9: 2 } khkey_t *new_keys = (khkey_t *)krealloc((voi| + {9: }d *)h->keys, new_n_buckets * sizeof(khkey_t));| + {9: }{1:>>}{2: very tabby}text with tabs | + {9: 3 } h->keys = new_keys; | + {9: 4 } if (kh_is_map && val_size) { | + {9: 5 } char *new_vals = krealloc( h->vals_buf, ne| + {9: }w_n_buckets * val_size); | + {9: 6 } h->vals_buf = new_vals; | + {9: 7 } } | + {9: 8 }} | + | + ]]} end) end) -- cgit From f8a1cadccff39923643fdea2e282be9fffa60e99 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 25 Sep 2022 22:29:25 +0800 Subject: fix(filetype): use :setf instead of nvim_buf_set_option (#20334) --- runtime/filetype.lua | 8 ++++++-- test/functional/lua/filetype_spec.lua | 8 ++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/runtime/filetype.lua b/runtime/filetype.lua index c50ba6453d..ee9d5a0a75 100644 --- a/runtime/filetype.lua +++ b/runtime/filetype.lua @@ -14,10 +14,14 @@ vim.api.nvim_create_autocmd({ 'BufRead', 'BufNewFile', 'StdinReadPost' }, { -- Generic configuration file used as fallback ft = require('vim.filetype.detect').conf(args.file, args.buf) if ft then - vim.api.nvim_cmd({ cmd = 'setf', args = { 'FALLBACK', ft } }, {}) + vim.api.nvim_buf_call(args.buf, function() + vim.api.nvim_cmd({ cmd = 'setf', args = { 'FALLBACK', ft } }, {}) + end) end else - vim.api.nvim_buf_set_option(args.buf, 'filetype', ft) + vim.api.nvim_buf_call(args.buf, function() + vim.api.nvim_cmd({ cmd = 'setf', args = { ft } }, {}) + end) if on_detect then on_detect(args.buf) end diff --git a/test/functional/lua/filetype_spec.lua b/test/functional/lua/filetype_spec.lua index be57b2db31..2a7be53164 100644 --- a/test/functional/lua/filetype_spec.lua +++ b/test/functional/lua/filetype_spec.lua @@ -1,6 +1,7 @@ local helpers = require('test.functional.helpers')(after_each) local exec_lua = helpers.exec_lua local eq = helpers.eq +local meths = helpers.meths local clear = helpers.clear local pathroot = helpers.pathroot local command = helpers.command @@ -94,3 +95,10 @@ describe('vim.filetype', function() ]]) end) end) + +describe('filetype.lua', function() + it('does not override user autocommands that set filetype #20333', function() + clear({args={'--clean', '--cmd', 'autocmd BufRead *.md set filetype=notmarkdown', 'README.md'}}) + eq('notmarkdown', meths.buf_get_option(0, 'filetype')) + end) +end) -- cgit From a6c9764edaa349f5f268e5e3bf8b940e137fb5c4 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 26 Sep 2022 07:00:37 +0800 Subject: fix(inccommand): deal with unsynced undo (#20041) --- src/nvim/ex_getln.c | 9 +++++++++ test/functional/ui/inccommand_spec.lua | 37 ++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 2d39ced582..0ccc12c9b4 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -136,6 +136,7 @@ typedef struct cmdpreview_win_info { typedef struct cmdpreview_buf_info { buf_T *buf; + bool save_b_u_synced; time_t save_b_u_time_cur; long save_b_u_seq_cur; u_header_T *save_b_u_newhead; @@ -2131,6 +2132,7 @@ static void cmdpreview_prepare(CpInfo *cpinfo) CpBufInfo cp_bufinfo; cp_bufinfo.buf = buf; + cp_bufinfo.save_b_u_synced = buf->b_u_synced; cp_bufinfo.save_b_u_time_cur = buf->b_u_time_cur; cp_bufinfo.save_b_u_seq_cur = buf->b_u_seq_cur; cp_bufinfo.save_b_u_newhead = buf->b_u_newhead; @@ -2168,6 +2170,8 @@ static void cmdpreview_prepare(CpInfo *cpinfo) cmdmod.cmod_split = 0; // Disable :leftabove/botright modifiers cmdmod.cmod_tab = 0; // Disable :tab modifier cmdmod.cmod_flags |= CMOD_NOSWAPFILE; // Disable swap for preview buffer + + u_sync(true); } // Restore the state of buffers and windows before command preview. @@ -2200,6 +2204,11 @@ static void cmdpreview_restore_state(CpInfo *cpinfo) buf->b_u_newhead = cp_bufinfo.save_b_u_newhead; buf->b_u_time_cur = cp_bufinfo.save_b_u_time_cur; } + + if (buf->b_u_curhead == NULL) { + buf->b_u_synced = cp_bufinfo.save_b_u_synced; + } + if (cp_bufinfo.save_changedtick != buf_get_changedtick(buf)) { buf_set_changedtick(buf, cp_bufinfo.save_changedtick); } diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua index 49b3c7a655..6fbf9b72c8 100644 --- a/test/functional/ui/inccommand_spec.lua +++ b/test/functional/ui/inccommand_spec.lua @@ -3047,6 +3047,43 @@ it(":substitute doesn't crash with inccommand, if undo is empty #12932", functio assert_alive() end) +it(':substitute with inccommand works properly if undo is not synced #20029', function() + local screen = Screen.new(30, 6) + clear() + common_setup(screen, 'nosplit', 'foo\nbar\nbaz') + meths.set_keymap('x', '', '``>obbbbb asdfV`lljj') + screen:expect([[ + aaaaa | + foo | + bar | + baz | + bbbbb | + :'<,'>s/asdf/^ | + ]]) + feed('hjkl') + screen:expect([[ + aaaaa {12:hjkl} | + foo | + bar | + baz | + bbbbb {12:hjkl} | + :'<,'>s/asdf/hjkl^ | + ]]) + feed('') + expect([[ + aaaaa hjkl + foo + bar + baz + bbbbb hjkl]]) + feed('u') + expect([[ + foo + bar + baz]]) +end) + it('long :%s/ with inccommand does not collapse cmdline', function() local screen = Screen.new(10,5) clear() -- cgit From ac66f5af06ac1f306b0ddb366ba81093508546c4 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 26 Sep 2022 07:15:07 +0800 Subject: fix!: make :undo! notify buffer update callbacks (#20344) When :undo! was introduced to Nvim the implementation of 'inccommand' preview callback hasn't been fully decided yet, so not notifying buffer update callbacks made sense for 'inccommand' preview callback in case it needs to undo the changes itself. Now it turns out that the undo-and-forget is done automatically for 'inccommand', so it doesn't make sense for :undo! to avoid notifying buffer update callbacks anymore. --- src/nvim/ex_docmd.c | 4 ++-- src/nvim/ex_getln.c | 2 +- src/nvim/undo.c | 8 ++++---- test/functional/lua/buffer_updates_spec.lua | 18 ++++++++++++++++++ 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 085948f7b1..7ece195374 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -5867,7 +5867,7 @@ static void ex_undo(exarg_T *eap) { if (eap->addr_count != 1) { if (eap->forceit) { - u_undo_and_forget(1); // :undo! + u_undo_and_forget(1, true); // :undo! } else { u_undo(1); // :undo } @@ -5894,7 +5894,7 @@ static void ex_undo(exarg_T *eap) emsg(_(e_undobang_cannot_redo_or_move_branch)); return; } - u_undo_and_forget(count); + u_undo_and_forget(count, true); } else { // :undo 123 undo_time(step, false, false, true); } diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 0ccc12c9b4..bc31f5a6cf 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2194,7 +2194,7 @@ static void cmdpreview_restore_state(CpInfo *cpinfo) aco_save_T aco; aucmd_prepbuf(&aco, buf); // Undo invisibly. This also moves the cursor! - if (!u_undo_and_forget(count)) { + if (!u_undo_and_forget(count, false)) { abort(); } aucmd_restbuf(&aco); diff --git a/src/nvim/undo.c b/src/nvim/undo.c index d67863f84f..1a9066d7f1 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -1771,16 +1771,16 @@ void u_redo(int count) /// Undo and remove the branch from the undo tree. /// Also moves the cursor (as a "normal" undo would). -bool u_undo_and_forget(int count) +/// +/// @param do_buf_event If `true`, send the changedtick with the buffer updates +bool u_undo_and_forget(int count, bool do_buf_event) { if (curbuf->b_u_synced == false) { u_sync(true); count = 1; } undo_undoes = true; - u_doit(count, true, - // Don't send nvim_buf_lines_event for u_undo_and_forget(). - false); + u_doit(count, true, do_buf_event); if (curbuf->b_u_curhead == NULL) { // nothing was undone. diff --git a/test/functional/lua/buffer_updates_spec.lua b/test/functional/lua/buffer_updates_spec.lua index 10de45274c..c6c0964ddb 100644 --- a/test/functional/lua/buffer_updates_spec.lua +++ b/test/functional/lua/buffer_updates_spec.lua @@ -118,6 +118,24 @@ describe('lua buffer event callbacks: on_lines', function() } tick = tick + 1 + tick = tick + 1 + command('redo') + check_events { + { "test1", "lines", 1, tick, 3, 5, 4, 32 }; + { "test2", "lines", 1, tick, 3, 5, 4, 32 }; + { "test2", "changedtick", 1, tick+1 }; + } + tick = tick + 1 + + tick = tick + 1 + command('undo!') + check_events { + { "test1", "lines", 1, tick, 3, 4, 5, 13 }; + { "test2", "lines", 1, tick, 3, 4, 5, 13 }; + { "test2", "changedtick", 1, tick+1 }; + } + tick = tick + 1 + -- simulate next callback returning true exec_lua("test_unreg = 'test1'") -- cgit From 9ffa041a9a5fc8cd9acca97cae16f66ba0c82805 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 26 Sep 2022 07:46:58 +0800 Subject: vim-patch:9.0.0586: missing change in test (#20347) Problem: Missing change in test. Solution: Add the test change. https://github.com/vim/vim/commit/124af71a28a633fa655cff41bc21d398481ce45f vim-patch:9.0.0585: when long message test fails the error message is not visible Problem: When long message test fails the error message is not visible. Solution: Dump more lines. https://github.com/vim/vim/commit/6a879878f4e1918a05244e6acd4c73c3135cf941 --- src/nvim/testdir/test_messages.vim | 7 +++---- test/functional/legacy/messages_spec.lua | 10 +++++++++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/nvim/testdir/test_messages.vim b/src/nvim/testdir/test_messages.vim index 2672fcb69d..8e66a2c529 100644 --- a/src/nvim/testdir/test_messages.vim +++ b/src/nvim/testdir/test_messages.vim @@ -357,15 +357,14 @@ func Test_quit_long_message() let content =<< trim END echom range(9999)->join("\x01") END - call writefile(content, 'Xtest_quit_message') - let buf = RunVimInTerminal('-S Xtest_quit_message', #{rows: 6, wait_for_ruler: 0}) - call WaitForAssert({-> assert_match('^-- More --', term_getline(buf, 6))}) + call writefile(content, 'Xtest_quit_message', 'D') + let buf = RunVimInTerminal('-S Xtest_quit_message', #{rows: 10, wait_for_ruler: 0}) + call WaitForAssert({-> assert_match('^-- More --', term_getline(buf, 10))}) call term_sendkeys(buf, "q") call VerifyScreenDump(buf, 'Test_quit_long_message', {}) " clean up call StopVimInTerminal(buf) - call delete('Xtest_quit_message') endfunc " this was missing a terminating NUL diff --git a/test/functional/legacy/messages_spec.lua b/test/functional/legacy/messages_spec.lua index c76ce62ef0..5b671bbfdf 100644 --- a/test/functional/legacy/messages_spec.lua +++ b/test/functional/legacy/messages_spec.lua @@ -352,7 +352,7 @@ describe('messages', function() -- oldtest: Test_quit_long_message() it('with control characters can be quit vim-patch:8.2.1844', function() - screen:try_resize(40, 6) + screen:try_resize(40, 10) feed([[:echom range(9999)->join("\x01")]]) screen:expect([[ 0{3:^A}1{3:^A}2{3:^A}3{3:^A}4{3:^A}5{3:^A}6{3:^A}7{3:^A}8{3:^A}9{3:^A}10{3:^A}11{3:^A}12| @@ -360,6 +360,10 @@ describe('messages', function() {3:^A}23{3:^A}24{3:^A}25{3:^A}26{3:^A}27{3:^A}28{3:^A}29{3:^A}30{3:^A}31{3:^A}32| {3:^A}33{3:^A}34{3:^A}35{3:^A}36{3:^A}37{3:^A}38{3:^A}39{3:^A}40{3:^A}41{3:^A}42| {3:^A}43{3:^A}44{3:^A}45{3:^A}46{3:^A}47{3:^A}48{3:^A}49{3:^A}50{3:^A}51{3:^A}52| + {3:^A}53{3:^A}54{3:^A}55{3:^A}56{3:^A}57{3:^A}58{3:^A}59{3:^A}60{3:^A}61{3:^A}62| + {3:^A}63{3:^A}64{3:^A}65{3:^A}66{3:^A}67{3:^A}68{3:^A}69{3:^A}70{3:^A}71{3:^A}72| + {3:^A}73{3:^A}74{3:^A}75{3:^A}76{3:^A}77{3:^A}78{3:^A}79{3:^A}80{3:^A}81{3:^A}82| + {3:^A}83{3:^A}84{3:^A}85{3:^A}86{3:^A}87{3:^A}88{3:^A}89{3:^A}90{3:^A}91{3:^A}92| {1:-- More --}^ | ]]) feed('q') @@ -368,6 +372,10 @@ describe('messages', function() {0:~ }| {0:~ }| {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| {0:~ }| | ]]) -- cgit From 63be7651829f8b77c4974d08ebe09f7775e41a8a Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 25 Sep 2022 19:58:27 -0400 Subject: fix(docs): invalid :help links #20345 Fix those naughty single quotes. closes #20159 --- runtime/doc/api.txt | 38 ++--- runtime/doc/autocmd.txt | 6 +- runtime/doc/builtin.txt | 32 ++-- runtime/doc/cmdline.txt | 2 +- runtime/doc/ft_ada.txt | 30 ++-- runtime/doc/ft_rust.txt | 8 +- runtime/doc/ft_sql.txt | 2 +- runtime/doc/help.txt | 1 - runtime/doc/index.txt | 23 ++- runtime/doc/insert.txt | 4 +- runtime/doc/lsp.txt | 75 ++++---- runtime/doc/lua.txt | 26 +-- runtime/doc/luaref.txt | 323 ++++++++++++++--------------------- runtime/doc/map.txt | 2 +- runtime/doc/mbyte.txt | 5 +- runtime/doc/options.txt | 6 +- runtime/doc/pi_netrw.txt | 14 +- runtime/doc/print.txt | 2 +- runtime/doc/provider.txt | 2 +- runtime/doc/quickfix.txt | 6 +- runtime/doc/quickref.txt | 7 - runtime/doc/repeat.txt | 2 +- runtime/doc/starting.txt | 2 - runtime/doc/syntax.txt | 16 +- runtime/doc/treesitter.txt | 16 +- runtime/doc/ui.txt | 4 +- runtime/doc/userfunc.txt | 5 +- runtime/doc/usr_41.txt | 2 +- runtime/doc/usr_45.txt | 3 +- runtime/doc/vim_diff.txt | 33 ++-- runtime/lua/vim/_editor.lua | 4 +- runtime/lua/vim/highlight.lua | 2 +- runtime/lua/vim/lsp.lua | 22 +-- runtime/lua/vim/lsp/buf.lua | 14 +- runtime/lua/vim/lsp/handlers.lua | 2 +- runtime/lua/vim/lsp/rpc.lua | 2 +- runtime/lua/vim/lsp/util.lua | 6 +- runtime/lua/vim/shared.lua | 2 +- runtime/lua/vim/treesitter/query.lua | 8 +- src/nvim/api/autocmd.c | 8 +- src/nvim/api/extmark.c | 6 +- src/nvim/api/options.c | 4 +- src/nvim/api/vim.c | 14 +- src/nvim/api/win_config.c | 2 +- src/nvim/api/window.c | 2 +- src/nvim/mapping.c | 2 +- src/nvim/mapping.h | 2 +- 47 files changed, 363 insertions(+), 436 deletions(-) diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 7e55bb8f4e..ec16d5c650 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -345,7 +345,7 @@ LUA ~ In-process Lua plugins can receive buffer updates in the form of Lua callbacks. These callbacks are called frequently in various contexts; |textlock| prevents changing buffer contents and window layout (use -|vim.schedule| to defer such operations to the main loop instead). +|vim.schedule()| to defer such operations to the main loop instead). |nvim_buf_attach()| will take keyword args for the callbacks. "on_lines" will receive parameters ("lines", {buf}, {changedtick}, {firstline}, {lastline}, @@ -989,7 +989,7 @@ nvim_get_proc_children({pid}) *nvim_get_proc_children()* nvim_get_runtime_file({name}, {all}) *nvim_get_runtime_file()* Find files in runtime directories - 'name' can contain wildcards. For example + "name" can contain wildcards. For example nvim_get_runtime_file("colors/*.vim", true) will return all color scheme files. Always use forward slashes (/) in the search pattern for subdirectories regardless of platform. @@ -1164,7 +1164,7 @@ nvim_open_term({buffer}, {opts}) *nvim_open_term()* terminal mode. Note: keypresses are sent raw as they would be to the pty master end. For instance, a carriage return is sent as a "\r", not as a "\n". |textlock| applies. It - is possible to call |nvim_chan_send| directly in the + is possible to call |nvim_chan_send()| directly in the callback however. ["input", term, bufnr, data] Return: ~ @@ -1396,15 +1396,15 @@ nvim_set_hl({ns_id}, {name}, {*val}) *nvim_set_hl()* • link: name of another highlight group to link to, see |:hi-link|. • default: Don't override existing definition |:hi-default| - • ctermfg: Sets foreground of cterm color |highlight-ctermfg| - • ctermbg: Sets background of cterm color |highlight-ctermbg| + • ctermfg: Sets foreground of cterm color |ctermfg| + • ctermbg: Sets background of cterm color |ctermbg| • cterm: cterm attribute map, like |highlight-args|. If not set, cterm attributes will match those from the attribute map documented above. nvim_set_hl_ns({ns_id}) *nvim_set_hl_ns()* Set active namespace for highlights. This can be set for a single window, - see |nvim_win_set_hl_ns|. + see |nvim_win_set_hl_ns()|. Parameters: ~ {ns_id} the namespace to use @@ -1413,7 +1413,7 @@ nvim_set_hl_ns_fast({ns_id}) *nvim_set_hl_ns_fast()* Set active namespace for highlights while redrawing. This function meant to be called while redrawing, primarily from - |nvim_set_decoration_provider| on_win and on_line callbacks, which are + |nvim_set_decoration_provider()| on_win and on_line callbacks, which are allowed to change the namespace during a redraw cycle. Attributes: ~ @@ -1445,7 +1445,7 @@ nvim_set_keymap({mode}, {lhs}, {rhs}, {*opts}) *nvim_set_keymap()* {rhs} Right-hand-side |{rhs}| of the mapping. {opts} Optional parameters map: keys are |:map-arguments|, values are booleans (default false). Accepts all |:map-arguments| as keys - excluding || but including |noremap| and "desc". + excluding || but including |:noremap| and "desc". Unknown key is an error. "desc" can be used to give a description to the mapping. When called from Lua, also accepts a "callback" key that takes a Lua function to call when the @@ -1886,7 +1886,7 @@ nvim_get_all_options_info() *nvim_get_all_options_info()* Gets the option information for all options. The dictionary has the full option names as keys and option metadata - dictionaries as detailed at |nvim_get_option_info|. + dictionaries as detailed at |nvim_get_option_info()|. Return: ~ dictionary of all options @@ -1960,7 +1960,7 @@ nvim_set_option_value({name}, {value}, {*opts}) {name} Option name {value} New option value {opts} Optional parameters - • scope: One of 'global' or 'local'. Analogous to + • scope: One of "global" or "local". Analogous to |:setglobal| and |:setlocal|, respectively. • win: |window-ID|. Used for setting window local option. • buf: Buffer number. Used for setting buffer local option. @@ -2576,7 +2576,7 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts}) highlight groups that will be stacked (highest priority last). A highlight group can be supplied either as a string or as an integer, the latter which can be obtained - using |nvim_get_hl_id_by_name|. + using |nvim_get_hl_id_by_name()|. • virt_text_pos : position of virtual text. Possible values: • "eol": right after eol character (default) • "overlay": display over the specified column, without @@ -2608,7 +2608,7 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts}) • virt_lines_above: place virtual lines above instead. • virt_lines_leftcol: Place extmarks in the leftmost column of the window, bypassing sign and number columns. - • ephemeral : for use with |nvim_set_decoration_provider| + • ephemeral : for use with |nvim_set_decoration_provider()| callbacks. The mark will only be used for the current redraw cycle, and not be permantently stored in the buffer. @@ -2686,7 +2686,7 @@ nvim_set_decoration_provider({ns_id}, {*opts}) triggered during the redraw code. The expected usage is to set extmarks for the currently redrawn buffer. - |nvim_buf_set_extmark| can be called to add marks on a per-window or + |nvim_buf_set_extmark()| can be called to add marks on a per-window or per-lines basis. Use the `ephemeral` key to only use the mark for the current screen redraw (the callback will be called again for the next redraw ). @@ -2844,7 +2844,7 @@ nvim_win_hide({window}) *nvim_win_hide()* Like |:hide| the buffer becomes hidden unless another window is editing it, or 'bufhidden' is `unload`, `delete` or `wipe` as opposed to |:close| - or |nvim_win_close|, which will close the buffer. + or |nvim_win_close()|, which will close the buffer. Attributes: ~ not allowed when |textlock| is active @@ -3012,7 +3012,7 @@ nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()* options. 'signcolumn' is changed to `auto` and 'colorcolumn' is cleared. The end-of-buffer region is hidden by setting `eob` flag of 'fillchars' to a space - char, and clearing the |EndOfBuffer| region in + char, and clearing the |hl-EndOfBuffer| region in 'winhighlight'. • border: Style of (optional) window border. This can either @@ -3148,7 +3148,7 @@ Autocmd Functions *api-autocmd* nvim_clear_autocmds({*opts}) *nvim_clear_autocmds()* Clear all autocommands that match the corresponding {opts}. To delete a - particular autocmd, see |nvim_del_autocmd|. + particular autocmd, see |nvim_del_autocmd()|. Parameters: ~ {opts} Parameters @@ -3295,7 +3295,7 @@ nvim_del_augroup_by_id({id}) *nvim_del_augroup_by_id()* To get a group id one can use |nvim_get_autocmds()|. - NOTE: behavior differs from |augroup-delete|. When deleting a group, + NOTE: behavior differs from |:augroup-delete|. When deleting a group, autocommands contained in this group will also be deleted and cleared. This group will no longer exist. @@ -3309,7 +3309,7 @@ nvim_del_augroup_by_id({id}) *nvim_del_augroup_by_id()* nvim_del_augroup_by_name({name}) *nvim_del_augroup_by_name()* Delete an autocommand group by name. - NOTE: behavior differs from |augroup-delete|. When deleting a group, + NOTE: behavior differs from |:augroup-delete|. When deleting a group, autocommands contained in this group will also be deleted and cleared. This group will no longer exist. @@ -3317,7 +3317,7 @@ nvim_del_augroup_by_name({name}) *nvim_del_augroup_by_name()* {name} String The name of the group. See also: ~ - |autocommand-groups| + |autocmd-groups| nvim_del_autocmd({id}) *nvim_del_autocmd()* Delete an autocommand by id. diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt index e55534b163..97a1bdc134 100644 --- a/runtime/doc/autocmd.txt +++ b/runtime/doc/autocmd.txt @@ -835,13 +835,13 @@ QuitPre When using `:quit`, `:wq` or `:qall`, before See also |ExitPre|, |WinClosed|. *RemoteReply* RemoteReply When a reply from a Vim that functions as - server was received |server2client()|. The + server was received server2client(). The pattern is matched against the {serverid}. is equal to the {serverid} from which the reply was sent, and is the actual reply string. Note that even if an autocommand is defined, - the reply should be read with |remote_read()| + the reply should be read with remote_read() to consume it. *SearchWrapped* SearchWrapped After making a search with |n| or |N| if the @@ -1206,7 +1206,7 @@ still executed. ============================================================================== 7. Buffer-local autocommands *autocmd-buflocal* *autocmd-buffer-local* - ** ** *E680* + ** ** ** *E680* Buffer-local autocommands are attached to a specific buffer. They are useful if the buffer does not have a name and when the name does not match a specific diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 7b1a50c1fb..77b85406b9 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -1537,7 +1537,7 @@ cursor({list}) debugbreak({pid}) *debugbreak()* Specifically used to interrupt a program being debugged. It will cause process {pid} to get a SIGTRAP. Behavior for other - processes is undefined. See |terminal-debugger|. + processes is undefined. See |terminal-debug|. {Sends a SIGINT to a process {pid} other than MS-Windows} Returns |TRUE| if successfully interrupted the program. @@ -3289,18 +3289,18 @@ getmatches([{win}]) *getmatches()* an empty list is returned. Example: > :echo getmatches() -< [{'group': 'MyGroup1', 'pattern': 'TODO', - 'priority': 10, 'id': 1}, {'group': 'MyGroup2', - 'pattern': 'FIXME', 'priority': 10, 'id': 2}] > +< [{"group": "MyGroup1", "pattern": "TODO", + "priority": 10, "id": 1}, {"group": "MyGroup2", + "pattern": "FIXME", "priority": 10, "id": 2}] > :let m = getmatches() :call clearmatches() :echo getmatches() < [] > :call setmatches(m) :echo getmatches() -< [{'group': 'MyGroup1', 'pattern': 'TODO', - 'priority': 10, 'id': 1}, {'group': 'MyGroup2', - 'pattern': 'FIXME', 'priority': 10, 'id': 2}] > +< [{"group": "MyGroup1", "pattern": "TODO", + "priority": 10, "id": 1}, {"group": "MyGroup2", + "pattern": "FIXME", "priority": 10, "id": 2}] > :unlet m < getmousepos() *getmousepos()* @@ -3499,7 +3499,7 @@ getreginfo([{regname}]) *getreginfo()* Dictionary with the following entries: regcontents List of lines contained in register {regname}, like - |getreg|({regname}, 1, 1). + getreg({regname}, 1, 1). regtype the type of register {regname}, as in |getregtype()|. isunnamed Boolean flag, v:true if this register @@ -4415,7 +4415,7 @@ jobstart({cmd} [, {opts}]) *jobstart()* killed when Nvim exits. If the process exits before Nvim, `on_exit` will be invoked. env: (dict) Map of environment variable name:value - pairs extending (or replacing with |clear_env|) + pairs extending (or replace with "clear_env") the current environment. |jobstart-env| height: (number) Height of the `pty` terminal. |on_exit|: (function) Callback invoked when the job exits. @@ -5209,12 +5209,12 @@ matchfuzzypos({list}, {str} [, {dict}]) *matchfuzzypos()* Example: > :echo matchfuzzypos(['testing'], 'tsg') -< results in [['testing'], [[0, 2, 6]], [99]] > +< results in [["testing"], [[0, 2, 6]], [99]] > :echo matchfuzzypos(['clay', 'lacy'], 'la') -< results in [['lacy', 'clay'], [[0, 1], [1, 2]], [153, 133]] > +< results in [["lacy", "clay"], [[0, 1], [1, 2]], [153, 133]] > :echo [{'text': 'hello', 'id' : 10}] \ ->matchfuzzypos('ll', {'key' : 'text'}) -< results in [[{'id': 10, 'text': 'hello'}], [[2, 3]], [127]] +< results in [[{"id": 10, "text": "hello"}], [[2, 3]], [127]] matchlist({expr}, {pat} [, {start} [, {count}]]) *matchlist()* Same as |match()|, but return a |List|. The first item in the @@ -8247,7 +8247,7 @@ synIDattr({synID}, {what} [, {mode}]) *synIDattr()* "bg" background color (as with "fg") "font" font name (only available in the GUI) |highlight-font| - "sp" special color (as with "fg") |highlight-guisp| + "sp" special color (as with "fg") |guisp| "fg#" like "fg", but for the GUI and the GUI is running the name in "#RRGGBB" form "bg#" like "fg#" for "bg" @@ -9106,12 +9106,12 @@ winlayout([{tabnr}]) *winlayout()* returns an empty list. For a leaf window, it returns: - ['leaf', {winid}] + ["leaf", {winid}] For horizontally split windows, which form a column, it returns: - ['col', [{nested list of windows}]] + ["col", [{nested list of windows}]] For vertically split windows, which form a row, it returns: - ['row', [{nested list of windows}]] + ["row", [{nested list of windows}]] Example: > " Only one window in the tab page diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt index f19671e713..b1013420fa 100644 --- a/runtime/doc/cmdline.txt +++ b/runtime/doc/cmdline.txt @@ -764,7 +764,7 @@ Count and Range *N:* When giving a count before entering ":", this is translated into: :.,.+(count - 1) -In words: The 'count' lines at and after the cursor. Example: To delete +In words: The "count" lines at and after the cursor. Example: To delete three lines: > 3:d is translated into: .,.+2d < diff --git a/runtime/doc/ft_ada.txt b/runtime/doc/ft_ada.txt index f6dfa708fb..fa069057c4 100644 --- a/runtime/doc/ft_ada.txt +++ b/runtime/doc/ft_ada.txt @@ -288,7 +288,7 @@ g:ada_rainbow_color bool (true when exists) rainbow_parenthesis for this to work. *g:ada_folding* -g:ada_folding set ('sigpft') +g:ada_folding set ("sigpft") Use folding for Ada sources. 's': activate syntax folding on load 'p': fold packages @@ -296,10 +296,10 @@ g:ada_folding set ('sigpft') 't': fold types 'c': fold conditionals 'g': activate gnat pretty print folding on load - 'i': lone 'is' folded with line above - 'b': lone 'begin' folded with line above - 'p': lone 'private' folded with line above - 'x': lone 'exception' folded with line above + 'i': lone "is" folded with line above + 'b': lone "begin" folded with line above + 'p': lone "private" folded with line above + 'x': lone "exception" folded with line above 'i': activate indent folding on load Note: Syntax folding is in an early (unusable) stage and @@ -334,10 +334,10 @@ g:ada_omni_with_keywords completion (|i_CTRL-X_CTRL-U|). *g:ada_extended_tagging* -g:ada_extended_tagging enum ('jump', 'list') +g:ada_extended_tagging enum ("jump", "list") use extended tagging, two options are available - 'jump': use tjump to jump. - 'list': add tags quick fix list. + "jump": use tjump to jump. + "list": add tags quick fix list. Normal tagging does not support function or operator overloading as these features are not available in C and tagging was originally developed for C. @@ -359,8 +359,8 @@ g:ada_with_gnat_project_files bool (true when exists) *g:ada_default_compiler* g:ada_default_compiler string - set default compiler. Currently supported are 'gnat' and - 'decada'. + set default compiler. Currently supported are "gnat" and + "decada". An "exists" type is a boolean considered true when the variable is defined and false when the variable is undefined. The value to which the variable is set @@ -406,14 +406,14 @@ makes no difference. g:gnat object Control object which manages GNAT compiles. The object is created when the first Ada source code is loaded provided - that |g:ada_default_compiler| is set to 'gnat'. See + that |g:ada_default_compiler| is set to "gnat". See |gnat_members| for details. *g:decada* g:decada object Control object which manages Dec Ada compiles. The object is created when the first Ada source code is loaded provided - that |g:ada_default_compiler| is set to 'decada'. See + that |g:ada_default_compiler| is set to "decada". See |decada_members| for details. ------------------------------------------------------------------------------ @@ -459,11 +459,11 @@ ada#List_Tag([{line}, {col}]) *ada#Listtags()* ada#Jump_Tag ({ident}, {mode}) *ada#Jump_Tag()* List all occurrences of the Ada entity under the cursor (or at given line/column) in the tag jump list. Mode can either be - 'tjump' or 'stjump'. + "tjump" or "stjump". ada#Create_Tags ({option}) *ada#Create_Tags()* - Creates tag file using Ctags. The option can either be 'file' - for the current file, 'dir' for the directory of the current + Creates tag file using Ctags. The option can either be "file" + for the current file, "dir" for the directory of the current file or a file name. gnat#Insert_Tags_Header() *gnat#Insert_Tags_Header()* diff --git a/runtime/doc/ft_rust.txt b/runtime/doc/ft_rust.txt index 5c8782ec7a..34932c48fb 100644 --- a/runtime/doc/ft_rust.txt +++ b/runtime/doc/ft_rust.txt @@ -92,8 +92,8 @@ g:ftplugin_rust_source_path~ *g:rustfmt_command* g:rustfmt_command~ - Set this option to the name of the 'rustfmt' executable in your $PATH. If - not specified it defaults to 'rustfmt' : > + Set this option to the name of the "rustfmt" executable in your $PATH. If + not specified it defaults to "rustfmt" : > let g:rustfmt_command = 'rustfmt' < *g:rustfmt_autosave* @@ -104,14 +104,14 @@ g:rustfmt_autosave~ < *g:rustfmt_fail_silently* g:rustfmt_fail_silently~ - Set this option to 1 to prevent 'rustfmt' from populating the + Set this option to 1 to prevent "rustfmt" from populating the |location-list| with errors. If not specified it defaults to 0: > let g:rustfmt_fail_silently = 0 < *g:rustfmt_options* g:rustfmt_options~ Set this option to a string of options to pass to 'rustfmt'. The - write-mode is already set to 'overwrite'. If not specified it + write-mode is already set to "overwrite". If not specified it defaults to '' : > let g:rustfmt_options = '' < diff --git a/runtime/doc/ft_sql.txt b/runtime/doc/ft_sql.txt index 335faf266e..685726de90 100644 --- a/runtime/doc/ft_sql.txt +++ b/runtime/doc/ft_sql.txt @@ -244,7 +244,7 @@ key to complete the optional parameter. After typing the function name and a space, you can use the completion to supply a parameter. The function takes the name of the Vim script you want to source. Using the |cmdline-completion| feature, the SQLSetType function will -search the |'runtimepath'| for all Vim scripts with a name containing 'sql'. +search the |'runtimepath'| for all Vim scripts with a name containing "sql". This takes the guess work out of the spelling of the names. The following are examples: > :SQLSetType diff --git a/runtime/doc/help.txt b/runtime/doc/help.txt index 34213f7512..a1bedfa500 100644 --- a/runtime/doc/help.txt +++ b/runtime/doc/help.txt @@ -98,7 +98,6 @@ General subjects ~ |help.txt| overview and quick reference (this file) |helphelp.txt| about using the help files |index.txt| alphabetical index of all commands -|help-tags| all the tags you can jump to (index of tags) |tips.txt| various tips on using Vim |message.txt| (error) messages and explanations |develop.txt| development of Nvim diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt index 7f3ef20762..f9ef99f819 100644 --- a/runtime/doc/index.txt +++ b/runtime/doc/index.txt @@ -13,7 +13,6 @@ to look for deleting something, use: "/delete". For an overview of options see |option-list|. For an overview of built-in functions see |functions|. For a list of Vim variables see |vim-variable|. -For a complete listing of all help items see |help-tags|. Type |gO| to see the table of contents. @@ -61,7 +60,7 @@ tag char action in Insert mode ~ |i_CTRL-Q| CTRL-Q same as CTRL-V, unless used for terminal control flow |i_CTRL-SHIFT-Q| CTRL-SHIFT-Q {char} - like CTRL-Q unless |modifyOtherKeys| is active + like CTRL-Q unless |tui-modifyOtherKeys| is active |i_CTRL-R| CTRL-R {register} insert the contents of a register |i_CTRL-R_CTRL-R| CTRL-R CTRL-R {register} @@ -79,7 +78,7 @@ tag char action in Insert mode ~ line |i_CTRL-V| CTRL-V {char} insert next non-digit literally |i_CTRL-SHIFT-V| CTRL-SHIFT-V {char} - like CTRL-V unless |modifyOtherKeys| is active + like CTRL-V unless |tui-modifyOtherKeys| is active |i_CTRL-V_digit| CTRL-V {number} insert three digit decimal number as a single byte. |i_CTRL-W| CTRL-W delete word before the cursor @@ -454,14 +453,14 @@ tag char note action in Normal mode ~ || 1 same as CTRL-B || 2 same as "u" || 1 same as "k" -|| move window three lines down -|| move window one page down -|| move window three lines up -|| move window one page up -|| move window six columns left -|| move window one page left -|| move window six columns right -|| move window one page right +** move window three lines down +** move window one page down +** move window three lines up +** move window one page up +** move window six columns left +** move window one page left +** move window six columns right +** move window one page right ============================================================================== 2.1 Text objects *objects* @@ -700,7 +699,7 @@ tag char note action in Normal mode ~ tag char note action in Normal mode ~ ------------------------------------------------------------------------------ -|g_CTRL-A| g CTRL-A dump a memory profile +g_CTRL-A g CTRL-A dump a memory profile |g_CTRL-G| g CTRL-G show information about current cursor position |g_CTRL-H| g CTRL-H start Select block mode diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt index 6b0899334b..f4ef8e65c4 100644 --- a/runtime/doc/insert.txt +++ b/runtime/doc/insert.txt @@ -1519,7 +1519,7 @@ RUBY *ft-ruby-omni* NOTE: |compl-omni| for Ruby code requires |provider-ruby| to be installed. Ruby completion will parse your buffer on demand in order to provide a list of -completions. These completions will be drawn from modules loaded by 'require' +completions. These completions will be drawn from modules loaded by "require" and modules defined in the current buffer. The completions provided by CTRL-X CTRL-O are sensitive to the context: @@ -1759,7 +1759,7 @@ In the example four special elements are visible: dialect. 2. If the list containing possible values of attributes has one element and this element is equal to the name of the attribute this attribute will be - treated as boolean and inserted as 'attrname' and not as 'attrname="' + treated as boolean and inserted as "attrname" and not as 'attrname="' 3. "vimxmltaginfo" - a special key with a Dictionary containing tag names as keys and two element List as values, for additional menu info and the long description. diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index 00aaf759e2..26bca21507 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -40,7 +40,7 @@ Follow these steps to get LSP features: root_dir = vim.fs.dirname(vim.fs.find({'setup.py', 'pyproject.toml'}, { upward = true })[1]), }) < - See |vim.lsp.start| for details. + See |vim.lsp.start()| for details. 3. Configure keymaps and autocmds to utilize LSP features. See |lsp-config|. @@ -48,19 +48,19 @@ Follow these steps to get LSP features: *lsp-config* Starting a LSP client will automatically report diagnostics via -|vim.diagnostic|. Read |vim.diagnostic.config| to learn how to customize the +|vim.diagnostic|. Read |vim.diagnostic.config()| to learn how to customize the display. It also sets some buffer options if the options are otherwise empty and if the language server supports the functionality. -- |omnifunc| is set to |vim.lsp.omnifunc|. This allows to trigger completion - using |i_CTRL-X_CTRL-o| -- |tagfunc| is set to |vim.lsp.tagfunc|. This enables features like +- 'omnifunc' is set to |vim.lsp.omnifunc()|. This allows to trigger completion + using |i_CTRL-X_CTRL-O| +- 'tagfunc' is set to |vim.lsp.tagfunc()|. This enables features like go-to-definition, |:tjump|, and keymaps like |CTRL-]|, |CTRL-W_]|, |CTRL-W_}| to utilize the language server. -- |formatexpr| is set to |vim.lsp.formatexpr| if both |formatprg| and - |formatexpr| are empty. This allows to format lines via |gq| if the language +- 'formatexpr' is set to |vim.lsp.formatexpr()| if both 'formatprg' and + 'formatexpr' are empty. This allows to format lines via |gq| if the language server supports it. To use other LSP features like hover, rename, etc. you can setup some @@ -245,7 +245,7 @@ For |lsp-request|, each |lsp-handler| has this signature: > Where `err` must be shaped like an RPC error: `{ code, message, data? }` - You can use |vim.lsp.rpc_response_error()| to create this object. + You can use |vim.lsp.rpc.rpc_response_error()| to create this object. For |lsp-notification|, each |lsp-handler| has this signature: > @@ -338,8 +338,8 @@ To configure the behavior of a builtin |lsp-handler|, the convenient method } < Some handlers do not have an explicitly named handler function (such as - |on_publish_diagnostics()|). To override these, first create a reference - to the existing handler: > + ||vim.lsp.diagnostic.on_publish_diagnostics()|). To override these, first + create a reference to the existing handler: > local on_references = vim.lsp.handlers["textDocument/references"] vim.lsp.handlers["textDocument/references"] = vim.lsp.with( @@ -360,7 +360,7 @@ Handlers can be set by: vim.lsp.handlers["textDocument/definition"] = my_custom_default_definition < -- The {handlers} parameter for |vim.lsp.start_client|. +- The {handlers} parameter for |vim.lsp.start_client()|. This will set the |lsp-handler| as the default handler for this server. For example: > @@ -514,7 +514,7 @@ callback in the "data" table. Example: > end, }) < -In addition, the following |User| |autocommands| are provided: +Also the following |User| |autocommand|s are provided: LspProgressUpdate *LspProgressUpdate* Upon receipt of a progress notification from the server. See @@ -788,7 +788,8 @@ start({config}, {opts}) *vim.lsp.start()* }) < - See |lsp.start_client| for all available options. The most important are: + See |vim.lsp.start_client()| for all available options. The most important + are: `name` is an arbitrary name for the LSP client. It should be unique per language server. @@ -798,9 +799,9 @@ start({config}, {opts}) *vim.lsp.start()* constructs like `~` are NOT expanded. `root_dir` path to the project root. By default this is used to decide if - an existing client should be re-used. The example above uses |vim.fs.find| - and |vim.fs.dirname| to detect the root by traversing the file system - upwards starting from the current directory until either a + an existing client should be re-used. The example above uses + |vim.fs.find()| and |vim.fs.dirname()| to detect the root by traversing + the file system upwards starting from the current directory until either a `pyproject.toml` or `setup.py` file is found. `workspace_folders` a list of { uri:string, name: string } tables. The @@ -812,13 +813,13 @@ start({config}, {opts}) *vim.lsp.start()* the project folder. To ensure a language server is only started for languages it can handle, - make sure to call |vim.lsp.start| within a |FileType| autocmd. Either use - |:au|, |nvim_create_autocmd()| or put the call in a + make sure to call |vim.lsp.start()| within a |FileType| autocmd. Either + use |:au|, |nvim_create_autocmd()| or put the call in a `ftplugin/.lua` (See |ftplugin-name|) Parameters: ~ {config} (table) Same configuration as documented in - |lsp.start_client()| + |vim.lsp.start_client()| {opts} nil|table Optional keyword arguments: • reuse_client (fun(client: client, config: table): boolean) Predicate used to decide if a client should be re-used. @@ -837,15 +838,16 @@ start_client({config}) *vim.lsp.start_client()* Parameters: ~ {cmd} (table|string|fun(dispatchers: table):table) - command string or list treated like |jobstart|. + command string or list treated like |jobstart()|. The command must launch the language server process. `cmd` can also be a function that creates an RPC client. The function receives a dispatchers table and must return a table with the functions `request`, `notify`, `is_closing` - and `terminate` See |vim.lsp.rpc.request| and - |vim.lsp.rpc.notify| For TCP there is a built-in - rpc client factory: |vim.lsp.rpc.connect| + and `terminate` See |vim.lsp.rpc.request()| and + |vim.lsp.rpc.notify()| For TCP there is a + built-in rpc client factory: + |vim.lsp.rpc.connect()| {cmd_cwd} (string, default=|getcwd()|) Directory to launch the `cmd` process. Not related to `root_dir`. {cmd_env} (table) Environment flags to pass to the LSP on @@ -900,7 +902,7 @@ start_client({config}) *vim.lsp.start_client()* when the client operation throws an error. `code` is a number describing the error. Other arguments may be passed depending on the error kind. See - |vim.lsp.rpc.client_errors| for possible errors. + `vim.lsp.rpc.client_errors` for possible errors. Use `vim.lsp.rpc.client_errors[code]` to get human-friendly name. {before_init} Callback with parameters (initialize_params, @@ -945,9 +947,9 @@ start_client({config}) *vim.lsp.start_client()* debounce occurs if nil • exit_timeout (number|boolean, default false): Milliseconds to wait for server to exit cleanly - after sending the 'shutdown' request before + after sending the "shutdown" request before sending kill -15. If set to false, nvim exits - immediately after sending the 'shutdown' + immediately after sending the "shutdown" request to the server. {root_dir} (string) Directory where the LSP server will base its workspaceFolders, rootUri, and rootPath on @@ -1047,7 +1049,7 @@ completion({context}) *vim.lsp.buf.completion()* character, if applicable) See also: ~ - |vim.lsp.protocol.constants.CompletionTriggerKind| + vim.lsp.protocol.constants.CompletionTriggerKind declaration({options}) *vim.lsp.buf.declaration()* Jumps to the declaration of the symbol under the cursor. @@ -1084,7 +1086,8 @@ document_highlight() *vim.lsp.buf.document_highlight()* Note: Usage of |vim.lsp.buf.document_highlight()| requires the following highlight groups to be defined or you won't be able to see the actual - highlights. |LspReferenceText| |LspReferenceRead| |LspReferenceWrite| + highlights. |hl-LspReferenceText| |hl-LspReferenceRead| + |hl-LspReferenceWrite| document_symbol({options}) *vim.lsp.buf.document_symbol()* Lists all symbols in the current buffer in the quickfix window. @@ -1193,7 +1196,7 @@ formatting_sync({options}, {timeout_ms}) {timeout_ms} (number) Request timeout See also: ~ - |vim.lsp.buf.formatting_seq_sync| + |vim.lsp.buf.format()| hover() *vim.lsp.buf.hover()* Displays hover information about the symbol under the cursor in a floating @@ -1211,7 +1214,7 @@ implementation({options}) *vim.lsp.buf.implementation()* incoming_calls() *vim.lsp.buf.incoming_calls()* Lists all the call sites of the symbol under the cursor in the |quickfix| window. If the symbol can resolve to multiple items, the user can pick one - in the |inputlist|. + in the |inputlist()|. list_workspace_folders() *vim.lsp.buf.list_workspace_folders()* List workspace folders. @@ -1219,7 +1222,7 @@ list_workspace_folders() *vim.lsp.buf.list_workspace_folders()* outgoing_calls() *vim.lsp.buf.outgoing_calls()* Lists all the items that are called by the symbol under the cursor in the |quickfix| window. If the symbol can resolve to multiple items, the user - can pick one in the |inputlist|. + can pick one in the |inputlist()|. *vim.lsp.buf.range_code_action()* range_code_action({context}, {start_pos}, {end_pos}) @@ -1434,7 +1437,7 @@ signature_help({_}, {result}, {ctx}, {config}) {config} (table) Configuration table. • border: (default=nil) • Add borders to the floating window - • See |vim.api.nvim_open_win()| + • See |nvim_open_win()| ============================================================================== @@ -1565,7 +1568,7 @@ get_effective_tabstop({bufnr}) *vim.lsp.util.get_effective_tabstop()* (number) indentation size See also: ~ - |shiftwidth| + 'shiftwidth' *vim.lsp.util.jump_to_location()* jump_to_location({location}, {offset_encoding}, {reuse_win}) @@ -1722,7 +1725,7 @@ open_floating_preview({contents}, {syntax}, {opts}) {contents} (table) of lines to show in window {syntax} (string) of syntax to set for opened buffer {opts} (table) with optional fields (additional keys are passed - on to |vim.api.nvim_open_win()|) + on to |nvim_open_win()|) • height: (number) height of floating window • width: (number) width of floating window • wrap: (boolean, default true) wrap long lines @@ -1859,7 +1862,7 @@ try_trim_markdown_code_blocks({lines}) {lines} (table) list of lines Return: ~ - (string) filetype or 'markdown' if it was unchanged. + (string) filetype or "markdown" if it was unchanged. ============================================================================== @@ -1964,7 +1967,7 @@ start({cmd}, {cmd_args}, {dispatchers}, {extra_spawn_params}) Starts an LSP server process and create an LSP RPC client object to interact with it. Communication with the spawned process happens via stdio. For communication via TCP, spawn a process manually and use - |vim.lsp.rpc.connect| + |vim.lsp.rpc.connect()| Parameters: ~ {cmd} (string) Command to start the LSP server. diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 88547edfe5..0c6eb6af78 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -285,7 +285,7 @@ These commands execute a Lua chunk from either the command line (:lua, :luado) or a file (:luafile) on the given line [range]. As always in Lua, each chunk has its own scope (closure), so only global variables are shared between command calls. The |lua-stdlib| modules, user modules, and anything else on -|lua-package-path| are available. +|package.path| are available. The Lua print() function redirects its output to the Nvim message area, with arguments separated by " " (space) instead of "\t" (tab). @@ -617,7 +617,7 @@ A subset of the `vim.*` API is available in threads. This includes: - `vim.loop` with a separate event loop per thread. - `vim.mpack` and `vim.json` (useful for serializing messages between threads) -- `require` in threads can use lua packages from the global |lua-package-path| +- `require` in threads can use lua packages from the global |package.path| - `print()` and `vim.inspect` - `vim.diff` - most utility functions in `vim.*` for working with pure lua values @@ -663,7 +663,7 @@ vim.highlight.range({bufnr}, {ns}, {hlgroup}, {start}, {finish}, {opts}) {finish} finish position (tuple {line,col}) {opts} optional parameters: • `regtype`: type of range (characterwise, linewise, - or blockwise, see |setreg|), default `'v'` + or blockwise, see |setreg()|), default `'v'` • `inclusive`: range includes end position, default `false` • `priority`: priority of highlight, default @@ -906,7 +906,7 @@ vim.defer_fn({fn}, {timeout}) *vim.defer_fn* Defers calling {fn} until {timeout} ms passes. Use to do a one-shot timer that calls {fn}. - Note: The {fn} is |schedule_wrap|ped automatically, so API functions are + Note: The {fn} is |vim.schedule_wrap()|ped automatically, so API functions are safe to call. Parameters: ~ @@ -1160,7 +1160,7 @@ window-scoped options. Note that this must NOT be confused with global value of a |global-local| option, see |:setglobal|. vim.o *vim.o* - Get or set an |option|. Like `:set`. Invalid key is an error. + Get or set |options|. Like `:set`. Invalid key is an error. Note: this works on both buffer-scoped and window-scoped options using the current buffer and window. @@ -1171,7 +1171,7 @@ vim.o *vim.o* print(vim.o.foo) -- error: invalid key < vim.go *vim.go* - Get or set a global |option|. Like `:setglobal`. Invalid key is + Get or set global |options|. Like `:setglobal`. Invalid key is an error. Note: this is different from |vim.o| because this accesses the global @@ -1260,7 +1260,7 @@ offers object-oriented method for adding and removing entries. Note that |vim.opt| returns an `Option` object, not the value of the option, -which is accessed through |Option:get()|: +which is accessed through |vim.opt:get()|: Examples: ~ @@ -1275,8 +1275,8 @@ which is accessed through |Option:get()|: `vim.pretty_print(vim.opt.wildignore:get())` -In any of the above examples, to replicate the behavior |setlocal|, use -`vim.opt_local`. Additionally, to replicate the behavior of |setglobal|, use +In any of the above examples, to replicate the behavior |:setlocal|, use +`vim.opt_local`. Additionally, to replicate the behavior of |:setglobal|, use `vim.opt_global`. @@ -1406,8 +1406,8 @@ connection_failure_errmsg({consequence}) defer_fn({fn}, {timeout}) *vim.defer_fn()* Defers calling `fn` until `timeout` ms passes. - Use to do a one-shot timer that calls `fn` Note: The {fn} is |schedule_wrap|ped automatically, so API functions are - safe to call. + Use to do a one-shot timer that calls `fn` Note: The {fn} is |vim.schedule_wrap()|ped automatically, so API functions + are safe to call. Parameters: ~ {fn} Callback to call once `timeout` expires @@ -1541,7 +1541,7 @@ region({bufnr}, {pos1}, {pos2}, {regtype}, {inclusive}) *vim.region()* {bufnr} (number) of buffer {pos1} (line, column) tuple marking beginning of region {pos2} (line, column) tuple marking end of region - {regtype} type of selection (:help setreg) + {regtype} type of selection, see |setreg()| {inclusive} (boolean) indicating whether the selection is end-inclusive @@ -1773,7 +1773,7 @@ tbl_deep_extend({behavior}, {...}) *vim.tbl_deep_extend()* (table) Merged table See also: ~ - |tbl_extend()| + |vim.tbl_extend()| tbl_extend({behavior}, {...}) *vim.tbl_extend()* Merges two or more map-like tables. diff --git a/runtime/doc/luaref.txt b/runtime/doc/luaref.txt index 9dbd2d4de5..ecb92d4bb6 100644 --- a/runtime/doc/luaref.txt +++ b/runtime/doc/luaref.txt @@ -20,72 +20,7 @@ See |luaref-copyright| for copyright and licenses. - CONTENTS - ============ - - 1 INTRODUCTION........................|luaref-intro| - - 2 THE LANGUAGE........................|luaref-language| - 2.1 Lexical Conventions...............|luaref-langLexConv| - 2.2 Values and Types..................|luaref-langValTypes| - 2.2.1 Coercion........................|luaref-langCoercion| - 2.3 Variables.........................|luaref-langVariables| - 2.4 Statements........................|luaref-langStats| - 2.4.1 Chunks..........................|luaref-langChunks| - 2.4.2 Blocks..........................|luaref-langBlocks| - 2.4.3 Assignment......................|luaref-langAssign| - 2.4.4 Control Structures..............|luaref-langContStructs| - 2.4.5 For Statement...................|luaref-langForStat| - 2.4.6 Function Calls as Statements....|luaref-langFuncStat| - 2.4.7 Local Declarations..............|luaref-langLocalDec| - 2.5 Expressions.......................|luaref-langExpressions| - 2.5.1 Arithmetic Operators............|luaref-langArithOp| - 2.5.2 Relational Operators............|luaref-langRelOp| - 2.5.3 Logical Operators...............|luaref-langLogOp| - 2.5.4 Concatenation...................|luaref-langConcat| - 2.5.5 The Length Operator.............|luaref-langLength| - 2.5.6 Precedence......................|luaref-langPrec| - 2.5.7 Table Constructors..............|luaref-langTableConst| - 2.5.8 Function Calls..................|luaref-langFuncCalls| - 2.5.9 Function Definitions............|luaref-langFuncDefs| - 2.6 Visibility Rules..................|luaref-langVisibRules| - 2.7 Error Handling....................|luaref-langError| - 2.8 Metatables........................|luaref-langMetatables| - 2.9 Environments......................|luaref-langEnvironments| - 2.10 Garbage Collection...............|luaref-langGC| - 2.10.1 Garbage-Collection Metamethods.|luaref-langGCMeta| - 2.10.2 Weak Tables....................|luaref-langWeaktables| - 2.11 Coroutines.......................|luaref-langCoro| - - 3 THE APPLICATION PROGRAM INTERFACE...|luaref-api| - 3.1 The Stack.........................|luaref-apiStack| - 3.2 Stack Size........................|luaref-apiStackSize| - 3.3 Pseudo-Indices....................|luaref-apiPseudoIndices| - 3.4 C Closures........................|luaref-apiCClosures| - 3.5 Registry..........................|luaref-apiRegistry| - 3.6 Error Handling in C...............|luaref-apiError| - 3.7 Functions and Types...............|luaref-apiFunctions| - 3.8 The Debug Interface...............|luaref-apiDebug| - - 4 THE AUXILIARY LIBRARY...............|luaref-aux| - 4.1 Functions and Types...............|luaref-auxFunctions| - - 5 STANDARD LIBRARIES..................|luaref-lib| - 5.1 Basic Functions...................|luaref-libBasic| - 5.2 Coroutine Manipulation............|luaref-libCoro| - 5.3 Modules...........................|luaref-libModule| - 5.4 String Manipulation...............|luaref-libString| - 5.4.1 Patterns........................|luaref-libStringPat| - 5.5 Table Manipulation................|luaref-libTable| - 5.6 Mathematical Functions............|luaref-libMath| - 5.7 Input and Output Facilities.......|luaref-libIO| - 5.8 Operating System Facilities.......|luaref-libOS| - 5.9 The Debug Library.................|luaref-libDebug| - - A BIBLIOGRAPHY........................|luaref-bibliography| - B COPYRIGHT & LICENSES................|luaref-copyright| - C LUAREF DOC..........................|luaref-doc| - +Type |gO| to see the table of contents. ============================================================================== 1 INTRODUCTION *luaref-intro* @@ -292,7 +227,7 @@ parameter passing, and function returns always manipulate references to such values; these operations do not imply any kind of copy. The library function `type` returns a string describing the type of a given -value (see |luaref-type|). +value (see |luaref-type()|). ------------------------------------------------------------------------------ 2.2.1 Coercion *luaref-langCoercion* @@ -303,7 +238,7 @@ string to a number, following the usual conversion rules. Conversely, whenever a number is used where a string is expected, the number is converted to a string, in a reasonable format. For complete control of how numbers are converted to strings, use the `format` function from the string library (see -|luaref-string.format|). +|string.format()|). ============================================================================== 2.3 Variables *luaref-langVariables* @@ -344,7 +279,7 @@ has its own reference to an environment, so that all global variables in this function will refer to this environment table. When a function is created, it inherits the environment from the function that created it. To get the environment table of a Lua function, you call `getfenv` (see -|luaref-getfenv|). To replace it, you call `setfenv` (see |luaref-setfenv|). +|lua_getfenv()|). To replace it, you call `setfenv` (see |luaref-setfenv()|). (You can only manipulate the environment of C functions through the debug library; see |luaref-libDebug|.) @@ -634,7 +569,7 @@ they are explained in |luaref-langFuncDefs|. Binary operators comprise arithmetic operators (see |luaref-langArithOp|), relational operators (see |luaref-langRelOp|), logical operators (see |luaref-langLogOp|), and the concatenation operator (see |luaref-langConcat|). -Unary operators comprise the unary minus (see |luaref-labgArithOp|), the unary +Unary operators comprise the unary minus (see |luaref-langArithOp|), the unary `not` (see |luaref-langLogOp|), and the unary length operator (see |luaref-langLength|). @@ -1050,13 +985,13 @@ them share the same `x`. Because Lua is an embedded extension language, all Lua actions start from C code in the host program calling a function from the Lua library (see -|luaref-lua_pcall|). Whenever an error occurs during Lua compilation or +|lua_pcall()|). Whenever an error occurs during Lua compilation or execution, control returns to C, which can take appropriate measures (such as print an error message). Lua code can explicitly generate an error by calling the `error` function (see -|luaref-error|). If you need to catch errors in Lua, you can use -the `pcall` function (see |luaref-pcall|). +|luaref-error()|). If you need to catch errors in Lua, you can use +the `pcall` function (see |luaref-pcall()|). ============================================================================== 2.8 Metatables *luaref-metatable* *luaref-langMetatables* @@ -1074,10 +1009,10 @@ previous example, the event is "add" and the metamethod is the function that performs the addition. You can query the metatable of any value through the `getmetatable` function -(see |luaref-getmetatable|). +(see |luaref-getmetatable()|). You can replace the metatable of tables through the `setmetatable` function (see -|luaref-setmetatable|). You cannot change the metatable of other types from Lua +|luaref-setmetatable()|). You cannot change the metatable of other types from Lua (except using the debug library); you must use the C API for that. Tables and userdata have individual metatables (although multiple tables and @@ -1385,8 +1320,8 @@ convenience feature for programmers to associate a table to a userdata. Environments associated with threads are called global environments. They are used as the default environment for their threads and non-nested functions -created by the thread (through `loadfile` |luaref-loadfile|, `loadstring` -|luaref-loadstring| or `load` |luaref-load|) and can be directly accessed by C +created by the thread (through `loadfile` |luaref-loadfile()|, `loadstring` +|luaref-loadstring()| or `load` |luaref-load()|) and can be directly accessed by C code (see |luaref-apiPseudoIndices|). Environments associated with C functions can be directly accessed by C code @@ -1399,10 +1334,10 @@ used as the default environment for other Lua functions created by the function. You can change the environment of a Lua function or the running thread by -calling `setfenv` (see |luaref-setenv|). You can get the environment of a Lua -function or the running thread by calling `getfenv` (see |luaref-getfenv|). To -manipulate the environment of other objects (userdata, C functions, other -threads) you must use the C API. +calling `setfenv`. You can get the environment of a Lua function or the +running thread by calling `getfenv` (see |lua_getfenv()|). To manipulate the +environment of other objects (userdata, C functions, other threads) you must +use the C API. ============================================================================== 2.10 Garbage Collection *luaref-langGC* @@ -1432,8 +1367,8 @@ collector too slow and may result in the collector never finishing a cycle. The default, 2, means that the collector runs at "twice" the speed of memory allocation. -You can change these numbers by calling `lua_gc` (see |luaref-lua_gc|) in C or -`collectgarbage` (see |luaref-collectgarbage|) in Lua. Both get percentage +You can change these numbers by calling `lua_gc` (see |lua_gc()|) in C or +`collectgarbage` (see |luaref-collectgarbage()|) in Lua. Both get percentage points as arguments (so an argument of 100 means a real value of 1). With these functions you can also control the collector directly (e.g., stop and restart it). @@ -1496,12 +1431,12 @@ multithread systems, however, a coroutine only suspends its execution by explicitly calling a yield function. You create a coroutine with a call to `coroutine.create` (see -|luaref-coroutine.create|). Its sole argument is a function that is the main +|coroutine.create()|). Its sole argument is a function that is the main function of the coroutine. The `create` function only creates a new coroutine and returns a handle to it (an object of type `thread`); it does not start the coroutine execution. -When you first call `coroutine.resume` (see |luaref-coroutine.resume|), +When you first call `coroutine.resume` (see |coroutine.resume()|), passing as its first argument the thread returned by `coroutine.create`, the coroutine starts its execution, at the first line of its main function. Extra arguments passed to `coroutine.resume` are passed on to the coroutine main @@ -1516,7 +1451,7 @@ main function. In case of errors, `coroutine.resume` returns `false` plus an error message. A coroutine yields by calling `coroutine.yield` (see -|luaref-coroutine.yield|). When a coroutine yields, the corresponding +|coroutine.yield()|). When a coroutine yields, the corresponding `coroutine.resume` returns immediately, even if the yield happens inside nested function calls (that is, not in the main function, but in a function directly or indirectly called by the main function). In the case of a yield, @@ -1526,7 +1461,7 @@ its execution from the point where it yielded, with the call to `coroutine.yield` returning any extra arguments passed to `coroutine.resume`. Like `coroutine.create`, the `coroutine.wrap` function (see -|luaref-coroutine.wrap|) also creates a coroutine, but instead of returning +|coroutine.wrap()|) also creates a coroutine, but instead of returning the coroutine itself, it returns a function that, when called, resumes the coroutine. Any arguments passed to this function go as extra arguments to `coroutine.resume`. `coroutine.wrap` returns all the values returned by @@ -1595,7 +1530,7 @@ Whenever Lua calls C, the called function gets a new stack, which is independent of previous stacks and of stacks of C functions that are still active. This stack initially contains any arguments to the C function and it is where the C function pushes its results to be returned to the caller (see -|luaref-lua_CFunction|). +|lua_CFunction()|). *luaref-stackindex* For convenience, most query operations in the API do not follow a strict stack @@ -1615,7 +1550,7 @@ if `1 <= abs(index) <= top`). When you interact with Lua API, you are responsible for ensuring consistency. In particular, you are responsible for controlling stack overflow. You can use the function `lua_checkstack` to grow the stack size (see -|luaref-lua_checkstack|). +|lua_checkstack()|). Whenever Lua calls C, it ensures that at least `LUA_MINSTACK` stack positions are available. `LUA_MINSTACK` is defined as 20, so that usually you do not @@ -1656,14 +1591,14 @@ global variable, do When a C function is created, it is possible to associate some values with it, thus creating a C closure; these values are called upvalues and are accessible -to the function whenever it is called (see |luaref-lua_pushcclosure|). +to the function whenever it is called (see |lua_pushcclosure()|). Whenever a C function is called, its upvalues are located at specific pseudo-indices. These pseudo-indices are produced by the macro -`lua_upvalueindex` (see |luaref-lua_upvalueindex|). The first value associated -with a function is at position `lua_upvalueindex(1)`, and so on. Any access to -`lua_upvalueindex(` `n` `)`, where `n` is greater than the number of upvalues of -the current function, produces an acceptable (but invalid) index. +`lua_upvalueindex`. The first value associated with a function is at position +`lua_upvalueindex(1)`, and so on. Any access to `lua_upvalueindex(` `n` `)`, +where `n` is greater than the number of upvalues of the current function, +produces an acceptable (but invalid) index. ============================================================================== 3.5 Registry *luaref-registry* *luaref-apiRegistry* @@ -1694,11 +1629,11 @@ Almost any function in the API may raise an error, for instance due to a memory allocation error. The following functions run in protected mode (that is, they create a protected environment to run), so they never raise an error: `lua_newstate`, `lua_close`, `lua_load`, `lua_pcall`, and `lua_cpcall` (see -|luaref-lua_newstate|, |luaref-lua_close|, |luaref-lua_load|, -|luaref-lua_pcall|, and |luaref-lua_cpcall|). +|lua_newstate()|, |lua_close()|, |lua_load()|, +|lua_pcall()|, and |lua_cpcall()|). Inside a C function you can raise an error by calling `lua_error` (see -|luaref-lua_error|). +|lua_error()|). ============================================================================== 3.7 Functions and Types *luaref-apiFunctions* @@ -1715,7 +1650,7 @@ lua_Alloc *lua_Alloc()* The type of the memory-allocation function used by Lua states. The allocator function must provide a functionality similar to `realloc`, but not exactly the same. Its arguments are `ud`, an opaque pointer - passed to `lua_newstate` (see |luaref-lua_newstate|); `ptr`, a pointer + passed to `lua_newstate` (see |lua_newstate()|); `ptr`, a pointer to the block being allocated/reallocated/freed; `osize`, the original size of the block; `nsize`, the new size of the block. `ptr` is `NULL` if and only if `osize` is zero. When `nsize` is zero, the allocator @@ -1729,7 +1664,7 @@ lua_Alloc *lua_Alloc()* Here is a simple implementation for the allocator function. It is used in the auxiliary library by `luaL_newstate` (see - |luaref-luaL_newstate|). + |luaL_newstate()|). > static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { @@ -1813,7 +1748,7 @@ lua_CFunction *luaref-cfunction* *lua_CFunction()* following protocol, which defines the way parameters and results are passed: a C function receives its arguments from Lua in its stack in direct order (the first argument is pushed first). So, when the - function starts, `lua_gettop(L)` (see |luaref-lua_gettop|) returns the + function starts, `lua_gettop(L)` (see |lua_gettop()|) returns the number of arguments received by the function. The first argument (if any) is at index 1 and its last argument is at index `lua_gettop(L)`. To return values to Lua, a C function just pushes them onto the stack, @@ -1881,7 +1816,7 @@ lua_cpcall *lua_cpcall()* Calls the C function `func` in protected mode. `func` starts with only one element in its stack, a light userdata containing `ud`. In case of errors, `lua_cpcall` returns the same error codes as `lua_pcall` (see - |luaref-lua_pcall|), plus the error object on the top of the stack; + |lua_pcall()|), plus the error object on the top of the stack; otherwise, it returns zero, and does not change the stack. All values returned by `func` are discarded. @@ -1893,7 +1828,7 @@ lua_createtable *lua_createtable()* has space pre-allocated for `narr` array elements and `nrec` non-array elements. This pre-allocation is useful when you know exactly how many elements the table will have. Otherwise you can use the function - `lua_newtable` (see |luaref-lua_newtable|). + `lua_newtable` (see |lua_newtable()|). lua_dump *lua_dump()* > @@ -1903,7 +1838,7 @@ lua_dump *lua_dump()* of the stack and produces a binary chunk that, if loaded again, results in a function equivalent to the one dumped. As it produces parts of the chunk, `lua_dump` calls function `writer` (see - |luaref-lua_Writer|) with the given `data` to write them. + |lua_Writer()|) with the given `data` to write them. The value returned is the error code returned by the last call to the writer; 0 means no errors. @@ -1925,7 +1860,7 @@ lua_error *lua_error()* < Generates a Lua error. The error message (which can actually be a Lua value of any type) must be on the stack top. This function does a long - jump, and therefore never returns (see |luaref-luaL_error|). + jump, and therefore never returns (see |luaL_error()|). lua_gc *lua_gc()* > @@ -1965,7 +1900,7 @@ lua_getallocf *lua_getallocf()* < Returns the memory-allocation function of a given state. If `ud` is not `NULL`, Lua stores in `*ud` the opaque pointer passed to - `lua_newstate` (see |luaref-lua_newstate|). + `lua_newstate` (see |lua_newstate()|). lua_getfenv *lua_getfenv()* > @@ -2136,10 +2071,10 @@ lua_load *lua_load()* This function only loads a chunk; it does not run it. `lua_load` automatically detects whether the chunk is text or binary, - and loads it accordingly (see program `luac`, |luaref-luac|). + and loads it accordingly (see program `luac`). The `lua_load` function uses a user-supplied `reader` function to read - the chunk (see |luaref-lua_Reader|). The `data` argument is an opaque + the chunk (see |lua_Reader()|). The `data` argument is an opaque value passed to the reader function. The `chunkname` argument gives a name to the chunk, which is used for @@ -2161,14 +2096,14 @@ lua_newtable *lua_newtable()* < Creates a new empty table and pushes it onto the stack. It is equivalent to `lua_createtable(L, 0, 0)` (see - |luaref-lua_createtable|). + |lua_createtable()|). lua_newthread *lua_newthread()* > lua_State *lua_newthread (lua_State *L); < Creates a new thread, pushes it on the stack, and returns a pointer to - a `lua_State` (see |luaref-lua_State|) that represents this new + a `lua_State` (see |lua_State()|) that represents this new thread. The new state returned by this function shares with the original state all global objects (such as tables), but has an independent execution stack. @@ -2218,7 +2153,7 @@ lua_next *lua_next()* } < While traversing a table, do not call `lua_tolstring` (see - |luaref-lua_tolstring|) directly on a key, unless you know that the + |lua_tolstring()|) directly on a key, unless you know that the key is actually a string. Recall that `lua_tolstring` `changes` the value at the given index; this confuses the next call to `lua_next`. @@ -2248,7 +2183,7 @@ lua_pcall *lua_pcall()* Calls a function in protected mode. Both `nargs` and `nresults` have the same meaning as in `lua_call` - (see |luaref-lua_call|). If there are no errors during the call, + (see |lua_call()|). If there are no errors during the call, `lua_pcall` behaves exactly like `lua_call`. However, if there is any error, `lua_pcall` catches it, pushes a single value on the stack (the error message), and returns an error code. Like `lua_call`, @@ -2314,7 +2249,7 @@ lua_pushcfunction *lua_pushcfunction()* Any function to be registered in Lua must follow the correct protocol to receive its parameters and return its results (see - |luaref-lua_CFunction|). + |lua_CFunction()|). `lua_pushcfunction` is defined as a macro: > @@ -2408,7 +2343,7 @@ lua_pushvfstring *lua_pushvfstring()* const char *fmt, va_list argp); < - Equivalent to `lua_pushfstring` (see |luaref-pushfstring|), except + Equivalent to `lua_pushfstring` (see |lua_pushfstring()|), except that it receives a `va_list` instead of a variable number of arguments. @@ -2425,7 +2360,7 @@ lua_rawget *lua_rawget()* > void lua_rawget (lua_State *L, int index); < - Similar to `lua_gettable` (see |luaref-lua_gettable|), but does a raw + Similar to `lua_gettable` (see |lua_gettable()|), but does a raw access (i.e., without metamethods). lua_rawgeti *lua_rawgeti()* @@ -2440,7 +2375,7 @@ lua_rawset *lua_rawset()* > void lua_rawset (lua_State *L, int index); < - Similar to `lua_settable` (see |luaref-lua_settable|), but does a raw + Similar to `lua_settable` (see |lua_settable()|), but does a raw assignment (i.e., without metamethods). lua_rawseti *lua_rawseti()* @@ -2459,7 +2394,7 @@ lua_Reader *lua_Reader()* void *data, size_t *size); < - The reader function used by `lua_load` (see |luaref-lua_load|). Every + The reader function used by `lua_load` (see |lua_load()|). Every time it needs another piece of the chunk, `lua_load` calls the reader, passing along its `data` parameter. The reader must return a pointer to a block of memory with a new piece of the chunk and set `size` to @@ -2504,15 +2439,15 @@ lua_resume *lua_resume()* Starts and resumes a coroutine in a given thread. To start a coroutine, you first create a new thread (see - |luaref-lua_newthread|); then you push onto its stack the main + |lua_newthread()|); then you push onto its stack the main function plus any arguments; then you call `lua_resume` (see - |luaref-lua_resume|) with `narg` being the number of arguments. This + |lua_resume()|) with `narg` being the number of arguments. This call returns when the coroutine suspends or finishes its execution. When it returns, the stack contains all values passed to `lua_yield` - (see |luaref-lua_yield|), or all values returned by the body function. + (see |lua_yield()|), or all values returned by the body function. `lua_resume` returns `LUA_YIELD` if the coroutine yields, 0 if the coroutine finishes its execution without errors, or an error code in - case of errors (see |luaref-lua_pcall|). In case of errors, the stack + case of errors (see |lua_pcall()|). In case of errors, the stack is not unwound, so you can use the debug API over it. The error message is on the top of the stack. To restart a coroutine, you put on its stack only the values to be passed as results from `lua_yield`, @@ -2593,7 +2528,7 @@ lua_State *lua_State()* A pointer to this state must be passed as the first argument to every function in the library, except to `lua_newstate` (see - |luaref-lua_newstate|), which creates a Lua state from scratch. + |lua_newstate()|), which creates a Lua state from scratch. lua_status *lua_status()* > @@ -2614,7 +2549,7 @@ lua_toboolean *lua_toboolean()* any Lua value different from `false` and `nil`; otherwise it returns 0. It also returns 0 when called with a non-valid index. (If you want to accept only actual boolean values, use `lua_isboolean` - |luaref-lua_isboolean| to test the value's type.) + |lua_isboolean()| to test the value's type.) lua_tocfunction *lua_tocfunction()* > @@ -2628,7 +2563,7 @@ lua_tointeger *lua_tointeger()* lua_Integer lua_tointeger (lua_State *L, int idx); < Converts the Lua value at the given acceptable index to the signed - integral type `lua_Integer` (see |luaref-lua_Integer|). The Lua value + integral type `lua_Integer` (see |lua_Integer()|). The Lua value must be a number or a string convertible to a number (see |luaref-langCoercion|); otherwise, `lua_tointeger` returns 0. @@ -2644,7 +2579,7 @@ lua_tolstring *lua_tolstring()* Lua value must be a string or a number; otherwise, the function returns `NULL`. If the value is a number, then `lua_tolstring` also `changes the actual value in the stack to a` `string`. (This change - confuses `lua_next` |luaref-lua_next| when `lua_tolstring` is applied + confuses `lua_next` |lua_next()| when `lua_tolstring` is applied to keys during a table traversal.) `lua_tolstring` returns a fully aligned pointer to a string inside the @@ -2659,7 +2594,7 @@ lua_tonumber *lua_tonumber()* lua_Number lua_tonumber (lua_State *L, int index); < Converts the Lua value at the given acceptable index to the C type - `lua_Number` (see |luaref-lua_Number|). The Lua value must be a number + `lua_Number` (see |lua_Number()|). The Lua value must be a number or a string convertible to a number (see |luaref-langCoercion|); otherwise, `lua_tonumber` returns 0. @@ -2679,7 +2614,7 @@ lua_tostring *lua_tostring()* > const char *lua_tostring (lua_State *L, int index); < - Equivalent to `lua_tolstring` (see |luaref-lua_tolstring|) with `len` + Equivalent to `lua_tolstring` (see |lua_tolstring()|) with `len` equal to `NULL`. lua_tothread *lua_tothread()* @@ -2687,7 +2622,7 @@ lua_tothread *lua_tothread()* lua_State *lua_tothread (lua_State *L, int index); < Converts the value at the given acceptable index to a Lua thread - (represented as `lua_State*` |luaref-lua_State|). This value must be a + (represented as `lua_State*` |lua_State()|). This value must be a thread; otherwise, the function returns `NULL`. lua_touserdata *lua_touserdata()* @@ -2723,7 +2658,7 @@ lua_Writer *lua_Writer()* size_t sz, void* ud); < - The writer function used by `lua_dump` (see |luaref-lua_dump|). Every + The writer function used by `lua_dump` (see |lua_dump()|). Every time it produces another piece of chunk, `lua_dump` calls the writer, passing along the buffer to be written (`p`), its size (`sz`), and the `data` parameter supplied to `lua_dump`. @@ -2753,7 +2688,7 @@ lua_yield *lua_yield()* < When a C function calls `lua_yield` in that way, the running coroutine suspends its execution, and the call to `lua_resume` (see - |luaref-lua_resume|) that started this coroutine returns. The + |lua_resume()|) that started this coroutine returns. The parameter `nresults` is the number of values from the stack that are passed as results to `lua_resume`. @@ -2798,9 +2733,9 @@ lua_Debug *lua_Debug()* `} lua_Debug;` A structure used to carry different pieces of information about an active -function. `lua_getstack` (see |luaref-lua_getstack|) fills only the private part +function. `lua_getstack` (see |lua_getstack()|) fills only the private part of this structure, for later use. To fill the other fields of `lua_Debug` with -useful information, call `lua_getinfo` (see |luaref-lua_getinfo|). +useful information, call `lua_getinfo` (see |lua_getinfo()|). The fields of `lua_Debug` have the following meaning: @@ -2858,8 +2793,8 @@ lua_getinfo *lua_getinfo()* To get information about a function invocation, the parameter `ar` must be a valid activation record that was filled by a previous call - to `lua_getstack` (see |luaref-lua_getstack|) or given as argument to - a hook (see |luaref-lua_Hook|). + to `lua_getstack` (see |lua_getstack()|) or given as argument to + a hook (see |lua_Hook()|). To get information about a function you push it onto the stack and start the `what` string with the character `>`. (In that case, @@ -2896,8 +2831,8 @@ lua_getlocal *lua_getlocal()* < Gets information about a local variable of a given activation record. The parameter `ar` must be a valid activation record that was filled - by a previous call to `lua_getstack` (see |luaref-lua_getstack|) or - given as argument to a hook (see |luaref-lua_Hook|). The index `n` + by a previous call to `lua_getstack` (see |lua_getstack()|) or + given as argument to a hook (see |lua_Hook()|). The index `n` selects which local variable to inspect (1 is the first parameter or active local variable, and so on, until the last active local variable). `lua_getlocal` pushes the variable's value onto the stack @@ -2916,7 +2851,7 @@ lua_getstack *lua_getstack()* < Gets information about the interpreter runtime stack. - This function fills parts of a `lua_Debug` (see |luaref-lua_Debug|) + This function fills parts of a `lua_Debug` (see |lua_Debug()|) structure with an identification of the `activation record` of the function executing at a given level. Level 0 is the current running function, whereas level `n+1` is the function that has called level @@ -2951,7 +2886,7 @@ lua_Hook *lua_Hook()* `LUA_HOOKTAILRET`, `LUA_HOOKLINE`, and `LUA_HOOKCOUNT`. Moreover, for line events, the field `currentline` is also set. To get the value of any other field in `ar`, the hook must call `lua_getinfo` (see - |luaref-lua_getinfo|). For return events, `event` may be + |lua_getinfo()|). For return events, `event` may be `LUA_HOOKRET`, the normal value, or `LUA_HOOKTAILRET`. In the latter case, Lua is simulating a return from a function that did a tail call; in this case, it is useless to call `lua_getinfo`. @@ -2996,7 +2931,7 @@ lua_setlocal *lua_setlocal()* < Sets the value of a local variable of a given activation record. Parameters `ar` and `n` are as in `lua_getlocal` (see - |luaref-lua_getlocal|). `lua_setlocal` assigns the value at the top of + |lua_getlocal()|). `lua_setlocal` assigns the value at the top of the stack to the variable and returns its name. It also pops the value from the stack. @@ -3010,7 +2945,7 @@ lua_setupvalue *lua_setupvalue()* Sets the value of a closure's upvalue. It assigns the value at the top of the stack to the upvalue and returns its name. It also pops the value from the stack. Parameters `funcindex` and `n` are as in the - `lua_getupvalue` (see |luaref-lua_getupvalue|). + `lua_getupvalue` (see |lua_getupvalue()|). Returns `NULL` (and pops nothing) when the index is greater than the number of upvalues. @@ -3071,36 +3006,36 @@ luaL_addchar *luaL_addchar()* > void luaL_addchar (luaL_Buffer *B, char c); < - Adds the character `c` to the buffer `B` (see |luaref-luaL_Buffer|). + Adds the character `c` to the buffer `B` (see |luaL_Buffer()|). luaL_addlstring *luaL_addlstring()* > void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l); < Adds the string pointed to by `s` with length `l` to the buffer `B` - (see |luaref-luaL_Buffer|). The string may contain embedded zeros. + (see |luaL_Buffer()|). The string may contain embedded zeros. luaL_addsize *luaL_addsize()* > void luaL_addsize (luaL_Buffer *B, size_t n); < - Adds to the buffer `B` (see |luaref-luaL_Buffer|) a string of length + Adds to the buffer `B` (see |luaL_Buffer()|) a string of length `n` previously copied to the buffer area (see - |luaref-luaL_prepbuffer|). + |luaL_prepbuffer()|). luaL_addstring *luaL_addstring()* > void luaL_addstring (luaL_Buffer *B, const char *s); < Adds the zero-terminated string pointed to by `s` to the buffer `B` - (see |luaref-luaL_Buffer|). The string may not contain embedded zeros. + (see |luaL_Buffer()|). The string may not contain embedded zeros. luaL_addvalue *luaL_addvalue()* > void luaL_addvalue (luaL_Buffer *B); < Adds the value at the top of the stack to the buffer `B` (see - |luaref-luaL_Buffer|). Pops the value. + |luaL_Buffer()|). Pops the value. This is the only function on string buffers that can (and must) be called with an extra element on the stack, which is the value to be @@ -3142,11 +3077,11 @@ luaL_Buffer *luaL_Buffer()* - First you declare a variable `b` of type `luaL_Buffer`. - Then you initialize it with a call `luaL_buffinit(L, &b)` (see - |luaref-luaL_buffinit|). + |luaL_buffinit()|). - Then you add string pieces to the buffer calling any of the `luaL_add*` functions. - You finish by calling `luaL_pushresult(&b)` (see - |luaref-luaL_pushresult|). This call leaves the final string on the + |luaL_pushresult()|). This call leaves the final string on the top of the stack. During its normal operation, a string buffer uses a variable number of @@ -3156,7 +3091,7 @@ luaL_Buffer *luaL_Buffer()* that is, when you call a buffer operation, the stack is at the same level it was immediately after the previous buffer operation. (The only exception to this rule is `luaL_addvalue` - |luaref-luaL_addvalue|.) After calling `luaL_pushresult` the stack is + |luaL_addvalue()|.) After calling `luaL_pushresult` the stack is back to its level when the buffer was initialized, plus the final string on its top. @@ -3165,7 +3100,7 @@ luaL_buffinit *luaL_buffinit()* void luaL_buffinit (lua_State *L, luaL_Buffer *B); < Initializes a buffer `B`. This function does not allocate any space; - the buffer must be declared as a variable (see |luaref-luaL_Buffer|). + the buffer must be declared as a variable (see |luaL_Buffer()|). luaL_callmeta *luaL_callmeta()* > @@ -3199,7 +3134,7 @@ luaL_checkinteger *luaL_checkinteger()* lua_Integer luaL_checkinteger (lua_State *L, int narg); < Checks whether the function argument `narg` is a number and returns - this number cast to a `lua_Integer` (see |luaref-lua_Integer|). + this number cast to a `lua_Integer` (see |lua_Integer()|). luaL_checklong *luaL_checklong()* > @@ -3220,7 +3155,7 @@ luaL_checknumber *luaL_checknumber()* lua_Number luaL_checknumber (lua_State *L, int narg); < Checks whether the function argument `narg` is a number and returns - this number (see |luaref-lua_Number|). + this number (see |lua_Number()|). luaL_checkoption *luaL_checkoption()* > @@ -3262,14 +3197,14 @@ luaL_checktype *luaL_checktype()* void luaL_checktype (lua_State *L, int narg, int t); < Checks whether the function argument `narg` has type `t` (see - |luaref-lua_type|). + |lua_type()|). luaL_checkudata *luaL_checkudata()* > void *luaL_checkudata (lua_State *L, int narg, const char *tname); < Checks whether the function argument `narg` is a userdata of the type - `tname` (see |luaref-luaL_newmetatable|). + `tname` (see |luaL_newmetatable()|). luaL_dofile *luaL_dofile()* > @@ -3297,7 +3232,7 @@ luaL_error *luaL_error()* < Raises an error. The error message format is given by `fmt` plus any extra arguments, following the same rules of `lua_pushfstring` (see - |luaref-lua_pushfstring|). It also adds at the beginning of the + |lua_pushfstring()|). It also adds at the beginning of the message the file name and the line number where the error occurred, if this information is available. @@ -3317,7 +3252,7 @@ luaL_getmetatable *luaL_getmetatable()* void luaL_getmetatable (lua_State *L, const char *tname); < Pushes onto the stack the metatable associated with name `tname` in - the registry (see |luaref-luaL_newmetatable|). + the registry (see |luaL_newmetatable()|). luaL_gsub *luaL_gsub()* > @@ -3338,7 +3273,7 @@ luaL_loadbuffer *luaL_loadbuffer()* const char *name); < Loads a buffer as a Lua chunk. This function uses `lua_load` (see - |luaref-lua_load|) to load the chunk in the buffer pointed to by + |lua_load()|) to load the chunk in the buffer pointed to by `buff` with size `sz`. This function returns the same results as `lua_load`. `name` is the @@ -3349,7 +3284,7 @@ luaL_loadfile *luaL_loadfile()* int luaL_loadfile (lua_State *L, const char *filename); < Loads a file as a Lua chunk. This function uses `lua_load` (see - |luaref-lua_load|) to load the chunk in the file named `filename`. If + |lua_load()|) to load the chunk in the file named `filename`. If `filename` is `NULL`, then it loads from the standard input. The first line in the file is ignored if it starts with a `#`. @@ -3363,7 +3298,7 @@ luaL_loadstring *luaL_loadstring()* int luaL_loadstring (lua_State *L, const char *s); < Loads a string as a Lua chunk. This function uses `lua_load` (see - |luaref-lua_load|) to load the chunk in the zero-terminated string + |lua_load()|) to load the chunk in the zero-terminated string `s`. This function returns the same results as `lua_load`. @@ -3387,9 +3322,9 @@ luaL_newstate *luaL_newstate()* lua_State *luaL_newstate (void); < Creates a new Lua state. It calls `lua_newstate` (see - |luaref-lua_newstate|) with an allocator based on the standard C + |lua_newstate()|) with an allocator based on the standard C `realloc` function and then sets a panic function (see - |luaref-lua_atpanic|) that prints an error message to the standard + |lua_atpanic()|) that prints an error message to the standard error output in case of fatal errors. Returns the new state, or `NULL` if there is a memory allocation @@ -3417,7 +3352,7 @@ luaL_optinteger *luaL_optinteger()* lua_Integer d); < If the function argument `narg` is a number, returns this number cast - to a `lua_Integer` (see |luaref-lua_Integer|). If this argument is + to a `lua_Integer` (see |lua_Integer()|). If this argument is absent or is `nil`, returns `d`. Otherwise, raises an error. luaL_optlong *luaL_optlong()* @@ -3464,9 +3399,9 @@ luaL_prepbuffer *luaL_prepbuffer()* char *luaL_prepbuffer (luaL_Buffer *B); < Returns an address to a space of size `LUAL_BUFFERSIZE` where you can - copy a string to be added to buffer `B` (see |luaref-luaL_Buffer|). + copy a string to be added to buffer `B` (see |luaL_Buffer()|). After copying the string into this space you must call `luaL_addsize` - (see |luaref-luaL_addsize|) with the size of the string to actually + (see |luaL_addsize()|) with the size of the string to actually add it to the buffer. luaL_pushresult *luaL_pushresult()* @@ -3486,8 +3421,8 @@ luaL_ref *luaL_ref()* A reference is a unique integer key. As long as you do not manually add integer keys into table `t`, `luaL_ref` ensures the uniqueness of the key it returns. You can retrieve an object referred by reference - `r` by calling `lua_rawgeti(L, t, r)` (see |luaref-lua_rawgeti|). - Function `luaL_unref` (see |luaref-luaL_unref|) frees a reference and + `r` by calling `lua_rawgeti(L, t, r)` (see |lua_rawgeti()|). + Function `luaL_unref` (see |luaL_unref()|) frees a reference and its associated object. If the object at the top of the stack is `nil`, `luaL_ref` returns the @@ -3502,7 +3437,7 @@ luaL_Reg *luaL_Reg()* } luaL_Reg; < Type for arrays of functions to be registered by `luaL_register` (see - |luaref-luaL_register|). `name` is the function name and `func` is a + |luaL_register()|). `name` is the function name and `func` is a pointer to the function. Any array of `luaL_Reg` must end with a sentinel entry in which both `name` and `func` are `NULL`. @@ -3515,7 +3450,7 @@ luaL_register *luaL_register()* Opens a library. When called with `libname` equal to `NULL`, it simply registers all - functions in the list `l` (see |luaref-luaL_Reg|) into the table on + functions in the list `l` (see |luaL_Reg()|) into the table on the top of the stack. When called with a non-null `libname`, `luaL_register` creates a new @@ -3543,7 +3478,7 @@ luaL_typerror *luaL_typerror()* `expected, got` `rt` `)` where `location` is produced by `luaL_where` (see - |luaref-luaL_where|), `func` is the name of the current function, and + |luaL_where()|), `func` is the name of the current function, and `rt` is the type name of the actual argument. luaL_unref *luaL_unref()* @@ -3551,7 +3486,7 @@ luaL_unref *luaL_unref()* void luaL_unref (lua_State *L, int t, int ref); < Releases reference `ref` from the table at index `t` (see - |luaref-luaL_ref|). The entry is removed from the table, so that the + |luaL_ref()|). The entry is removed from the table, so that the referred object can be collected. The reference `ref` is also freed to be used again. @@ -3601,14 +3536,14 @@ functions as fields of a global table or as methods of its objects. *luaref-openlibs* To have access to these libraries, the C host program should call the `luaL_openlibs` function, which opens all standard libraries (see -|luaref-luaL_openlibs|). Alternatively, the host program can open the libraries +|luaL_openlibs()|). Alternatively, the host program can open the libraries individually by calling `luaopen_base` (for the basic library), `luaopen_package` (for the package library), `luaopen_string` (for the string library), `luaopen_table` (for the table library), `luaopen_math` (for the mathematical library), `luaopen_io` (for the I/O and the Operating System libraries), and `luaopen_debug` (for the debug library). These functions are declared in `lualib.h` and should not be called directly: you must call them -like any other Lua C function, e.g., by using `lua_call` (see |luaref-lua_call|). +like any other Lua C function, e.g., by using `lua_call` (see |lua_call()|). ============================================================================== 5.1 Basic Functions *luaref-libBasic* @@ -3700,11 +3635,11 @@ load({func} [, {chunkname}]) *luaref-load()* information. loadfile([{filename}]) *luaref-loadfile()* - Similar to `load` (see |luaref-load|), but gets the chunk from file + Similar to `load` (see |luaref-load()|), but gets the chunk from file {filename} or from the standard input, if no file name is given. loadstring({string} [, {chunkname}]) *luaref-loadstring()* - Similar to `load` (see |luaref-load|), but gets the chunk from the + Similar to `load` (see |luaref-load()|), but gets the chunk from the given {string}. To load and run a given string, use the idiom @@ -3724,14 +3659,14 @@ next({table} [, {index}]) *luaref-next()* The order in which the indices are enumerated is not specified, `even for` `numeric indices`. (To traverse a table in numeric order, use a - numerical `for` or the `ipairs` |luaref-ipairs| function.) + numerical `for` or the `ipairs` |luaref-ipairs()| function.) The behavior of `next` is `undefined` if, during the traversal, you assign any value to a non-existent field in the table. You may however modify existing fields. In particular, you may clear existing fields. pairs({t}) *luaref-pairs()* - Returns three values: the `next` |luaref-next| function, the table + Returns three values: the `next` |luaref-next()| function, the table {t}, and `nil`, so that the construction `for k,v in pairs(t) do` `body` `end` @@ -3749,10 +3684,10 @@ pcall({f}, {arg1}, {...}) *luaref-pcall()* print({...}) *luaref-print()* Receives any number of arguments, and prints their values to `stdout`, - using the `tostring` |luaref-tostring| function to convert them to + using the `tostring` |luaref-tostring()| function to convert them to strings. `print` is not intended for formatted output, but only as a quick way to show a value, typically for debugging. For formatted - output, use `string.format` (see |luaref-string.format|). + output, use `string.format` (see |string.format()|). rawequal({v1}, {v2}) *luaref-rawequal()* Checks whether {v1} is equal to {v2}, without invoking any metamethod. @@ -3807,7 +3742,7 @@ tonumber({e} [, {base}]) *luaref-tonumber()* tostring({e}) *luaref-tostring()* Receives an argument of any type and converts it to a string in a reasonable format. For complete control of how numbers are converted, - use `string.format` (see |luaref-string.format|). + use `string.format` (see |string.format()|). *__tostring* If the metatable of {e} has a `"__tostring"` field, `tostring` calls @@ -3836,7 +3771,7 @@ _VERSION *luaref-_VERSION()* `"Lua 5.1"` . xpcall({f}, {err}) *luaref-xpcall()* - This function is similar to `pcall` (see |luaref-pcall|), except that + This function is similar to `pcall` (see |luaref-pcall()|), except that you can set a new error handler. `xpcall` calls function {f} in protected mode, using {err} as the @@ -3901,7 +3836,7 @@ coroutine.yield({...}) *coroutine.yield()* The package library provides basic facilities for loading and building modules in Lua. It exports two of its functions directly in the global environment: -`require` and `module` (see |luaref-require| and |luaref-module|). Everything else is +`require` and `module` (see |luaref-require()| and |luaref-module()|). Everything else is exported in a table `package`. module({name} [, {...}]) *luaref-module()* @@ -3914,7 +3849,7 @@ module({name} [, {...}]) *luaref-module()* `t._PACKAGE` with the package name (the full module name minus last component; see below). Finally, `module` sets `t` as the new environment of the current function and the new value of - `package.loaded[name]`, so that `require` (see |luaref-require|) + `package.loaded[name]`, so that `require` (see |luaref-require()|) returns `t`. If {name} is a compound name (that is, one with components separated @@ -3968,7 +3903,7 @@ require({modname}) *luaref-require()* If there is any error loading or running the module, or if it cannot find any loader for the module, then `require` signals an error. -package.cpath *package.cpath()* +package.cpath *package.cpath* The path used by `require` to search for a C loader. Lua initializes the C path `package.cpath` in the same way it @@ -3985,7 +3920,7 @@ package.loadlib({libname}, {funcname}) *package.loadlib()* Dynamically links the host program with the C library {libname}. Inside this library, looks for a function {funcname} and returns this function as a C function. (So, {funcname} must follow the protocol - (see |luaref-lua_CFunction|)). + (see |lua_CFunction()|)). This is a low-level function. It completely bypasses the package and module system. Unlike `require`, it does not perform any path @@ -3998,7 +3933,7 @@ package.loadlib({libname}, {funcname}) *package.loadlib()* available on some platforms (Windows, Linux, Mac OS X, Solaris, BSD, plus other Unix systems that support the `dlfcn` standard). -package.path *package.path()* +package.path *package.path* The path used by `require` to search for a Lua loader. At start-up, Lua initializes this variable with the value of the @@ -4019,7 +3954,7 @@ package.path *package.path()* order. package.preload *package.preload()* - A table to store loaders for specific modules (see |luaref-require|). + A table to store loaders for specific modules (see |luaref-require()|). package.seeall({module}) *package.seeall()* Sets a metatable for {module} with its `__index` field referring to @@ -4059,7 +3994,7 @@ string.char({...}) *string.char()* string.dump({function}) *string.dump()* Returns a string containing a binary representation of the given - function, so that a later |luaref-loadstring| on this string returns a + function, so that a later |luaref-loadstring()| on this string returns a copy of the function. {function} must be a Lua function without upvalues. @@ -4341,7 +4276,7 @@ table.foreach({table}, {f}) *table.foreach()* returns a non-`nil` value, then the loop is broken, and this value is returned as the final value of `table.foreach`. - See |luaref-next| for extra information about table traversals. + See |luaref-next()| for extra information about table traversals. table.foreachi({table}, {f}) *table.foreachi()* Executes the given {f} over the numerical indices of {table}. For each @@ -4658,7 +4593,7 @@ file:setvbuf({mode} [, {size}]) *luaref-file:setvbuf()* immediately. `"full"` full buffering; output operation is performed only when the buffer is full (or when you explicitly `flush` the file - (see |luaref-io.flush|). + (see |io.flush()|). `"line"` line buffering; output is buffered until a newline is output or there is any input from some special files (such as a terminal device). @@ -4669,7 +4604,7 @@ file:setvbuf({mode} [, {size}]) *luaref-file:setvbuf()* file:write({...}) *luaref-file:write()* Writes the value of each of its arguments to `file`. The arguments must be strings or numbers. To write other values, use `tostring` - |luaref-tostring| or `string.format` |luaref-string.format| before + |luaref-tostring()| or `string.format` |string.format()| before `write`. ============================================================================== @@ -4686,7 +4621,7 @@ os.date([{format} [, {time}]]) *os.date()* according to the given string {format}. If the {time} argument is present, this is the time to be formatted - (see the `os.time` function |luaref-os.time| for a description of this + (see the `os.time` function |os.time()| for a description of this value). Otherwise, `date` formats the current time. If {format} starts with `!`, then the date is formatted in @@ -4744,7 +4679,7 @@ os.time([{table}]) *os.time()* representing the date and time specified by the given table. This table must have fields `year`, `month`, and `day`, and may have fields `hour`, `min`, `sec`, and `isdst` (for a description of these fields, - see the `os.date` function |luaref-os.date|). + see the `os.date` function |os.date()|). The returned value is a number, whose meaning depends on your system. In POSIX, Windows, and some other systems, this number counts the @@ -4802,7 +4737,7 @@ debug.getinfo([{thread},] {function} [, {what}]) *debug.getinfo()* functions, then `getinfo` returns `nil`. The returned table may contain all the fields returned by - `lua_getinfo` (see |luaref-lua_getinfo|), with the string {what} + `lua_getinfo` (see |lua_getinfo()|), with the string {what} describing which fields to fill in. The default for {what} is to get all information available, except the table of valid lines. If present, the option `f` adds a field named `func` with the function @@ -4821,7 +4756,7 @@ debug.getlocal([{thread},] {level}, {local}) *debug.getlocal()* last active local variable.) The function returns `nil` if there is no local variable with the given index, and raises an error when called with a {level} out of range. (You can call `debug.getinfo` - |luaref-debug.getinfo| to check whether the level is valid.) + |debug.getinfo()| to check whether the level is valid.) Variable names starting with `(` (open parentheses) represent internal variables (loop control variables, temporaries, and C @@ -4953,7 +4888,7 @@ C LUAREF DOC *luarefvim* *luarefvimdoc* *luaref-help* *luaref-d This is a Vim help file containing a reference for Lua 5.1, and it is -- with a few exceptions and adaptations -- a copy of the Lua 5.1 Reference Manual (see |luaref-bibliography|). For usage information, refer to -|luaref-docUsage|. For copyright information, see |luaref-copyright|. +|luaref-doc|. For copyright information, see |luaref-copyright|. The main ideas and concepts on how to implement this reference were taken from Christian Habermann's CRefVim project diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index da6a305e89..e5d22de748 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -1673,7 +1673,7 @@ backslash followed by a character other than white space or a backslash remains unmodified. Overview: command ~ - XX ab 'ab' + XX ab "ab" XX a\b 'a\b' XX a\ b 'a b' XX a\ b 'a ', 'b' diff --git a/runtime/doc/mbyte.txt b/runtime/doc/mbyte.txt index 2aa49cee1e..7a76c57fc2 100644 --- a/runtime/doc/mbyte.txt +++ b/runtime/doc/mbyte.txt @@ -86,9 +86,8 @@ You can also set 'guifont' alone, the Nvim GUI will try to find a matching INPUT There are several ways to enter multibyte characters: -- For X11 XIM can be used. See |XIM|. -- For MS-Windows IME can be used. See |IME|. -- For all systems keymaps can be used. See |mbyte-keymap|. +- Your system IME can be used. +- Keymaps can be used. See |mbyte-keymap|. The options 'iminsert', 'imsearch' and 'imcmdline' can be used to choose the different input methods or disable them temporarily. diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 14b7eb2d71..e5ad61062f 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -5704,7 +5704,7 @@ A jump table for the options with a short description can be found at |Q_op|. "yes:[1-9]" always, with fixed space for signs up to the given number (maximum 9), e.g. "yes:3" "number" display signs in the 'number' column. If the number - column is not present, then behaves like 'auto'. + column is not present, then behaves like "auto". Note regarding 'orphaned signs': with signcolumn numbers higher than 1, deleting lines will also remove the associated signs automatically, @@ -6481,7 +6481,7 @@ A jump table for the options with a short description can be found at |Q_op|. 'termguicolors' 'tgc' boolean (default off) global Enables 24-bit RGB color in the |TUI|. Uses "gui" |:highlight| - attributes instead of "cterm" attributes. |highlight-guifg| + attributes instead of "cterm" attributes. |guifg| Requires an ISO-8613-3 compatible terminal. *'termpastefilter'* *'tpf'* @@ -7136,7 +7136,7 @@ A jump table for the options with a short description can be found at |Q_op|. the window. Note: highlight namespaces take precedence over 'winhighlight'. - See |nvim_win_set_hl_ns| and |nvim_set_hl|. + See |nvim_win_set_hl_ns()| and |nvim_set_hl()|. Highlights of vertical separators are determined by the window to the left of the separator. The 'tabline' highlight of a tabpage is diff --git a/runtime/doc/pi_netrw.txt b/runtime/doc/pi_netrw.txt index 1eaa76264f..ae0169491b 100644 --- a/runtime/doc/pi_netrw.txt +++ b/runtime/doc/pi_netrw.txt @@ -2353,7 +2353,7 @@ MARKED FILES: DIFF *netrw-md* {{{2 (See |netrw-mf| and |netrw-mr| for how to mark files) (uses the global marked file list) -Use |vimdiff| to visualize difference between selected files (two or +Use vimdiff to visualize difference between selected files (two or three may be selected for this). Uses the global marked file list. MARKED FILES: EDITING *netrw-me* {{{2 @@ -3469,7 +3469,7 @@ Example: Clear netrw's marked file list via a mapping on gu > *netrw-p4* P4. I would like long listings to be the default. {{{2 - Put the following statement into your |.vimrc|: > + Put the following statement into your |vimrc|: > let g:netrw_liststyle= 1 < @@ -3482,7 +3482,7 @@ Example: Clear netrw's marked file list via a mapping on gu > Does your system's strftime() accept the "%c" to yield dates such as "Sun Apr 27 11:49:23 1997"? If not, do a "man strftime" and find out what option should be used. Then - put it into your |.vimrc|: > + put it into your |vimrc|: > let g:netrw_timefmt= "%X" (where X is the option) < @@ -3490,7 +3490,7 @@ Example: Clear netrw's marked file list via a mapping on gu > P6. I want my current directory to track my browsing. {{{2 How do I do that? - Put the following line in your |.vimrc|: + Put the following line in your |vimrc|: > let g:netrw_keepdir= 0 < @@ -3839,7 +3839,7 @@ netrw: or http://vim.sourceforge.net/scripts/script.php?script_id=120 - Decho.vim is provided as a "vimball"; see |vimball-intro|. You + Decho.vim is provided as a "vimball". You should edit the Decho.vba.gz file and source it in: > vim Decho.vba.gz @@ -3917,7 +3917,7 @@ netrw: * Installed |g:netrw_clipboard| setting * Installed option bypass for |'guioptions'| a/A settings - * Changed popup_beval() to |popup_atcursor()| + * Changed popup_beval() to popup_atcursor() in netrw#ErrorMsg (lacygoill). Apparently popup_beval doesn't reliably close the popup when the mouse is moved. @@ -3943,7 +3943,7 @@ netrw: did not restore options correctly that had a single quote in the option string. Apr 13, 2020 * implemented error handling via popup - windows (see |popup_beval()|) + windows (see popup_beval()) Apr 30, 2020 * (reported by Manatsu Takahashi) while using Lexplore, a modified file could be overwritten. Sol'n: will not overwrite, diff --git a/runtime/doc/print.txt b/runtime/doc/print.txt index 924fab175e..0e02c7d42d 100644 --- a/runtime/doc/print.txt +++ b/runtime/doc/print.txt @@ -659,7 +659,7 @@ It is possible to achieve a poor man's version of duplex printing using the PS utility psselect. This utility has options -e and -o for printing just the even or odd pages of a PS file respectively. -First generate a PS file with the 'hardcopy' command, then generate new +First generate a PS file with the ":hardcopy" command, then generate new files with all the odd and even numbered pages with: > psselect -o test.ps odd.ps diff --git a/runtime/doc/provider.txt b/runtime/doc/provider.txt index 9fd35f19c5..782bd19441 100644 --- a/runtime/doc/provider.txt +++ b/runtime/doc/provider.txt @@ -240,7 +240,7 @@ a list of lines and `regtype` is a register type conforming to |setreg()|. Paste *provider-paste* *paste* "Paste" is a separate concept from |clipboard|: paste means "dump a bunch of -text to the editor", whereas clipboard provides features like |quote-+| to get +text to the editor", whereas clipboard provides features like |quote+| to get and set the OS clipboard directly. For example, middle-click or CTRL-SHIFT-v (macOS: CMD-v) in your terminal is "paste", not "clipboard": the terminal application (Nvim) just gets a stream of text, it does not interact with the diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt index dab3bfa280..80110211f9 100644 --- a/runtime/doc/quickfix.txt +++ b/runtime/doc/quickfix.txt @@ -466,7 +466,7 @@ You can parse a list of lines using 'errorformat' without creating or modifying a quickfix list using the |getqflist()| function. Examples: > echo getqflist({'lines' : ["F1:10:Line10", "F2:20:Line20"]}) echo getqflist({'lines' : systemlist('grep -Hn quickfix *')}) -This returns a dictionary where the 'items' key contains the list of quickfix +This returns a dictionary where the "items" key contains the list of quickfix entries parsed from lines. The following shows how to use a custom 'errorformat' to parse the lines without modifying the 'errorformat' option: > echo getqflist({'efm' : '%f#%l#%m', 'lines' : ['F1#10#Line']}) @@ -585,7 +585,7 @@ can go back to the unfiltered list using the |:colder|/|:lolder| command. quickfix command or function, the |b:changedtick| variable is incremented. You can get the number of this buffer using the getqflist() and getloclist() - functions by passing the 'qfbufnr' item. For a + functions by passing the "qfbufnr" item. For a location list, this buffer is wiped out when the location list is removed. @@ -1965,7 +1965,7 @@ The function should return a single line of text to display in the quickfix window for each entry from start_idx to end_idx. The function can obtain information about the entries using the |getqflist()| function and specifying the quickfix list identifier "id". For a location list, getloclist() function -can be used with the 'winid' argument. If an empty list is returned, then the +can be used with the "winid" argument. If an empty list is returned, then the default format is used to display all the entries. If an item in the returned list is an empty string, then the default format is used to display the corresponding entry. diff --git a/runtime/doc/quickref.txt b/runtime/doc/quickref.txt index 9f3993506a..cb065cef2c 100644 --- a/runtime/doc/quickref.txt +++ b/runtime/doc/quickref.txt @@ -615,10 +615,6 @@ Short explanation of each option: *option-list* 'backupdir' 'bdir' list of directories for the backup file 'backupext' 'bex' extension used for the backup file 'backupskip' 'bsk' no backup for files that match these patterns -'balloondelay' 'bdlay' delay in mS before a balloon may pop up -'ballooneval' 'beval' switch on balloon evaluation in the GUI -'balloonevalterm' 'bevalterm' switch on balloon evaluation in the terminal -'balloonexpr' 'bexpr' expression to show in balloon 'belloff' 'bo' do not ring the bell for these reasons 'binary' 'bin' read/write/edit file in binary mode 'bomb' prepend a Byte Order Mark to the file @@ -817,8 +813,6 @@ Short explanation of each option: *option-list* 'printoptions' 'popt' controls the format of :hardcopy output 'pumheight' 'ph' maximum height of the popup menu 'pumwidth' 'pw' minimum width of the popup menu -'pythondll' name of the Python 2 dynamic library -'pythonthreedll' name of the Python 3 dynamic library 'pyxversion' 'pyx' Python version used for pyx* commands 'quoteescape' 'qe' escape characters used in a string 'readonly' 'ro' disallow writing the buffer @@ -829,7 +823,6 @@ Short explanation of each option: *option-list* 'revins' 'ri' inserting characters will work backwards 'rightleft' 'rl' window is right-to-left oriented 'rightleftcmd' 'rlc' commands for which editing works right-to-left -'rubydll' name of the Ruby dynamic library 'ruler' 'ru' show cursor line and column in the status line 'rulerformat' 'ruf' custom format for the ruler 'runtimepath' 'rtp' list of directories used for runtime files diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt index 508565dea4..0b316b4727 100644 --- a/runtime/doc/repeat.txt +++ b/runtime/doc/repeat.txt @@ -591,7 +591,7 @@ This could be done if some conditions are met. For example, depending on whether Vim supports a feature or a dependency is missing. You can also load an optional plugin at startup, by putting this command in -your |.vimrc|: > +your |config|: > :packadd! foodebug The extra "!" is so that the plugin isn't loaded if Vim was started with |--noplugin|. diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt index d57a85423c..351fe868d9 100644 --- a/runtime/doc/starting.txt +++ b/runtime/doc/starting.txt @@ -82,12 +82,10 @@ argument. --help *-h* *--help* *-?* -? -h Give usage (help) message and exit. - See |info-message| about capturing the text. --version *-v* *--version* -v Print version information and exit. Same output as for |:version| command. - See |info-message| about capturing the text. *--clean* --clean Mimics a fresh install of Nvim: diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index 6fcf292513..1368814952 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -3118,7 +3118,7 @@ The default is to use the twice sh_minlines. Set it to a smaller number to speed up displaying. The disadvantage is that highlight errors may appear. syntax/sh.vim tries to flag certain problems as errors; usually things like -extra ']'s, 'done's, 'fi's, etc. If you find the error handling problematic +extra "]"s, "done"s, "fi"s, etc. If you find the error handling problematic for your purposes, you may suppress such error highlighting by putting the following line in your .vimrc: > @@ -4935,7 +4935,7 @@ cterm={attr-list} *attr-list* *highlight-cterm* *E418* have the same effect. "undercurl", "underdouble", "underdotted", and "underdashed" fall back to "underline" in a terminal that does not support them. The color is - set using |highlight-guisp|. + set using |guisp|. start={term-list} *highlight-start* *E422* stop={term-list} *term-list* *highlight-stop* @@ -4956,8 +4956,8 @@ stop={term-list} *term-list* *highlight-stop* like "" and "". Example: start=[27h;[r; -ctermfg={color-nr} *highlight-ctermfg* *E421* -ctermbg={color-nr} *highlight-ctermbg* +ctermfg={color-nr} *ctermfg* *E421* +ctermbg={color-nr} *ctermbg* The {color-nr} argument is a color number. Its range is zero to (not including) the number of |tui-colors| available. The actual color with this number depends on the type of terminal @@ -5064,9 +5064,9 @@ font={font-name} *highlight-font* Example: > :hi comment font='Monospace 10' -guifg={color-name} *highlight-guifg* -guibg={color-name} *highlight-guibg* -guisp={color-name} *highlight-guisp* +guifg={color-name} *guifg* +guibg={color-name} *guibg* +guisp={color-name} *guisp* These give the foreground (guifg), background (guibg) and special (guisp) color to use in the GUI. "guisp" is used for various underlines. @@ -5123,7 +5123,7 @@ Cursor Character under the cursor. lCursor Character under the cursor when |language-mapping| is used (see 'guicursor'). *hl-CursorIM* -CursorIM Like Cursor, but used when in IME mode. |CursorIM| +CursorIM Like Cursor, but used when in IME mode. *CursorIM* *hl-CursorColumn* CursorColumn Screen-column at the cursor, when 'cursorcolumn' is set. *hl-CursorLine* diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index 3102c6da9a..75395e89ac 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -50,13 +50,13 @@ Whenever you need to access the current syntax tree, parse the buffer: > tstree = tsparser:parse() < -This will return a table of immutable |lua-treesitter-tree|s that represent the +This will return a table of immutable |treesitter-tree|s that represent the current state of the buffer. When the plugin wants to access the state after a (possible) edit it should call `parse()` again. If the buffer wasn't edited, the same tree will be returned again without extra work. If the buffer was parsed before, incremental parsing will be done of the changed parts. -Note: To use the parser directly inside a |nvim_buf_attach/)| Lua callback, you +Note: To use the parser directly inside a |nvim_buf_attach()| Lua callback, you must call |get_parser()| before you register your callback. But preferably parsing shouldn't be done directly in the change callback anyway as they will be very frequent. Rather a plugin that does any kind of analysis on a tree @@ -233,7 +233,7 @@ The following predicates are built in: node's text. `lua-match?` *treesitter-predicate-lua-match?* - Match a |lua-pattern| against the text corresponding to a node, + Match |lua-patterns| against the text corresponding to a node, similar to `match?` `contains?` *treesitter-predicate-contains?* @@ -394,7 +394,7 @@ still highlighted the same as other operators: > "!=" @operator (#set! conceal "≠") < -Conceals specified in this way respect |conceallevel|. +Conceals specified in this way respect 'conceallevel'. *treesitter-highlight-priority* Treesitter uses |nvim_buf_set_extmark()| to set highlights with a default @@ -650,7 +650,7 @@ get_query({lang}, {query_name}) *get_query()* Parameters: ~ {lang} (string) Language to use for the query - {query_name} (string) Name of the query (e.g. 'highlights') + {query_name} (string) Name of the query (e.g. "highlights") Return: ~ Query Parsed query @@ -661,7 +661,7 @@ get_query_files({lang}, {query_name}, {is_included}) Parameters: ~ {lang} (string) Language to get query for - {query_name} (string) Name of the query to load (e.g., 'highlights') + {query_name} (string) Name of the query to load (e.g., "highlights") {is_included} (boolean|nil) Internal parameter, most of the time left as `nil` @@ -742,7 +742,7 @@ Query:iter_matches({self}, {node}, {source}, {start}, {stop}) Iterates the matches of self on a given range. Iterate over all matches within a {node}. The arguments are the same as - for |query:iter_captures()| but the iterated values are different: an + for |Query:iter_captures()| but the iterated values are different: an (1-based) index of the pattern in the query, a table mapping capture indices to nodes, and metadata from any directives processing the match. If the query has more than one pattern, the capture table might be sparse @@ -780,7 +780,7 @@ set_query({lang}, {query_name}, {text}) *set_query()* Parameters: ~ {lang} (string) Language to use for the query - {query_name} (string) Name of the query (e.g., 'highlights') + {query_name} (string) Name of the query (e.g., "highlights") {text} (string) Query text (unparsed). diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt index 955af84679..2d0c8d3b75 100644 --- a/runtime/doc/ui.txt +++ b/runtime/doc/ui.txt @@ -576,7 +576,7 @@ The multigrid extension gives UIs more control over how windows are displayed: per-window. Or reserve space around the border of the window for its own elements, such as scrollbars from the UI toolkit. - A dedicated grid is used for messages, which may scroll over the window - area. (Alternatively |ext_messages| can be used). + area. (Alternatively |ui-messages| can be used). By default, the grid size is handled by Nvim and set to the outer grid size (i.e. the size of the window frame in Nvim) whenever the split is created. @@ -618,7 +618,7 @@ tabs. flag). The Builtin TUI draws a full line filled with `sep_char` and |hl-MsgSeparator| highlight. - When |ext_messages| is active, no message grid is used, and this event + When |ui-messages| is active, no message grid is used, and this event will not be sent. ["win_viewport", grid, win, topline, botline, curline, curcol] diff --git a/runtime/doc/userfunc.txt b/runtime/doc/userfunc.txt index c015b12c27..32c5b0b671 100644 --- a/runtime/doc/userfunc.txt +++ b/runtime/doc/userfunc.txt @@ -214,7 +214,7 @@ It is allowed to define another function inside a function body. You can provide default values for positional named arguments. This makes them optional for function calls. When a positional argument is not specified at a call, the default expression is used to initialize it. -This only works for functions declared with |function|, not for +This only works for functions declared with |:function|, not for lambda expressions |expr-lambda|. Example: > @@ -422,8 +422,7 @@ Also note that if you have two script files, and one calls a function in the other and vice versa, before the used function is defined, it won't work. Avoid using the autoload functionality at the toplevel. -Hint: If you distribute a bunch of scripts you can pack them together with the -|vimball| utility. Also read the user manual |distribute-script|. +Hint: If you distribute a bunch of scripts read |distribute-script|. vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index 1aa9aaa0c4..adb5130a53 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -1710,7 +1710,7 @@ There is a little "catch" with comments for some commands. Examples: > :execute cmd " do it :!ls *.c " list C files -The abbreviation 'dev' will be expanded to 'development " shorthand'. The +The abbreviation "dev" will be expanded to 'development " shorthand'. The mapping of will actually be the whole line after the 'o# ....' including the '" insert include'. The "execute" command will give an error. The "!" command will send everything after it to the shell, causing an error for an diff --git a/runtime/doc/usr_45.txt b/runtime/doc/usr_45.txt index 3199c4d8ea..0d23ef50fd 100644 --- a/runtime/doc/usr_45.txt +++ b/runtime/doc/usr_45.txt @@ -300,8 +300,7 @@ can use digraphs. This was already explained in |24.9|. keyboard, you will want to use an Input Method (IM). This requires learning the translation from typed keys to resulting character. When you need an IM you probably already have one on your system. It should work with Vim like -with other programs. For details see |mbyte-XIM| for the X Window system and -|mbyte-IME| for MS-Windows. +with other programs. KEYMAPS diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index e254e5edd0..672d064478 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -417,8 +417,8 @@ Normal commands: Options: 'ttimeout', 'ttimeoutlen' behavior was simplified - |jumpoptions| "stack" behavior - |jumpoptions| "view" tries to restore the |mark-view| when moving through + 'jumpoptions' "stack" behavior + 'jumpoptions' "view" tries to restore the |mark-view| when moving through the |jumplist|, |changelist|, |alternate-file| or using |mark-motions|. 'shortmess' the "F" flag does not affect output from autocommands @@ -498,13 +498,16 @@ Working directory (Vim implemented some of these later than Nvim): ============================================================================== 5. Missing legacy features *nvim-features-missing* -Some legacy Vim features are not implemented: +Some legacy Vim features are not yet implemented: -- |if_lua|: Nvim Lua API is not compatible with Vim's "if_lua" +- *if_lua* : Nvim |Lua| API is not compatible with Vim's "if_lua" - *if_mzscheme* -- |if_py|: *python-bindeval* *python-Function* are not supported +- |if_pyth|: *python-bindeval* *python-Function* are not supported - *if_tcl* +*:gui* +*:gvim* + ============================================================================== 6. Removed features *nvim-features-removed* @@ -566,18 +569,18 @@ Highlight groups: < Options: - 'antialias' + antialias *'balloondelay'* *'bdlay'* *'ballooneval'* *'beval'* *'noballooneval'* *'nobeval'* *'balloonexpr'* *'bexpr'* - 'bioskey' (MS-DOS) - 'conskey' (MS-DOS) + bioskey (MS-DOS) + conskey (MS-DOS) *'cp'* *'nocompatible'* *'nocp'* *'compatible'* (Nvim is always "nocompatible".) 'cpoptions' (gjkHw<*- and all POSIX flags were removed) *'cryptmethod'* *'cm'* *'key'* (Vim encryption implementation) *'ed'* *'edcompatible'* *'noed'* *'noedcompatible'* 'encoding' ("utf-8" is always used) - 'esckeys' + esckeys 'guioptions' "t" flag was removed *'guifontset'* *'gfs'* (Use 'guifont' instead.) *'guipty'* (Nvim uses pipes and PTYs consistently on all platforms.) @@ -618,18 +621,18 @@ Options: Nvim always displays up to 6 combining characters. You can still edit text with more than 6 combining characters, you just can't see them. Use |g8| or |ga|. See |mbyte-combining|. - 'maxmem' Nvim delegates memory-management to the OS. - 'maxmemtot' Nvim delegates memory-management to the OS. + *'maxmem'* Nvim delegates memory-management to the OS. + *'maxmemtot'* Nvim delegates memory-management to the OS. *'prompt'* *'noprompt'* *'remap'* *'noremap'* *'restorescreen'* *'rs'* *'norestorescreen'* *'nors'* - 'shelltype' + *'shelltype'* *'shortname'* *'sn'* *'noshortname'* *'nosn'* *'swapsync'* *'sws'* *'termencoding'* *'tenc'* (Vim 7.4.852 also removed this for Windows) *'terse'* *'noterse'* (Add "s" to 'shortmess' instead) - 'textauto' - 'textmode' + textauto + textmode *'toolbar'* *'tb'* *'toolbariconsize'* *'tbis'* *'ttybuiltin'* *'tbi'* *'nottybuiltin'* *'notbi'* @@ -637,7 +640,7 @@ Options: *'ttymouse'* *'ttym'* *'ttyscroll'* *'tsl'* *'ttytype'* *'tty'* - 'weirdinvert' + weirdinvert Startup: --literal (file args are always literal; to expand wildcards on Windows, use diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index b8a7f71145..96a87b8bb9 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -401,7 +401,7 @@ end ---@param bufnr number of buffer ---@param pos1 (line, column) tuple marking beginning of region ---@param pos2 (line, column) tuple marking end of region ----@param regtype type of selection (:help setreg) +---@param regtype type of selection, see |setreg()| ---@param inclusive boolean indicating whether the selection is end-inclusive ---@return region lua table of the form {linenr = {startcol,endcol}} function vim.region(bufnr, pos1, pos2, regtype, inclusive) @@ -448,7 +448,7 @@ end --- Defers calling `fn` until `timeout` ms passes. --- --- Use to do a one-shot timer that calls `fn` ---- Note: The {fn} is |schedule_wrap|ped automatically, so API functions are +--- Note: The {fn} is |vim.schedule_wrap()|ped automatically, so API functions are --- safe to call. ---@param fn Callback to call once `timeout` expires ---@param timeout Number of milliseconds to wait before calling `fn` diff --git a/runtime/lua/vim/highlight.lua b/runtime/lua/vim/highlight.lua index ddd504a0e0..0fde515bd9 100644 --- a/runtime/lua/vim/highlight.lua +++ b/runtime/lua/vim/highlight.lua @@ -41,7 +41,7 @@ end ---@param start first position (tuple {line,col}) ---@param finish second position (tuple {line,col}) ---@param opts table with options: --- - regtype type of range (:help setreg, default charwise) +-- - regtype type of range (see |setreg()|, default charwise) -- - inclusive boolean indicating whether the range is end-inclusive (default false) -- - priority number indicating priority of highlight (default priorities.user) function M.range(bufnr, ns, higroup, start, finish, opts) diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 22933d8143..a64facf214 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -823,7 +823,7 @@ end --- }) --- --- ---- See |lsp.start_client| for all available options. The most important are: +--- See |vim.lsp.start_client()| for all available options. The most important are: --- --- `name` is an arbitrary name for the LSP client. It should be unique per --- language server. @@ -834,7 +834,7 @@ end --- --- `root_dir` path to the project root. --- By default this is used to decide if an existing client should be re-used. ---- The example above uses |vim.fs.find| and |vim.fs.dirname| to detect the +--- The example above uses |vim.fs.find()| and |vim.fs.dirname()| to detect the --- root by traversing the file system upwards starting --- from the current directory until either a `pyproject.toml` or `setup.py` --- file is found. @@ -849,11 +849,11 @@ end --- --- --- To ensure a language server is only started for languages it can handle, ---- make sure to call |vim.lsp.start| within a |FileType| autocmd. +--- make sure to call |vim.lsp.start()| within a |FileType| autocmd. --- Either use |:au|, |nvim_create_autocmd()| or put the call in a --- `ftplugin/.lua` (See |ftplugin-name|) --- ----@param config table Same configuration as documented in |lsp.start_client()| +---@param config table Same configuration as documented in |vim.lsp.start_client()| ---@param opts nil|table Optional keyword arguments: --- - reuse_client (fun(client: client, config: table): boolean) --- Predicate used to decide if a client should be re-used. @@ -902,12 +902,12 @@ end --- --- ---@param cmd: (table|string|fun(dispatchers: table):table) command string or ---- list treated like |jobstart|. The command must launch the language server +--- list treated like |jobstart()|. The command must launch the language server --- process. `cmd` can also be a function that creates an RPC client. --- The function receives a dispatchers table and must return a table with the --- functions `request`, `notify`, `is_closing` and `terminate` ---- See |vim.lsp.rpc.request| and |vim.lsp.rpc.notify| ---- For TCP there is a built-in rpc client factory: |vim.lsp.rpc.connect| +--- See |vim.lsp.rpc.request()| and |vim.lsp.rpc.notify()| +--- For TCP there is a built-in rpc client factory: |vim.lsp.rpc.connect()| --- ---@param cmd_cwd: (string, default=|getcwd()|) Directory to launch --- the `cmd` process. Not related to `root_dir`. @@ -963,7 +963,7 @@ end ---@param on_error Callback with parameters (code, ...), invoked --- when the client operation throws an error. `code` is a number describing --- the error. Other arguments may be passed depending on the error kind. See ---- |vim.lsp.rpc.client_errors| for possible errors. +--- `vim.lsp.rpc.client_errors` for possible errors. --- Use `vim.lsp.rpc.client_errors[code]` to get human-friendly name. --- ---@param before_init Callback with parameters (initialize_params, config) @@ -999,8 +999,8 @@ end --- notifications to the server by the given number in milliseconds. No debounce --- occurs if nil --- - exit_timeout (number|boolean, default false): Milliseconds to wait for server to ---- exit cleanly after sending the 'shutdown' request before sending kill -15. ---- If set to false, nvim exits immediately after sending the 'shutdown' request to the server. +--- exit cleanly after sending the "shutdown" request before sending kill -15. +--- If set to false, nvim exits immediately after sending the "shutdown" request to the server. --- ---@param root_dir string Directory where the LSP --- server will base its workspaceFolders, rootUri, and rootPath @@ -1078,7 +1078,7 @@ function lsp.start_client(config) --- ---@param code (number) Error code ---@param err (...) Other arguments may be passed depending on the error kind - ---@see |vim.lsp.rpc.client_errors| for possible errors. Use + ---@see `vim.lsp.rpc.client_errors` for possible errors. Use ---`vim.lsp.rpc.client_errors[code]` to get a human-friendly name. function dispatch.on_error(code, err) local _ = log.error() diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index 8567619228..b9aaacb437 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -111,7 +111,7 @@ end --- about the context in which a completion was triggered (how it was triggered, --- and by which trigger character, if applicable) --- ----@see |vim.lsp.protocol.constants.CompletionTriggerKind| +---@see vim.lsp.protocol.constants.CompletionTriggerKind function M.completion(context) local params = util.make_position_params() params.context = context @@ -317,7 +317,7 @@ end --- ---@param options table|nil with valid `FormattingOptions` entries ---@param timeout_ms (number) Request timeout ----@see |vim.lsp.buf.formatting_seq_sync| +---@see |vim.lsp.buf.format()| function M.formatting_sync(options, timeout_ms) vim.notify_once( 'vim.lsp.buf.formatting_sync is deprecated. Use vim.lsp.buf.format instead', @@ -614,14 +614,14 @@ end --- Lists all the call sites of the symbol under the cursor in the --- |quickfix| window. If the symbol can resolve to multiple ---- items, the user can pick one in the |inputlist|. +--- items, the user can pick one in the |inputlist()|. function M.incoming_calls() call_hierarchy('callHierarchy/incomingCalls') end --- Lists all the items that are called by the symbol under the --- cursor in the |quickfix| window. If the symbol can resolve to ---- multiple items, the user can pick one in the |inputlist|. +--- multiple items, the user can pick one in the |inputlist()|. function M.outgoing_calls() call_hierarchy('callHierarchy/outgoingCalls') end @@ -730,9 +730,9 @@ end --- --- Note: Usage of |vim.lsp.buf.document_highlight()| requires the following highlight groups --- to be defined or you won't be able to see the actual highlights. ---- |LspReferenceText| ---- |LspReferenceRead| ---- |LspReferenceWrite| +--- |hl-LspReferenceText| +--- |hl-LspReferenceRead| +--- |hl-LspReferenceWrite| function M.document_highlight() local params = util.make_position_params() request('textDocument/documentHighlight', params) diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index 624436bc9b..a32c59dd17 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -389,7 +389,7 @@ M['textDocument/implementation'] = location_handler ---@param config table Configuration table. --- - border: (default=nil) --- - Add borders to the floating window ---- - See |vim.api.nvim_open_win()| +--- - See |nvim_open_win()| function M.signature_help(_, result, ctx, config) config = config or {} config.focus_id = ctx.method diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index 755c0ffc6f..842a0ce329 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -635,7 +635,7 @@ end --- Starts an LSP server process and create an LSP RPC client object to --- interact with it. Communication with the spawned process happens via stdio. For ---- communication via TCP, spawn a process manually and use |vim.lsp.rpc.connect| +--- communication via TCP, spawn a process manually and use |vim.lsp.rpc.connect()| --- ---@param cmd (string) Command to start the LSP server. ---@param cmd_args (table) List of additional string arguments to pass to {cmd}. diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 64512a9739..dbc18963f9 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -1504,7 +1504,7 @@ end --- ---@param contents table of lines to show in window ---@param syntax string of syntax to set for opened buffer ----@param opts table with optional fields (additional keys are passed on to |vim.api.nvim_open_win()|) +---@param opts table with optional fields (additional keys are passed on to |nvim_open_win()|) --- - height: (number) height of floating window --- - width: (number) width of floating window --- - wrap: (boolean, default true) wrap long lines @@ -1819,7 +1819,7 @@ end --- CAUTION: Modifies the input in-place! --- ---@param lines (table) list of lines ----@returns (string) filetype or 'markdown' if it was unchanged. +---@returns (string) filetype or "markdown" if it was unchanged. function M.try_trim_markdown_code_blocks(lines) local language_id = lines[1]:match('^```(.*)') if language_id then @@ -1992,7 +1992,7 @@ function M.make_workspace_params(added, removed) end --- Returns indentation size. --- ----@see |shiftwidth| +---@see 'shiftwidth' ---@param bufnr (number|nil): Buffer handle, defaults to current ---@returns (number) indentation size function M.get_effective_tabstop(bufnr) diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index de5f7240aa..c5c31b6ddf 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -302,7 +302,7 @@ end --- Merges recursively two or more map-like tables. --- ----@see |tbl_extend()| +---@see |vim.tbl_extend()| --- ---@param behavior string Decides what to do if a key is found in more than one map: --- - "error": raise an error diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index d1dc29969b..1e46daaccf 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -54,7 +54,7 @@ end --- Gets the list of files used to make up a query --- ---@param lang string Language to get query for ----@param query_name string Name of the query to load (e.g., 'highlights') +---@param query_name string Name of the query to load (e.g., "highlights") ---@param is_included (boolean|nil) Internal parameter, most of the time left as `nil` ---@return string[] query_files List of files to load for given query and language function M.get_query_files(lang, query_name, is_included) @@ -162,7 +162,7 @@ local explicit_queries = setmetatable({}, { --- set by plugins. --- ---@param lang string Language to use for the query ----@param query_name string Name of the query (e.g., 'highlights') +---@param query_name string Name of the query (e.g., "highlights") ---@param text string Query text (unparsed). function M.set_query(lang, query_name, text) explicit_queries[lang][query_name] = M.parse_query(lang, text) @@ -171,7 +171,7 @@ end --- Returns the runtime query {query_name} for {lang}. --- ---@param lang string Language to use for the query ----@param query_name string Name of the query (e.g. 'highlights') +---@param query_name string Name of the query (e.g. "highlights") --- ---@return Query Parsed query function M.get_query(lang, query_name) @@ -596,7 +596,7 @@ end --- Iterates the matches of self on a given range. --- --- Iterate over all matches within a {node}. The arguments are the same as ---- for |query:iter_captures()| but the iterated values are different: +--- for |Query:iter_captures()| but the iterated values are different: --- an (1-based) index of the pattern in the query, a table mapping --- capture indices to nodes, and metadata from any directives processing the match. --- If the query has more than one pattern, the capture table might be sparse diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c index ac4cb953b8..b5c695b9ce 100644 --- a/src/nvim/api/autocmd.c +++ b/src/nvim/api/autocmd.c @@ -599,7 +599,7 @@ void nvim_del_autocmd(Integer id, Error *err) } /// Clear all autocommands that match the corresponding {opts}. To delete -/// a particular autocmd, see |nvim_del_autocmd|. +/// a particular autocmd, see |nvim_del_autocmd()|. /// @param opts Parameters /// - event: (string|table) /// Examples: @@ -728,7 +728,7 @@ Integer nvim_create_augroup(uint64_t channel_id, String name, Dict(create_augrou /// /// To get a group id one can use |nvim_get_autocmds()|. /// -/// NOTE: behavior differs from |augroup-delete|. When deleting a group, autocommands contained in +/// NOTE: behavior differs from |:augroup-delete|. When deleting a group, autocommands contained in /// this group will also be deleted and cleared. This group will no longer exist. /// @param id Integer The id of the group. /// @see |nvim_del_augroup_by_name()| @@ -746,10 +746,10 @@ void nvim_del_augroup_by_id(Integer id, Error *err) /// Delete an autocommand group by name. /// -/// NOTE: behavior differs from |augroup-delete|. When deleting a group, autocommands contained in +/// NOTE: behavior differs from |:augroup-delete|. When deleting a group, autocommands contained in /// this group will also be deleted and cleared. This group will no longer exist. /// @param name String The name of the group. -/// @see |autocommand-groups| +/// @see |autocmd-groups| void nvim_del_augroup_by_name(String name, Error *err) FUNC_API_SINCE(9) { diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index edcea52838..c92a97519d 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -393,7 +393,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e /// multiple highlight groups that will be stacked /// (highest priority last). A highlight group can be supplied /// either as a string or as an integer, the latter which -/// can be obtained using |nvim_get_hl_id_by_name|. +/// can be obtained using |nvim_get_hl_id_by_name()|. /// - virt_text_pos : position of virtual text. Possible values: /// - "eol": right after eol character (default) /// - "overlay": display over the specified column, without @@ -430,7 +430,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e /// column of the window, bypassing /// sign and number columns. /// -/// - ephemeral : for use with |nvim_set_decoration_provider| +/// - ephemeral : for use with |nvim_set_decoration_provider()| /// callbacks. The mark will only be used for the current /// redraw cycle, and not be permantently stored in the /// buffer. @@ -958,7 +958,7 @@ void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start, /// being triggered during the redraw code. /// /// The expected usage is to set extmarks for the currently -/// redrawn buffer. |nvim_buf_set_extmark| can be called to add marks +/// redrawn buffer. |nvim_buf_set_extmark()| can be called to add marks /// on a per-window or per-lines basis. Use the `ephemeral` key to only /// use the mark for the current screen redraw (the callback will be called /// again for the next redraw ). diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c index 867584dd71..ec1f19cf6a 100644 --- a/src/nvim/api/options.c +++ b/src/nvim/api/options.c @@ -147,7 +147,7 @@ Object nvim_get_option_value(String name, Dict(option) *opts, Error *err) /// @param name Option name /// @param value New option value /// @param opts Optional parameters -/// - scope: One of 'global' or 'local'. Analogous to +/// - scope: One of "global" or "local". Analogous to /// |:setglobal| and |:setlocal|, respectively. /// - win: |window-ID|. Used for setting window local option. /// - buf: Buffer number. Used for setting buffer local option. @@ -202,7 +202,7 @@ void nvim_set_option_value(String name, Object value, Dict(option) *opts, Error /// Gets the option information for all options. /// /// The dictionary has the full option names as keys and option metadata -/// dictionaries as detailed at |nvim_get_option_info|. +/// dictionaries as detailed at |nvim_get_option_info()|. /// /// @return dictionary of all options Dictionary nvim_get_all_options_info(Error *err) diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index ad9ed72f43..d65127e406 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -160,8 +160,8 @@ Dictionary nvim__get_hl_defs(Integer ns_id, Arena *arena, Error *err) /// - nocombine: boolean /// - link: name of another highlight group to link to, see |:hi-link|. /// - default: Don't override existing definition |:hi-default| -/// - ctermfg: Sets foreground of cterm color |highlight-ctermfg| -/// - ctermbg: Sets background of cterm color |highlight-ctermbg| +/// - ctermfg: Sets foreground of cterm color |ctermfg| +/// - ctermbg: Sets background of cterm color |ctermbg| /// - cterm: cterm attribute map, like |highlight-args|. If not set, /// cterm attributes will match those from the attribute map /// documented above. @@ -185,7 +185,7 @@ void nvim_set_hl(Integer ns_id, String name, Dict(highlight) *val, Error *err) } /// Set active namespace for highlights. This can be set for a single window, -/// see |nvim_win_set_hl_ns|. +/// see |nvim_win_set_hl_ns()|. /// /// @param ns_id the namespace to use /// @param[out] err Error details, if any @@ -205,7 +205,7 @@ void nvim_set_hl_ns(Integer ns_id, Error *err) /// Set active namespace for highlights while redrawing. /// /// This function meant to be called while redrawing, primarily from -/// |nvim_set_decoration_provider| on_win and on_line callbacks, which +/// |nvim_set_decoration_provider()| on_win and on_line callbacks, which /// are allowed to change the namespace during a redraw cycle. /// /// @param ns_id the namespace to activate @@ -523,7 +523,7 @@ Array nvim__runtime_inspect(void) /// Find files in runtime directories /// -/// 'name' can contain wildcards. For example +/// "name" can contain wildcards. For example /// nvim_get_runtime_file("colors/*.vim", true) will return all color /// scheme files. Always use forward slashes (/) in the search pattern for /// subdirectories regardless of platform. @@ -964,7 +964,7 @@ fail: /// mode. Note: keypresses are sent raw as they would be to the pty /// master end. For instance, a carriage return is sent /// as a "\r", not as a "\n". |textlock| applies. It is possible -/// to call |nvim_chan_send| directly in the callback however. +/// to call |nvim_chan_send()| directly in the callback however. /// ["input", term, bufnr, data] /// @param[out] err Error details, if any /// @return Channel id, or 0 on error @@ -1452,7 +1452,7 @@ ArrayOf(Dictionary) nvim_get_keymap(String mode) /// @param rhs Right-hand-side |{rhs}| of the mapping. /// @param opts Optional parameters map: keys are |:map-arguments|, values are booleans (default /// false). Accepts all |:map-arguments| as keys excluding || but including -/// |noremap| and "desc". Unknown key is an error. +/// |:noremap| and "desc". Unknown key is an error. /// "desc" can be used to give a description to the mapping. /// When called from Lua, also accepts a "callback" key that takes a Lua function to /// call when the mapping is executed. diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c index 96c560efa1..636b9566ce 100644 --- a/src/nvim/api/win_config.c +++ b/src/nvim/api/win_config.c @@ -109,7 +109,7 @@ /// is changed to `auto` and 'colorcolumn' is cleared. The /// end-of-buffer region is hidden by setting `eob` flag of /// 'fillchars' to a space char, and clearing the -/// |EndOfBuffer| region in 'winhighlight'. +/// |hl-EndOfBuffer| region in 'winhighlight'. /// - border: Style of (optional) window border. This can either be a string /// or an array. The string values are /// - "none": No border (default). diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c index 5203003369..59e806adb1 100644 --- a/src/nvim/api/window.c +++ b/src/nvim/api/window.c @@ -340,7 +340,7 @@ Boolean nvim_win_is_valid(Window window) /// /// Like |:hide| the buffer becomes hidden unless another window is editing it, /// or 'bufhidden' is `unload`, `delete` or `wipe` as opposed to |:close| or -/// |nvim_win_close|, which will close the buffer. +/// |nvim_win_close()|, which will close the buffer. /// /// @param window Window handle, or 0 for current window /// @param[out] err Error details, if any diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c index 6267e1c875..001bbf7e48 100644 --- a/src/nvim/mapping.c +++ b/src/nvim/mapping.c @@ -890,7 +890,7 @@ theend: /// /// @param maptype MAPTYPE_MAP for |:map| /// MAPTYPE_UNMAP for |:unmap| -/// MAPTYPE_NOREMAP for |noremap|. +/// MAPTYPE_NOREMAP for |:noremap|. /// @param arg C-string containing the arguments of the map/abbrev /// command, i.e. everything except the initial `:[X][nore]map`. /// - Cannot be a read-only string; it will be modified. diff --git a/src/nvim/mapping.h b/src/nvim/mapping.h index 182d1a48cb..156187b5d8 100644 --- a/src/nvim/mapping.h +++ b/src/nvim/mapping.h @@ -9,7 +9,7 @@ /// All possible |:map-arguments| usable in a |:map| command. /// /// The argument has no effect on mappings and is excluded from this -/// struct declaration. |noremap| is included, since it behaves like a map +/// struct declaration. |:noremap| is included, since it behaves like a map /// argument when used in a mapping. /// /// @see mapblock_T -- cgit From 4bb1d1df79bd1f125499e556d5d4e21ac2ff1e5a Mon Sep 17 00:00:00 2001 From: Andrey Bushev Date: Sat, 24 Sep 2022 22:54:30 -0700 Subject: feat(terminal): recognize underdouble and undercurl --- src/nvim/terminal.c | 18 +++++++++++++++++- test/functional/terminal/helpers.lua | 4 ++++ test/functional/terminal/highlight_spec.lua | 10 ++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index 326c868be8..8ec51438fb 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -759,6 +759,22 @@ static int get_rgb(VTermState *state, VTermColor color) return RGB_(color.rgb.red, color.rgb.green, color.rgb.blue); } +static int get_underline_hl_flag(VTermScreenCellAttrs attrs) +{ + switch (attrs.underline) { + case VTERM_UNDERLINE_OFF: + return 0; + case VTERM_UNDERLINE_SINGLE: + return HL_UNDERLINE; + case VTERM_UNDERLINE_DOUBLE: + return HL_UNDERDOUBLE; + case VTERM_UNDERLINE_CURLY: + return HL_UNDERCURL; + default: + return HL_UNDERLINE; + } +} + void terminal_get_line_attributes(Terminal *term, win_T *wp, int linenr, int *term_attrs) { int height, width; @@ -795,7 +811,7 @@ void terminal_get_line_attributes(Terminal *term, win_T *wp, int linenr, int *te int hl_attrs = (cell.attrs.bold ? HL_BOLD : 0) | (cell.attrs.italic ? HL_ITALIC : 0) | (cell.attrs.reverse ? HL_INVERSE : 0) - | (cell.attrs.underline ? HL_UNDERLINE : 0) + | get_underline_hl_flag(cell.attrs) | (cell.attrs.strike ? HL_STRIKETHROUGH: 0) | ((fg_indexed && !fg_set) ? HL_FG_INDEXED : 0) | ((bg_indexed && !bg_set) ? HL_BG_INDEXED : 0); diff --git a/test/functional/terminal/helpers.lua b/test/functional/terminal/helpers.lua index bcfd3559e6..d69f3207f1 100644 --- a/test/functional/terminal/helpers.lua +++ b/test/functional/terminal/helpers.lua @@ -31,6 +31,8 @@ local function set_bg(num) feed_termcode('[48;5;'..num..'m') end local function set_bold() feed_termcode('[1m') end local function set_italic() feed_termcode('[3m') end local function set_underline() feed_termcode('[4m') end +local function set_underdouble() feed_termcode('[4:2m') end +local function set_undercurl() feed_termcode('[4:3m') end local function set_strikethrough() feed_termcode('[9m') end local function clear_attrs() feed_termcode('[0;10m') end -- mouse @@ -116,6 +118,8 @@ return { set_bold = set_bold, set_italic = set_italic, set_underline = set_underline, + set_underdouble = set_underdouble, + set_undercurl = set_undercurl, set_strikethrough = set_strikethrough, clear_attrs = clear_attrs, enable_mouse = enable_mouse, diff --git a/test/functional/terminal/highlight_spec.lua b/test/functional/terminal/highlight_spec.lua index 28ca07d815..a119d4acd3 100644 --- a/test/functional/terminal/highlight_spec.lua +++ b/test/functional/terminal/highlight_spec.lua @@ -26,6 +26,8 @@ describe(':terminal highlight', function() [9] = {foreground = 130}, [10] = {reverse = true}, [11] = {background = 11}, + [12] = {bold = true, underdouble = true}, + [13] = {italic = true, undercurl = true}, }) screen:attach({rgb=false}) command(("enew | call termopen(['%s'])"):format(testprg('tty-test'))) @@ -114,6 +116,14 @@ describe(':terminal highlight', function() thelpers.set_underline() thelpers.set_strikethrough() end) + descr('bold and underdouble', 12, function() + thelpers.set_bold() + thelpers.set_underdouble() + end) + descr('italics and undercurl', 13, function() + thelpers.set_italic() + thelpers.set_undercurl() + end) end) it(':terminal highlight has lower precedence than editor #9964', function() -- cgit From db0ea1ab444c5e45fe02e1f2984aefc2eb613096 Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 26 Sep 2022 10:40:34 +0200 Subject: fix(messages): validate msg_grid before silent! message with cmdheight=0 fixes #20316 --- src/nvim/message.c | 1 + test/functional/ui/cmdline_spec.lua | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/nvim/message.c b/src/nvim/message.c index 0b9cbfe474..b3e99d99a1 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -1401,6 +1401,7 @@ void msg_start(void) if (!msg_scroll && full_screen) { // overwrite last message if (cmdline_row >= Rows && !ui_has(kUIMessages)) { + msg_grid_validate(); msg_scroll_up(false, true); msg_scrolled++; cmdline_row = Rows - 1; diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua index 92eb853686..3669352901 100644 --- a/test/functional/ui/cmdline_spec.lua +++ b/test/functional/ui/cmdline_spec.lua @@ -1183,4 +1183,17 @@ describe('cmdheight=0', function() {1:~ }| ]]} end) + + it('with silent! at startup', function() + clear{args={'-c', 'set cmdheight=0', '-c', 'autocmd VimEnter * silent! call Foo()'}} + screen:attach() + -- doesn't crash while not displaying silent! error message + screen:expect{grid=[[ + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ]]} + end) end) -- cgit From c815aadfccd6bada47ecfb09fe188ee7f7c5caf3 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Mon, 26 Sep 2022 11:43:23 +0200 Subject: docs: fix typos (#20150) Co-authored-by: Miguel Carneiro Co-authored-by: Gregory Anders Co-authored-by: Raphael Co-authored-by: C.D. MacEachern Co-authored-by: zeertzjq --- runtime/doc/api.txt | 6 +++--- runtime/doc/builtin.txt | 19 +++++++++++-------- runtime/doc/diagnostic.txt | 2 +- runtime/doc/eval.txt | 13 ++++++++----- runtime/doc/insert.txt | 3 ++- runtime/doc/motion.txt | 12 ++++++------ runtime/doc/options.txt | 6 +++--- runtime/doc/pi_health.txt | 2 +- runtime/doc/quickfix.txt | 4 ++-- runtime/doc/syntax.txt | 8 ++++---- runtime/doc/tabpage.txt | 2 +- runtime/doc/userfunc.txt | 2 +- runtime/doc/usr_22.txt | 2 +- runtime/doc/usr_41.txt | 1 + runtime/doc/windows.txt | 11 ++++++----- src/nvim/api/ui.c | 4 ++-- src/nvim/buffer_defs.h | 2 +- src/nvim/debugger.c | 2 +- src/nvim/if_cscope.c | 2 +- src/nvim/keycodes.c | 9 ++++----- test/functional/vimscript/map_functions_spec.lua | 9 +++------ 21 files changed, 63 insertions(+), 58 deletions(-) diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index ec16d5c650..ce59f5ad52 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -3435,8 +3435,8 @@ nvim_ui_detach() *nvim_ui_detach()* *nvim_ui_pum_set_bounds()* nvim_ui_pum_set_bounds({width}, {height}, {row}, {col}) - Tells Nvim the geometry of the popumenu, to align floating windows with an - external popup menu. + Tells Nvim the geometry of the popupmenu, to align floating windows with + an external popup menu. Note that this method is not to be confused with |nvim_ui_pum_set_height()|, which sets the number of visible items in the @@ -3455,7 +3455,7 @@ nvim_ui_pum_set_bounds({width}, {height}, {row}, {col}) {col} Popupmenu height. nvim_ui_pum_set_height({height}) *nvim_ui_pum_set_height()* - Tells Nvim the number of elements displaying in the popumenu, to decide + Tells Nvim the number of elements displaying in the popupmenu, to decide and movement. Attributes: ~ diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 77b85406b9..735116f9a0 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -1131,13 +1131,14 @@ chdir({dir}) *chdir()* directory (|:tcd|) then changes the tabpage local directory. - Otherwise, changes the global directory. + {dir} must be a String. If successful, returns the previous working directory. Pass this to another chdir() to restore the directory. On failure, returns an empty string. Example: > let save_dir = chdir(newdir) - if save_dir + if save_dir != "" " ... do some work call chdir(save_dir) endif @@ -3240,7 +3241,7 @@ getloclist({nr} [, {what}]) *getloclist()* In addition to the items supported by |getqflist()| in {what}, the following item is supported by |getloclist()|: - filewinid id of the window used to display files + filewinid id of the window used to display files from the location list. This field is applicable only when called from a location list window. See @@ -6069,6 +6070,8 @@ rand([{expr}]) *rand()* *readdir()* readdir({directory} [, {expr}]) Return a list with file and directory names in {directory}. + You can also use |glob()| if you don't need to do complicated + things, such as limiting the number of matches. When {expr} is omitted all entries are included. When {expr} is given, it is evaluated to check what to do: @@ -8303,12 +8306,12 @@ synconcealed({lnum}, {col}) *synconcealed()* the text is "123456" and both "23" and "45" are concealed and replaced by the character "X", then: call returns ~ - synconcealed(lnum, 1) [0, '', 0] - synconcealed(lnum, 2) [1, 'X', 1] - synconcealed(lnum, 3) [1, 'X', 1] - synconcealed(lnum, 4) [1, 'X', 2] - synconcealed(lnum, 5) [1, 'X', 2] - synconcealed(lnum, 6) [0, '', 0] + synconcealed(lnum, 1) [0, '', 0] + synconcealed(lnum, 2) [1, 'X', 1] + synconcealed(lnum, 3) [1, 'X', 1] + synconcealed(lnum, 4) [1, 'X', 2] + synconcealed(lnum, 5) [1, 'X', 2] + synconcealed(lnum, 6) [0, '', 0] synstack({lnum}, {col}) *synstack()* diff --git a/runtime/doc/diagnostic.txt b/runtime/doc/diagnostic.txt index 78254c6f2b..ada7b93f7c 100644 --- a/runtime/doc/diagnostic.txt +++ b/runtime/doc/diagnostic.txt @@ -296,7 +296,7 @@ EVENTS *diagnostic-events* *DiagnosticChanged* DiagnosticChanged After diagnostics have changed. When used from Lua, - the new diagnostics are passed to the autocmcd + the new diagnostics are passed to the autocmd callback in the "data" table. Example: > diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 3e068e3b4e..bfaa3b12e8 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -457,7 +457,7 @@ String automatically. Thus the String '4' and the number 4 will find the same entry. Note that the String '04' and the Number 04 are different, since the Number will be converted to the String '4', leading zeros are dropped. The empty string can also be used as a key. - *literal-Dict* + *literal-Dict* *#{}* To avoid having to put quotes around every key the #{} form can be used. This does require the key to consist only of ASCII letters, digits, '-' and '_'. Example: > @@ -681,7 +681,7 @@ similar to -1. > :let shortblob = myblob[2:2] " Blob with one byte: 0z22 :let otherblob = myblob[:] " make a copy of the Blob -If the first index is beyond the last byte of the Blob or the second byte is +If the first index is beyond the last byte of the Blob or the second index is before the first index, the result is an empty Blob. There is no error message. @@ -704,8 +704,8 @@ The length of the replaced bytes must be exactly the same as the value provided. *E972* To change part of a blob you can specify the first and last byte to be -modified. The value must at least have the number of bytes in the range: > - :let blob[3:5] = [3, 4, 5] +modified. The value must have the same number of bytes in the range: > + :let blob[3:5] = 0z334455 You can also use the functions |add()|, |remove()| and |insert()|. @@ -1228,7 +1228,10 @@ And NOT: > \ ->map(mapexpr) \ ->sort() \ ->join() -< + +When using the lambda form there must be no white space between the } and the +(. + *expr9* number diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt index f4ef8e65c4..9ea963c812 100644 --- a/runtime/doc/insert.txt +++ b/runtime/doc/insert.txt @@ -1126,7 +1126,8 @@ that contains the List. The Dict can have these items: leading text is changed. Other items are ignored. -For acting upon end of completion, see the |CompleteDone| autocommand event. +For acting upon end of completion, see the |CompleteDonePre| and +|CompleteDone| autocommand event. For example, the function can contain this: > let matches = ... list of words ... diff --git a/runtime/doc/motion.txt b/runtime/doc/motion.txt index 511b1bd7b2..77b6b83289 100644 --- a/runtime/doc/motion.txt +++ b/runtime/doc/motion.txt @@ -831,12 +831,12 @@ deletes the lines from the cursor position to mark 't'. Hint: Use mark 't' for Top, 'b' for Bottom, etc.. Lowercase marks are restored when using undo and redo. -Uppercase marks 'A to 'Z include the file name. -You can use them to jump from file to file. You can only use an uppercase -mark with an operator if the mark is in the current file. The line number of -the mark remains correct, even if you insert/delete lines or edit another file -for a moment. When the 'shada' option is not empty, uppercase marks are -kept in the .shada file. See |shada-file-marks|. +Uppercase marks 'A to 'Z include the file name. You can use them to jump from +file to file. You can only use an uppercase mark with an operator if the mark +is in the current file. The line number of the mark remains correct, even if +you insert/delete lines or edit another file for a moment. When the 'shada' +option is not empty, uppercase marks are kept in the .shada file. See +|shada-file-marks|. Numbered marks '0 to '9 are quite different. They can not be set directly. They are only present when using a shada file |shada-file|. Basically '0 diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index e5ad61062f..c1a0836f5b 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -6748,11 +6748,11 @@ A jump table for the options with a short description can be found at |Q_op|. final value applying to all subsequent tabs. For example, when editing assembly language files where statements - start in the 8th column and comments in the 40th, it may be useful + start in the 9th column and comments in the 41st, it may be useful to use the following: > :set varsofttabstop=8,32,8 -< This will set soft tabstops at the 8th and 40th columns, and at every - 8th column thereafter. +< This will set soft tabstops with 8 and 8 + 32 spaces, and 8 more + for every column thereafter. Note that the value of |'softtabstop'| will be ignored while 'varsofttabstop' is set. diff --git a/runtime/doc/pi_health.txt b/runtime/doc/pi_health.txt index cc36e7186c..8a6437fdc8 100644 --- a/runtime/doc/pi_health.txt +++ b/runtime/doc/pi_health.txt @@ -75,7 +75,7 @@ vim.health.report_error({msg} [, {advice}]) *vim.health.report_error Create a healthcheck *health-dev* Healthchecks are functions that check the user environment, configuration, or -any other prerequisities that a plugin cares about. Nvim ships with +any other prerequisites that a plugin cares about. Nvim ships with healthchecks in: - $VIMRUNTIME/autoload/health/ - $VIMRUNTIME/lua/vim/lsp/health.lua diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt index 80110211f9..924a6d4743 100644 --- a/runtime/doc/quickfix.txt +++ b/runtime/doc/quickfix.txt @@ -916,7 +916,7 @@ To get the number of the current list in the stack: > screen). 5. The errorfile is read using 'errorformat'. 6. All relevant |QuickFixCmdPost| autocommands are - executed. See example below. + executed. See example below. 7. If [!] is not given the first error is jumped to. 8. The errorfile is deleted. 9. You can now move through the errors with commands @@ -1939,7 +1939,7 @@ list window is: The values displayed in each line correspond to the "bufnr", "lnum", "col" and "text" fields returned by the |getqflist()| function. -For some quickfix/location lists, the displayed text need to be customized. +For some quickfix/location lists, the displayed text needs to be customized. For example, if only the filename is present for a quickfix entry, then the two "|" field separator characters after the filename are not needed. Another use case is to customize the path displayed for a filename. By default, the diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index 1368814952..83f19db4a9 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -2057,7 +2057,7 @@ The g:lisp_rainbow option provides 10 levels of individual colorization for the parentheses and backquoted parentheses. Because of the quantity of colorization levels, unlike non-rainbow highlighting, the rainbow mode specifies its highlighting using ctermfg and guifg, thereby bypassing the -usual colorscheme control using standard highlighting groups. The actual +usual color scheme control using standard highlighting groups. The actual highlighting used depends on the dark/bright setting (see |'bg'|). @@ -4838,7 +4838,7 @@ in their own color. To customize a color scheme use another name, e.g. "~/.config/nvim/colors/mine.vim", and use `:runtime` to - load the original colorscheme: > + load the original color scheme: > runtime colors/evening.vim hi Statement ctermfg=Blue guifg=Blue @@ -4846,7 +4846,7 @@ in their own color. |ColorSchemePre| autocommand event is triggered. After the color scheme has been loaded the |ColorScheme| autocommand event is triggered. - For info about writing a colorscheme file: > + For info about writing a color scheme file: > :edit $VIMRUNTIME/colors/README.txt :hi[ghlight] List all the current highlight groups that have @@ -5016,7 +5016,7 @@ ctermbg={color-nr} *ctermbg* explicitly. This causes the highlight groups that depend on 'background' to change! This means you should set the colors for Normal first, before setting other colors. - When a colorscheme is being used, changing 'background' causes it to + When a color scheme is being used, changing 'background' causes it to be reloaded, which may reset all colors (including Normal). First delete the "g:colors_name" variable when you don't want this. diff --git a/runtime/doc/tabpage.txt b/runtime/doc/tabpage.txt index 9197710819..49b2773253 100644 --- a/runtime/doc/tabpage.txt +++ b/runtime/doc/tabpage.txt @@ -186,8 +186,8 @@ gt *i_CTRL-* *i_* :+2tabnext " go to the two next tab page :1tabnext " go to the first tab page :$tabnext " go to the last tab page - :tabnext # " go to the last accessed tab page :tabnext $ " as above + :tabnext # " go to the last accessed tab page :tabnext - " go to the previous tab page :tabnext -1 " as above :tabnext + " go to the next tab page diff --git a/runtime/doc/userfunc.txt b/runtime/doc/userfunc.txt index 32c5b0b671..5462fa952c 100644 --- a/runtime/doc/userfunc.txt +++ b/runtime/doc/userfunc.txt @@ -214,7 +214,7 @@ It is allowed to define another function inside a function body. You can provide default values for positional named arguments. This makes them optional for function calls. When a positional argument is not specified at a call, the default expression is used to initialize it. -This only works for functions declared with |:function|, not for +This only works for functions declared with `:function`, not for lambda expressions |expr-lambda|. Example: > diff --git a/runtime/doc/usr_22.txt b/runtime/doc/usr_22.txt index f53d578456..539bda3980 100644 --- a/runtime/doc/usr_22.txt +++ b/runtime/doc/usr_22.txt @@ -220,7 +220,7 @@ a tab page share this directory except for windows with a window-local directory. Any new windows opened in this tab page will use this directory as the current working directory. Using a `:cd` command in a tab page will not change the working directory of tab pages which have a tab local directory. -When the global working directory is changed using the ":cd" command in a tab +When the global working directory is changed using the `:cd` command in a tab page, it will also change the current tab page working directory. diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index adb5130a53..4e7ec00148 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -1016,6 +1016,7 @@ Testing: *test-functions* assert_beeps() assert that a command beeps assert_nobeep() assert that a command does not cause a beep assert_fails() assert that a command fails + assert_report() report a test failure Timers: *timer-functions* timer_start() create a timer diff --git a/runtime/doc/windows.txt b/runtime/doc/windows.txt index 6386e4ace1..3dc718a68f 100644 --- a/runtime/doc/windows.txt +++ b/runtime/doc/windows.txt @@ -148,7 +148,7 @@ CTRL-W CTRL-S *CTRL-W_CTRL-S* Note: CTRL-S does not work on all terminals and might block further input, use CTRL-Q to get going again. Also see |++opt| and |+cmd|. - *E242* + *E242* *E1159* Be careful when splitting a window in an autocommand, it may mess up the window layout if this happens while making other window layout changes. @@ -291,9 +291,8 @@ Closing a window :{count}q[uit] *:count_quit* CTRL-W q *CTRL-W_q* CTRL-W CTRL-Q *CTRL-W_CTRL-Q* - Without {count}: Quit the current window. If {count} is - given quit the {count} window - + Without {count}: Quit the current window. If {count} is + given quit the {count} window. *edit-window* When quitting the last edit window (not counting help or preview windows), exit Vim. @@ -352,7 +351,7 @@ CTRL-W CTRL-C *CTRL-W_CTRL-C* window, but that does not work, because the CTRL-C cancels the command. - *:hide* + *:hide* :hid[e] :{count}hid[e] Without {count}: Quit the current window, unless it is the @@ -751,6 +750,7 @@ can also get to them with the buffer list commands, like ":bnext". the current window. {cmd} can contain '|' to concatenate several commands. {cmd} must not open or close windows or reorder them. + Also see |:tabdo|, |:argdo|, |:bufdo|, |:cdo|, |:ldo|, |:cfdo| and |:lfdo|. @@ -778,6 +778,7 @@ can also get to them with the buffer list commands, like ":bnext". autocommand event is disabled by adding it to 'eventignore'. This considerably speeds up editing each buffer. + Also see |:tabdo|, |:argdo|, |:windo|, |:cdo|, |:ldo|, |:cfdo| and |:lfdo|. diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 45c20d07e1..e6d8cb2fdb 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -453,7 +453,7 @@ void nvim_ui_try_resize_grid(uint64_t channel_id, Integer grid, Integer width, I } } -/// Tells Nvim the number of elements displaying in the popumenu, to decide +/// Tells Nvim the number of elements displaying in the popupmenu, to decide /// and movement. /// /// @param channel_id @@ -483,7 +483,7 @@ void nvim_ui_pum_set_height(uint64_t channel_id, Integer height, Error *err) ui->pum_nlines = (int)height; } -/// Tells Nvim the geometry of the popumenu, to align floating windows with an +/// Tells Nvim the geometry of the popupmenu, to align floating windows with an /// external popup menu. /// /// Note that this method is not to be confused with |nvim_ui_pum_set_height()|, diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index c18a8209cf..a8834b85aa 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -618,7 +618,7 @@ struct file_buffer { bool b_u_synced; // entry lists are synced long b_u_seq_last; // last used undo sequence number long b_u_save_nr_last; // counter for last file write - long b_u_seq_cur; // hu_seq of header below which we are now + long b_u_seq_cur; // uh_seq of header below which we are now time_t b_u_time_cur; // uh_time of header below which we are now long b_u_save_nr_cur; // file write nr after which we are now diff --git a/src/nvim/debugger.c b/src/nvim/debugger.c index 8adeb19082..3e0cf82740 100644 --- a/src/nvim/debugger.c +++ b/src/nvim/debugger.c @@ -128,7 +128,7 @@ void do_debug(char *cmd) ignore_script = true; } - // don't debug any function call, e.g. from an expresion mapping + // don't debug any function call, e.g. from an expression mapping n = debug_break_level; debug_break_level = -1; diff --git a/src/nvim/if_cscope.c b/src/nvim/if_cscope.c index a23fa22da2..bc31d702f4 100644 --- a/src/nvim/if_cscope.c +++ b/src/nvim/if_cscope.c @@ -649,7 +649,7 @@ static char *cs_create_cmd(char *csoption, char *pattern) return NULL; } - // Skip white space before the patter, except for text and pattern search, + // Skip white space before the pattern, except for text and pattern search, // they may want to use the leading white space. pat = pattern; if (search != 4 && search != 6) { diff --git a/src/nvim/keycodes.c b/src/nvim/keycodes.c index 9ec37fd564..61dc2ac035 100644 --- a/src/nvim/keycodes.c +++ b/src/nvim/keycodes.c @@ -861,10 +861,9 @@ int get_mouse_button(int code, bool *is_click, bool *is_drag) /// @param[in] from What characters to replace. /// @param[in] from_len Length of the "from" argument. /// @param[out] bufp Location where results were saved in case of success (allocated). -/// if *bufp is non-NULL, it will be used directly. it is -/// assumed to be 128 bytes long (enough for transcoding LHS -/// of mapping) -/// Will be set to NULL in case of failure. +/// If `*bufp` is non-NULL, it will be used directly, +/// and is assumed to be 128 bytes long (enough for transcoding LHS of mapping), +/// and will be set to NULL in case of failure. /// @param[in] flags REPTERM_FROM_PART see above /// REPTERM_DO_LT also translate /// REPTERM_NO_SPECIAL do not accept notation @@ -872,7 +871,7 @@ int get_mouse_button(int code, bool *is_click, bool *is_drag) /// @param[out] did_simplify set when some code was simplied, unless it is NULL. /// @param[in] cpo_flags Relevant flags derived from p_cpo, see CPO_TO_CPO_FLAGS. /// -/// @return Pointer to an allocated memory, which is also saved to "bufp". +/// @return The same as what `*bufp` is set to. char *replace_termcodes(const char *const from, const size_t from_len, char **const bufp, const int flags, bool *const did_simplify, const int cpo_flags) FUNC_ATTR_NONNULL_ARG(1, 3) diff --git a/test/functional/vimscript/map_functions_spec.lua b/test/functional/vimscript/map_functions_spec.lua index ed1863754a..8645b1e506 100644 --- a/test/functional/vimscript/map_functions_spec.lua +++ b/test/functional/vimscript/map_functions_spec.lua @@ -176,15 +176,12 @@ describe('mapset()', function() it('can restore mapping description from the dict returned by maparg()', function() meths.set_keymap('n', 'lhs', 'rhs', {desc = 'map description'}) - eq('\nn lhs rhs\n map description', - helpers.exec_capture("nmap lhs")) + eq('\nn lhs rhs\n map description', exec_capture("nmap lhs")) local mapargs = funcs.maparg('lhs', 'n', false, true) meths.set_keymap('n', 'lhs', 'rhs', {desc = 'MAP DESCRIPTION'}) - eq('\nn lhs rhs\n MAP DESCRIPTION', - helpers.exec_capture("nmap lhs")) + eq('\nn lhs rhs\n MAP DESCRIPTION', exec_capture("nmap lhs")) funcs.mapset('n', false, mapargs) - eq('\nn lhs rhs\n map description', - helpers.exec_capture("nmap lhs")) + eq('\nn lhs rhs\n map description', exec_capture("nmap lhs")) end) it('can restore "replace_keycodes" from the dict returned by maparg()', function() -- cgit From be72af2f9b6aa9ff57ef21eb4e517a74b7c2a2da Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 26 Sep 2022 11:40:06 +0200 Subject: fix(cmdline): don't send invalid cursor with incsearch and cmdheight=0 fixes #20306 --- src/nvim/message.c | 14 +++++++------ test/functional/ui/cmdline_spec.lua | 42 +++++++++++++++++++++++++++++++++++++ test/functional/ui/screen.lua | 1 + 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/src/nvim/message.c b/src/nvim/message.c index b3e99d99a1..e0b0dfb0bc 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -1399,13 +1399,15 @@ void msg_start(void) msg_clr_eos(); } + // if cmdheight=0, we need to scroll in the first line of msg_grid upon the screen + if (p_ch == 0 && !ui_has(kUIMessages) && !msg_scrolled) { + msg_grid_validate(); + msg_scroll_up(false, true); + msg_scrolled++; + cmdline_row = Rows - 1; + } + if (!msg_scroll && full_screen) { // overwrite last message - if (cmdline_row >= Rows && !ui_has(kUIMessages)) { - msg_grid_validate(); - msg_scroll_up(false, true); - msg_scrolled++; - cmdline_row = Rows - 1; - } msg_row = cmdline_row; msg_col = cmdmsg_rl ? Columns - 1 : 0; } else if (msg_didout || (p_ch == 0 && !ui_has(kUIMessages))) { // start message on next line diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua index 3669352901..845291b2eb 100644 --- a/test/functional/ui/cmdline_spec.lua +++ b/test/functional/ui/cmdline_spec.lua @@ -1196,4 +1196,46 @@ describe('cmdheight=0', function() {1:~ }| ]]} end) + + it('with multigrid', function() + clear{args={'--cmd', 'set cmdheight=0'}} + screen:attach{ext_multigrid=true} + screen:expect{grid=[[ + ## grid 1 + [2:-------------------------]| + [2:-------------------------]| + [2:-------------------------]| + [2:-------------------------]| + [2:-------------------------]| + ## grid 2 + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + }} + + feed '/p' + screen:expect{grid=[[ + ## grid 1 + [2:-------------------------]| + [2:-------------------------]| + [2:-------------------------]| + [2:-------------------------]| + [3:-------------------------]| + ## grid 2 + | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + /p^ | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + }} + end) end) diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index 6ee9e7b393..028fa2825d 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -769,6 +769,7 @@ end function Screen:_handle_grid_cursor_goto(grid, row, col) self._cursor.grid = grid + assert(row >= 0 and col >= 0) self._cursor.row = row + 1 self._cursor.col = col + 1 end -- cgit From be693462d5a5fd696b46ea4ea854c924421089b4 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 26 Sep 2022 21:23:43 +0800 Subject: fix(ui): allow redrawing statusline when msgsep is used (#20337) --- src/nvim/ex_docmd.c | 2 +- src/nvim/ex_getln.c | 4 +- test/functional/ui/cmdline_spec.lua | 128 ++++++++++++++++++++++++++++++++++-- 3 files changed, 127 insertions(+), 7 deletions(-) diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 7ece195374..96f98b92ca 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -6088,7 +6088,7 @@ static void ex_redrawstatus(exarg_T *eap) } else { status_redraw_curbuf(); } - if (msg_scrolled && (State & MODE_CMDLINE)) { + if (msg_scrolled && !msg_use_msgsep() && (State & MODE_CMDLINE)) { return; // redraw later } diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index bc31f5a6cf..4b54b58ac1 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -774,11 +774,11 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool init // Redraw the statusline in case it uses the current mode using the mode() // function. - if (!cmd_silent && msg_scrolled == 0) { + if (!cmd_silent && (msg_scrolled == 0 || msg_use_msgsep())) { bool found_one = false; FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { - if (*p_stl != NUL || *wp->w_p_stl != NUL) { + if (*p_stl != NUL || *wp->w_p_stl != NUL || *p_wbr != NUL || *wp->w_p_wbr != NUL) { wp->w_redr_status = true; found_one = true; } diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua index 845291b2eb..d7f2b2335e 100644 --- a/test/functional/ui/cmdline_spec.lua +++ b/test/functional/ui/cmdline_spec.lua @@ -5,6 +5,7 @@ local source = helpers.source local command = helpers.command local assert_alive = helpers.assert_alive local uname = helpers.uname +local exec = helpers.exec local eval = helpers.eval local eq = helpers.eq @@ -821,12 +822,23 @@ describe('statusline is redrawn on entering cmdline', function() ]]} end) - it('but not with scrolled messages', function() - command('set statusline=%{mode()}') - screen:try_resize(35,10) + it('with scrolled messages and msgsep', function() + screen:try_resize(35,14) + exec([[ + let g:count = 0 + autocmd CmdlineEnter * let g:count += 1 + split + resize 1 + setlocal statusline=%{mode()}%{g:count} + setlocal winbar=%{mode()}%{g:count} + ]]) feed(':echoerr doesnotexist') screen:expect{grid=[[ + {9:c1 }| | + {3:c1 }| + | + {1:~ }| {1:~ }| {1:~ }| {1:~ }| @@ -839,8 +851,27 @@ describe('statusline is redrawn on entering cmdline', function() ]]} feed(':echoerr doesnotexist') screen:expect{grid=[[ + {9:c2 }| + | + {3:c2 }| | {1:~ }| + {1:~ }| + {3: }| + {4:E121: Undefined variable: doesnotex}| + {4:ist} | + {5:Press ENTER or type command to cont}| + {4:E121: Undefined variable: doesnotex}| + {4:ist} | + {5:Press ENTER or type command to cont}| + {5:inue}^ | + ]]} + + feed(':echoerr doesnotexist') + screen:expect{grid=[[ + {9:c3 }| + | + {3:c3 }| {3: }| {4:E121: Undefined variable: doesnotex}| {4:ist} | @@ -848,6 +879,63 @@ describe('statusline is redrawn on entering cmdline', function() {4:E121: Undefined variable: doesnotex}| {4:ist} | {5:Press ENTER or type command to cont}| + {4:E121: Undefined variable: doesnotex}| + {4:ist} | + {5:Press ENTER or type command to cont}| + {5:inue}^ | + ]]} + + feed('') + screen:expect{grid=[[ + {9:n3 }| + ^ | + {3:n3 }| + | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {2:[No Name] }| + | + ]]} + end) + + it('but not with scrolled messages without msgsep', function() + screen:try_resize(35,10) + exec([[ + let g:count = 0 + autocmd CmdlineEnter * let g:count += 1 + set display-=msgsep + set statusline=%{mode()}%{g:count} + ]]) + feed(':echoerr doesnotexist') + screen:expect{grid=[[ + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {3:c1 }| + {4:E121: Undefined variable: doesnotex}| + {4:ist} | + {5:Press ENTER or type command to cont}| + {5:inue}^ | + ]]} + feed(':echoerr doesnotexist') + screen:expect{grid=[[ + {1:~ }| + {1:~ }| + {3:c1 }| + {4:E121: Undefined variable: doesnotex}| + {4:ist} | + {5:Press ENTER or type command to cont}| + {4:E121: Undefined variable: doesnotex}| + {4:ist} | + {5:Press ENTER or type command to cont}| {5:inue}^ | ]]} @@ -875,7 +963,7 @@ describe('statusline is redrawn on entering cmdline', function() {1:~ }| {1:~ }| {1:~ }| - {3:n }| + {3:n3 }| | ]]} end) @@ -1238,4 +1326,36 @@ describe('cmdheight=0', function() [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; }} end) + + it('winbar is redrawn on entering cmdline and :redrawstatus #20336', function() + exec([[ + set cmdheight=0 + set winbar=%{mode()}%=:%{getcmdline()} + ]]) + feed(':') + screen:expect([[ + {3:c :}| + | + {1:~ }| + {1:~ }| + :^ | + ]]) + feed('echo') + -- not redrawn yet + screen:expect([[ + {3:c :}| + | + {1:~ }| + {1:~ }| + :echo^ | + ]]) + command('redrawstatus') + screen:expect([[ + {3:c :echo}| + | + {1:~ }| + {1:~ }| + :echo^ | + ]]) + end) end) -- cgit From 9a5ac065093b58cceb676700b988584931cef150 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 26 Sep 2022 09:56:07 -0400 Subject: fix(docs): invalid :help links #20353 ref #20159 --- runtime/doc/builtin.txt | 8 ++++---- runtime/doc/eval.txt | 4 ++-- runtime/doc/ft_rust.txt | 2 +- runtime/doc/ft_sql.txt | 2 +- runtime/doc/insert.txt | 2 +- runtime/doc/pi_netrw.txt | 2 +- runtime/doc/quickref.txt | 1 - runtime/doc/usr_41.txt | 2 +- runtime/doc/windows.txt | 2 +- 9 files changed, 12 insertions(+), 13 deletions(-) diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 735116f9a0..4a889c67be 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -2628,7 +2628,7 @@ get({dict}, {key} [, {default}]) {default} is omitted. Useful example: > let val = get(g:, 'var_name', 'default') < This gets the value of g:var_name if it exists, and uses - 'default' when it does not exist. + "default" when it does not exist. get({func}, {what}) Get item {what} from Funcref {func}. Possible values for {what} are: @@ -3035,7 +3035,7 @@ getcurpos([{winid}]) cursor vertically. Also see |getcursorcharpos()| and |getpos()|. The first "bufnum" item is always zero. The byte position of - the cursor is returned in 'col'. To get the character + the cursor is returned in "col". To get the character position, use |getcursorcharpos()|. The optional {winid} argument can specify the window. It can @@ -3414,7 +3414,7 @@ getqflist([{what}]) *getqflist()* |quickfix-ID|; zero means the id for the current list or the list specified by "nr" idx get information for the quickfix entry at this - index in the list specified by 'id' or 'nr'. + index in the list specified by "id" or "nr". If set to zero, then uses the current entry. See |quickfix-index| items quickfix list entries @@ -7226,7 +7226,7 @@ setqflist({list} [, {action} [, {what}]]) *setqflist()* See |quickfix-parse| id quickfix list identifier |quickfix-ID| idx index of the current entry in the quickfix - list specified by 'id' or 'nr'. If set to '$', + list specified by "id" or "nr". If set to '$', then the last entry in the list is set as the current entry. See |quickfix-index| items list of quickfix entries. Same as the {list} diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index bfaa3b12e8..ae28977556 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -40,7 +40,7 @@ List An ordered sequence of items, see |List| for details. Dictionary An associative, unordered array: Each entry has a key and a value. |Dictionary| Examples: - {'blue': "#0000ff", 'red': "#ff0000"} + {"blue": "#0000ff", "red": "#ff0000"} #{blue: "#0000ff", red: "#ff0000"} Blob Binary Large Object. Stores any sequence of bytes. See |Blob| @@ -2531,7 +2531,7 @@ text... echo 'done' endif END -< Results in: ["if ok", " echo 'done'", "endif"] +< Results in: `["if ok", " echo 'done'", "endif"]` The marker must line up with "let" and the indentation of the first line is removed from all the text lines. Specifically: all the leading indentation exactly diff --git a/runtime/doc/ft_rust.txt b/runtime/doc/ft_rust.txt index 34932c48fb..3a0bf2293e 100644 --- a/runtime/doc/ft_rust.txt +++ b/runtime/doc/ft_rust.txt @@ -110,7 +110,7 @@ g:rustfmt_fail_silently~ < *g:rustfmt_options* g:rustfmt_options~ - Set this option to a string of options to pass to 'rustfmt'. The + Set this option to a string of options to pass to "rustfmt". The write-mode is already set to "overwrite". If not specified it defaults to '' : > let g:rustfmt_options = '' diff --git a/runtime/doc/ft_sql.txt b/runtime/doc/ft_sql.txt index 685726de90..03d9082aab 100644 --- a/runtime/doc/ft_sql.txt +++ b/runtime/doc/ft_sql.txt @@ -757,7 +757,7 @@ the syntax items for Perl. Step 2 ------ -Manually setting the filetype to 'sql' will also fire the appropriate filetype +Manually setting the filetype to "sql" will also fire the appropriate filetype files ftplugin/sql.vim. This file will define a number of buffer specific maps for SQL completion, see |sql-completion-maps|. Now these maps have been created and the SQL completion plugin has been initialized. All SQL diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt index 9ea963c812..63ceab78a8 100644 --- a/runtime/doc/insert.txt +++ b/runtime/doc/insert.txt @@ -1534,7 +1534,7 @@ The completions provided by CTRL-X CTRL-O are sensitive to the context: 3. After '.', '::' or ':' Methods applicable to the object being dereferenced - 4. After ':' or ':foo' Symbol name (beginning with 'foo') + 4. After ':' or ':foo' Symbol name (beginning with "foo") Notes: - Vim will load/evaluate code in order to provide completions. This may diff --git a/runtime/doc/pi_netrw.txt b/runtime/doc/pi_netrw.txt index ae0169491b..63d4496dc4 100644 --- a/runtime/doc/pi_netrw.txt +++ b/runtime/doc/pi_netrw.txt @@ -3569,7 +3569,7 @@ Example: Clear netrw's marked file list via a mapping on gu > http://www.chiark.greenend.org.uk/~sgtatham/putty/0.60/htmldoc/Chapter8.html#pubkey-gettingready (8.3 Getting ready for public key authentication) < - How to use a private key with 'pscp': > + How to use a private key with "pscp": > http://www.chiark.greenend.org.uk/~sgtatham/putty/0.60/htmldoc/Chapter5.html (5.2.4 Using public key authentication with PSCP) diff --git a/runtime/doc/quickref.txt b/runtime/doc/quickref.txt index cb065cef2c..23ce16a40a 100644 --- a/runtime/doc/quickref.txt +++ b/runtime/doc/quickref.txt @@ -798,7 +798,6 @@ Short explanation of each option: *option-list* 'patchexpr' 'pex' expression used to patch a file 'patchmode' 'pm' keep the oldest version of a file 'path' 'pa' list of directories searched with "gf" et.al. -'perldll' name of the Perl dynamic library 'preserveindent' 'pi' preserve the indent structure when reindenting 'previewheight' 'pvh' height of the preview window 'previewpopup' 'pvp' use popup window for preview diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index 4e7ec00148..fb9d59f885 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -1762,7 +1762,7 @@ does not exist as a mapped sequence. An error will be issued, which is very hard to identify, because the ending whitespace character in ":unmap ,ab " is not visible. -And this is the same as what happens when one uses a comment after an 'unmap' +And this is the same as what happens when one uses a comment after an "unmap" command: > :unmap ,ab " comment diff --git a/runtime/doc/windows.txt b/runtime/doc/windows.txt index 3dc718a68f..45cedd2cd8 100644 --- a/runtime/doc/windows.txt +++ b/runtime/doc/windows.txt @@ -119,7 +119,7 @@ windows. *filler-lines* The lines after the last buffer line in a window are called filler lines. By -default, these lines start with a tilde (~) character. The 'eob' item in the +default, these lines start with a tilde (~) character. The "eob" item in the 'fillchars' option can be used to change this character. By default, these characters are highlighted as NonText (|hl-NonText|). The EndOfBuffer highlight group (|hl-EndOfBuffer|) can be used to change the highlighting of -- cgit From 7e98821e56a88487f24584463869432d8373a28e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 27 Sep 2022 06:33:48 +0800 Subject: fix(ui): redraw end of buffer if last line is modified (#20354) --- src/nvim/drawscreen.c | 3 +- test/functional/ui/decorations_spec.lua | 104 ++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 1 deletion(-) diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c index c95f3f3550..fdf70a081c 100644 --- a/src/nvim/drawscreen.c +++ b/src/nvim/drawscreen.c @@ -1965,7 +1965,8 @@ win_update_start: if (mid_end >= row) { lastline = MIN(lastline, mid_start); } - if (mod_bot > buf->b_ml.ml_line_count + 1) { + // if (mod_bot > buf->b_ml.ml_line_count + 1) { + if (mod_bot > buf->b_ml.ml_line_count) { lastline = 0; } diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua index eff6fe6d23..9b48f0ac35 100644 --- a/test/functional/ui/decorations_spec.lua +++ b/test/functional/ui/decorations_spec.lua @@ -1281,6 +1281,110 @@ if (h->n_buckets < new_n_buckets) { // expand ]]} end) + it('works beyond end of the buffer with virt_lines_above', function() + insert(example_text) + feed 'G' + + screen:expect{grid=[[ + if (h->n_buckets < new_n_buckets) { // expand | + khkey_t *new_keys = (khkey_t *)krealloc((void *)| + h->keys, new_n_buckets * sizeof(khkey_t)); | + h->keys = new_keys; | + if (kh_is_map && val_size) { | + char *new_vals = krealloc( h->vals_buf, new_n_| + buckets * val_size); | + h->vals_buf = new_vals; | + } | + ^} | + {1:~ }| + | + ]]} + + local id = meths.buf_set_extmark(0, ns, 8, 0, { + virt_lines={{{"Grugg"}}}; + virt_lines_above = true, + }) + + screen:expect{grid=[[ + if (h->n_buckets < new_n_buckets) { // expand | + khkey_t *new_keys = (khkey_t *)krealloc((void *)| + h->keys, new_n_buckets * sizeof(khkey_t)); | + h->keys = new_keys; | + if (kh_is_map && val_size) { | + char *new_vals = krealloc( h->vals_buf, new_n_| + buckets * val_size); | + h->vals_buf = new_vals; | + } | + ^} | + Grugg | + | + ]]} + + feed('dd') + screen:expect{grid=[[ + if (h->n_buckets < new_n_buckets) { // expand | + khkey_t *new_keys = (khkey_t *)krealloc((void *)| + h->keys, new_n_buckets * sizeof(khkey_t)); | + h->keys = new_keys; | + if (kh_is_map && val_size) { | + char *new_vals = krealloc( h->vals_buf, new_n_| + buckets * val_size); | + h->vals_buf = new_vals; | + ^} | + Grugg | + {1:~ }| + | + ]]} + + feed('dk') + screen:expect{grid=[[ + if (h->n_buckets < new_n_buckets) { // expand | + khkey_t *new_keys = (khkey_t *)krealloc((void *)| + h->keys, new_n_buckets * sizeof(khkey_t)); | + h->keys = new_keys; | + if (kh_is_map && val_size) { | + ^char *new_vals = krealloc( h->vals_buf, new_n_| + buckets * val_size); | + Grugg | + {1:~ }| + {1:~ }| + {1:~ }| + | + ]]} + + feed('dgg') + screen:expect{grid=[[ + ^ | + Grugg | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + --No lines in buffer-- | + ]]} + + meths.buf_del_extmark(0, ns, id) + screen:expect{grid=[[ + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + --No lines in buffer-- | + ]]} + end) + it('does not cause syntax ml_get error at the end of a buffer #17816', function() command([[syntax region foo keepend start='^foo' end='^$']]) command('syntax sync minlines=100') -- cgit From 1d337d4e2f2265b13ecf19a3bc17ad302d3b0d96 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 27 Sep 2022 08:29:21 +0800 Subject: vim-patch:9.0.0595: extra newline in messages after a verbose shell message (#20359) Problem: Extra newline in messages after a verbose shell message. Solution: Output the newline with msg_putchar_attr(). (closes vim/vim#11233) Make it possible to filter a screendump before comparing it. https://github.com/vim/vim/commit/1190139ed01c27539615beea9559a88b2551daf3 Cherry-pick Test_message_more_scrolledback() from patch 9.0.0592 because Nvim already behaves as intended. --- src/nvim/message.c | 2 +- src/nvim/testdir/test_messages.vim | 60 ++++++++++++ test/functional/legacy/messages_spec.lua | 152 +++++++++++++++++++++++++++---- 3 files changed, 197 insertions(+), 17 deletions(-) diff --git a/src/nvim/message.c b/src/nvim/message.c index e0b0dfb0bc..fd20d9dd81 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -2315,7 +2315,7 @@ static void msg_puts_display(const char *str, int maxlen, int attr, int recurse) if (t_col > 0) { t_puts(&t_col, t_s, s, attr); } - if (p_more && !recurse) { + if (p_more && !recurse && !(s == sb_str + 1 && *sb_str == '\n')) { store_sb_text((char **)&sb_str, (char *)s, attr, &sb_col, false); } diff --git a/src/nvim/testdir/test_messages.vim b/src/nvim/testdir/test_messages.vim index 8e66a2c529..42a1fdcfe2 100644 --- a/src/nvim/testdir/test_messages.vim +++ b/src/nvim/testdir/test_messages.vim @@ -316,6 +316,66 @@ func Test_message_more() call StopVimInTerminal(buf) endfunc +" Test more-prompt scrollback +func Test_message_more_scrollback() + CheckRunVimInTerminal + + let lines =<< trim END + set t_ut= + hi Normal ctermfg=15 ctermbg=0 + for i in range(100) + echo i + endfor + END + call writefile(lines, 'XmoreScrollback', 'D') + let buf = RunVimInTerminal('-S XmoreScrollback', {'rows': 10}) + call VerifyScreenDump(buf, 'Test_more_scrollback_1', {}) + + call term_sendkeys(buf, 'f') + call TermWait(buf) + call term_sendkeys(buf, 'b') + call VerifyScreenDump(buf, 'Test_more_scrollback_2', {}) + + call term_sendkeys(buf, 'q') + call TermWait(buf) + call StopVimInTerminal(buf) +endfunc + +" Test verbose message before echo command +func Test_echo_verbose_system() + CheckRunVimInTerminal + CheckUnix + + let buf = RunVimInTerminal('', {'rows': 10}) + call term_sendkeys(buf, ":4 verbose echo system('seq 20')\") + " Note that the screendump is filtered to remove the name of the temp file + call VerifyScreenDump(buf, 'Test_verbose_system_1', {}) + + " display a page and go back, results in exactly the same view + call term_sendkeys(buf, ' ') + call TermWait(buf) + call term_sendkeys(buf, 'b') + call VerifyScreenDump(buf, 'Test_verbose_system_1', {}) + + " do the same with 'cmdheight' set to 2 + call term_sendkeys(buf, 'q') + call TermWait(buf) + call term_sendkeys(buf, ":set ch=2\") + call TermWait(buf) + call term_sendkeys(buf, ":4 verbose echo system('seq 20')\") + call VerifyScreenDump(buf, 'Test_verbose_system_2', {}) + + call term_sendkeys(buf, ' ') + call TermWait(buf) + call term_sendkeys(buf, 'b') + call VerifyScreenDump(buf, 'Test_verbose_system_2', {}) + + call term_sendkeys(buf, 'q') + call TermWait(buf) + call StopVimInTerminal(buf) +endfunc + + func Test_ask_yesno() CheckRunVimInTerminal let buf = RunVimInTerminal('', {'rows': 6}) diff --git a/test/functional/legacy/messages_spec.lua b/test/functional/legacy/messages_spec.lua index 5b671bbfdf..71a53c8381 100644 --- a/test/functional/legacy/messages_spec.lua +++ b/test/functional/legacy/messages_spec.lua @@ -4,6 +4,8 @@ local clear = helpers.clear local command = helpers.command local exec = helpers.exec local feed = helpers.feed +local meths = helpers.meths +local nvim_dir = helpers.nvim_dir before_each(clear) @@ -49,19 +51,18 @@ describe('messages', function() describe('more prompt', function() before_each(function() + command('set more') + end) + + -- oldtest: Test_message_more() + it('works', function() screen = Screen.new(75, 6) screen:set_default_attr_ids({ - [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText [1] = {bold = true, foreground = Screen.colors.SeaGreen}, -- MoreMsg [2] = {foreground = Screen.colors.Brown}, -- LineNr - [3] = {foreground = Screen.colors.Blue}, -- SpecialKey }) screen:attach() - command('set more') - end) - -- oldtest: Test_message_more() - it('works', function() command('call setline(1, range(1, 100))') feed(':%pfoo#') @@ -350,20 +351,139 @@ describe('messages', function() ]]) end) + -- oldtest: Test_echo_verbose_system() + it('verbose message before echo command', function() + screen = Screen.new(60, 10) + screen:set_default_attr_ids({ + [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText + [1] = {bold = true, foreground = Screen.colors.SeaGreen}, -- MoreMsg + }) + screen:attach() + + command('cd '..nvim_dir) + meths.set_option('shell', './shell-test') + meths.set_option('shellcmdflag', 'REP 20') + meths.set_option('shellxquote', '') -- win: avoid extra quotes + + -- display a page and go back, results in exactly the same view + feed([[:4 verbose echo system('foo')]]) + screen:expect([[ + Executing command: "'./shell-test' 'REP' '20' 'foo'" | + | + 0: foo | + 1: foo | + 2: foo | + 3: foo | + 4: foo | + 5: foo | + 6: foo | + {1:-- More --}^ | + ]]) + feed('') + screen:expect([[ + 7: foo | + 8: foo | + 9: foo | + 10: foo | + 11: foo | + 12: foo | + 13: foo | + 14: foo | + 15: foo | + {1:-- More --}^ | + ]]) + feed('b') + screen:expect([[ + Executing command: "'./shell-test' 'REP' '20' 'foo'" | + | + 0: foo | + 1: foo | + 2: foo | + 3: foo | + 4: foo | + 5: foo | + 6: foo | + {1:-- More --}^ | + ]]) + + -- do the same with 'cmdheight' set to 2 + feed('q') + command('set ch=2') + command('mode') -- FIXME: bottom is invalid after scrolling + screen:expect([[ + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + | + | + ]]) + feed([[:4 verbose echo system('foo')]]) + screen:expect([[ + Executing command: "'./shell-test' 'REP' '20' 'foo'" | + | + 0: foo | + 1: foo | + 2: foo | + 3: foo | + 4: foo | + 5: foo | + 6: foo | + {1:-- More --}^ | + ]]) + feed('') + screen:expect([[ + 7: foo | + 8: foo | + 9: foo | + 10: foo | + 11: foo | + 12: foo | + 13: foo | + 14: foo | + 15: foo | + {1:-- More --}^ | + ]]) + feed('b') + screen:expect([[ + Executing command: "'./shell-test' 'REP' '20' 'foo'" | + | + 0: foo | + 1: foo | + 2: foo | + 3: foo | + 4: foo | + 5: foo | + 6: foo | + {1:-- More --}^ | + ]]) + end) + -- oldtest: Test_quit_long_message() it('with control characters can be quit vim-patch:8.2.1844', function() - screen:try_resize(40, 10) + screen = Screen.new(40, 10) + screen:set_default_attr_ids({ + [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText + [1] = {bold = true, foreground = Screen.colors.SeaGreen}, -- MoreMsg + [2] = {foreground = Screen.colors.Blue}, -- SpecialKey + }) + screen:attach() + feed([[:echom range(9999)->join("\x01")]]) screen:expect([[ - 0{3:^A}1{3:^A}2{3:^A}3{3:^A}4{3:^A}5{3:^A}6{3:^A}7{3:^A}8{3:^A}9{3:^A}10{3:^A}11{3:^A}12| - {3:^A}13{3:^A}14{3:^A}15{3:^A}16{3:^A}17{3:^A}18{3:^A}19{3:^A}20{3:^A}21{3:^A}22| - {3:^A}23{3:^A}24{3:^A}25{3:^A}26{3:^A}27{3:^A}28{3:^A}29{3:^A}30{3:^A}31{3:^A}32| - {3:^A}33{3:^A}34{3:^A}35{3:^A}36{3:^A}37{3:^A}38{3:^A}39{3:^A}40{3:^A}41{3:^A}42| - {3:^A}43{3:^A}44{3:^A}45{3:^A}46{3:^A}47{3:^A}48{3:^A}49{3:^A}50{3:^A}51{3:^A}52| - {3:^A}53{3:^A}54{3:^A}55{3:^A}56{3:^A}57{3:^A}58{3:^A}59{3:^A}60{3:^A}61{3:^A}62| - {3:^A}63{3:^A}64{3:^A}65{3:^A}66{3:^A}67{3:^A}68{3:^A}69{3:^A}70{3:^A}71{3:^A}72| - {3:^A}73{3:^A}74{3:^A}75{3:^A}76{3:^A}77{3:^A}78{3:^A}79{3:^A}80{3:^A}81{3:^A}82| - {3:^A}83{3:^A}84{3:^A}85{3:^A}86{3:^A}87{3:^A}88{3:^A}89{3:^A}90{3:^A}91{3:^A}92| + 0{2:^A}1{2:^A}2{2:^A}3{2:^A}4{2:^A}5{2:^A}6{2:^A}7{2:^A}8{2:^A}9{2:^A}10{2:^A}11{2:^A}12| + {2:^A}13{2:^A}14{2:^A}15{2:^A}16{2:^A}17{2:^A}18{2:^A}19{2:^A}20{2:^A}21{2:^A}22| + {2:^A}23{2:^A}24{2:^A}25{2:^A}26{2:^A}27{2:^A}28{2:^A}29{2:^A}30{2:^A}31{2:^A}32| + {2:^A}33{2:^A}34{2:^A}35{2:^A}36{2:^A}37{2:^A}38{2:^A}39{2:^A}40{2:^A}41{2:^A}42| + {2:^A}43{2:^A}44{2:^A}45{2:^A}46{2:^A}47{2:^A}48{2:^A}49{2:^A}50{2:^A}51{2:^A}52| + {2:^A}53{2:^A}54{2:^A}55{2:^A}56{2:^A}57{2:^A}58{2:^A}59{2:^A}60{2:^A}61{2:^A}62| + {2:^A}63{2:^A}64{2:^A}65{2:^A}66{2:^A}67{2:^A}68{2:^A}69{2:^A}70{2:^A}71{2:^A}72| + {2:^A}73{2:^A}74{2:^A}75{2:^A}76{2:^A}77{2:^A}78{2:^A}79{2:^A}80{2:^A}81{2:^A}82| + {2:^A}83{2:^A}84{2:^A}85{2:^A}86{2:^A}87{2:^A}88{2:^A}89{2:^A}90{2:^A}91{2:^A}92| {1:-- More --}^ | ]]) feed('q') -- cgit From 760a8754c07a62afa4d83f4e254b1d45ae8cfc65 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Tue, 27 Sep 2022 12:36:33 +0200 Subject: vim-patch:9.0.0599: latexmkrc files are not recognized Problem: Latexmkrc files are not recognized. Solution: Use Perl filetype for latexmkrc files. (closes vim/vim#11241) https://github.com/vim/vim/commit/cde031938537970938437cdbb235bc0da755ae4a --- runtime/filetype.vim | 3 +++ runtime/lua/vim/filetype.lua | 2 ++ src/nvim/testdir/test_filetype.vim | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 11536adf69..ef04943d45 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1027,6 +1027,9 @@ au BufNewFile,BufRead Kconfig,Kconfig.debug setf kconfig " Lace (ISE) au BufNewFile,BufRead *.ace,*.ACE setf lace +" Latexmkrc +au BufNewFile,BufRead .latexmkrc,latexmkrc setf perl + " Latte au BufNewFile,BufRead *.latte,*.lte setf latte diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index bd317baae9..642f783e78 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -1496,6 +1496,8 @@ local filename = { ['/etc/shadow-'] = 'passwd', ['/etc/shadow'] = 'passwd', ['/etc/passwd.edit'] = 'passwd', + ['latexmkrc'] = 'perl', + ['.latexmkrc'] = 'perl', ['pf.conf'] = 'pf', ['main.cf'] = 'pfmain', pinerc = 'pine', diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index 4755d39cd3..6525bb3f62 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -412,7 +412,7 @@ let s:filename_checks = { \ 'pccts': ['file.g'], \ 'pcmk': ['file.pcmk'], \ 'pdf': ['file.pdf'], - \ 'perl': ['file.plx', 'file.al', 'file.psgi', 'gitolite.rc', '.gitolite.rc', 'example.gitolite.rc'], + \ 'perl': ['file.plx', 'file.al', 'file.psgi', 'gitolite.rc', '.gitolite.rc', 'example.gitolite.rc', '.latexmkrc', 'latexmkrc'], \ 'pf': ['pf.conf'], \ 'pfmain': ['main.cf'], \ 'php': ['file.php', 'file.php9', 'file.phtml', 'file.ctp', 'file.phpt', 'file.theme'], -- cgit From e176f9dacf28f56e91fcbc92f392228588a46c85 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Tue, 27 Sep 2022 12:38:31 +0200 Subject: vim-patch:9.0.0600: GYP files are not recognized Problem: GYP files are not recognized. Solution: Recognize GYP files. (closes vim/vim#11242) https://github.com/vim/vim/commit/d32474229213276c64cb293885a975dcb406fbc9 --- runtime/filetype.vim | 3 +++ runtime/lua/vim/filetype.lua | 2 ++ src/nvim/testdir/test_filetype.vim | 1 + 3 files changed, 6 insertions(+) diff --git a/runtime/filetype.vim b/runtime/filetype.vim index ef04943d45..5f58ad87b8 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -803,6 +803,9 @@ au BufNewFile,BufRead */etc/group,*/etc/group-,*/etc/group.edit,*/etc/gshadow,*/ " GTK RC au BufNewFile,BufRead .gtkrc,gtkrc setf gtkrc +" GYP +au BufNewFile,BufRead *.gyp,*.gypi setf gyp + " Hack au BufRead,BufNewFile *.hack,*.hackpartial setf hack diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 642f783e78..66b89a7078 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -448,6 +448,8 @@ local extension = { gsp = 'gsp', gjs = 'javascript.glimmer', gts = 'typescript.glimmer', + gyp = 'gyp', + gypi = 'gyp', hack = 'hack', hackpartial = 'hack', haml = 'haml', diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index 6525bb3f62..746ca3318f 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -240,6 +240,7 @@ let s:filename_checks = { \ 'grub': ['/boot/grub/menu.lst', '/boot/grub/grub.conf', '/etc/grub.conf', 'any/boot/grub/grub.conf', 'any/boot/grub/menu.lst', 'any/etc/grub.conf'], \ 'gsp': ['file.gsp'], \ 'gtkrc': ['.gtkrc', 'gtkrc', '.gtkrc-file', 'gtkrc-file'], + \ 'gyp': ['file.gyp', 'file.gypi'], \ 'hack': ['file.hack', 'file.hackpartial'], \ 'haml': ['file.haml'], \ 'hamster': ['file.hsm'], -- cgit From fe0727a1bfebdb8dc27bd8c276566f203b4d6a18 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Tue, 27 Sep 2022 13:03:28 +0200 Subject: vim-patch:9.0.0602: new TypeScript extensions are not recognized Problem: New TypeScript extensions are not recognized. Solution: Recognize .mts and .cts files. (closes vim/vim#11237) https://github.com/vim/vim/commit/7fc6c0e4dab4e80b9806a973936af54276468513 --- runtime/filetype.vim | 11 +++++++---- runtime/lua/vim/filetype.lua | 2 ++ src/nvim/testdir/test_filetype.vim | 1 + 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 5f58ad87b8..3042e62508 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -771,8 +771,8 @@ au BufNewFile,BufRead gitolite.conf setf gitolite au BufNewFile,BufRead {,.}gitolite.rc,example.gitolite.rc setf perl " Glimmer-flavored TypeScript and JavaScript -au BufNewFile,BufRead *.gts setf typescript.glimmer -au BufNewFile,BufRead *.gjs setf javascript.glimmer +au BufNewFile,BufRead *.gts setf typescript.glimmer +au BufNewFile,BufRead *.gjs setf javascript.glimmer " Gnuplot scripts au BufNewFile,BufRead *.gpi,.gnuplot setf gnuplot @@ -2090,7 +2090,7 @@ au BufNewFile,BufReadPost *.tutor setf tutor " TWIG files au BufNewFile,BufReadPost *.twig setf twig -" Typescript or Qt translation file (which is XML) +" TypeScript or Qt translation file (which is XML) au BufNewFile,BufReadPost *.ts \ if getline(1) =~ ' Date: Sat, 14 Aug 2021 12:19:05 -0500 Subject: fix(api): notify dict watchers on nvim_set_var and vim.g setter Co-authored-by: bfredl Co-authored-by: Christian Clason --- src/nvim/api/private/helpers.c | 18 +++++++ src/nvim/eval/typval.c | 2 +- src/nvim/eval/vars.c | 8 +-- src/nvim/lua/stdlib.c | 19 +++++++ .../functional/ex_cmds/dict_notifications_spec.lua | 63 ++++++++++++++++++++++ 5 files changed, 103 insertions(+), 7 deletions(-) diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index b888d09343..73b5489d5c 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -218,6 +218,8 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del, bool retva return rv; } + bool watched = tv_dict_is_watched(dict); + if (del) { // Delete the key if (di == NULL) { @@ -225,6 +227,10 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del, bool retva api_set_error(err, kErrorTypeValidation, "Key not found: %s", key.data); } else { + // Notify watchers + if (watched) { + tv_dict_watcher_notify(dict, key.data, NULL, &di->di_tv); + } // Return the old value if (retval) { rv = vim_to_object(&di->di_tv); @@ -241,11 +247,16 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del, bool retva return rv; } + typval_T oldtv = TV_INITIAL_VALUE; + if (di == NULL) { // Need to create an entry di = tv_dict_item_alloc_len(key.data, key.size); tv_dict_add(dict, di); } else { + if (watched) { + tv_copy(&di->di_tv, &oldtv); + } // Return the old value if (retval) { rv = vim_to_object(&di->di_tv); @@ -255,6 +266,13 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del, bool retva // Update the value tv_copy(&tv, &di->di_tv); + + // Notify watchers + if (watched) { + tv_dict_watcher_notify(dict, key.data, &tv, &oldtv); + tv_clear(&oldtv); + } + // Clear the temporary variable tv_clear(&tv); } diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index f9aed7a966..5639414dad 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -1781,7 +1781,7 @@ void tv_dict_watcher_notify(dict_T *const dict, const char *const key, typval_T tv_dict_add(argv[2].vval.v_dict, v); } - if (oldtv) { + if (oldtv && oldtv->v_type != VAR_UNKNOWN) { dictitem_T *const v = tv_dict_item_alloc_len(S_LEN("old")); tv_copy(oldtv, &v->di_tv); tv_dict_add(argv[2].vval.v_dict, v); diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 1c07fc4d45..4d7214205d 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1348,12 +1348,8 @@ void set_var_const(const char *name, const size_t name_len, typval_T *const tv, } if (watched) { - if (oldtv.v_type == VAR_UNKNOWN) { - tv_dict_watcher_notify(dict, (char *)v->di_key, &v->di_tv, NULL); - } else { - tv_dict_watcher_notify(dict, (char *)v->di_key, &v->di_tv, &oldtv); - tv_clear(&oldtv); - } + tv_dict_watcher_notify(dict, (char *)v->di_key, &v->di_tv, &oldtv); + tv_clear(&oldtv); } if (is_const) { diff --git a/src/nvim/lua/stdlib.c b/src/nvim/lua/stdlib.c index 9b1890403e..498f956ed9 100644 --- a/src/nvim/lua/stdlib.c +++ b/src/nvim/lua/stdlib.c @@ -369,12 +369,19 @@ int nlua_setvar(lua_State *lstate) return 0; } + bool watched = tv_dict_is_watched(dict); + if (del) { // Delete the key if (di == NULL) { // Doesn't exist, nothing to do return 0; } else { + // Notify watchers + if (watched) { + tv_dict_watcher_notify(dict, key.data, NULL, &di->di_tv); + } + // Delete the entry tv_dict_item_remove(dict, di); } @@ -388,17 +395,29 @@ int nlua_setvar(lua_State *lstate) return luaL_error(lstate, "Couldn't convert lua value"); } + typval_T oldtv = TV_INITIAL_VALUE; + if (di == NULL) { // Need to create an entry di = tv_dict_item_alloc_len(key.data, key.size); tv_dict_add(dict, di); } else { + if (watched) { + tv_copy(&di->di_tv, &oldtv); + } // Clear the old value tv_clear(&di->di_tv); } // Update the value tv_copy(&tv, &di->di_tv); + + // Notify watchers + if (watched) { + tv_dict_watcher_notify(dict, key.data, &tv, &oldtv); + tv_clear(&oldtv); + } + // Clear the temporary variable tv_clear(&tv); } diff --git a/test/functional/ex_cmds/dict_notifications_spec.lua b/test/functional/ex_cmds/dict_notifications_spec.lua index 21adcf37da..afa6b519d5 100644 --- a/test/functional/ex_cmds/dict_notifications_spec.lua +++ b/test/functional/ex_cmds/dict_notifications_spec.lua @@ -4,6 +4,7 @@ local clear, nvim, source = helpers.clear, helpers.nvim, helpers.source local insert = helpers.insert local eq, next_msg = helpers.eq, helpers.next_msg local exc_exec = helpers.exc_exec +local exec_lua = helpers.exec_lua local command = helpers.command local eval = helpers.eval @@ -21,6 +22,8 @@ describe('VimL dictionary notifications', function() -- t:) and a dictionary variable, so we generate them in the following -- function. local function gentests(dict_expr, dict_init) + local is_g = dict_expr == 'g:' + local function update(opval, key) if not key then key = 'watched' @@ -32,6 +35,28 @@ describe('VimL dictionary notifications', function() end end + local function update_with_api(opval, key) + if not key then + key = 'watched' + end + if opval == '' then + exec_lua(('vim.api.nvim_del_var(\'%s\')'):format(key)) + else + exec_lua(('vim.api.nvim_set_var(\'%s\', %s)'):format(key, opval)) + end + end + + local function update_with_vim_g(opval, key) + if not key then + key = 'watched' + end + if opval == '' then + exec_lua(('vim.g.%s = nil'):format(key)) + else + exec_lua(('vim.g.%s %s'):format(key, opval)) + end + end + local function verify_echo() -- helper to verify that no notifications are sent after certain change -- to a dict @@ -76,6 +101,18 @@ describe('VimL dictionary notifications', function() update('', 'watched2') update('') verify_echo() + if is_g then + update_with_api('"test"') + update_with_api('"test2"', 'watched2') + update_with_api('', 'watched2') + update_with_api('') + verify_echo() + update_with_vim_g('= "test"') + update_with_vim_g('= "test2"', 'watched2') + update_with_vim_g('', 'watched2') + update_with_vim_g('') + verify_echo() + end end) it('is not triggered when unwatched keys are updated', function() @@ -83,6 +120,16 @@ describe('VimL dictionary notifications', function() update('.= "noop2"', 'unwatched') update('', 'unwatched') verify_echo() + if is_g then + update_with_api('"noop"', 'unwatched') + update_with_api('vim.g.unwatched .. "noop2"', 'unwatched') + update_with_api('', 'unwatched') + verify_echo() + update_with_vim_g('= "noop"', 'unwatched') + update_with_vim_g('= vim.g.unwatched .. "noop2"', 'unwatched') + update_with_vim_g('', 'unwatched') + verify_echo() + end end) it('is triggered by remove()', function() @@ -92,6 +139,22 @@ describe('VimL dictionary notifications', function() verify_value({old = 'test'}) end) + if is_g then + it('is triggered by remove() when updated with nvim_*_var', function() + update_with_api('"test"') + verify_value({new = 'test'}) + nvim('command', 'call remove('..dict_expr..', "watched")') + verify_value({old = 'test'}) + end) + + it('is triggered by remove() when updated with vim.g', function() + update_with_vim_g('= "test"') + verify_value({new = 'test'}) + nvim('command', 'call remove('..dict_expr..', "watched")') + verify_value({old = 'test'}) + end) + end + it('is triggered by extend()', function() update('= "xtend"') verify_value({new = 'xtend'}) -- cgit From 6afe5cce7964258f7ee0b25ae08faa551bc76090 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Tue, 27 Sep 2022 14:53:48 +0200 Subject: ci(backport): bump to backport-action@v0.0.8 #20366 Primary bug fix is allowing backports with empty PR description. --- .github/workflows/backport.yml | 2 +- MAINTAIN.md | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index b5fd22d036..910df32a51 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -21,7 +21,7 @@ jobs: fetch-depth: 0 ref: ${{ github.event.pull_request.head.sha }} - name: Create backport PRs - uses: zeebe-io/backport-action@v0.0.7 + uses: zeebe-io/backport-action@v0.0.8 with: github_token: ${{ secrets.GITHUB_TOKEN }} github_workspace: ${{ github.workspace }} diff --git a/MAINTAIN.md b/MAINTAIN.md index 9a8531fbd9..36ba07593d 100644 --- a/MAINTAIN.md +++ b/MAINTAIN.md @@ -57,8 +57,7 @@ has a major bug: The neovim repository includes a backport [github action](https://github.com/zeebe-io/backport-action). In order to trigger the action, a PR must be labeled with a label matching the -form `backport release-0.X`. Note, the PR must have a description in the issue body, -or the backport will fail. +form `backport release-0.X`. Third-party dependencies -------------- -- cgit From f46060c4cbc1efe100019075214def53fe4d47b3 Mon Sep 17 00:00:00 2001 From: ObserverOfTime Date: Tue, 27 Sep 2022 17:10:19 +0300 Subject: vim-patch:9.0.0604: luacheckrc file is not recognized (#20371) Problem: Luacheckrc file is not recognized. Solution: Use lua filetype for luacheckrc. (closes vim/vim#11236) https://github.com/vim/vim/commit/49c311c9b18e18c05f93728d1f8a552923a18423 --- runtime/filetype.vim | 3 +++ runtime/lua/vim/filetype.lua | 1 + src/nvim/testdir/test_filetype.vim | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 3042e62508..204bf1865f 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1113,6 +1113,9 @@ au BufNewFile,BufRead *.lou,*.lout setf lout " Lua au BufNewFile,BufRead *.lua setf lua +" Luacheck +au BufNewFile,BufRead .luacheckrc setf lua + " Luarocks au BufNewFile,BufRead *.rockspec setf lua diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index a7a34a54cd..d584d2659d 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -1455,6 +1455,7 @@ local filename = { ['.sawfishrc'] = 'lisp', ['/etc/login.access'] = 'loginaccess', ['/etc/login.defs'] = 'logindefs', + ['.luacheckrc'] = 'lua', ['lynx.cfg'] = 'lynx', ['m3overrides'] = 'm3build', ['m3makefile'] = 'm3build', diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index 6f7d9f75e6..05aee9b31d 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -328,7 +328,7 @@ let s:filename_checks = { \ 'lpc': ['file.lpc', 'file.ulpc'], \ 'lsl': ['file.lsl'], \ 'lss': ['file.lss'], - \ 'lua': ['file.lua', 'file.rockspec', 'file.nse'], + \ 'lua': ['file.lua', 'file.rockspec', 'file.nse', '.luacheckrc'], \ 'lynx': ['lynx.cfg'], \ 'lyrics': ['file.lrc'], \ 'm3build': ['m3makefile', 'm3overrides'], -- cgit From e6c214033a4fadf60faf99e95f8e9787e3c5e630 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 28 Sep 2022 06:22:11 +0800 Subject: fix(window): fix equalization with cmdheight=0 (#20369) --- src/nvim/window.c | 2 +- test/functional/ui/cmdline_spec.lua | 57 +++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/nvim/window.c b/src/nvim/window.c index 22c1b77570..5523c3df8b 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2239,7 +2239,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int // Compute maximum number of windows vertically in this frame. n = frame_minheight(topfr, NOWIN); // add one for the bottom window if it doesn't have a statusline or separator - if (row + height == cmdline_row && p_ls == 0) { + if (row + height >= cmdline_row && p_ls == 0) { extra_sep = STATUS_HEIGHT; } else if (global_stl_height() > 0) { extra_sep = 1; diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua index d7f2b2335e..1528b5307d 100644 --- a/test/functional/ui/cmdline_spec.lua +++ b/test/functional/ui/cmdline_spec.lua @@ -1358,4 +1358,61 @@ describe('cmdheight=0', function() :echo^ | ]]) end) + + it('window equalization with laststatus=0 #20367', function() + screen:try_resize(60, 9) + command('set cmdheight=0 laststatus=0') + command('vsplit') + screen:expect([[ + ^ │ | + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + ]]) + feed(':') + command('split') + feed('') + screen:expect([[ + ^ │ | + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {2:[No Name] }│{1:~ }| + │{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + ]]) + command('resize 2') + screen:expect([[ + ^ │ | + {1:~ }│{1:~ }| + {2:[No Name] }│{1:~ }| + │{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + ]]) + feed(':') + command('wincmd =') + feed('') + screen:expect([[ + ^ │ | + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {2:[No Name] }│{1:~ }| + │{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + {1:~ }│{1:~ }| + ]]) + end) end) -- cgit From 4b7904d16b11915b16ea46b96f1ea6e28d87d5fd Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Tue, 27 Sep 2022 21:16:28 +0600 Subject: refactor: replace unnecessary helper functions in optionstr.c Replaces unnecessary helper functions in `optionstr.c` such as `get_option_flags()`, `get_option_fullname()`, `set_option_flag()`, `is_global_option()`, etc. with a single `get_option()` helper function that allows direct access to the `options` array. Also refactors `f_exists()` to use `get_varp_scope` instead of using `get_option_tv`. This opens up the path for removing `getoptions_T` altogether later down the line since the hidden option logic is no longer needed. --- src/nvim/eval.c | 5 --- src/nvim/eval/funcs.c | 11 ++++-- src/nvim/option.c | 101 ++----------------------------------------------- src/nvim/option_defs.h | 37 ++++++++++++++++++ src/nvim/optionstr.c | 76 +++++++++++++++++++------------------ 5 files changed, 89 insertions(+), 141 deletions(-) diff --git a/src/nvim/eval.c b/src/nvim/eval.c index c2a7b6bba5..6eaf3d1f5e 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -3659,7 +3659,6 @@ static int eval_index(char **arg, typval_T *rettv, int evaluate, int verbose) int get_option_tv(const char **const arg, typval_T *const rettv, const bool evaluate) FUNC_ATTR_NONNULL_ARG(1) { - bool working = (**arg == '+'); // has("+option") int opt_flags; // Isolate the option name and find its value. @@ -3704,10 +3703,6 @@ int get_option_tv(const char **const arg, typval_T *const rettv, const bool eval rettv->v_type = VAR_STRING; rettv->vval.v_string = stringval; } - } else if (working && (opt_type == gov_hidden_bool - || opt_type == gov_hidden_number - || opt_type == gov_hidden_string)) { - ret = FAIL; } *option_end = c; // put back for error messages diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 9ba2ce2365..f2ef8e5cdd 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1938,9 +1938,14 @@ static void f_exists(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) xfree(exp); } } else if (*p == '&' || *p == '+') { // Option. - n = (get_option_tv(&p, NULL, true) == OK); - if (*skipwhite(p) != NUL) { - n = false; // Trailing garbage. + bool working = (*p == '+'); // whether option needs to be working + int opt_flags; + + if (find_option_end(&p, &opt_flags) != NULL) { + int opt_idx = findoption(p); + n = (opt_idx >= 0 && (!working || get_varp_scope(get_option(opt_idx), opt_flags) != NULL)); + } else { + n = false; } } else if (*p == '*') { // Internal or user defined function. n = function_exists(p + 1, false); diff --git a/src/nvim/option.c b/src/nvim/option.c index 5b67f0e471..e7d0b171f6 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -106,30 +106,6 @@ static char e_number_required_after_equal[] static char e_preview_window_already_exists[] = N_("E590: A preview window already exists"); -// The options that are local to a window or buffer have "indir" set to one of -// these values. Special values: -// PV_NONE: global option. -// PV_WIN is added: window-local option -// PV_BUF is added: buffer-local option -// PV_BOTH is added: global option which also has a local value. -#define PV_BOTH 0x1000 -#define PV_WIN 0x2000 -#define PV_BUF 0x4000 -#define PV_MASK 0x0fff -#define OPT_WIN(x) (idopt_T)(PV_WIN + (int)(x)) -#define OPT_BUF(x) (idopt_T)(PV_BUF + (int)(x)) -#define OPT_BOTH(x) (idopt_T)(PV_BOTH + (int)(x)) - -// WV_ and BV_ values get typecasted to this for the "indir" field -typedef enum { - PV_NONE = 0, - PV_MAXVAL = 0xffff, // to avoid warnings for value out of range -} idopt_T; - -// Options local to a window have a value local to a buffer and global to all -// buffers. Indicate this by setting "var" to VAR_WIN. -#define VAR_WIN ((char_u *)-1) - static char *p_term = NULL; static char *p_ttytype = NULL; @@ -147,19 +123,6 @@ static long p_tw_nopaste; static long p_wm_nopaste; static char *p_vsts_nopaste; -typedef struct vimoption { - char *fullname; // full option name - char *shortname; // permissible abbreviation - uint32_t flags; // see below - char_u *var; // global option: pointer to variable; - // window-local option: VAR_WIN; - // buffer-local option: global value - idopt_T indir; // global option: PV_NONE; - // local option: indirect option index - char *def_val; // default values for variable (neovim!!) - LastSet last_set; // script in which the option was last set -} vimoption_T; - // options[] is initialized here. // The order of the options MUST be alphabetic for ":set all" and findoption(). // All option names MUST start with a lowercase letter (for findoption()). @@ -3047,47 +3010,10 @@ int get_option_value_strict(char *name, int64_t *numval, char **stringval, int o return rv; } -/// Return the flags for the option at 'opt_idx'. -uint32_t get_option_flags(int opt_idx) -{ - return options[opt_idx].flags; -} - -/// Set a flag for the option at 'opt_idx'. -void set_option_flag(int opt_idx, uint32_t flag) -{ - options[opt_idx].flags |= flag; -} - -/// Clear a flag for the option at 'opt_idx'. -void clear_option_flag(int opt_idx, uint32_t flag) -{ - options[opt_idx].flags &= ~flag; -} - -/// Returns true if the option at 'opt_idx' is a global option -bool is_global_option(int opt_idx) -{ - return options[opt_idx].indir == PV_NONE; -} - -/// Returns true if the option at 'opt_idx' is a global option which also has a -/// local value. -int is_global_local_option(int opt_idx) +// Return information for option at 'opt_idx' +vimoption_T *get_option(int opt_idx) { - return options[opt_idx].indir & PV_BOTH; -} - -/// Returns true if the option at 'opt_idx' is a window-local option -bool is_window_local_option(int opt_idx) -{ - return options[opt_idx].var == VAR_WIN; -} - -/// Returns true if the option at 'opt_idx' is a hidden option -bool is_hidden_option(int opt_idx) -{ - return options[opt_idx].var == NULL; + return &options[opt_idx]; } /// Set the value of an option @@ -3761,7 +3687,7 @@ void unset_global_local_option(char *name, void *from) } /// Get pointer to option variable, depending on local or global scope. -static char *get_varp_scope(vimoption_T *p, int opt_flags) +char *get_varp_scope(vimoption_T *p, int opt_flags) { if ((opt_flags & OPT_GLOBAL) && p->indir != PV_NONE) { if (p->var == VAR_WIN) { @@ -3833,13 +3759,6 @@ static char *get_varp_scope(vimoption_T *p, int opt_flags) return (char *)get_varp(p); } -/// Get pointer to option variable at 'opt_idx', depending on local or global -/// scope. -char *get_option_varp_scope(int opt_idx, int opt_flags) -{ - return get_varp_scope(&(options[opt_idx]), opt_flags); -} - /// Get pointer to option variable. static char_u *get_varp(vimoption_T *p) { @@ -4149,18 +4068,6 @@ static char_u *get_varp(vimoption_T *p) return (char_u *)&(curbuf->b_p_wm); } -/// Return a pointer to the variable for option at 'opt_idx' -char_u *get_option_var(int opt_idx) -{ - return options[opt_idx].var; -} - -/// Return the full name of the option at 'opt_idx' -char *get_option_fullname(int opt_idx) -{ - return options[opt_idx].fullname; -} - /// Get the value of 'equalprg', either the buffer-local one or the global one. char_u *get_equalprg(void) { diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index e8cf338cf1..e27607d7a8 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -990,4 +990,41 @@ typedef struct { uint64_t channel_id; /// Only used when script_id is SID_API_CLIENT. } LastSet; +// WV_ and BV_ values get typecasted to this for the "indir" field +typedef enum { + PV_NONE = 0, + PV_MAXVAL = 0xffff, // to avoid warnings for value out of range +} idopt_T; + +typedef struct vimoption { + char *fullname; // full option name + char *shortname; // permissible abbreviation + uint32_t flags; // see below + char_u *var; // global option: pointer to variable; + // window-local option: VAR_WIN; + // buffer-local option: global value + idopt_T indir; // global option: PV_NONE; + // local option: indirect option index + char *def_val; // default values for variable (neovim!!) + LastSet last_set; // script in which the option was last set +} vimoption_T; + +// The options that are local to a window or buffer have "indir" set to one of +// these values. Special values: +// PV_NONE: global option. +// PV_WIN is added: window-local option +// PV_BUF is added: buffer-local option +// PV_BOTH is added: global option which also has a local value. +#define PV_BOTH 0x1000 +#define PV_WIN 0x2000 +#define PV_BUF 0x4000 +#define PV_MASK 0x0fff +#define OPT_WIN(x) (idopt_T)(PV_WIN + (int)(x)) +#define OPT_BUF(x) (idopt_T)(PV_BUF + (int)(x)) +#define OPT_BOTH(x) (idopt_T)(PV_BOTH + (int)(x)) + +// Options local to a window have a value local to a buffer and global to all +// buffers. Indicate this by setting "var" to VAR_WIN. +#define VAR_WIN ((char_u *)-1) + #endif // NVIM_OPTION_DEFS_H diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 7278b1a12d..aff88a755b 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -178,7 +178,7 @@ void trigger_optionsset_string(int opt_idx, int opt_flags, char *oldval, char *o set_vim_var_string(VV_OPTION_COMMAND, "modeline", -1); set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1); } - apply_autocmds(EVENT_OPTIONSET, get_option_fullname(opt_idx), NULL, false, NULL); + apply_autocmds(EVENT_OPTIONSET, get_option(opt_idx)->fullname, NULL, false, NULL); reset_v_option_vars(); } } @@ -280,19 +280,19 @@ void check_string_option(char **pp) /// Set global value for string option when it's a local option. /// -/// @param opt_idx option index +/// @param opt option /// @param varp pointer to option variable -static void set_string_option_global(int opt_idx, char **varp) +static void set_string_option_global(vimoption_T *opt, char **varp) { char **p; // the global value is always allocated - if (is_window_local_option(opt_idx)) { + if (opt->var == VAR_WIN) { p = (char **)GLOBAL_WO(varp); } else { - p = (char **)get_option_var(opt_idx); + p = (char **)opt->var; } - if (!is_global_option(opt_idx) && p != varp) { + if (opt->indir != PV_NONE && p != varp) { char *s = xstrdup(*varp); free_string_option(*p); *p = s; @@ -324,30 +324,32 @@ void set_string_option_direct(const char *name, int opt_idx, const char *val, in } } - if (is_hidden_option(idx)) { // can't set hidden option + vimoption_T *opt = get_option(idx); + + if (opt->var == NULL) { // can't set hidden option return; } - assert((void *)get_option_var(idx) != (void *)&p_shada); + assert((void *)opt->var != (void *)&p_shada); s = xstrdup(val); { - varp = (char **)get_option_varp_scope(idx, both ? OPT_LOCAL : opt_flags); - if ((opt_flags & OPT_FREE) && (get_option_flags(idx) & P_ALLOCED)) { + varp = (char **)get_varp_scope(opt, both ? OPT_LOCAL : opt_flags); + if ((opt_flags & OPT_FREE) && (opt->flags & P_ALLOCED)) { free_string_option(*varp); } *varp = s; // For buffer/window local option may also set the global value. if (both) { - set_string_option_global(idx, varp); + set_string_option_global(opt, varp); } - set_option_flag(idx, P_ALLOCED); + opt->flags |= P_ALLOCED; // When setting both values of a global option with a local value, // make the local value empty, so that the global value is used. - if (is_global_local_option(idx) && both) { + if ((opt->indir & PV_BOTH) && both) { free_string_option(*varp); *varp = empty_option; } @@ -393,24 +395,24 @@ void set_string_option_direct_in_win(win_T *wp, const char *name, int opt_idx, c char *set_string_option(const int opt_idx, const char *const value, const int opt_flags) FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_WARN_UNUSED_RESULT { - if (is_hidden_option(opt_idx)) { // don't set hidden option + vimoption_T *opt = get_option(opt_idx); + + if (opt->var == NULL) { // don't set hidden option return NULL; } char *const s = xstrdup(value); char **const varp - = (char **)get_option_varp_scope(opt_idx, - (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 - ? (is_global_local_option(opt_idx) - ? OPT_GLOBAL : OPT_LOCAL) - : opt_flags); + = (char **)get_varp_scope(opt, ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 + ? ((opt->indir & PV_BOTH) ? OPT_GLOBAL : OPT_LOCAL) + : opt_flags)); char *const oldval = *varp; char *oldval_l = NULL; char *oldval_g = NULL; if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) { - oldval_l = *(char **)get_option_varp_scope(opt_idx, OPT_LOCAL); - oldval_g = *(char **)get_option_varp_scope(opt_idx, OPT_GLOBAL); + oldval_l = *(char **)get_varp_scope(opt, OPT_LOCAL); + oldval_g = *(char **)get_varp_scope(opt, OPT_GLOBAL); } *varp = s; @@ -434,8 +436,8 @@ char *set_string_option(const int opt_idx, const char *const value, const int op trigger_optionsset_string(opt_idx, opt_flags, saved_oldval, saved_oldval_l, saved_oldval_g, saved_newval); } - if (get_option_flags(opt_idx) & P_UI_OPTION) { - ui_call_option_set(cstr_as_string(get_option_fullname(opt_idx)), + if (opt->flags & P_UI_OPTION) { + ui_call_option_set(cstr_as_string(opt->fullname), STRING_OBJ(cstr_as_string(saved_newval))); } } @@ -638,20 +640,21 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf char *errmsg = NULL; char *s, *p; int did_chartab = false; - bool free_oldval = (get_option_flags(opt_idx) & P_ALLOCED); + vimoption_T *opt = get_option(opt_idx); + bool free_oldval = (opt->flags & P_ALLOCED); bool value_changed = false; // Get the global option to compare with, otherwise we would have to check // two values for all local options. - char **gvarp = (char **)get_option_varp_scope(opt_idx, OPT_GLOBAL); + char **gvarp = (char **)get_varp_scope(opt, OPT_GLOBAL); // Disallow changing some options from secure mode if ((secure || sandbox != 0) - && (get_option_flags(opt_idx) & P_SECURE)) { + && (opt->flags & P_SECURE)) { errmsg = e_secure; - } else if (((get_option_flags(opt_idx) & P_NFNAME) + } else if (((opt->flags & P_NFNAME) && strpbrk(*varp, (secure ? "/\\*?[|;&<>\r\n" : "/\\*?[<>\r\n")) != NULL) - || ((get_option_flags(opt_idx) & P_NDNAME) + || ((opt->flags & P_NDNAME) && strpbrk(*varp, "*?[|;&<>\r\n") != NULL)) { // Check for a "normal" directory or file name in some options. Disallow a // path separator (slash and/or backslash), wildcards and characters that @@ -986,13 +989,14 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf } else if (varp == &p_shada) { // 'shada' // TODO(ZyX-I): Remove this code in the future, alongside with &viminfo // option. - opt_idx = ((get_option_fullname(opt_idx)[0] == 'v') + opt_idx = ((opt->fullname[0] == 'v') ? (shada_idx == -1 ? ((shada_idx = findoption("shada"))) : shada_idx) : opt_idx); + opt = get_option(opt_idx); // Update free_oldval now that we have the opt_idx for 'shada', otherwise // there would be a disconnect between the check for P_ALLOCED at the start // of the function and the set of P_ALLOCED at the end of the function. - free_oldval = (get_option_flags(opt_idx) & P_ALLOCED); + free_oldval = (opt->flags & P_ALLOCED); for (s = p_shada; *s;) { // Check it's a valid character if (vim_strchr("!\"%'/:<@cfhnrs", *s) == NULL) { @@ -1522,18 +1526,18 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf if (free_oldval) { free_string_option(oldval); } - set_option_flag(opt_idx, P_ALLOCED); + opt->flags |= P_ALLOCED; if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 - && is_global_local_option(opt_idx)) { + && (opt->indir & PV_BOTH)) { // global option with local value set to use global value; free // the local value and make it empty - p = get_option_varp_scope(opt_idx, OPT_LOCAL); + p = get_varp_scope(opt, OPT_LOCAL); free_string_option(*(char **)p); *(char **)p = empty_option; } else if (!(opt_flags & OPT_LOCAL) && opt_flags != OPT_GLOBAL) { // May set global value for local option. - set_string_option_global(opt_idx, varp); + set_string_option_global(opt, varp); } // Trigger the autocommand only after setting the flags. @@ -1604,11 +1608,11 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf } if (curwin->w_curswant != MAXCOL - && (get_option_flags(opt_idx) & (P_CURSWANT | P_RALL)) != 0) { + && (opt->flags & (P_CURSWANT | P_RALL)) != 0) { curwin->w_set_curswant = true; } - check_redraw(get_option_flags(opt_idx)); + check_redraw(opt->flags); return errmsg; } -- cgit From 6427dc8ab66e5885c133698e3e96e82ab74a89f3 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Wed, 28 Sep 2022 09:28:15 +0200 Subject: build(deps): require libtermkey version 0.22 Reduces #ifdef code. --- CMakeLists.txt | 2 +- src/nvim/tui/input.c | 4 ---- src/nvim/tui/input.h | 2 -- src/nvim/tui/tui.c | 8 ++------ 4 files changed, 3 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 81a0a2f667..034c349c9f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -498,7 +498,7 @@ if(FEAT_TUI) add_definitions(-DNVIM_UNIBI_HAS_VAR_FROM) endif() - find_package(LibTermkey 0.18 REQUIRED) + find_package(LibTermkey 0.22 REQUIRED) include_directories(SYSTEM ${LIBTERMKEY_INCLUDE_DIRS}) endif() diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c index 998e8cfed0..fbeca26274 100644 --- a/src/nvim/tui/input.c +++ b/src/nvim/tui/input.c @@ -159,14 +159,10 @@ void tinput_init(TermInput *input, Loop *loop) term = ""; // termkey_new_abstract assumes non-null (#2745) } -#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18 input->tk = termkey_new_abstract(term, TERMKEY_FLAG_UTF8 | TERMKEY_FLAG_NOSTART); termkey_hook_terminfo_getstr(input->tk, input->tk_ti_hook_fn, NULL); termkey_start(input->tk); -#else - input->tk = termkey_new_abstract(term, TERMKEY_FLAG_UTF8); -#endif int curflags = termkey_get_canonflags(input->tk); termkey_set_canonflags(input->tk, curflags | TERMKEY_CANON_DELBS); diff --git a/src/nvim/tui/input.h b/src/nvim/tui/input.h index 51df57938c..0b60394850 100644 --- a/src/nvim/tui/input.h +++ b/src/nvim/tui/input.h @@ -26,9 +26,7 @@ typedef struct term_input { ExtkeysType extkeys_type; long ttimeoutlen; TermKey *tk; -#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18 TermKey_Terminfo_Getstr_Hook *tk_ti_hook_fn; ///< libtermkey terminfo hook -#endif TimeWatcher timer_handle; Loop *loop; Stream read_stream; diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 4eabecb74a..b483ad3486 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -485,9 +485,7 @@ static void tui_main(UIBridgeData *bridge, UI *ui) // TODO(bfredl): zero hl is empty, send this explicitly? kv_push(data->attrs, HLATTRS_INIT); -#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18 data->input.tk_ti_hook_fn = tui_tk_ti_getstr; -#endif tinput_init(&data->input, &tui_loop); tui_terminal_start(ui); @@ -2278,7 +2276,6 @@ static void flush_buf(UI *ui) data->overflow = false; } -#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18 /// Try to get "kbs" code from stty because "the terminfo kbs entry is extremely /// unreliable." (Vim, Bash, and tmux also do this.) /// @@ -2287,14 +2284,14 @@ static void flush_buf(UI *ui) static const char *tui_get_stty_erase(void) { static char stty_erase[2] = { 0 }; -# if defined(HAVE_TERMIOS_H) +#if defined(HAVE_TERMIOS_H) struct termios t; if (tcgetattr(input_global_fd(), &t) != -1) { stty_erase[0] = (char)t.c_cc[VERASE]; stty_erase[1] = '\0'; DLOG("stty/termios:erase=%s", stty_erase); } -# endif +#endif return stty_erase; } @@ -2328,4 +2325,3 @@ static const char *tui_tk_ti_getstr(const char *name, const char *value, void *d return value; } -#endif -- cgit From 6917a2e569e9f7306a9858f1aeeb32dd1c3ece4e Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Wed, 28 Sep 2022 09:30:47 +0200 Subject: build(deps): require libvterm version 0.3 --- CMakeLists.txt | 2 +- src/nvim/terminal.c | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 81a0a2f667..5a613a812c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -502,7 +502,7 @@ if(FEAT_TUI) include_directories(SYSTEM ${LIBTERMKEY_INCLUDE_DIRS}) endif() -find_package(LIBVTERM 0.1 REQUIRED) +find_package(LIBVTERM 0.3 REQUIRED) include_directories(SYSTEM ${LIBVTERM_INCLUDE_DIRS}) option(CLANG_ASAN_UBSAN "Enable Clang address & undefined behavior sanitizer for nvim binary." OFF) diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index 8ec51438fb..c52586fea2 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -908,7 +908,6 @@ static int term_settermprop(VTermProp prop, VTermValue *val, void *data) case VTERM_PROP_TITLE: { buf_T *buf = handle_get_buffer(term->buf_handle); -#if VTERM_VERSION_MAJOR > 0 || (VTERM_VERSION_MAJOR == 0 && VTERM_VERSION_MINOR >= 2) VTermStringFragment frag = val->string; if (frag.initial && frag.final) { @@ -933,9 +932,6 @@ static int term_settermprop(VTermProp prop, VTermValue *val, void *data) xfree(term->title); term->title = NULL; } -#else - buf_set_term_title(buf, val->string, strlen(val->string)); -#endif break; } -- cgit From d7358118aa57ec636ef6f84c6ac96f26d8bed32c Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Wed, 28 Sep 2022 10:53:44 +0200 Subject: fix: compiler warnings from clang 15 (#20321) Add -Wno-strict-prototypes flag to external dependencies to suppress cjson warnings. These needs to be fixed upstream first. --- src/nvim/CMakeLists.txt | 2 +- src/nvim/eval/typval.c | 2 -- src/nvim/input.c | 5 +---- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index f28b7a7e28..6f5f2b53f6 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -159,7 +159,7 @@ list(REMOVE_ITEM NVIM_SOURCES ${to_remove}) if(NOT MSVC) # xdiff, mpack, lua-cjson: inlined external project, we don't maintain it. #9306 set_source_files_properties( - ${EXTERNAL_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-conversion -Wno-missing-noreturn -Wno-missing-format-attribute -Wno-double-promotion") + ${EXTERNAL_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-conversion -Wno-missing-noreturn -Wno-missing-format-attribute -Wno-double-promotion -Wno-strict-prototypes") endif() if(NOT "${MIN_LOG_LEVEL}" MATCHES "^$") diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 5639414dad..961c963170 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -1249,14 +1249,12 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) item_compare_func_ptr = item_compare_keeping_zero; } - int idx = 0; for (listitem_T *li = TV_LIST_ITEM_NEXT(l, tv_list_first(l)) ; li != NULL;) { listitem_T *const prev_li = TV_LIST_ITEM_PREV(l, li); if (item_compare_func_ptr(&prev_li, &li) == 0) { li = tv_list_item_remove(l, li); } else { - idx++; li = TV_LIST_ITEM_NEXT(l, li); } if (info.item_compare_func_err) { // -V547 diff --git a/src/nvim/input.c b/src/nvim/input.c index 0aa9feaca3..681d9d5f9c 100644 --- a/src/nvim/input.c +++ b/src/nvim/input.c @@ -83,7 +83,6 @@ int get_keystroke(MultiQueue *events) int len = 0; int n; int save_mapped_ctrl_c = mapped_ctrl_c; - int waited = 0; mapped_ctrl_c = 0; // mappings are not used here for (;;) { @@ -110,10 +109,8 @@ int get_keystroke(MultiQueue *events) // Replace zero and K_SPECIAL by a special key code. n = fix_input_buffer(buf + len, n); len += n; - waited = 0; - } else if (len > 0) { - waited++; // keep track of the waiting time } + if (n > 0) { // found a termcode: adjust length len = n; } -- cgit From eb4844b5ed9bcf8c434a93b9f9def4fe81557f37 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Wed, 28 Sep 2022 11:06:11 +0200 Subject: build(macos): restore and test universal build (#20383) Build tree-sitter parsers for arm64 as well as x86 Check that all created binaries contain both architectures --- .github/workflows/release.yml | 5 +++++ cmake.deps/cmake/BuildTreesitterParsers.cmake | 2 ++ 2 files changed, 7 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5e0ea5e5f4..5fc40a2471 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -113,6 +113,11 @@ jobs: DEPS_CMAKE_FLAGS="$OSX_FLAGS" make DESTDIR="$GITHUB_WORKSPACE/build/release/nvim-macos" install cd "$GITHUB_WORKSPACE/build/" + # Make sure we build everything for M1 as well + for macho in bin/* lib/nvim/parser/*.so + do + lipo -info "$macho" | grep -q arm64 || exit 1 + done cpack -C "$NVIM_BUILD_TYPE" - uses: actions/upload-artifact@v3 with: diff --git a/cmake.deps/cmake/BuildTreesitterParsers.cmake b/cmake.deps/cmake/BuildTreesitterParsers.cmake index 25d2fd21a3..e08792f62a 100644 --- a/cmake.deps/cmake/BuildTreesitterParsers.cmake +++ b/cmake.deps/cmake/BuildTreesitterParsers.cmake @@ -4,6 +4,8 @@ function(BuildTSParser LANG TS_URL TS_SHA256 TS_CMAKE_FILE) PREFIX ${DEPS_BUILD_DIR} URL ${TREESITTER_C_URL} DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/${NAME} + CMAKE_CACHE_ARGS + -DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES} DOWNLOAD_COMMAND ${CMAKE_COMMAND} -DPREFIX=${DEPS_BUILD_DIR} -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/${NAME} -- cgit From 35e2c4a2edd28f72c48c70530c5486365c2502a4 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 28 Sep 2022 18:27:59 +0800 Subject: fix(lua): fix architecture-dependent behavior in usercmd "reg" (#20384) I don't think using an integer as a NUL-terminated string can work on big-endian systems, at least. This is also not tested. Add a test. Also fix a mistake in the docs of nvim_parse_cmd. --- runtime/doc/api.txt | 2 +- src/nvim/api/command.c | 6 ++---- src/nvim/lua/executor.c | 3 ++- test/functional/api/command_spec.lua | 37 ++++++++++++++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 6 deletions(-) diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index ce59f5ad52..f0145344a4 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -1811,7 +1811,7 @@ nvim_parse_cmd({str}, {opts}) *nvim_parse_cmd()* range items were specified. • count: (number) Any || that was supplied to the command. -1 if command cannot take a count. - • reg: (number) The optional command ||, if specified. Empty + • reg: (string) The optional command ||, if specified. Empty string if not specified or if command cannot take a register. • bang: (boolean) Whether command contains a || (!) modifier. • args: (array) Command arguments. diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index ed0907e8f8..699c62c15c 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -37,7 +37,7 @@ /// specified and two elements if both range items were specified. /// - count: (number) Any || that was supplied to the command. -1 if command cannot /// take a count. -/// - reg: (number) The optional command ||, if specified. Empty string if not +/// - reg: (string) The optional command ||, if specified. Empty string if not /// specified or if command cannot take a register. /// - bang: (boolean) Whether command contains a || (!) modifier. /// - args: (array) Command arguments. @@ -165,9 +165,7 @@ Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err) PUT(result, "count", INTEGER_OBJ(-1)); } - char reg[2]; - reg[0] = (char)ea.regname; - reg[1] = '\0'; + char reg[2] = { (char)ea.regname, NUL }; PUT(result, "reg", CSTR_TO_OBJ(reg)); PUT(result, "bang", BOOLEAN_OBJ(ea.forceit)); diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 6063414a02..f3821f149a 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -2036,7 +2036,8 @@ int nlua_do_ucmd(ucmd_T *cmd, exarg_T *eap, bool preview) } lua_setfield(lstate, -2, "fargs"); - lua_pushstring(lstate, (const char *)&eap->regname); + char reg[2] = { (char)eap->regname, NUL }; + lua_pushstring(lstate, reg); lua_setfield(lstate, -2, "reg"); lua_pushinteger(lstate, eap->addr_count); diff --git a/test/functional/api/command_spec.lua b/test/functional/api/command_spec.lua index 44a19d8348..f19d7a362b 100644 --- a/test/functional/api/command_spec.lua +++ b/test/functional/api/command_spec.lua @@ -423,6 +423,7 @@ describe('nvim_create_user_command', function() nargs = 0, bang = true, count = 2, + register = true, }) ]] eq({ @@ -460,6 +461,42 @@ describe('nvim_create_user_command', function() vim.cmd('CommandWithNoArgs') return result ]]) + -- register can be specified + eq({ + args = "", + fargs = {}, + bang = false, + line1 = 1, + line2 = 1, + mods = "", + smods = { + browse = false, + confirm = false, + emsg_silent = false, + hide = false, + horizontal = false, + keepalt = false, + keepjumps = false, + keepmarks = false, + keeppatterns = false, + lockmarks = false, + noautocmd = false, + noswapfile = false, + sandbox = false, + silent = false, + split = "", + tab = -1, + unsilent = false, + verbose = -1, + vertical = false, + }, + range = 0, + count = 2, + reg = "+", + }, exec_lua [[ + vim.cmd('CommandWithNoArgs +') + return result + ]]) end) -- cgit From 9ca313fb968448011aae0509e6552c52b9f8aa8c Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Wed, 28 Sep 2022 12:48:36 +0200 Subject: vim-patch:9fbdbb814f4a (#20376) Update runtime files https://github.com/vim/vim/commit/9fbdbb814f4ad67a14979aba4a6a49800c2f1a99 Skip ftplugin/vim.vim (vim9script change) Drop indent/vim.vim and autoload/dist/vimindent.vim (vim9script rewrite) --- runtime/compiler/hare.vim | 31 +++ runtime/doc/map.txt | 14 +- runtime/doc/motion.txt | 2 +- runtime/doc/repeat.txt | 3 +- runtime/doc/syntax.txt | 2 +- runtime/filetype.vim | 2 +- runtime/ftplugin/chatito.vim | 15 ++ runtime/ftplugin/elixir.vim | 6 +- runtime/ftplugin/gyp.vim | 14 ++ runtime/ftplugin/hare.vim | 27 +++ runtime/ftplugin/heex.vim | 16 ++ runtime/indent/chatito.vim | 32 +++ runtime/indent/gyp.vim | 7 + runtime/indent/hare.vim | 138 +++++++++++++ runtime/indent/solidity.vim | 442 +++++++++++++++++++++++++++++++++++++++++ runtime/indent/vue.vim | 12 ++ runtime/syntax/chatito.vim | 62 ++++++ runtime/syntax/desktop.vim | 6 +- runtime/syntax/gyp.vim | 49 +++++ runtime/syntax/hare.vim | 133 +++++++++++++ runtime/syntax/help.vim | 3 +- runtime/syntax/hlsplaylist.vim | 120 +++++++++++ runtime/syntax/plsql.vim | 68 ++++--- runtime/syntax/solidity.vim | 173 ++++++++++++++++ runtime/syntax/vim.vim | 2 +- 25 files changed, 1339 insertions(+), 40 deletions(-) create mode 100644 runtime/compiler/hare.vim create mode 100644 runtime/ftplugin/chatito.vim create mode 100644 runtime/ftplugin/gyp.vim create mode 100644 runtime/ftplugin/hare.vim create mode 100644 runtime/ftplugin/heex.vim create mode 100644 runtime/indent/chatito.vim create mode 100644 runtime/indent/gyp.vim create mode 100644 runtime/indent/hare.vim create mode 100644 runtime/indent/solidity.vim create mode 100644 runtime/indent/vue.vim create mode 100644 runtime/syntax/chatito.vim create mode 100644 runtime/syntax/gyp.vim create mode 100644 runtime/syntax/hare.vim create mode 100644 runtime/syntax/hlsplaylist.vim create mode 100644 runtime/syntax/solidity.vim diff --git a/runtime/compiler/hare.vim b/runtime/compiler/hare.vim new file mode 100644 index 0000000000..c0fa68cc00 --- /dev/null +++ b/runtime/compiler/hare.vim @@ -0,0 +1,31 @@ +" Vim compiler file +" Compiler: Hare Compiler +" Maintainer: Amelia Clarke +" Last Change: 2022-09-21 + +if exists("g:current_compiler") + finish +endif +let g:current_compiler = "hare" + +let s:cpo_save = &cpo +set cpo&vim + +if exists(':CompilerSet') != 2 + command -nargs=* CompilerSet setlocal +endif + +if filereadable("Makefile") || filereadable("makefile") + CompilerSet makeprg=make +else + CompilerSet makeprg=hare\ build +endif + +CompilerSet errorformat= + \Error\ %f:%l:%c:\ %m, + \Syntax\ error:\ %.%#\ at\ %f:%l:%c\\,\ %m, + \%-G%.%# + +let &cpo = s:cpo_save +unlet s:cpo_save +" vim: tabstop=2 shiftwidth=2 expandtab diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index e5d22de748..cbc92a8cb5 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -1660,7 +1660,8 @@ The valid escape sequences are If the first two characters of an escape sequence are "q-" (for example, ) then the value is quoted in such a way as to make it a valid value for use in an expression. This uses the argument as one single value. -When there is no argument is an empty string. +When there is no argument is an empty string. See the +|q-args-example| below. ** To allow commands to pass their arguments on to a user-defined function, there is a special form ("function args"). This splits the command @@ -1670,7 +1671,7 @@ See the Mycmd example below. If no arguments are given is removed. To embed whitespace into an argument of , prepend a backslash. replaces every pair of backslashes (\\) with one backslash. A backslash followed by a character other than white space or a backslash -remains unmodified. Overview: +remains unmodified. Also see |f-args-example| below. Overview: command ~ XX ab "ab" @@ -1684,7 +1685,8 @@ remains unmodified. Overview: XX a\\\\b 'a\\b' XX a\\\\ b 'a\\', 'b' -Examples > + +Examples for user commands: > " Delete everything after here to the end :com Ddel +,$d @@ -1700,7 +1702,8 @@ Examples > " Count the number of lines in the range :com! -range -nargs=0 Lines echo - + 1 "lines" - " Call a user function (example of ) +< *f-args-example* +Call a user function (example of ) > :com -nargs=* Mycmd call Myfunc() When executed as: > @@ -1708,7 +1711,8 @@ When executed as: > This will invoke: > :call Myfunc("arg1","arg2") - :" A more substantial example +< *q-args-example* +A more substantial example: > :function Allargs(command) : let i = 0 : while i < argc() diff --git a/runtime/doc/motion.txt b/runtime/doc/motion.txt index 77b6b83289..8ff4ed4f96 100644 --- a/runtime/doc/motion.txt +++ b/runtime/doc/motion.txt @@ -1172,7 +1172,7 @@ g; Go to [count] older position in change list. (not a motion command) *g,* *E663* -g, Go to [count] newer cursor position in change list. +g, Go to [count] newer position in change list. Just like |g;| but in the opposite direction. (not a motion command) diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt index 0b316b4727..b0332269d7 100644 --- a/runtime/doc/repeat.txt +++ b/runtime/doc/repeat.txt @@ -83,7 +83,8 @@ pattern and do not match another pattern: > This first finds all lines containing "found", but only executes {cmd} when there is no match for "notfound". -To execute a non-Ex command, you can use the `:normal` command: > +Any Ex command can be used, see |ex-cmd-index|. To execute a Normal mode +command, you can use the `:normal` command: > :g/pat/normal {commands} Make sure that {commands} ends with a whole command, otherwise Vim will wait for you to type the rest of the command for each match. The screen will not diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index 83f19db4a9..c97376a629 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -3118,7 +3118,7 @@ The default is to use the twice sh_minlines. Set it to a smaller number to speed up displaying. The disadvantage is that highlight errors may appear. syntax/sh.vim tries to flag certain problems as errors; usually things like -extra "]"s, "done"s, "fi"s, etc. If you find the error handling problematic +unmatched "]", "done", "fi", etc. If you find the error handling problematic for your purposes, you may suppress such error highlighting by putting the following line in your .vimrc: > diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 204bf1865f..475dafb9e9 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1,7 +1,7 @@ " Vim support file to detect file types " " Maintainer: Bram Moolenaar -" Last Change: 2022 Sep 11 +" Last Change: 2022 Sep 27 " Only run this if enabled if !exists("do_legacy_filetype") diff --git a/runtime/ftplugin/chatito.vim b/runtime/ftplugin/chatito.vim new file mode 100644 index 0000000000..af212e9581 --- /dev/null +++ b/runtime/ftplugin/chatito.vim @@ -0,0 +1,15 @@ +" Vim filetype plugin +" Language: Chatito +" Maintainer: ObserverOfTime +" Last Change: 2022 Sep 19 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +setlocal comments=:#,:// commentstring=#\ %s +" indent of 4 spaces is mandated by the spec +setlocal expandtab softtabstop=4 shiftwidth=4 + +let b:undo_ftplugin = 'setl com< cms< et< sts< sw<' diff --git a/runtime/ftplugin/elixir.vim b/runtime/ftplugin/elixir.vim index c423c2acb7..50f63673dc 100644 --- a/runtime/ftplugin/elixir.vim +++ b/runtime/ftplugin/elixir.vim @@ -1,7 +1,7 @@ " Elixir filetype plugin " Language: Elixir " Maintainer: Mitchell Hanberg -" Last Change: 2022 August 10 +" Last Change: 2022 Sep 20 if exists("b:did_ftplugin") finish @@ -23,7 +23,11 @@ if exists('loaded_matchit') && !exists('b:match_words') \ ',{:},\[:\],(:)' endif +setlocal shiftwidth=2 softtabstop=2 expandtab iskeyword+=!,? +setlocal comments=:# setlocal commentstring=#\ %s +let b:undo_ftplugin = 'setlocal sw< sts< et< isk< com< cms<' + let &cpo = s:save_cpo unlet s:save_cpo diff --git a/runtime/ftplugin/gyp.vim b/runtime/ftplugin/gyp.vim new file mode 100644 index 0000000000..becfcadb6d --- /dev/null +++ b/runtime/ftplugin/gyp.vim @@ -0,0 +1,14 @@ +" Vim filetype plugin +" Language: GYP +" Maintainer: ObserverOfTime +" Last Change: 2022 Sep 27 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +setlocal formatoptions-=t +setlocal commentstring=#\ %s comments=b:#,fb:- + +let b:undo_ftplugin = 'setlocal fo< cms< com<' diff --git a/runtime/ftplugin/hare.vim b/runtime/ftplugin/hare.vim new file mode 100644 index 0000000000..bb10daf38c --- /dev/null +++ b/runtime/ftplugin/hare.vim @@ -0,0 +1,27 @@ +" Vim filetype plugin +" Language: Hare +" Maintainer: Amelia Clarke +" Previous Maintainer: Drew DeVault +" Last Updated: 2022-09-21 + +" Only do this when not done yet for this buffer +if exists('b:did_ftplugin') + finish +endif + +" Don't load another plugin for this buffer +let b:did_ftplugin = 1 + +setlocal noexpandtab +setlocal tabstop=8 +setlocal shiftwidth=0 +setlocal softtabstop=0 +setlocal textwidth=80 +setlocal commentstring=//\ %s + +" Set 'formatoptions' to break comment lines but not other lines, +" and insert the comment leader when hitting or using "o". +setlocal fo-=t fo+=croql + +compiler hare +" vim: tabstop=2 shiftwidth=2 expandtab diff --git a/runtime/ftplugin/heex.vim b/runtime/ftplugin/heex.vim new file mode 100644 index 0000000000..5274d59fbf --- /dev/null +++ b/runtime/ftplugin/heex.vim @@ -0,0 +1,16 @@ +" Elixir filetype plugin +" Language: HEEx +" Maintainer: Mitchell Hanberg +" Last Change: 2022 Sep 21 + +if exists("b:did_ftplugin") + finish +endif +let b:did_ftplugin = 1 + +setlocal shiftwidth=2 softtabstop=2 expandtab + +setlocal comments=:<%!-- +setlocal commentstring=<%!--\ %s\ --%> + +let b:undo_ftplugin = 'set sw< sts< et< com< cms<' diff --git a/runtime/indent/chatito.vim b/runtime/indent/chatito.vim new file mode 100644 index 0000000000..1ff5e9e3f1 --- /dev/null +++ b/runtime/indent/chatito.vim @@ -0,0 +1,32 @@ +" Vim indent file +" Language: Chatito +" Maintainer: ObserverOfTime +" Last Change: 2022 Sep 20 + +if exists('b:did_indent') + finish +endif +let b:did_indent = 1 + +setlocal indentexpr=GetChatitoIndent() +setlocal indentkeys=o,O,*,0#,!^F + +let b:undo_indent = 'setl inde< indk<' + +if exists('*GetChatitoIndent') + finish +endif + +function GetChatitoIndent() + let l:prev = v:lnum - 1 + if getline(prevnonblank(l:prev)) =~# '^[~%@]\[' + " shift indent after definitions + return shiftwidth() + elseif getline(l:prev) !~# '^\s*$' + " maintain indent in sentences + return indent(l:prev) + else + " reset indent after a blank line + return 0 + end +endfunction diff --git a/runtime/indent/gyp.vim b/runtime/indent/gyp.vim new file mode 100644 index 0000000000..c3980ac568 --- /dev/null +++ b/runtime/indent/gyp.vim @@ -0,0 +1,7 @@ +" Vim indent file +" Language: GYP +" Maintainer: ObserverOfTime +" Last Change: 2022 Sep 27 + +" JSON indent works well +runtime! indent/json.vim diff --git a/runtime/indent/hare.vim b/runtime/indent/hare.vim new file mode 100644 index 0000000000..bc4fea4e61 --- /dev/null +++ b/runtime/indent/hare.vim @@ -0,0 +1,138 @@ +" Vim indent file +" Language: Hare +" Maintainer: Amelia Clarke +" Last Change: 2022 Sep 22 + +if exists("b:did_indent") + finish +endif +let b:did_indent = 1 + +if !has("cindent") || !has("eval") + finish +endif + +setlocal cindent + +" L0 -> don't deindent labels +" (s -> use one indent after a trailing ( +" m1 -> if ) starts a line, indent it the same as its matching ( +" ks -> add an extra indent to extra lines in an if expression or for expression +" j1 -> indent code inside {} one level when in parentheses +" J1 -> see j1 +" *0 -> don't search for unclosed block comments +" #1 -> don't deindent lines that begin with # +setlocal cinoptions=L0,(s,m1,ks,j1,J1,*0,#1 + +" Controls which keys reindent the current line. +" 0{ -> { at beginning of line +" 0} -> } at beginning of line +" 0) -> ) at beginning of line +" 0] -> ] at beginning of line +" !^F -> (not inserted) +" o -> or `o` command +" O -> `O` command +" e -> else +" 0=case -> case +setlocal indentkeys=0{,0},0),0],!^F,o,O,e,0=case + +setlocal cinwords=if,else,for,switch,match + +setlocal indentexpr=GetHareIndent() + +function! FloorCindent(lnum) + return cindent(a:lnum) / shiftwidth() * shiftwidth() +endfunction + +function! GetHareIndent() + let line = getline(v:lnum) + let prevlnum = prevnonblank(v:lnum - 1) + let prevline = getline(prevlnum) + let prevprevline = getline(prevnonblank(prevlnum - 1)) + + " This is all very hacky and imperfect, but it's tough to do much better when + " working with regex-based indenting rules. + + " If the previous line ended with =, indent by one shiftwidth. + if prevline =~# '\v\=\s*(//.*)?$' + return indent(prevlnum) + shiftwidth() + endif + + " If the previous line ended in a semicolon and the line before that ended + " with =, deindent by one shiftwidth. + if prevline =~# '\v;\s*(//.*)?$' && prevprevline =~# '\v\=\s*(//.*)?$' + return indent(prevlnum) - shiftwidth() + endif + + " TODO: The following edge-case is still indented incorrectly: + " case => + " if (foo) { + " bar; + " }; + " | // cursor is incorrectly deindented by one shiftwidth. + " + " This only happens if the {} block is the first statement in the case body. + " If `case` is typed, the case will also be incorrectly deindented by one + " shiftwidth. Are you having fun yet? + + " Deindent cases. + if line =~# '\v^\s*case' + " If the previous line was also a case, don't do any special indenting. + if prevline =~# '\v^\s*case' + return indent(prevlnum) + end + + " If the previous line was a multiline case, deindent by one shiftwidth. + if prevline =~# '\v\=\>\s*(//.*)?$' + return indent(prevlnum) - shiftwidth() + endif + + " If the previous line started a block, deindent by one shiftwidth. + " This handles the first case in a switch/match block. + if prevline =~# '\v\{\s*(//.*)?$' + return FloorCindent(v:lnum) - shiftwidth() + end + + " If the previous line ended in a semicolon and the line before that wasn't + " a case, deindent by one shiftwidth. + if prevline =~# '\v;\s*(//.*)?$' && prevprevline !~# '\v\=\>\s*(//.*)?$' + return FloorCindent(v:lnum) - shiftwidth() + end + + let l:indent = FloorCindent(v:lnum) + + " If a normal cindent would indent the same amount as the previous line, + " deindent by one shiftwidth. This fixes some issues with `case let` blocks. + if l:indent == indent(prevlnum) + return l:indent - shiftwidth() + endif + + " Otherwise, do a normal cindent. + return l:indent + endif + + " Don't indent an extra shiftwidth for cases which span multiple lines. + if prevline =~# '\v\=\>\s*(//.*)?$' && prevline !~# '\v^\s*case\W' + return indent(prevlnum) + endif + + " Indent the body of a case. + " If the previous line ended in a semicolon and the line before that was a + " case, don't do any special indenting. + if prevline =~# '\v;\s*(//.*)?$' && prevprevline =~# '\v\=\>\s*(//.*)?$' && line !~# '\v^\s*}' + return indent(prevlnum) + endif + + let l:indent = FloorCindent(v:lnum) + + " If the previous line was a case and a normal cindent wouldn't indent, indent + " an extra shiftwidth. + if prevline =~# '\v\=\>\s*(//.*)?$' && l:indent == indent(prevlnum) + return l:indent + shiftwidth() + endif + + " If everything above is false, do a normal cindent. + return l:indent +endfunction + +" vim: tabstop=2 shiftwidth=2 expandtab diff --git a/runtime/indent/solidity.vim b/runtime/indent/solidity.vim new file mode 100644 index 0000000000..caed726c0a --- /dev/null +++ b/runtime/indent/solidity.vim @@ -0,0 +1,442 @@ +" Vim indent file +" Language: Solidity +" Acknowledgement: Based off of vim-javascript +" Maintainer: Cothi (jiungdev@gmail.com) +" Original Author: tomlion (https://github.com/tomlion/vim-solidity) +" Last Changed: 2022 Sep 27 +" +" 0. Initialization {{{1 +" ================= + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") + finish +endif +let b:did_indent = 1 + +setlocal nosmartindent + +" Now, set up our indentation expression and keys that trigger it. +setlocal indentexpr=GetSolidityIndent() +setlocal indentkeys=0{,0},0),0],0\,,!^F,o,O,e + +" Only define the function once. +if exists("*GetSolidityIndent") + finish +endif + +let s:cpo_save = &cpo +set cpo&vim + +" 1. Variables {{{1 +" ============ + +let s:js_keywords = '^\s*\(break\|case\|catch\|continue\|debugger\|default\|delete\|do\|else\|finally\|for\|function\|if\|in\|instanceof\|new\|return\|switch\|this\|throw\|try\|typeof\|var\|void\|while\|with\)' + +" Regex of syntax group names that are or delimit string or are comments. +let s:syng_strcom = 'string\|regex\|comment\c' + +" Regex of syntax group names that are strings. +let s:syng_string = 'regex\c' + +" Regex of syntax group names that are strings or documentation. +let s:syng_multiline = 'comment\c' + +" Regex of syntax group names that are line comment. +let s:syng_linecom = 'linecomment\c' + +" Expression used to check whether we should skip a match with searchpair(). +let s:skip_expr = "synIDattr(synID(line('.'),col('.'),1),'name') =~ '".s:syng_strcom."'" + +let s:line_term = '\s*\%(\%(\/\/\).*\)\=$' + +" Regex that defines continuation lines, not including (, {, or [. +let s:continuation_regex = '\%([\\*+/.:]\|\%(<%\)\@[^{;]*' . s:line_term + +" Regex that defines blocks. +let s:block_regex = '\%([{[]\)\s*\%(|\%([*@]\=\h\w*,\=\s*\)\%(,\s*[*@]\=\h\w*\)*|\)\=' . s:line_term + +let s:var_stmt = '^\s*var' + +let s:comma_first = '^\s*,' +let s:comma_last = ',\s*$' + +let s:ternary = '^\s\+[?|:]' +let s:ternary_q = '^\s\+?' + +" 2. Auxiliary Functions {{{1 +" ====================== + +" Check if the character at lnum:col is inside a string, comment, or is ascii. +function s:IsInStringOrComment(lnum, col) + return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_strcom +endfunction + +" Check if the character at lnum:col is inside a string. +function s:IsInString(lnum, col) + return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_string +endfunction + +" Check if the character at lnum:col is inside a multi-line comment. +function s:IsInMultilineComment(lnum, col) + return !s:IsLineComment(a:lnum, a:col) && synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_multiline +endfunction + +" Check if the character at lnum:col is a line comment. +function s:IsLineComment(lnum, col) + return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_linecom +endfunction + +" Find line above 'lnum' that isn't empty, in a comment, or in a string. +function s:PrevNonBlankNonString(lnum) + let in_block = 0 + let lnum = prevnonblank(a:lnum) + while lnum > 0 + " Go in and out of blocks comments as necessary. + " If the line isn't empty (with opt. comment) or in a string, end search. + let line = getline(lnum) + if line =~ '/\*' + if in_block + let in_block = 0 + else + break + endif + elseif !in_block && line =~ '\*/' + let in_block = 1 + elseif !in_block && line !~ '^\s*\%(//\).*$' && !(s:IsInStringOrComment(lnum, 1) && s:IsInStringOrComment(lnum, strlen(line))) + break + endif + let lnum = prevnonblank(lnum - 1) + endwhile + return lnum +endfunction + +" Find line above 'lnum' that started the continuation 'lnum' may be part of. +function s:GetMSL(lnum, in_one_line_scope) + " Start on the line we're at and use its indent. + let msl = a:lnum + let lnum = s:PrevNonBlankNonString(a:lnum - 1) + while lnum > 0 + " If we have a continuation line, or we're in a string, use line as MSL. + " Otherwise, terminate search as we have found our MSL already. + let line = getline(lnum) + let col = match(line, s:msl_regex) + 1 + if (col > 0 && !s:IsInStringOrComment(lnum, col)) || s:IsInString(lnum, strlen(line)) + let msl = lnum + else + " Don't use lines that are part of a one line scope as msl unless the + " flag in_one_line_scope is set to 1 + " + if a:in_one_line_scope + break + end + let msl_one_line = s:Match(lnum, s:one_line_scope_regex) + if msl_one_line == 0 + break + endif + endif + let lnum = s:PrevNonBlankNonString(lnum - 1) + endwhile + return msl +endfunction + +function s:RemoveTrailingComments(content) + let single = '\/\/\(.*\)\s*$' + let multi = '\/\*\(.*\)\*\/\s*$' + return substitute(substitute(a:content, single, '', ''), multi, '', '') +endfunction + +" Find if the string is inside var statement (but not the first string) +function s:InMultiVarStatement(lnum) + let lnum = s:PrevNonBlankNonString(a:lnum - 1) + +" let type = synIDattr(synID(lnum, indent(lnum) + 1, 0), 'name') + + " loop through previous expressions to find a var statement + while lnum > 0 + let line = getline(lnum) + + " if the line is a js keyword + if (line =~ s:js_keywords) + " check if the line is a var stmt + " if the line has a comma first or comma last then we can assume that we + " are in a multiple var statement + if (line =~ s:var_stmt) + return lnum + endif + + " other js keywords, not a var + return 0 + endif + + let lnum = s:PrevNonBlankNonString(lnum - 1) + endwhile + + " beginning of program, not a var + return 0 +endfunction + +" Find line above with beginning of the var statement or returns 0 if it's not +" this statement +function s:GetVarIndent(lnum) + let lvar = s:InMultiVarStatement(a:lnum) + let prev_lnum = s:PrevNonBlankNonString(a:lnum - 1) + + if lvar + let line = s:RemoveTrailingComments(getline(prev_lnum)) + + " if the previous line doesn't end in a comma, return to regular indent + if (line !~ s:comma_last) + return indent(prev_lnum) - &sw + else + return indent(lvar) + &sw + endif + endif + + return -1 +endfunction + + +" Check if line 'lnum' has more opening brackets than closing ones. +function s:LineHasOpeningBrackets(lnum) + let open_0 = 0 + let open_2 = 0 + let open_4 = 0 + let line = getline(a:lnum) + let pos = match(line, '[][(){}]', 0) + while pos != -1 + if !s:IsInStringOrComment(a:lnum, pos + 1) + let idx = stridx('(){}[]', line[pos]) + if idx % 2 == 0 + let open_{idx} = open_{idx} + 1 + else + let open_{idx - 1} = open_{idx - 1} - 1 + endif + endif + let pos = match(line, '[][(){}]', pos + 1) + endwhile + return (open_0 > 0) . (open_2 > 0) . (open_4 > 0) +endfunction + +function s:Match(lnum, regex) + let col = match(getline(a:lnum), a:regex) + 1 + return col > 0 && !s:IsInStringOrComment(a:lnum, col) ? col : 0 +endfunction + +function s:IndentWithContinuation(lnum, ind, width) + " Set up variables to use and search for MSL to the previous line. + let p_lnum = a:lnum + let lnum = s:GetMSL(a:lnum, 1) + let line = getline(lnum) + + " If the previous line wasn't a MSL and is continuation return its indent. + " TODO: the || s:IsInString() thing worries me a bit. + if p_lnum != lnum + if s:Match(p_lnum,s:continuation_regex)||s:IsInString(p_lnum,strlen(line)) + return a:ind + endif + endif + + " Set up more variables now that we know we aren't continuation bound. + let msl_ind = indent(lnum) + + " If the previous line ended with [*+/.-=], start a continuation that + " indents an extra level. + if s:Match(lnum, s:continuation_regex) + if lnum == p_lnum + return msl_ind + a:width + else + return msl_ind + endif + endif + + return a:ind +endfunction + +function s:InOneLineScope(lnum) + let msl = s:GetMSL(a:lnum, 1) + if msl > 0 && s:Match(msl, s:one_line_scope_regex) + return msl + endif + return 0 +endfunction + +function s:ExitingOneLineScope(lnum) + let msl = s:GetMSL(a:lnum, 1) + if msl > 0 + " if the current line is in a one line scope .. + if s:Match(msl, s:one_line_scope_regex) + return 0 + else + let prev_msl = s:GetMSL(msl - 1, 1) + if s:Match(prev_msl, s:one_line_scope_regex) + return prev_msl + endif + endif + endif + return 0 +endfunction + +" 3. GetSolidityIndent Function {{{1 +" ========================= + +function GetSolidityIndent() + " 3.1. Setup {{{2 + " ---------- + + " Set up variables for restoring position in file. Could use v:lnum here. + let vcol = col('.') + + " 3.2. Work on the current line {{{2 + " ----------------------------- + + let ind = -1 + " Get the current line. + let line = getline(v:lnum) + " previous nonblank line number + let prevline = prevnonblank(v:lnum - 1) + + " If we got a closing bracket on an empty line, find its match and indent + " according to it. For parentheses we indent to its column - 1, for the + " others we indent to the containing line's MSL's level. Return -1 if fail. + let col = matchend(line, '^\s*[],})]') + if col > 0 && !s:IsInStringOrComment(v:lnum, col) + call cursor(v:lnum, col) + + let lvar = s:InMultiVarStatement(v:lnum) + if lvar + let prevline_contents = s:RemoveTrailingComments(getline(prevline)) + + " check for comma first + if (line[col - 1] =~ ',') + " if the previous line ends in comma or semicolon don't indent + if (prevline_contents =~ '[;,]\s*$') + return indent(s:GetMSL(line('.'), 0)) + " get previous line indent, if it's comma first return prevline indent + elseif (prevline_contents =~ s:comma_first) + return indent(prevline) + " otherwise we indent 1 level + else + return indent(lvar) + &sw + endif + endif + endif + + + let bs = strpart('(){}[]', stridx(')}]', line[col - 1]) * 2, 2) + if searchpair(escape(bs[0], '\['), '', bs[1], 'bW', s:skip_expr) > 0 + if line[col-1]==')' && col('.') != col('$') - 1 + let ind = virtcol('.')-1 + else + let ind = indent(s:GetMSL(line('.'), 0)) + endif + endif + return ind + endif + + " If the line is comma first, dedent 1 level + if (getline(prevline) =~ s:comma_first) + return indent(prevline) - &sw + endif + + if (line =~ s:ternary) + if (getline(prevline) =~ s:ternary_q) + return indent(prevline) + else + return indent(prevline) + &sw + endif + endif + + " If we are in a multi-line comment, cindent does the right thing. + if s:IsInMultilineComment(v:lnum, 1) && !s:IsLineComment(v:lnum, 1) + return cindent(v:lnum) + endif + + " Check for multiple var assignments +" let var_indent = s:GetVarIndent(v:lnum) +" if var_indent >= 0 +" return var_indent +" endif + + " 3.3. Work on the previous line. {{{2 + " ------------------------------- + + " If the line is empty and the previous nonblank line was a multi-line + " comment, use that comment's indent. Deduct one char to account for the + " space in ' */'. + if line =~ '^\s*$' && s:IsInMultilineComment(prevline, 1) + return indent(prevline) - 1 + endif + + " Find a non-blank, non-multi-line string line above the current line. + let lnum = s:PrevNonBlankNonString(v:lnum - 1) + + " If the line is empty and inside a string, use the previous line. + if line =~ '^\s*$' && lnum != prevline + return indent(prevnonblank(v:lnum)) + endif + + " At the start of the file use zero indent. + if lnum == 0 + return 0 + endif + + " Set up variables for current line. + let line = getline(lnum) + let ind = indent(lnum) + + " If the previous line ended with a block opening, add a level of indent. + if s:Match(lnum, s:block_regex) + return indent(s:GetMSL(lnum, 0)) + &sw + endif + + " If the previous line contained an opening bracket, and we are still in it, + " add indent depending on the bracket type. + if line =~ '[[({]' + let counts = s:LineHasOpeningBrackets(lnum) + if counts[0] == '1' && searchpair('(', '', ')', 'bW', s:skip_expr) > 0 + if col('.') + 1 == col('$') + return ind + &sw + else + return virtcol('.') + endif + elseif counts[1] == '1' || counts[2] == '1' + return ind + &sw + else + call cursor(v:lnum, vcol) + end + endif + + " 3.4. Work on the MSL line. {{{2 + " -------------------------- + + let ind_con = ind + let ind = s:IndentWithContinuation(lnum, ind_con, &sw) + + " }}}2 + " + " + let ols = s:InOneLineScope(lnum) + if ols > 0 + let ind = ind + &sw + else + let ols = s:ExitingOneLineScope(lnum) + while ols > 0 && ind > 0 + let ind = ind - &sw + let ols = s:InOneLineScope(ols - 1) + endwhile + endif + + return ind +endfunction + +" }}}1 + +let &cpo = s:cpo_save +unlet s:cpo_save diff --git a/runtime/indent/vue.vim b/runtime/indent/vue.vim new file mode 100644 index 0000000000..7ff623b3d1 --- /dev/null +++ b/runtime/indent/vue.vim @@ -0,0 +1,12 @@ +" Vim indent file placeholder +" Language: Vue +" Maintainer: None, please volunteer if you have a real Vue indent script + +" Only load this indent file when no other was loaded. +if exists("b:did_indent") + finish +endif +let b:did_indent = 1 + +" Html comes closest +runtime! indent/html.vim diff --git a/runtime/syntax/chatito.vim b/runtime/syntax/chatito.vim new file mode 100644 index 0000000000..d89307cf06 --- /dev/null +++ b/runtime/syntax/chatito.vim @@ -0,0 +1,62 @@ +" Vim syntax file +" Language: Chatito +" Maintainer: ObserverOfTime +" Filenames: *.chatito +" Last Change: 2022 Sep 19 + +if exists('b:current_syntax') + finish +endif + +" Comment +syn keyword chatitoTodo contained TODO FIXME XXX +syn match chatitoComment /^#.*/ contains=chatitoTodo,@Spell +syn match chatitoComment +^//.*+ contains=chatitoTodo,@Spell + +" Import +syn match chatitoImport /^import \+.*$/ transparent contains=chatitoImportKeyword,chatitoImportFile +syn keyword chatitoImportKeyword import contained nextgroup=chatitoImportFile +syn match chatitoImportFile /.*$/ contained skipwhite + +" Intent +syn match chatitoIntent /^%\[[^\]?]\+\]\((.\+)\)\=$/ contains=chatitoArgs + +" Slot +syn match chatitoSlot /^@\[[^\]?#]\+\(#[^\]?#]\+\)\=\]\((.\+)\)\=$/ contains=chatitoArgs,chatitoVariation +syn match chatitoSlot /@\[[^\]?#]\+\(#[^\]?#]\+\)\=?\=\]/ contained contains=chatitoOpt,chatitoVariation + +" Alias +syn match chatitoAlias /^\~\[[^\]?]\+\]\=$/ +syn match chatitoAlias /\~\[[^\]?]\+?\=\]/ contained contains=chatitoOpt + +" Probability +syn match chatitoProbability /\*\[\d\+\(\.\d\+\)\=%\=\]/ contained + +" Optional +syn match chatitoOpt '?' contained + +" Arguments +syn match chatitoArgs /(.\+)/ contained + +" Variation +syn match chatitoVariation /#[^\]?#]\+/ contained + +" Value +syn match chatitoValue /^ \{4\}\zs.\+$/ contains=chatitoProbability,chatitoSlot,chatitoAlias,@Spell + +" Errors +syn match chatitoError /^\t/ + +hi def link chatitoAlias String +hi def link chatitoArgs Special +hi def link chatitoComment Comment +hi def link chatitoError Error +hi def link chatitoImportKeyword Include +hi def link chatitoIntent Statement +hi def link chatitoOpt SpecialChar +hi def link chatitoProbability Number +hi def link chatitoSlot Identifier +hi def link chatitoTodo Todo +hi def link chatitoVariation Special + +let b:current_syntax = 'chatito' diff --git a/runtime/syntax/desktop.vim b/runtime/syntax/desktop.vim index 2c1102238d..461ba855b9 100644 --- a/runtime/syntax/desktop.vim +++ b/runtime/syntax/desktop.vim @@ -3,7 +3,7 @@ " Filenames: *.desktop, *.directory " Maintainer: Eisuke Kawashima ( e.kawaschima+vim AT gmail.com ) " Previous Maintainer: Mikolaj Machowski ( mikmach AT wp DOT pl ) -" Last Change: 2020-06-11 +" Last Change: 2022 Sep 22 " Version Info: desktop.vim 1.5 " References: " - https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.5.html (2020-04-27) @@ -60,10 +60,10 @@ syn match dtLocaleSuffix " Boolean Value {{{2 syn match dtBoolean - \ /^\%(DBusActivatable\|Hidden\|NoDisplay\|PrefersNonDefaultGPU\|StartupNotify\|Terminal\)\s*=\s*\%(true\|false\)/ + \ /^\%(DBusActivatable\|Hidden\|NoDisplay\|PrefersNonDefaultGPU\|SingleMainWindow\|StartupNotify\|Terminal\)\s*=\s*\%(true\|false\)/ \ contains=dtBooleanKey,dtDelim,dtBooleanValue transparent syn keyword dtBooleanKey - \ DBusActivatable Hidden NoDisplay PrefersNonDefaultGPU StartupNotify Terminal + \ DBusActivatable Hidden NoDisplay PrefersNonDefaultGPU SingleMainWindow StartupNotify Terminal \ contained nextgroup=dtDelim if s:desktop_enable_kde diff --git a/runtime/syntax/gyp.vim b/runtime/syntax/gyp.vim new file mode 100644 index 0000000000..14c07b8726 --- /dev/null +++ b/runtime/syntax/gyp.vim @@ -0,0 +1,49 @@ +" Vim syntax file +" Language: GYP +" Maintainer: ObserverOfTime +" Filenames: *.gyp,*.gypi +" Last Change: 2022 Sep 27 + +if !exists('g:main_syntax') + if exists('b:current_syntax') && b:current_syntax ==# 'gyp' + finish + endif + let g:main_syntax = 'gyp' +endif + +" Based on JSON syntax +runtime! syntax/json.vim + +" Single quotes are allowed +syn clear jsonStringSQError + +syn match jsonKeywordMatch /'\([^']\|\\\'\)\+'[[:blank:]\r\n]*\:/ contains=jsonKeyword +if has('conceal') && (!exists('g:vim_json_conceal') || g:vim_json_conceal==1) + syn region jsonKeyword matchgroup=jsonQuote start=/'/ end=/'\ze[[:blank:]\r\n]*\:/ concealends contained +else + syn region jsonKeyword matchgroup=jsonQuote start=/'/ end=/'\ze[[:blank:]\r\n]*\:/ contained +endif + +syn match jsonStringMatch /'\([^']\|\\\'\)\+'\ze[[:blank:]\r\n]*[,}\]]/ contains=jsonString +if has('conceal') && (!exists('g:vim_json_conceal') || g:vim_json_conceal==1) + syn region jsonString oneline matchgroup=jsonQuote start=/'/ skip=/\\\\\|\\'/ end=/'/ concealends contains=jsonEscape contained +else + syn region jsonString oneline matchgroup=jsonQuote start=/'/ skip=/\\\\\|\\'/ end=/'/ contains=jsonEscape contained +endif + +" Trailing commas are allowed +if !exists('g:vim_json_warnings') || g:vim_json_warnings==1 + syn clear jsonTrailingCommaError +endif + +" Python-style comments are allowed +syn match jsonComment /#.*$/ contains=jsonTodo,@Spell +syn keyword jsonTodo FIXME NOTE TODO XXX TBD contained + +hi def link jsonComment Comment +hi def link jsonTodo Todo + +let b:current_syntax = 'gyp' +if g:main_syntax ==# 'gyp' + unlet g:main_syntax +endif diff --git a/runtime/syntax/hare.vim b/runtime/syntax/hare.vim new file mode 100644 index 0000000000..07cf33fb11 --- /dev/null +++ b/runtime/syntax/hare.vim @@ -0,0 +1,133 @@ +" PRELUDE {{{1 +" Vim syntax file +" Language: Hare +" Maintainer: Amelia Clarke +" Last Change: 2022-09-21 + +if exists("b:current_syntax") + finish +endif +let b:current_syntax = "hare" + +" SYNTAX {{{1 +syn case match + +" KEYWORDS {{{2 +syn keyword hareConditional if else match switch +syn keyword hareKeyword break continue return yield +syn keyword hareKeyword defer +syn keyword hareKeyword fn +syn keyword hareKeyword let +syn keyword hareLabel case +syn keyword hareOperator as is +syn keyword hareRepeat for +syn keyword hareStorageClass const def export nullable static +syn keyword hareStructure enum struct union +syn keyword hareTypedef type + +" C ABI. +syn keyword hareKeyword vastart vaarg vaend + +" BUILTINS {{{2 +syn keyword hareBuiltin abort +syn keyword hareBuiltin alloc free +syn keyword hareBuiltin append delete insert +syn keyword hareBuiltin assert +syn keyword hareBuiltin len offset + +" TYPES {{{2 +syn keyword hareType bool +syn keyword hareType char str +syn keyword hareType f32 f64 +syn keyword hareType u8 u16 u32 u64 i8 i16 i32 i64 +syn keyword hareType uint int +syn keyword hareType rune +syn keyword hareType uintptr +syn keyword hareType void + +" C ABI. +syn keyword hareType valist + +" LITERALS {{{2 +syn keyword hareBoolean true false +syn keyword hareNull null + +" Number literals. +syn match hareNumber "\v(\.@1" display +syn match hareNumber "\v(\.@1" display +syn match hareNumber "\v(\.@1" display +syn match hareNumber "\v(\.@1" display + +" Floating-point number literals. +syn match hareFloat "\v<\d+\.\d+([Ee][+-]?\d+)?(f32|f64)?>" display +syn match hareFloat "\v<\d+([Ee][+-]?\d+)?(f32|f64)>" display + +" String and rune literals. +syn match hareEscape "\\[\\'"0abfnrtv]" contained display +syn match hareEscape "\v\\(x\x{2}|u\x{4}|U\x{8})" contained display +syn match hareFormat "\v\{\d*(\%\d*|(:[ 0+-]?\d*(\.\d+)?[Xbox]?))?}" contained display +syn match hareFormat "\({{\|}}\)" contained display +syn region hareRune start="'" end="'\|$" skip="\\'" contains=hareEscape display extend +syn region hareString start=+"+ end=+"\|$+ skip=+\\"+ contains=hareEscape,hareFormat display extend +syn region hareString start="`" end="`\|$" contains=hareFormat display + +" MISCELLANEOUS {{{2 +syn keyword hareTodo FIXME TODO XXX contained + +" Attributes. +syn match hareAttribute "@[a-z]*" + +" Blocks. +syn region hareBlock start="{" end="}" fold transparent + +" Comments. +syn region hareComment start="//" end="$" contains=hareCommentDoc,hareTodo,@Spell display keepend +syn region hareCommentDoc start="\[\[" end="]]\|\ze\_s" contained display + +" The size keyword can be either a builtin or a type. +syn match hareBuiltin "\v\ze(\_s*//.*\_$)*\_s*\(" contains=hareComment +syn match hareType "\v((\_s*//.*\_$)*\_s*\()@!" contains=hareComment + +" Trailing whitespace. +syn match hareSpaceError "\v\s+$" display excludenl +syn match hareSpaceError "\v\zs +\ze\t" display + +" Use statement. +syn region hareUse start="\v^\s*\zsuse>" end=";" contains=hareComment display + +syn match hareErrorAssertion "\v(^([^/]|//@!)*\)\_s*)@<=!\=@!" +syn match hareQuestionMark "?" + +" DEFAULT HIGHLIGHTING {{{1 +hi def link hareAttribute Keyword +hi def link hareBoolean Boolean +hi def link hareBuiltin Function +hi def link hareComment Comment +hi def link hareCommentDoc SpecialComment +hi def link hareConditional Conditional +hi def link hareEscape SpecialChar +hi def link hareFloat Float +hi def link hareFormat SpecialChar +hi def link hareKeyword Keyword +hi def link hareLabel Label +hi def link hareNull Constant +hi def link hareNumber Number +hi def link hareOperator Operator +hi def link hareQuestionMark Special +hi def link hareRepeat Repeat +hi def link hareRune Character +hi def link hareStorageClass StorageClass +hi def link hareString String +hi def link hareStructure Structure +hi def link hareTodo Todo +hi def link hareType Type +hi def link hareTypedef Typedef +hi def link hareUse PreProc + +hi def link hareSpaceError Error +autocmd InsertEnter * hi link hareSpaceError NONE +autocmd InsertLeave * hi link hareSpaceError Error + +hi def hareErrorAssertion ctermfg=red cterm=bold guifg=red gui=bold + +" vim: tabstop=8 shiftwidth=2 expandtab diff --git a/runtime/syntax/help.vim b/runtime/syntax/help.vim index 01915d23d7..5773e94c3e 100644 --- a/runtime/syntax/help.vim +++ b/runtime/syntax/help.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: Vim help file " Maintainer: Bram Moolenaar (Bram@vim.org) -" Last Change: 2021 Jun 13 +" Last Change: 2022 Sep 26 " Quit when a (custom) syntax file was already loaded if exists("b:current_syntax") @@ -39,6 +39,7 @@ syn match helpVim "VIM REFERENCE.*" syn match helpVim "NVIM REFERENCE.*" syn match helpOption "'[a-z]\{2,\}'" syn match helpOption "'t_..'" +syn match helpNormal "'ab'" syn match helpCommand "`[^` \t]\+`"hs=s+1,he=e-1 contains=helpBacktick syn match helpCommand "\(^\|[^a-z"[]\)\zs`[^`]\+`\ze\([^a-z\t."']\|$\)"hs=s+1,he=e-1 contains=helpBacktick syn match helpHeader "\s*\zs.\{-}\ze\s\=\~$" nextgroup=helpIgnore diff --git a/runtime/syntax/hlsplaylist.vim b/runtime/syntax/hlsplaylist.vim new file mode 100644 index 0000000000..245eee213b --- /dev/null +++ b/runtime/syntax/hlsplaylist.vim @@ -0,0 +1,120 @@ +" Vim syntax file +" Language: HLS Playlist +" Maintainer: BenoĂ®t Ryder +" Latest Revision: 2022-09-23 + +if exists("b:current_syntax") + finish +endif + +let s:cpo_save = &cpo +set cpo&vim + +" Comment line +syn match hlsplaylistComment "^#\(EXT\)\@!.*$" +" Segment URL +syn match hlsplaylistUrl "^[^#].*$" + +" Unknown tags, assume an attribute list or nothing +syn match hlsplaylistTagUnknown "^#EXT[^:]*$" +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagUnknown start="^#EXT[^:]*\ze:" end="$" keepend contains=hlsplaylistAttributeList + +" Basic Tags +syn match hlsplaylistTagHeader "^#EXTM3U$" +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagHeader start="^#EXT-X-VERSION\ze:" end="$" keepend contains=hlsplaylistValueInt + +" Media or Multivariant Playlist Tags +syn match hlsplaylistTagHeader "^#EXT-X-INDEPENDENT-SEGMENTS$" +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagDelimiter start="^#EXT-X-START\ze:" end="$" keepend contains=hlsplaylistAttributeList +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagStandard start="^#EXT-X-DEFINE\ze:" end="$" keepend contains=hlsplaylistAttributeList + +" Media Playlist Tags +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagHeader start="^#EXT-X-TARGETDURATION\ze:" end="$" keepend contains=hlsplaylistValueFloat +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagHeader start="^#EXT-X-MEDIA-SEQUENCE\ze:" end="$" keepend contains=hlsplaylistValueInt +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagHeader start="^#EXT-X-DISCONTINUITY-SEQUENCE\ze:" end="$" keepend contains=hlsplaylistValueInt +syn match hlsplaylistTagDelimiter "^#EXT-X-ENDLIST$" +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagHeader start="^#EXT-X-PLAYLIST-TYPE\ze:" end="$" keepend contains=hlsplaylistAttributeEnum +syn match hlsplaylistTagStandard "^#EXT-X-I-FRAME-ONLY$" +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagHeader start="^#EXT-X-PART-INF\ze:" end="$" keepend contains=hlsplaylistAttributeList +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagHeader start="^#EXT-X-SERVER-CONTROL\ze:" end="$" keepend contains=hlsplaylistAttributeList + +" Media Segment Tags +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagStatement start="^#EXTINF\ze:" end="$" keepend contains=hlsplaylistValueFloat,hlsplaylistExtInfDesc +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagStandard start="^#EXT-X-BYTERANGE\ze:" end="$" keepend contains=hlsplaylistValueInt +syn match hlsplaylistTagDelimiter "^#EXT-X-DISCONTINUITY$" +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagStandard start="^#EXT-X-KEY\ze:" end="$" keepend contains=hlsplaylistAttributeList +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagStandard start="^#EXT-X-MAP\ze:" end="$" keepend contains=hlsplaylistAttributeList +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagStandard start="^#EXT-X-PROGRAM-DATE-TIME\ze:" end="$" keepend contains=hlsplaylistValueDateTime +syn match hlsplaylistTagDelimiter "^#EXT-X-GAP$" +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagStandard start="^#EXT-X-BITRATE\ze:" end="$" keepend contains=hlsplaylistValueFloat +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagStatement start="^#EXT-X-PART\ze:" end="$" keepend contains=hlsplaylistAttributeList + +" Media Metadata Tags +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagStandard start="^#EXT-X-DATERANGE\ze:" end="$" keepend contains=hlsplaylistAttributeList +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagStandard start="^#EXT-X-SKIP\ze:" end="$" keepend contains=hlsplaylistAttributeList +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagStatement start="^#EXT-X-PRELOAD-HINT\ze:" end="$" keepend contains=hlsplaylistAttributeList +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagStatement start="^#EXT-X-RENDITION-REPORT\ze:" end="$" keepend contains=hlsplaylistAttributeList + +" Multivariant Playlist Tags +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagStandard start="^#EXT-X-MEDIA\ze:" end="$" keepend contains=hlsplaylistAttributeList +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagStatement start="^#EXT-X-STREAM-INF\ze:" end="$" keepend contains=hlsplaylistAttributeList +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagStatement start="^#EXT-X-I-FRAME-STREAM-INF\ze:" end="$" keepend contains=hlsplaylistAttributeList +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagStandard start="^#EXT-X-SESSION-DATA\ze:" end="$" keepend contains=hlsplaylistAttributeList +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagStandard start="^#EXT-X-SESSION-KEY\ze:" end="$" keepend contains=hlsplaylistAttributeList +syn region hlsplaylistTagLine matchgroup=hlsplaylistTagStandard start="^#EXT-X-CONTENT-STEERING\ze:" end="$" keepend contains=hlsplaylistAttributeList + +" Attributes +syn region hlsplaylistAttributeList start=":" end="$" keepend contained + \ contains=hlsplaylistAttributeName,hlsplaylistAttributeInt,hlsplaylistAttributeHex,hlsplaylistAttributeFloat,hlsplaylistAttributeString,hlsplaylistAttributeEnum,hlsplaylistAttributeResolution,hlsplaylistAttributeUri +" Common attributes +syn match hlsplaylistAttributeName "[A-Za-z-]\+\ze=" contained +syn match hlsplaylistAttributeEnum "=\zs[A-Za-z][A-Za-z0-9-_]*" contained +syn match hlsplaylistAttributeString +=\zs"[^"]*"+ contained +syn match hlsplaylistAttributeInt "=\zs\d\+" contained +syn match hlsplaylistAttributeFloat "=\zs-\?\d*\.\d*" contained +syn match hlsplaylistAttributeHex "=\zs0[xX]\d*" contained +syn match hlsplaylistAttributeResolution "=\zs\d\+x\d\+" contained +" Allow different highligting for URI attributes +syn region hlsplaylistAttributeUri matchgroup=hlsplaylistAttributeName start="\zsURI\ze" end="\(,\|$\)" contained contains=hlsplaylistUriQuotes +syn region hlsplaylistUriQuotes matchgroup=hlsplaylistAttributeString start=+"+ end=+"+ keepend contained contains=hlsplaylistUriValue +syn match hlsplaylistUriValue /[^" ]\+/ contained +" Individual values +syn match hlsplaylistValueInt "[0-9]\+" contained +syn match hlsplaylistValueFloat "\(\d\+\|\d*\.\d*\)" contained +syn match hlsplaylistExtInfDesc ",\zs.*$" contained +syn match hlsplaylistValueDateTime "\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d\(\.\d*\)\?\(Z\|\d\d:\?\d\d\)$" contained + + +" Define default highlighting + +hi def link hlsplaylistComment Comment +hi def link hlsplaylistUrl NONE + +hi def link hlsplaylistTagHeader Special +hi def link hlsplaylistTagStandard Define +hi def link hlsplaylistTagDelimiter Delimiter +hi def link hlsplaylistTagStatement Statement +hi def link hlsplaylistTagUnknown Special + +hi def link hlsplaylistUriQuotes String +hi def link hlsplaylistUriValue Underlined +hi def link hlsplaylistAttributeQuotes String +hi def link hlsplaylistAttributeName Identifier +hi def link hlsplaylistAttributeInt Number +hi def link hlsplaylistAttributeHex Number +hi def link hlsplaylistAttributeFloat Float +hi def link hlsplaylistAttributeString String +hi def link hlsplaylistAttributeEnum Constant +hi def link hlsplaylistAttributeResolution Constant +hi def link hlsplaylistValueInt Number +hi def link hlsplaylistValueFloat Float +hi def link hlsplaylistExtInfDesc String +hi def link hlsplaylistValueDateTime Constant + + +let b:current_syntax = "hlsplaylist" + +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim: sts=2 sw=2 et diff --git a/runtime/syntax/plsql.vim b/runtime/syntax/plsql.vim index 21681d59e4..9b4df09ac7 100644 --- a/runtime/syntax/plsql.vim +++ b/runtime/syntax/plsql.vim @@ -4,8 +4,11 @@ " Previous Maintainer: Jeff Lanzarotta (jefflanzarotta at yahoo dot com) " Previous Maintainer: C. Laurence Gonsalves (clgonsal@kami.com) " URL: https://github.com/lee-lindley/vim_plsql_syntax -" Last Change: Aug 21, 2022 -" History Lee Lindley (lee dot lindley at gmail dot com) +" Last Change: Sep 19, 2022 +" History Carsten Czarski (carsten dot czarski at oracle com) +" add handling for typical SQL*Plus commands (rem, start, host, set, etc) +" add error highlight for non-breaking space +" Lee Lindley (lee dot lindley at gmail dot com) " use get with default 0 instead of exists per Bram suggestion " make procedure folding optional " updated to 19c keywords. refined quoting. @@ -54,8 +57,13 @@ syn case ignore syn match plsqlGarbage "[^ \t()]" syn match plsqlIdentifier "[a-z][a-z0-9$_#]*" +syn match plsqlSqlPlusDefine "&&\?[a-z][a-z0-9$_#]*\.\?" syn match plsqlHostIdentifier ":[a-z][a-z0-9$_#]*" +" The Non-Breaking is often accidentally typed (Mac User: Opt+Space, after typing the "|", Opt+7); +" error highlight for these avoids running into annoying compiler errors. +syn match plsqlIllegalSpace "[\xa0]" + " When wanted, highlight the trailing whitespace. if get(g:,"plsql_space_errors",0) == 1 if get(g:,"plsql_no_trail_space_error",0) == 0 @@ -79,7 +87,6 @@ syn match plsqlOperator "\" " " conditional compilation Preprocessor directives and sqlplus define sigil syn match plsqlPseudo "$[$a-z][a-z0-9$_#]*" -syn match plsqlPseudo "&" syn match plsqlReserved "\<\(CREATE\|THEN\|UPDATE\|INSERT\|SET\)\>" syn match plsqlKeyword "\<\(REPLACE\|PACKAGE\|FUNCTION\|PROCEDURE\|TYPE|BODY\|WHEN\|MATCHED\)\>" @@ -150,7 +157,7 @@ syn keyword plsqlKeyword DATA_SECURITY_REWRITE_LIMIT DATA_VALIDATE DATE_MODE DAY syn keyword plsqlKeyword DBMS_STATS DBSTR2UTF8 DBTIMEZONE DB_ROLE_CHANGE DB_UNIQUE_NAME DB_VERSION syn keyword plsqlKeyword DDL DEALLOCATE DEBUG DEBUGGER DECLARE DECODE DECOMPOSE DECOMPRESS DECORRELATE syn keyword plsqlKeyword DECR DECREMENT DECRYPT DEDUPLICATE DEFAULTS DEFAULT_COLLATION DEFAULT_PDB_HINT -syn keyword plsqlKeyword DEFERRABLE DEFERRED DEFINE DEFINED DEFINER DEFINITION DEGREE DELAY DELEGATE +syn keyword plsqlKeyword DEFERRABLE DEFERRED DEFINED DEFINER DEFINITION DEGREE DELAY DELEGATE syn keyword plsqlKeyword DELETEXML DELETE_ALL DEMAND DENORM_AV DENSE_RANK DENSE_RANKM DEPENDENT DEPTH syn keyword plsqlKeyword DEQUEUE DEREF DEREF_NO_REWRITE DESCENDANT DESCRIPTION DESTROY DETACHED DETERMINED syn keyword plsqlKeyword DETERMINES DETERMINISTIC DG_GATHER_STATS DIAGNOSTICS DICTIONARY DIGEST DIMENSION @@ -189,7 +196,7 @@ syn keyword plsqlKeyword HELP HEXTORAW HEXTOREF HIDDEN HIDE HIERARCHICAL HIERARC syn keyword plsqlKeyword HIER_CAPTION HIER_CHILDREN HIER_CHILD_COUNT HIER_COLUMN HIER_CONDITION HIER_DEPTH syn keyword plsqlKeyword HIER_DESCRIPTION HIER_HAS_CHILDREN HIER_LAG HIER_LEAD HIER_LEVEL HIER_MEMBER_NAME syn keyword plsqlKeyword HIER_MEMBER_UNIQUE_NAME HIER_ORDER HIER_PARENT HIER_WINDOW HIGH HINTSET_BEGIN -syn keyword plsqlKeyword HINTSET_END HOST HOT HOUR HOURS HTTP HWM_BROKERED HYBRID ID IDENTIFIER IDENTITY +syn keyword plsqlKeyword HINTSET_END HOT HOUR HOURS HTTP HWM_BROKERED HYBRID ID IDENTIFIER IDENTITY syn keyword plsqlKeyword IDGENERATORS IDLE IDLE_TIME IGNORE IGNORE_OPTIM_EMBEDDED_HINTS IGNORE_ROW_ON_DUPKEY_INDEX syn keyword plsqlKeyword IGNORE_WHERE_CLAUSE ILM IMMEDIATE IMMUTABLE IMPACT IMPORT INACTIVE INACTIVE_ACCOUNT_TIME syn keyword plsqlKeyword INCLUDE INCLUDES INCLUDE_VERSION INCLUDING INCOMING INCR INCREMENT INCREMENTAL @@ -342,7 +349,7 @@ syn keyword plsqlKeyword SELF SEMIJOIN SEMIJOIN_DRIVER SEMI_TO_INNER SENSITIVE S syn keyword plsqlKeyword SERIAL SERIALIZABLE SERVERERROR SERVICE SERVICES SERVICE_NAME_CONVERT SESSION syn keyword plsqlKeyword SESSIONS_PER_USER SESSIONTIMEZONE SESSIONTZNAME SESSION_CACHED_CURSORS SETS syn keyword plsqlKeyword SETTINGS SET_GBY_PUSHDOWN SET_TO_JOIN SEVERE SHARD SHARDED SHARDS SHARDSPACE -syn keyword plsqlKeyword SHARD_CHUNK_ID SHARED SHARED_POOL SHARE_OF SHARING SHD$COL$MAP SHELFLIFE SHOW +syn keyword plsqlKeyword SHARD_CHUNK_ID SHARED SHARED_POOL SHARE_OF SHARING SHD$COL$MAP SHELFLIFE syn keyword plsqlKeyword SHRINK SHUTDOWN SIBLING SIBLINGS SID SIGN SIGNAL_COMPONENT SIGNAL_FUNCTION syn keyword plsqlKeyword SIGNATURE SIMPLE SIN SINGLE SINGLETASK SINH SITE SKEWNESS_POP SKEWNESS_SAMP syn keyword plsqlKeyword SKIP SKIP_EXT_OPTIMIZER SKIP_PROXY SKIP_UNQ_UNUSABLE_IDX SKIP_UNUSABLE_INDEXES @@ -445,7 +452,7 @@ syn keyword plsqlKeyword VECTOR_READ_TRACE VECTOR_TRANSFORM VECTOR_TRANSFORM_DIM syn keyword plsqlKeyword VERIFIER VERIFY VERSION VERSIONING VERSIONS VERSIONS_ENDSCN VERSIONS_ENDTIME syn keyword plsqlKeyword VERSIONS_OPERATION VERSIONS_STARTSCN VERSIONS_STARTTIME VERSIONS_XID VIEWS syn keyword plsqlKeyword VIOLATION VIRTUAL VISIBILITY VISIBLE VOLUME VSIZE WAIT WALLET WEEK WEEKS WELLFORMED -syn keyword plsqlKeyword WHENEVER WHITESPACE WIDTH_BUCKET WINDOW WITHIN WITHOUT WITH_EXPRESSION +syn keyword plsqlKeyword WHITESPACE WIDTH_BUCKET WINDOW WITHIN WITHOUT WITH_EXPRESSION syn keyword plsqlKeyword WITH_PLSQL WORK WRAPPED WRAPPER WRITE XDB_FASTPATH_INSERT XID XML XML2OBJECT syn keyword plsqlKeyword XMLATTRIBUTES XMLCAST XMLCDATA XMLCOLATTVAL XMLCOMMENT XMLCONCAT XMLDIFF XMLELEMENT syn keyword plsqlKeyword XMLEXISTS XMLEXISTS2 XMLFOREST XMLINDEX_REWRITE XMLINDEX_REWRITE_IN_SELECT @@ -468,13 +475,13 @@ syn keyword plsqlReserved MINUS MODE NOCOMPRESS NOWAIT NUMBER_BASE OCICOLL OCIDA syn keyword plsqlReserved OCIDURATION OCIINTERVAL OCILOBLOCATOR OCINUMBER OCIRAW OCIREF OCIREFCURSOR syn keyword plsqlReserved OCIROWID OCISTRING OCITYPE OF ON OPTION ORACLE ORADATA ORDER ORLANY ORLVARY syn keyword plsqlReserved OUT OVERRIDING PARALLEL_ENABLE PARAMETER PASCAL PCTFREE PIPE PIPELINED POLYMORPHIC -syn keyword plsqlReserved PRAGMA PRIOR PUBLIC RAISE RECORD RELIES_ON REM RENAME RESOURCE RESULT REVOKE ROWID +syn keyword plsqlReserved PRAGMA PRIOR PUBLIC RAISE RECORD RELIES_ON RENAME RESOURCE RESULT REVOKE ROWID syn keyword plsqlReserved SB1 SB2 syn match plsqlReserved "\" syn keyword plsqlReserved SEPARATE SHARE SHORT SIZE SIZE_T SPARSE SQLCODE SQLDATA syn keyword plsqlReserved SQLNAME SQLSTATE STANDARD START STORED STRUCT STYLE SYNONYM TABLE TDO syn keyword plsqlReserved TRANSACTIONAL TRIGGER UB1 UB4 UNION UNIQUE UNSIGNED UNTRUSTED VALIST -syn keyword plsqlReserved VALUES VARIABLE VIEW VOID WHERE WITH +syn keyword plsqlReserved VALUES VIEW VOID WHERE WITH " PL/SQL and SQL functions. syn keyword plsqlFunction ABS ACOS ADD_MONTHS APPROX_COUNT APPROX_COUNT_DISTINCT APPROX_COUNT_DISTINCT_AGG @@ -584,18 +591,18 @@ syn match plsqlEND "\" syn match plsqlISAS "\<\(IS\|AS\)\>" " Various types of comments. -syntax region plsqlCommentL start="--" skip="\\$" end="$" keepend extend contains=@plsqlCommentGroup,plsqlSpaceError +syntax region plsqlCommentL start="--" skip="\\$" end="$" keepend extend contains=@plsqlCommentGroup,plsqlSpaceError,plsqlIllegalSpace,plsqlSqlplusDefine if get(g:,"plsql_fold",0) == 1 syntax region plsqlComment \ start="/\*" end="\*/" \ extend - \ contains=@plsqlCommentGroup,plsqlSpaceError + \ contains=@plsqlCommentGroup,plsqlSpaceError,plsqlIllegalSpace,plsqlSqlplusDefine \ fold else syntax region plsqlComment \ start="/\*" end="\*/" \ extend - \ contains=@plsqlCommentGroup,plsqlSpaceError + \ contains=@plsqlCommentGroup,plsqlSpaceError,plsqlIllegalSpace,plsqlSqlplusDefine endif syn cluster plsqlCommentAll contains=plsqlCommentL,plsqlComment @@ -618,23 +625,23 @@ syn match plsqlFloatLiteral contained "\.\(\d\+\([eE][+-]\?\d\+\)\?\)[fd]\?" " double quoted strings in SQL are database object names. Should be a subgroup of Normal. " We will use Character group as a proxy for that so color can be chosen close to Normal syn region plsqlQuotedIdentifier matchgroup=plsqlOperator start=+n\?"+ end=+"+ keepend extend -syn cluster plsqlIdentifiers contains=plsqlIdentifier,plsqlQuotedIdentifier +syn cluster plsqlIdentifiers contains=plsqlIdentifier,plsqlQuotedIdentifier,plsqlSqlPlusDefine " quoted string literals if get(g:,"plsql_fold",0) == 1 - syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?'+ skip=+''+ end=+'+ fold keepend extend - syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?q'\z([^[(<{]\)+ end=+\z1'+ fold keepend extend - syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?q'<+ end=+>'+ fold keepend extend - syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?q'{+ end=+}'+ fold keepend extend - syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?q'(+ end=+)'+ fold keepend extend - syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?q'\[+ end=+]'+ fold keepend extend + syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?'+ skip=+''+ end=+'+ contains=plsqlSqlplusDefine fold keepend extend + syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?q'\z([^[(<{]\)+ end=+\z1'+ contains=plsqlSqlplusDefine fold keepend extend + syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?q'<+ end=+>'+ contains=plsqlSqlplusDefine fold keepend extend + syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?q'{+ end=+}'+ contains=plsqlSqlplusDefine fold keepend extend + syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?q'(+ end=+)'+ contains=plsqlSqlplusDefine fold keepend extend + syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?q'\[+ end=+]'+ contains=plsqlSqlplusDefine fold keepend extend else - syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?'+ skip=+''+ end=+'+ - syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?q'\z([^[(<{]\)+ end=+\z1'+ - syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?q'<+ end=+>'+ - syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?q'{+ end=+}'+ - syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?q'(+ end=+)'+ - syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?q'\[+ end=+]'+ + syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?'+ skip=+''+ end=+'+ contains=plsqlSqlplusDefine + syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?q'\z([^[(<{]\)+ end=+\z1'+ contains=plsqlSqlplusDefine + syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?q'<+ end=+>'+ contains=plsqlSqlplusDefine + syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?q'{+ end=+}'+ contains=plsqlSqlplusDefine + syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?q'(+ end=+)'+ contains=plsqlSqlplusDefine + syn region plsqlStringLiteral matchgroup=plsqlOperator start=+n\?q'\[+ end=+]'+ contains=plsqlSqlplusDefine endif syn keyword plsqlBooleanLiteral TRUE FALSE @@ -682,6 +689,10 @@ syn match plsqlConditional "\\_s\+\" syn match plsqlCase "\\_s\+\" syn match plsqlCase "\" +syn region plsqlSqlPlusCommentL start="^\(REM\)\( \|$\)" skip="\\$" end="$" keepend extend contains=@plsqlCommentGroup,plsqlSpaceError,plsqlIllegalSpace +syn region plsqlSqlPlusCommand start="^\(SET\|DEFINE\|PROMPT\|ACCEPT\|EXEC\|HOST\|SHOW\|VAR\|VARIABLE\|COL\|WHENEVER\|TIMING\)\( \|$\)" skip="\\$" end="$" keepend extend +syn region plsqlSqlPlusRunFile start="^\(@\|@@\)" skip="\\$" end="$" keepend extend + if get(g:,"plsql_fold",0) == 1 setlocal foldmethod=syntax syn sync fromstart @@ -826,6 +837,13 @@ hi def link plsqlComment2String String hi def link plsqlTrigger Function hi def link plsqlTypeAttribute StorageClass hi def link plsqlTodo Todo + +hi def link plsqlIllegalSpace Error +hi def link plsqlSqlPlusDefine PreProc +hi def link plsqlSqlPlusCommand PreProc +hi def link plsqlSqlPlusRunFile Include +hi def link plsqlSqlPlusCommentL Comment + " to be able to change them after loading, need override whether defined or not if get(g:,"plsql_legacy_sql_keywords",0) == 1 hi link plsqlSQLKeyword Function diff --git a/runtime/syntax/solidity.vim b/runtime/syntax/solidity.vim new file mode 100644 index 0000000000..e552446e10 --- /dev/null +++ b/runtime/syntax/solidity.vim @@ -0,0 +1,173 @@ +" Vim syntax file +" Language: Solidity +" Maintainer: Cothi (jiungdev@gmail.com) +" Original Author: tomlion (https://github.com/tomlion/vim-solidity/blob/master/syntax/solidity.vim) +" Last Changed: 2022 Sep 27 +" +" Additional contributors: +" Modified by thesis (https://github.com/thesis/vim-solidity/blob/main/indent/solidity.vim) + +if exists("b:current_syntax") + finish +endif + +" keyword +syn keyword solKeyword abstract anonymous as break calldata case catch constant constructor continue default switch revert require +syn keyword solKeyword ecrecover addmod mulmod keccak256 +syn keyword solKeyword delete do else emit enum external final for function if immutable import in indexed inline +syn keyword solKeyword interface internal is let match memory modifier new of payable pragma private public pure override virtual +syn keyword solKeyword relocatable return returns static storage struct throw try type typeof using +syn keyword solKeyword var view while + +syn keyword solConstant true false wei szabo finney ether seconds minutes hours days weeks years now +syn keyword solConstant abi block blockhash msg tx this super selfdestruct + +syn keyword solBuiltinType mapping address bool +syn keyword solBuiltinType int int8 int16 int24 int32 int40 int48 int56 int64 int72 int80 int88 int96 int104 int112 int120 int128 int136 int144 int152 int160 int168 int178 int184 int192 int200 int208 int216 int224 int232 int240 int248 int256 +syn keyword solBuiltinType uint uint8 uint16 uint24 uint32 uint40 uint48 uint56 uint64 uint72 uint80 uint88 uint96 uint104 uint112 uint120 uint128 uint136 uint144 uint152 uint160 uint168 uint178 uint184 uint192 uint200 uint208 uint216 uint224 uint232 uint240 uint248 uint256 +syn keyword solBuiltinType fixed +syn keyword solBuiltinType fixed0x8 fixed0x16 fixed0x24 fixed0x32 fixed0x40 fixed0x48 fixed0x56 fixed0x64 fixed0x72 fixed0x80 fixed0x88 fixed0x96 fixed0x104 fixed0x112 fixed0x120 fixed0x128 fixed0x136 fixed0x144 fixed0x152 fixed0x160 fixed0x168 fixed0x178 fixed0x184 fixed0x192 fixed0x200 fixed0x208 fixed0x216 fixed0x224 fixed0x232 fixed0x240 fixed0x248 fixed0x256 +syn keyword solBuiltinType fixed8x8 fixed8x16 fixed8x24 fixed8x32 fixed8x40 fixed8x48 fixed8x56 fixed8x64 fixed8x72 fixed8x80 fixed8x88 fixed8x96 fixed8x104 fixed8x112 fixed8x120 fixed8x128 fixed8x136 fixed8x144 fixed8x152 fixed8x160 fixed8x168 fixed8x178 fixed8x184 fixed8x192 fixed8x200 fixed8x208 fixed8x216 fixed8x224 fixed8x232 fixed8x240 fixed8x248 +syn keyword solBuiltinType fixed16x8 fixed16x16 fixed16x24 fixed16x32 fixed16x40 fixed16x48 fixed16x56 fixed16x64 fixed16x72 fixed16x80 fixed16x88 fixed16x96 fixed16x104 fixed16x112 fixed16x120 fixed16x128 fixed16x136 fixed16x144 fixed16x152 fixed16x160 fixed16x168 fixed16x178 fixed16x184 fixed16x192 fixed16x200 fixed16x208 fixed16x216 fixed16x224 fixed16x232 fixed16x240 +syn keyword solBuiltinType fixed24x8 fixed24x16 fixed24x24 fixed24x32 fixed24x40 fixed24x48 fixed24x56 fixed24x64 fixed24x72 fixed24x80 fixed24x88 fixed24x96 fixed24x104 fixed24x112 fixed24x120 fixed24x128 fixed24x136 fixed24x144 fixed24x152 fixed24x160 fixed24x168 fixed24x178 fixed24x184 fixed24x192 fixed24x200 fixed24x208 fixed24x216 fixed24x224 fixed24x232 +syn keyword solBuiltinType fixed32x8 fixed32x16 fixed32x24 fixed32x32 fixed32x40 fixed32x48 fixed32x56 fixed32x64 fixed32x72 fixed32x80 fixed32x88 fixed32x96 fixed32x104 fixed32x112 fixed32x120 fixed32x128 fixed32x136 fixed32x144 fixed32x152 fixed32x160 fixed32x168 fixed32x178 fixed32x184 fixed32x192 fixed32x200 fixed32x208 fixed32x216 fixed32x224 +syn keyword solBuiltinType fixed40x8 fixed40x16 fixed40x24 fixed40x32 fixed40x40 fixed40x48 fixed40x56 fixed40x64 fixed40x72 fixed40x80 fixed40x88 fixed40x96 fixed40x104 fixed40x112 fixed40x120 fixed40x128 fixed40x136 fixed40x144 fixed40x152 fixed40x160 fixed40x168 fixed40x178 fixed40x184 fixed40x192 fixed40x200 fixed40x208 fixed40x216 +syn keyword solBuiltinType fixed48x8 fixed48x16 fixed48x24 fixed48x32 fixed48x40 fixed48x48 fixed48x56 fixed48x64 fixed48x72 fixed48x80 fixed48x88 fixed48x96 fixed48x104 fixed48x112 fixed48x120 fixed48x128 fixed48x136 fixed48x144 fixed48x152 fixed48x160 fixed48x168 fixed48x178 fixed48x184 fixed48x192 fixed48x200 fixed48x208 +syn keyword solBuiltinType fixed56x8 fixed56x16 fixed56x24 fixed56x32 fixed56x40 fixed56x48 fixed56x56 fixed56x64 fixed56x72 fixed56x80 fixed56x88 fixed56x96 fixed56x104 fixed56x112 fixed56x120 fixed56x128 fixed56x136 fixed56x144 fixed56x152 fixed56x160 fixed56x168 fixed56x178 fixed56x184 fixed56x192 fixed56x200 +syn keyword solBuiltinType fixed64x8 fixed64x16 fixed64x24 fixed64x32 fixed64x40 fixed64x48 fixed64x56 fixed64x64 fixed64x72 fixed64x80 fixed64x88 fixed64x96 fixed64x104 fixed64x112 fixed64x120 fixed64x128 fixed64x136 fixed64x144 fixed64x152 fixed64x160 fixed64x168 fixed64x178 fixed64x184 fixed64x192 +syn keyword solBuiltinType fixed72x8 fixed72x16 fixed72x24 fixed72x32 fixed72x40 fixed72x48 fixed72x56 fixed72x64 fixed72x72 fixed72x80 fixed72x88 fixed72x96 fixed72x104 fixed72x112 fixed72x120 fixed72x128 fixed72x136 fixed72x144 fixed72x152 fixed72x160 fixed72x168 fixed72x178 fixed72x184 +syn keyword solBuiltinType fixed80x8 fixed80x16 fixed80x24 fixed80x32 fixed80x40 fixed80x48 fixed80x56 fixed80x64 fixed80x72 fixed80x80 fixed80x88 fixed80x96 fixed80x104 fixed80x112 fixed80x120 fixed80x128 fixed80x136 fixed80x144 fixed80x152 fixed80x160 fixed80x168 fixed80x178 +syn keyword solBuiltinType fixed88x8 fixed88x16 fixed88x24 fixed88x32 fixed88x40 fixed88x48 fixed88x56 fixed88x64 fixed88x72 fixed88x80 fixed88x88 fixed88x96 fixed88x104 fixed88x112 fixed88x120 fixed88x128 fixed88x136 fixed88x144 fixed88x152 fixed88x160 fixed88x168 +syn keyword solBuiltinType fixed96x8 fixed96x16 fixed96x24 fixed96x32 fixed96x40 fixed96x48 fixed96x56 fixed96x64 fixed96x72 fixed96x80 fixed96x88 fixed96x96 fixed96x104 fixed96x112 fixed96x120 fixed96x128 fixed96x136 fixed96x144 fixed96x152 fixed96x160 +syn keyword solBuiltinType fixed104x8 fixed104x16 fixed104x24 fixed104x32 fixed104x40 fixed104x48 fixed104x56 fixed104x64 fixed104x72 fixed104x80 fixed104x88 fixed104x96 fixed104x104 fixed104x112 fixed104x120 fixed104x128 fixed104x136 fixed104x144 fixed104x152 +syn keyword solBuiltinType fixed112x8 fixed112x16 fixed112x24 fixed112x32 fixed112x40 fixed112x48 fixed112x56 fixed112x64 fixed112x72 fixed112x80 fixed112x88 fixed112x96 fixed112x104 fixed112x112 fixed112x120 fixed112x128 fixed112x136 fixed112x144 +syn keyword solBuiltinType fixed120x8 fixed120x16 fixed120x24 fixed120x32 fixed120x40 fixed120x48 fixed120x56 fixed120x64 fixed120x72 fixed120x80 fixed120x88 fixed120x96 fixed120x104 fixed120x112 fixed120x120 fixed120x128 fixed120x136 +syn keyword solBuiltinType fixed128x8 fixed128x16 fixed128x24 fixed128x32 fixed128x40 fixed128x48 fixed128x56 fixed128x64 fixed128x72 fixed128x80 fixed128x88 fixed128x96 fixed128x104 fixed128x112 fixed128x120 fixed128x128 +syn keyword solBuiltinType fixed136x8 fixed136x16 fixed136x24 fixed136x32 fixed136x40 fixed136x48 fixed136x56 fixed136x64 fixed136x72 fixed136x80 fixed136x88 fixed136x96 fixed136x104 fixed136x112 fixed136x120 +syn keyword solBuiltinType fixed144x8 fixed144x16 fixed144x24 fixed144x32 fixed144x40 fixed144x48 fixed144x56 fixed144x64 fixed144x72 fixed144x80 fixed144x88 fixed144x96 fixed144x104 fixed144x112 +syn keyword solBuiltinType fixed152x8 fixed152x16 fixed152x24 fixed152x32 fixed152x40 fixed152x48 fixed152x56 fixed152x64 fixed152x72 fixed152x80 fixed152x88 fixed152x96 fixed152x104 +syn keyword solBuiltinType fixed160x8 fixed160x16 fixed160x24 fixed160x32 fixed160x40 fixed160x48 fixed160x56 fixed160x64 fixed160x72 fixed160x80 fixed160x88 fixed160x96 +syn keyword solBuiltinType fixed168x8 fixed168x16 fixed168x24 fixed168x32 fixed168x40 fixed168x48 fixed168x56 fixed168x64 fixed168x72 fixed168x80 fixed168x88 +syn keyword solBuiltinType fixed176x8 fixed176x16 fixed176x24 fixed176x32 fixed176x40 fixed176x48 fixed176x56 fixed176x64 fixed176x72 fixed176x80 +syn keyword solBuiltinType fixed184x8 fixed184x16 fixed184x24 fixed184x32 fixed184x40 fixed184x48 fixed184x56 fixed184x64 fixed184x72 +syn keyword solBuiltinType fixed192x8 fixed192x16 fixed192x24 fixed192x32 fixed192x40 fixed192x48 fixed192x56 fixed192x64 +syn keyword solBuiltinType fixed200x8 fixed200x16 fixed200x24 fixed200x32 fixed200x40 fixed200x48 fixed200x56 +syn keyword solBuiltinType fixed208x8 fixed208x16 fixed208x24 fixed208x32 fixed208x40 fixed208x48 +syn keyword solBuiltinType fixed216x8 fixed216x16 fixed216x24 fixed216x32 fixed216x40 +syn keyword solBuiltinType fixed224x8 fixed224x16 fixed224x24 fixed224x32 +syn keyword solBuiltinType fixed232x8 fixed232x16 fixed232x24 +syn keyword solBuiltinType fixed240x8 fixed240x16 +syn keyword solBuiltinType fixed248x8 +syn keyword solBuiltinType ufixed +syn keyword solBuiltinType ufixed0x8 ufixed0x16 ufixed0x24 ufixed0x32 ufixed0x40 ufixed0x48 ufixed0x56 ufixed0x64 ufixed0x72 ufixed0x80 ufixed0x88 ufixed0x96 ufixed0x104 ufixed0x112 ufixed0x120 ufixed0x128 ufixed0x136 ufixed0x144 ufixed0x152 ufixed0x160 ufixed0x168 ufixed0x178 ufixed0x184 ufixed0x192 ufixed0x200 ufixed0x208 ufixed0x216 ufixed0x224 ufixed0x232 ufixed0x240 ufixed0x248 ufixed0x256 +syn keyword solBuiltinType ufixed8x8 ufixed8x16 ufixed8x24 ufixed8x32 ufixed8x40 ufixed8x48 ufixed8x56 ufixed8x64 ufixed8x72 ufixed8x80 ufixed8x88 ufixed8x96 ufixed8x104 ufixed8x112 ufixed8x120 ufixed8x128 ufixed8x136 ufixed8x144 ufixed8x152 ufixed8x160 ufixed8x168 ufixed8x178 ufixed8x184 ufixed8x192 ufixed8x200 ufixed8x208 ufixed8x216 ufixed8x224 ufixed8x232 ufixed8x240 ufixed8x248 +syn keyword solBuiltinType ufixed16x8 ufixed16x16 ufixed16x24 ufixed16x32 ufixed16x40 ufixed16x48 ufixed16x56 ufixed16x64 ufixed16x72 ufixed16x80 ufixed16x88 ufixed16x96 ufixed16x104 ufixed16x112 ufixed16x120 ufixed16x128 ufixed16x136 ufixed16x144 ufixed16x152 ufixed16x160 ufixed16x168 ufixed16x178 ufixed16x184 ufixed16x192 ufixed16x200 ufixed16x208 ufixed16x216 ufixed16x224 ufixed16x232 ufixed16x240 +syn keyword solBuiltinType ufixed24x8 ufixed24x16 ufixed24x24 ufixed24x32 ufixed24x40 ufixed24x48 ufixed24x56 ufixed24x64 ufixed24x72 ufixed24x80 ufixed24x88 ufixed24x96 ufixed24x104 ufixed24x112 ufixed24x120 ufixed24x128 ufixed24x136 ufixed24x144 ufixed24x152 ufixed24x160 ufixed24x168 ufixed24x178 ufixed24x184 ufixed24x192 ufixed24x200 ufixed24x208 ufixed24x216 ufixed24x224 ufixed24x232 +syn keyword solBuiltinType ufixed32x8 ufixed32x16 ufixed32x24 ufixed32x32 ufixed32x40 ufixed32x48 ufixed32x56 ufixed32x64 ufixed32x72 ufixed32x80 ufixed32x88 ufixed32x96 ufixed32x104 ufixed32x112 ufixed32x120 ufixed32x128 ufixed32x136 ufixed32x144 ufixed32x152 ufixed32x160 ufixed32x168 ufixed32x178 ufixed32x184 ufixed32x192 ufixed32x200 ufixed32x208 ufixed32x216 ufixed32x224 +syn keyword solBuiltinType ufixed40x8 ufixed40x16 ufixed40x24 ufixed40x32 ufixed40x40 ufixed40x48 ufixed40x56 ufixed40x64 ufixed40x72 ufixed40x80 ufixed40x88 ufixed40x96 ufixed40x104 ufixed40x112 ufixed40x120 ufixed40x128 ufixed40x136 ufixed40x144 ufixed40x152 ufixed40x160 ufixed40x168 ufixed40x178 ufixed40x184 ufixed40x192 ufixed40x200 ufixed40x208 ufixed40x216 +syn keyword solBuiltinType ufixed48x8 ufixed48x16 ufixed48x24 ufixed48x32 ufixed48x40 ufixed48x48 ufixed48x56 ufixed48x64 ufixed48x72 ufixed48x80 ufixed48x88 ufixed48x96 ufixed48x104 ufixed48x112 ufixed48x120 ufixed48x128 ufixed48x136 ufixed48x144 ufixed48x152 ufixed48x160 ufixed48x168 ufixed48x178 ufixed48x184 ufixed48x192 ufixed48x200 ufixed48x208 +syn keyword solBuiltinType ufixed56x8 ufixed56x16 ufixed56x24 ufixed56x32 ufixed56x40 ufixed56x48 ufixed56x56 ufixed56x64 ufixed56x72 ufixed56x80 ufixed56x88 ufixed56x96 ufixed56x104 ufixed56x112 ufixed56x120 ufixed56x128 ufixed56x136 ufixed56x144 ufixed56x152 ufixed56x160 ufixed56x168 ufixed56x178 ufixed56x184 ufixed56x192 ufixed56x200 +syn keyword solBuiltinType ufixed64x8 ufixed64x16 ufixed64x24 ufixed64x32 ufixed64x40 ufixed64x48 ufixed64x56 ufixed64x64 ufixed64x72 ufixed64x80 ufixed64x88 ufixed64x96 ufixed64x104 ufixed64x112 ufixed64x120 ufixed64x128 ufixed64x136 ufixed64x144 ufixed64x152 ufixed64x160 ufixed64x168 ufixed64x178 ufixed64x184 ufixed64x192 +syn keyword solBuiltinType ufixed72x8 ufixed72x16 ufixed72x24 ufixed72x32 ufixed72x40 ufixed72x48 ufixed72x56 ufixed72x64 ufixed72x72 ufixed72x80 ufixed72x88 ufixed72x96 ufixed72x104 ufixed72x112 ufixed72x120 ufixed72x128 ufixed72x136 ufixed72x144 ufixed72x152 ufixed72x160 ufixed72x168 ufixed72x178 ufixed72x184 +syn keyword solBuiltinType ufixed80x8 ufixed80x16 ufixed80x24 ufixed80x32 ufixed80x40 ufixed80x48 ufixed80x56 ufixed80x64 ufixed80x72 ufixed80x80 ufixed80x88 ufixed80x96 ufixed80x104 ufixed80x112 ufixed80x120 ufixed80x128 ufixed80x136 ufixed80x144 ufixed80x152 ufixed80x160 ufixed80x168 ufixed80x178 +syn keyword solBuiltinType ufixed88x8 ufixed88x16 ufixed88x24 ufixed88x32 ufixed88x40 ufixed88x48 ufixed88x56 ufixed88x64 ufixed88x72 ufixed88x80 ufixed88x88 ufixed88x96 ufixed88x104 ufixed88x112 ufixed88x120 ufixed88x128 ufixed88x136 ufixed88x144 ufixed88x152 ufixed88x160 ufixed88x168 +syn keyword solBuiltinType ufixed96x8 ufixed96x16 ufixed96x24 ufixed96x32 ufixed96x40 ufixed96x48 ufixed96x56 ufixed96x64 ufixed96x72 ufixed96x80 ufixed96x88 ufixed96x96 ufixed96x104 ufixed96x112 ufixed96x120 ufixed96x128 ufixed96x136 ufixed96x144 ufixed96x152 ufixed96x160 +syn keyword solBuiltinType ufixed104x8 ufixed104x16 ufixed104x24 ufixed104x32 ufixed104x40 ufixed104x48 ufixed104x56 ufixed104x64 ufixed104x72 ufixed104x80 ufixed104x88 ufixed104x96 ufixed104x104 ufixed104x112 ufixed104x120 ufixed104x128 ufixed104x136 ufixed104x144 ufixed104x152 +syn keyword solBuiltinType ufixed112x8 ufixed112x16 ufixed112x24 ufixed112x32 ufixed112x40 ufixed112x48 ufixed112x56 ufixed112x64 ufixed112x72 ufixed112x80 ufixed112x88 ufixed112x96 ufixed112x104 ufixed112x112 ufixed112x120 ufixed112x128 ufixed112x136 ufixed112x144 +syn keyword solBuiltinType ufixed120x8 ufixed120x16 ufixed120x24 ufixed120x32 ufixed120x40 ufixed120x48 ufixed120x56 ufixed120x64 ufixed120x72 ufixed120x80 ufixed120x88 ufixed120x96 ufixed120x104 ufixed120x112 ufixed120x120 ufixed120x128 ufixed120x136 +syn keyword solBuiltinType ufixed128x8 ufixed128x16 ufixed128x24 ufixed128x32 ufixed128x40 ufixed128x48 ufixed128x56 ufixed128x64 ufixed128x72 ufixed128x80 ufixed128x88 ufixed128x96 ufixed128x104 ufixed128x112 ufixed128x120 ufixed128x128 +syn keyword solBuiltinType ufixed136x8 ufixed136x16 ufixed136x24 ufixed136x32 ufixed136x40 ufixed136x48 ufixed136x56 ufixed136x64 ufixed136x72 ufixed136x80 ufixed136x88 ufixed136x96 ufixed136x104 ufixed136x112 ufixed136x120 +syn keyword solBuiltinType ufixed144x8 ufixed144x16 ufixed144x24 ufixed144x32 ufixed144x40 ufixed144x48 ufixed144x56 ufixed144x64 ufixed144x72 ufixed144x80 ufixed144x88 ufixed144x96 ufixed144x104 ufixed144x112 +syn keyword solBuiltinType ufixed152x8 ufixed152x16 ufixed152x24 ufixed152x32 ufixed152x40 ufixed152x48 ufixed152x56 ufixed152x64 ufixed152x72 ufixed152x80 ufixed152x88 ufixed152x96 ufixed152x104 +syn keyword solBuiltinType ufixed160x8 ufixed160x16 ufixed160x24 ufixed160x32 ufixed160x40 ufixed160x48 ufixed160x56 ufixed160x64 ufixed160x72 ufixed160x80 ufixed160x88 ufixed160x96 +syn keyword solBuiltinType ufixed168x8 ufixed168x16 ufixed168x24 ufixed168x32 ufixed168x40 ufixed168x48 ufixed168x56 ufixed168x64 ufixed168x72 ufixed168x80 ufixed168x88 +syn keyword solBuiltinType ufixed176x8 ufixed176x16 ufixed176x24 ufixed176x32 ufixed176x40 ufixed176x48 ufixed176x56 ufixed176x64 ufixed176x72 ufixed176x80 +syn keyword solBuiltinType ufixed184x8 ufixed184x16 ufixed184x24 ufixed184x32 ufixed184x40 ufixed184x48 ufixed184x56 ufixed184x64 ufixed184x72 +syn keyword solBuiltinType ufixed192x8 ufixed192x16 ufixed192x24 ufixed192x32 ufixed192x40 ufixed192x48 ufixed192x56 ufixed192x64 +syn keyword solBuiltinType ufixed200x8 ufixed200x16 ufixed200x24 ufixed200x32 ufixed200x40 ufixed200x48 ufixed200x56 +syn keyword solBuiltinType ufixed208x8 ufixed208x16 ufixed208x24 ufixed208x32 ufixed208x40 ufixed208x48 +syn keyword solBuiltinType ufixed216x8 ufixed216x16 ufixed216x24 ufixed216x32 ufixed216x40 +syn keyword solBuiltinType ufixed224x8 ufixed224x16 ufixed224x24 ufixed224x32 +syn keyword solBuiltinType ufixed232x8 ufixed232x16 ufixed232x24 +syn keyword solBuiltinType ufixed240x8 ufixed240x16 +syn keyword solBuiltinType ufixed248x8 +syn keyword solBuiltinType string string1 string2 string3 string4 string5 string6 string7 string8 string9 string10 string11 string12 string13 string14 string15 string16 string17 string18 string19 string20 string21 string22 string23 string24 string25 string26 string27 string28 string29 string30 string31 string32 +syn keyword solBuiltinType byte bytes bytes1 bytes2 bytes3 bytes4 bytes5 bytes6 bytes7 bytes8 bytes9 bytes10 bytes11 bytes12 bytes13 bytes14 bytes15 bytes16 bytes17 bytes18 bytes19 bytes20 bytes21 bytes22 bytes23 bytes24 bytes25 bytes26 bytes27 bytes28 bytes29 bytes30 bytes31 bytes32 + +hi def link solKeyword Keyword +hi def link solConstant Constant +hi def link solBuiltinType Type +hi def link solBuiltinFunction Keyword + +syn match solOperator /\(!\||\|&\|+\|-\|<\|>\|=\|%\|\/\|*\|\~\|\^\)/ +syn match solNumber /\<-\=\d\+L\=\>\|\<0[xX]\x\+\>/ +syn match solFloat /\<-\=\%(\d\+\.\d\+\|\d\+\.\|\.\d\+\)\%([eE][+-]\=\d\+\)\=\>/ + +syn region solString start=+"+ skip=+\\\\\|\\$"\|\\"+ end=+"+ +syn region solString start=+'+ skip=+\\\\\|\\$'\|\\'+ end=+'+ + +hi def link solOperator Operator +hi def link solNumber Number +hi def link solFloat Float +hi def link solString String + +" Function +syn match solFunction /\/ nextgroup=solFuncName,solFuncArgs skipwhite +syn match solFuncName contained /\<[a-zA-Z_$][0-9a-zA-Z_$]*/ nextgroup=solFuncArgs skipwhite + +syn region solFuncArgs contained matchgroup=solFuncParens start='(' end=')' contains=solFuncArgCommas,solBuiltinType nextgroup=solModifierName,solFuncReturns,solFuncBody keepend skipwhite skipempty +syn match solModifierName contained /\<[a-zA-Z_$][0-9a-zA-Z_$]*/ nextgroup=solModifierArgs,solModifierName skipwhite +syn region solModifierArgs contained matchgroup=solFuncParens start='(' end=')' contains=solFuncArgCommas nextgroup=solModifierName,solFuncReturns,solFuncBody skipwhite +syn region solFuncReturns contained matchgroup=solFuncParens nextgroup=solFuncBody start='(' end=')' contains=solFuncArgCommas,solBuiltinType skipwhite + +syn match solFuncArgCommas contained ',' +syn region solFuncBody start="{" end="}" fold transparent + +hi def link solFunction Type +hi def link solFuncName Function +hi def link solModifierName Function + +" Yul blocks +syn match yul /\/ skipwhite skipempty nextgroup=yulBody +syn region yulBody contained start='{' end='}' fold contains=yulAssemblyOp,solNumber,yulVarDeclaration,solLineComment,solComment skipwhite skipempty +syn keyword yulAssemblyOp contained stop add sub mul div sdiv mod smod exp not lt gt slt sgt eq iszero and or xor byte shl shr sar addmod mulmod signextend keccak256 pc pop mload mstore mstore8 sload sstore msize gas address balance selfbalance caller callvalue calldataload calldatasize calldatacopy codesize codecopy extcodesize extcodecopy returndatasize returndatacopy extcodehash create create2 call callcode delegatecall staticcall return revert selfdestruct invalid log0 log1 log2 log3 log4 chainid basefee origin gasprice blockhash coinbase timestamp number difficulty gaslimit +syn keyword yulVarDeclaration contained let + +hi def link yul Keyword +hi def link yulVarDeclaration Keyword +hi def link yulAssemblyOp Keyword + +" Contract +syn match solContract /\<\%(contract\|library\|interface\)\>/ nextgroup=solContractName skipwhite +syn match solContractName contained /\<[a-zA-Z_$][0-9a-zA-Z_$]*/ nextgroup=solContractParent skipwhite +syn region solContractParent contained start='is' end='{' contains=solContractName,solContractNoise,solContractCommas skipwhite skipempty +syn match solContractNoise contained 'is' containedin=solContractParent +syn match solContractCommas contained ',' + +hi def link solContract Type +hi def link solContractName Function + +" Event +syn match solEvent /\/ nextgroup=solEventName,solEventArgs skipwhite +syn match solEventName contained /\<[a-zA-Z_$][0-9a-zA-Z_$]*/ nextgroup=solEventArgs skipwhite +syn region solEventArgs contained matchgroup=solFuncParens start='(' end=')' contains=solEventArgCommas,solBuiltinType,solEventArgSpecial skipwhite skipempty +syn match solEventArgCommas contained ',' +syn match solEventArgSpecial contained 'indexed' + +hi def link solEvent Type +hi def link solEventName Function +hi def link solEventArgSpecial Label + +" Comment +syn keyword solCommentTodo TODO FIXME XXX TBD contained +syn match solNatSpec contained /@title\|@author\|@notice\|@dev\|@param\|@inheritdoc\|@return/ +syn region solLineComment start=+\/\/+ end=+$+ contains=solCommentTodo,solNatSpec,@Spell +syn region solLineComment start=+^\s*\/\/+ skip=+\n\s*\/\/+ end=+$+ contains=solCommentTodo,solNatSpec,@Spell fold +syn region solComment start="/\*" end="\*/" contains=solCommentTodo,solNatSpec,@Spell fold + +hi def link solCommentTodo Todo +hi def link solNatSpec Label +hi def link solLineComment Comment +hi def link solComment Comment + +let b:current_syntax = "solidity" diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim index d5e138dbc3..cbd793fd3c 100644 --- a/runtime/syntax/vim.vim +++ b/runtime/syntax/vim.vim @@ -368,7 +368,7 @@ syn match vimSetMod contained "&vim\=\|[!&?<]\|all&" " Let: {{{2 " === syn keyword vimLet let unl[et] skipwhite nextgroup=vimVar,vimFuncVar,vimLetHereDoc -VimFoldh syn region vimLetHereDoc matchgroup=vimLetHereDocStart start='=<<\s\+\%(trim\|eval\>\)\=\s*\z(\L\S*\)' matchgroup=vimLetHereDocStop end='^\s*\z1\s*$' +VimFoldh syn region vimLetHereDoc matchgroup=vimLetHereDocStart start='=<<\s\+\%(trim\s\+\)\=\%(eval\s\+\)\=\z(\L\S*\)' matchgroup=vimLetHereDocStop end='^\s*\z1\s*$' " Abbreviations: {{{2 " ============= -- cgit From bafeb32b95c61b91220b3090e4293478a74ce31d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 28 Sep 2022 21:55:22 +0800 Subject: fix(spell): correct spell move behavior without "noplainbuffer" (#20386) --- src/nvim/spell.c | 12 ++--- test/functional/ui/spell_spec.lua | 94 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 6 deletions(-) diff --git a/src/nvim/spell.c b/src/nvim/spell.c index 53fa920358..7d2b58ff46 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -1344,14 +1344,14 @@ size_t spell_move_to(win_T *wp, int dir, bool allwords, bool curline, hlf_T *att : p - buf) > wp->w_cursor.col)) { col = (colnr_T)(p - buf); - bool can_spell = (wp->w_s->b_p_spo_flags & SPO_NPBUFFER) == 0; + bool can_spell = decor_spell_nav_col(wp, lnum, &decor_lnum, col, &decor_error); if (!can_spell) { - can_spell = decor_spell_nav_col(wp, lnum, &decor_lnum, col, &decor_error); - } - - if (!can_spell && has_syntax) { - (void)syn_get_id(wp, lnum, col, false, &can_spell, false); + if (has_syntax) { + (void)syn_get_id(wp, lnum, col, false, &can_spell, false); + } else { + can_spell = (wp->w_s->b_p_spo_flags & SPO_NPBUFFER) == 0; + } } if (!can_spell) { diff --git a/test/functional/ui/spell_spec.lua b/test/functional/ui/spell_spec.lua index de77100cc0..1aa73e7b13 100644 --- a/test/functional/ui/spell_spec.lua +++ b/test/functional/ui/spell_spec.lua @@ -19,6 +19,10 @@ describe("'spell'", function() [0] = {bold=true, foreground=Screen.colors.Blue}, [1] = {special = Screen.colors.Red, undercurl = true}, [2] = {special = Screen.colors.Blue1, undercurl = true}, + [3] = {foreground = tonumber('0x6a0dad')}, + [4] = {foreground = Screen.colors.Magenta}, + [5] = {bold = true, foreground = Screen.colors.SeaGreen}, + [6] = {foreground = Screen.colors.Red}, }) end) @@ -68,4 +72,94 @@ describe("'spell'", function() | ]]) end) + + it('"noplainbuffer" and syntax #20385', function() + command('set filetype=c') + command('syntax on') + command('set spell') + insert([[ + #include + bool func(void);]]) + screen:expect([[ + {3:#include }{4:} | + {5:bool} func({5:void})^; | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]) + feed('[s') + screen:expect([[ + {3:#include }{4:} | + {5:bool} func({5:void})^; | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {6:search hit TOP, continuing at BOTTOM} | + ]]) + -- "noplainbuffer" shouldn't change spellchecking behavior with syntax enabled + command('set spelloptions+=noplainbuffer') + screen:expect_unchanged() + feed(']s') + screen:expect([[ + {3:#include }{4:} | + {5:bool} func({5:void})^; | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {6:search hit BOTTOM, continuing at TOP} | + ]]) + -- no spellchecking with "noplainbuffer" and syntax disabled + command('syntax off') + screen:expect([[ + #include | + bool func(void)^; | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {6:search hit BOTTOM, continuing at TOP} | + ]]) + feed('[s') + screen:expect([[ + #include | + bool func(void)^; | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {6:search hit TOP, continuing at BOTTOM} | + ]]) + -- everything is spellchecked without "noplainbuffer" with syntax disabled + command('set spelloptions&') + screen:expect([[ + #include <{1:stdbool}.h> | + {1:bool} {1:func}(void)^; | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {6:search hit TOP, continuing at BOTTOM} | + ]]) + feed(']s') + screen:expect([[ + #include <{1:^stdbool}.h> | + {1:bool} {1:func}(void); | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {6:search hit BOTTOM, continuing at TOP} | + ]]) + end) end) -- cgit From 47b821eccf7bd08f429bb16e9d4ea309d6994896 Mon Sep 17 00:00:00 2001 From: bfredl Date: Wed, 28 Sep 2022 16:16:02 +0200 Subject: docs: mark cmdheight=0 and vim.attach_ui as experimental These will require further work for user experience out of the box during the 0.9 cycle. --- runtime/doc/lua.txt | 6 ++++++ runtime/doc/options.txt | 10 +++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 0c6eb6af78..3026476ab9 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -978,6 +978,12 @@ vim.ui_attach({ns}, {options}, {callback}) *vim.ui_attach()* {callback} receives event name plus additional parameters. See |ui-popupmenu| and the sections below for event format for respective events. + WARNING: This api is considered experimental. Usability will vary for + different screen elements. In particular `ext_messages` behavior is subject + to further changes and usability improvements. This is expected to be + used to handle messages when setting 'cmdheight' to zero (which is + likewise experimental). + Example (stub for a |ui-popupmenu| implementation): > ns = vim.api.nvim_create_namespace('my_fancy_pum') diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index c1a0836f5b..0654265dbe 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1338,9 +1338,13 @@ A jump table for the options with a short description can be found at |Q_op|. When 'cmdheight' is zero, there is no command-line unless it is being used. The command-line will cover the last line of the screen when - shown. Some informative messages will not be displayed, any other - messages will cause the |hit-enter| prompt. Expect some other - unexpected behavior too. + shown. + + WARNING: `cmdheight=0` is considered experimental. Except some + unwanted behaviour. Some 'shortmess' flags and similar + mechanism might fail to take effect, causing unwanted hit-enter + prompts. Some informative messages, both from Nvim itself and + plugins, will not be displayed. *'cmdwinheight'* *'cwh'* 'cmdwinheight' 'cwh' number (default 7) -- cgit From a5effcedd2888298fda62947410316c080e9a4dc Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Wed, 28 Sep 2022 16:29:35 +0200 Subject: build(deps): bump help parser and queries (#20388) --- cmake.deps/CMakeLists.txt | 4 ++-- runtime/queries/help/highlights.scm | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/cmake.deps/CMakeLists.txt b/cmake.deps/CMakeLists.txt index 897d056860..da95fe31b3 100644 --- a/cmake.deps/CMakeLists.txt +++ b/cmake.deps/CMakeLists.txt @@ -210,8 +210,8 @@ set(TREESITTER_LUA_SHA256 564594fe0ffd2f2fb3578a15019b723e1bc94ac82cb6a0103a6b3b set(TREESITTER_VIM_URL https://github.com/vigoux/tree-sitter-viml/archive/v0.2.0.tar.gz) set(TREESITTER_VIM_SHA256 608dcc31a7948cb66ae7f45494620e2e9face1af75598205541f80d782ec4501) -set(TREESITTER_HELP_URL https://github.com/vigoux/tree-sitter-vimdoc/archive/a2c5c01f797eef67634941630442eea66eb7e1b6.tar.gz) -set(TREESITTER_HELP_SHA256 b999c145da02652c235d497cb32e72660175d3b9fa129a7a6ba164b60414e73d) +set(TREESITTER_HELP_URL https://github.com/neovim/tree-sitter-vimdoc/archive/v1.0.tar.gz) +set(TREESITTER_HELP_SHA256 42821a3aa35e7fefcedbe1090f76f997dbdb2de7cbe76ba1507c1426d9a6af19) set(TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/v0.20.7.tar.gz) set(TREESITTER_SHA256 b355e968ec2d0241bbd96748e00a9038f83968f85d822ecb9940cbe4c42e182e) diff --git a/runtime/queries/help/highlights.scm b/runtime/queries/help/highlights.scm index 41c78a7f1c..6be4e49c81 100644 --- a/runtime/queries/help/highlights.scm +++ b/runtime/queries/help/highlights.scm @@ -1,14 +1,16 @@ -(headline) @text.title +(h1) @text.title +(h2) @text.title +(h3) @text.title (column_heading) @text.title (tag "*" @conceal (#set! conceal "") - name: (_) @label) -(option - name: (_) @text.literal) -(hotlink + text: (_) @label) +(taglink "|" @conceal (#set! conceal "") - destination: (_) @text.reference) -(backtick + text: (_) @text.reference) +(optionlink + text: (_) @text.literal) +(codespan "`" @conceal (#set! conceal "") - content: (_) @string) + text: (_) @string) (argument) @parameter -- cgit From cd96fe06e188bcd6e64f78cb078a307fb45f31f0 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Wed, 28 Sep 2022 16:39:42 +0200 Subject: build(deps): bump treesitter-vimdoc to v1.0.0 --- cmake.deps/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake.deps/CMakeLists.txt b/cmake.deps/CMakeLists.txt index da95fe31b3..30587b39e9 100644 --- a/cmake.deps/CMakeLists.txt +++ b/cmake.deps/CMakeLists.txt @@ -210,8 +210,8 @@ set(TREESITTER_LUA_SHA256 564594fe0ffd2f2fb3578a15019b723e1bc94ac82cb6a0103a6b3b set(TREESITTER_VIM_URL https://github.com/vigoux/tree-sitter-viml/archive/v0.2.0.tar.gz) set(TREESITTER_VIM_SHA256 608dcc31a7948cb66ae7f45494620e2e9face1af75598205541f80d782ec4501) -set(TREESITTER_HELP_URL https://github.com/neovim/tree-sitter-vimdoc/archive/v1.0.tar.gz) -set(TREESITTER_HELP_SHA256 42821a3aa35e7fefcedbe1090f76f997dbdb2de7cbe76ba1507c1426d9a6af19) +set(TREESITTER_HELP_URL https://github.com/neovim/tree-sitter-vimdoc/archive/v1.0.0.tar.gz) +set(TREESITTER_HELP_SHA256 bb026d479b0a8ac4d05b6c0cc11f698f2476828e7df9ff34c11dc5178a361e5a) set(TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/v0.20.7.tar.gz) set(TREESITTER_SHA256 b355e968ec2d0241bbd96748e00a9038f83968f85d822ecb9940cbe4c42e182e) -- cgit From d9ed8d1110847e4cd4c49c23eba1f86fff8b29bf Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Wed, 28 Sep 2022 16:19:33 +0200 Subject: feat(treesitter): update :help parser and queries --- cmake.deps/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake.deps/CMakeLists.txt b/cmake.deps/CMakeLists.txt index 30587b39e9..941db5fb0a 100644 --- a/cmake.deps/CMakeLists.txt +++ b/cmake.deps/CMakeLists.txt @@ -210,8 +210,8 @@ set(TREESITTER_LUA_SHA256 564594fe0ffd2f2fb3578a15019b723e1bc94ac82cb6a0103a6b3b set(TREESITTER_VIM_URL https://github.com/vigoux/tree-sitter-viml/archive/v0.2.0.tar.gz) set(TREESITTER_VIM_SHA256 608dcc31a7948cb66ae7f45494620e2e9face1af75598205541f80d782ec4501) -set(TREESITTER_HELP_URL https://github.com/neovim/tree-sitter-vimdoc/archive/v1.0.0.tar.gz) -set(TREESITTER_HELP_SHA256 bb026d479b0a8ac4d05b6c0cc11f698f2476828e7df9ff34c11dc5178a361e5a) +set(TREESITTER_HELP_URL https://github.com/neovim/tree-sitter-vimdoc/archive/2ba61cf9e7236d0ae3ce5c526bbd689ace3ff3bd.tar.gz) +set(TREESITTER_HELP_SHA256 ce89e486c2cc52c0d82edf0600d0f67af9ae9e4b438673224633d0c9f47c62be) set(TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/v0.20.7.tar.gz) set(TREESITTER_SHA256 b355e968ec2d0241bbd96748e00a9038f83968f85d822ecb9940cbe4c42e182e) -- cgit From 7b4c49888a97c21f346b8337330fbc8e196b9cf8 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Fri, 23 Sep 2022 14:26:59 +0200 Subject: feat(gen_help_html.lua): put commit-id in footer --- scripts/gen_help_html.lua | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua index d79ece53f3..6e297814b8 100644 --- a/scripts/gen_help_html.lua +++ b/scripts/gen_help_html.lua @@ -16,7 +16,7 @@ -- -- NOTES: -- * gen() and validate() are the primary entrypoints. validate() only exists because gen() is too --- slow (~1 min) to run in per-commit CI. +-- slow (~1 min) to run in per-commit CI. -- * visit_node() is the core function used by gen() to traverse the document tree and produce HTML. -- * visit_validate() is the core function used by validate(). -- * Files in `new_layout` will be generated with a "flow" layout instead of preformatted/fixed-width layout. @@ -50,7 +50,6 @@ local tagmap = nil local helpfiles = nil local invalid_tags = {} -local commit = '?' local api = vim.api local M = {} @@ -477,7 +476,7 @@ end -- @param old boolean Preformat paragraphs (for old :help files which are full of arbitrary whitespace) -- -- @returns html, stats -local function gen_one(fname, to_fname, old) +local function gen_one(fname, to_fname, old, commit) local stats = { noise_lines = {}, parse_errors = {}, @@ -604,7 +603,7 @@ local function gen_one(fname, to_fname, old)
- Generated on %s from {%s} + Generated at %s from %s
parse_errors: %d %s | noise_lines: %d @@ -612,7 +611,7 @@ local function gen_one(fname, to_fname, old)
]]):format( - os.date('%Y-%m-%d %H:%M:%S'), commit, #stats.parse_errors, bug_link, + os.date('%Y-%m-%d %H:%M'), commit, commit:sub(1, 7), #stats.parse_errors, bug_link, html_esc(table.concat(stats.noise_lines, '\n')), #stats.noise_lines) html = ('%s%s%s
\n%s\n\n'):format( @@ -763,11 +762,12 @@ end --- @param include table|nil Process only these filenames. Example: {'api.txt', 'autocmd.txt', 'channel.txt'} --- --- @returns info dict -function M.gen(help_dir, to_dir, include) +function M.gen(help_dir, to_dir, include, commit) vim.validate{ help_dir={help_dir, function(d) return vim.fn.isdirectory(d) == 1 end, 'valid directory'}, to_dir={to_dir, 's'}, include={include, 't', true}, + commit={commit, 's', true}, } local err_count = 0 @@ -781,7 +781,7 @@ function M.gen(help_dir, to_dir, include) for _, f in ipairs(helpfiles) do local helpfile = vim.fs.basename(f) local to_fname = ('%s/%s'):format(to_dir, get_helppage(helpfile)) - local html, stats = gen_one(f, to_fname, not new_layout[helpfile]) + local html, stats = gen_one(f, to_fname, not new_layout[helpfile], commit or '?') tofile(to_fname, html) print(('generated (%-4s errors): %-15s => %s'):format(#stats.parse_errors, helpfile, vim.fs.basename(to_fname))) err_count = err_count + #stats.parse_errors -- cgit From 16336c486ecb5a60e85a870904316308c7d7fc3f Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 25 Sep 2022 02:20:47 +0200 Subject: feat(gen_help_html.lua): adapt to new parser - adapt to parser changes from https://github.com/vigoux/tree-sitter-vimdoc/pull/16 - numerous other generator improvements --- runtime/doc/api.txt | 53 ++-- runtime/doc/develop.txt | 17 ++ runtime/doc/eval.txt | 2 +- runtime/doc/filetype.txt | 2 +- runtime/doc/helphelp.txt | 7 +- runtime/doc/luaref.txt | 110 +++---- runtime/doc/quickref.txt | 45 ++- runtime/doc/ui.txt | 201 +++++++------ runtime/lua/vim/lsp/util.lua | 4 +- scripts/gen_help_html.lua | 467 +++++++++++++++++++----------- test/functional/core/startup_spec.lua | 4 +- test/functional/helpers.lua | 13 +- test/functional/lua/help_spec.lua | 31 +- test/functional/options/defaults_spec.lua | 58 ++-- 14 files changed, 601 insertions(+), 413 deletions(-) diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index f0145344a4..59d1d36be9 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -83,6 +83,7 @@ and |rpcnotify()|: let nvim = jobstart(['nvim', '--embed'], {'rpc': v:true}) echo rpcrequest(nvim, 'nvim_eval', '"Hello " . "world!"') call jobstop(nvim) +< ============================================================================== API Definitions *api-definitions* @@ -92,7 +93,7 @@ The Nvim C API defines custom types for all function parameters. Some are just typedefs around C99 standard types, others are Nvim-defined data structures. Basic types ~ - +> API Type C type ------------------------------------------------------------------------ Nil @@ -103,7 +104,7 @@ Basic types ~ Array Dictionary (msgpack: map) Object - +< Note: empty Array is accepted as a valid argument for Dictionary parameter. Special types (msgpack EXT) ~ @@ -115,13 +116,13 @@ Special types (msgpack EXT) ~ The EXT object data is the (integer) object handle. The EXT type codes given in the |api-metadata| `types` key are stable: they will not change and are thus forward-compatible. - +> EXT Type C type Data ------------------------------------------------------------------------ Buffer enum value kObjectTypeBuffer |bufnr()| Window enum value kObjectTypeWindow |window-ID| Tabpage enum value kObjectTypeTabpage internal handle - +< *api-indexing* Most of the API uses 0-based indices, and ranges are end-exclusive. For the @@ -130,19 +131,19 @@ end of a range, -1 denotes the last line/column. Exception: the following API functions use "mark-like" indexing (1-based lines, 0-based columns): - |nvim_get_mark()| - |nvim_buf_get_mark()| - |nvim_buf_set_mark()| - |nvim_win_get_cursor()| - |nvim_win_set_cursor()| +- |nvim_get_mark()| +- |nvim_buf_get_mark()| +- |nvim_buf_set_mark()| +- |nvim_win_get_cursor()| +- |nvim_win_set_cursor()| Exception: the following API functions use |extmarks| indexing (0-based indices, end-inclusive): - |nvim_buf_del_extmark()| - |nvim_buf_get_extmark_by_id()| - |nvim_buf_get_extmarks()| - |nvim_buf_set_extmark()| +- |nvim_buf_del_extmark()| +- |nvim_buf_get_extmark_by_id()| +- |nvim_buf_get_extmarks()| +- |nvim_buf_set_extmark()| *api-fast* Most API functions are "deferred": they are queued on the main loop and @@ -162,19 +163,19 @@ and return values. Nvim exposes its API metadata as a Dictionary with these items: -version Nvim version, API level/compatibility -version.api_level API version integer *api-level* -version.api_compatible API is backwards-compatible with this level -version.api_prerelease Declares the API as unstable/unreleased > - (version.api_prerelease && fn.since == version.api_level) -functions API function signatures, containing |api-types| info - describing the return value and parameters. -ui_events |UI| event signatures -ui_options Supported |ui-option|s -{fn}.since API level where function {fn} was introduced -{fn}.deprecated_since API level where function {fn} was deprecated -types Custom handle types defined by Nvim -error_types Possible error types returned by API functions +- version Nvim version, API level/compatibility +- version.api_level API version integer *api-level* +- version.api_compatible API is backwards-compatible with this level +- version.api_prerelease Declares the API as unstable/unreleased + `(version.api_prerelease && fn.since == version.api_level)` +- functions API function signatures, containing |api-types| info + describing the return value and parameters. +- ui_events |UI| event signatures +- ui_options Supported |ui-option|s +- {fn}.since API level where function {fn} was introduced +- {fn}.deprecated_since API level where function {fn} was deprecated +- types Custom handle types defined by Nvim +- error_types Possible error types returned by API functions About the `functions` map: diff --git a/runtime/doc/develop.txt b/runtime/doc/develop.txt index 4f17e7d34a..ebb0dfeb4e 100644 --- a/runtime/doc/develop.txt +++ b/runtime/doc/develop.txt @@ -151,6 +151,23 @@ DOCUMENTATION *dev-doc* /// @param dirname The path fragment before `pend` < +Documentation format ~ + +For Nvim-owned docs, use the following strict subset of "vimdoc" to ensure +the help doc renders nicely in other formats (such as HTML: +https://neovim.io/doc/user ). + +Strict "vimdoc" subset: + +- Use lists (like this!) prefixed with "-", "*", or "•", for adjacent lines + that you don't want auto-wrapped. Lists are always rendered with "flow" + (soft-wrapped) layout instead of preformatted (hard-wrapped) layout common + in legacy :help docs. +- Separate blocks (paragraphs) of content by a blank line(s). +- Do not use indentation in random places—that prevents the page from using + "flow" layout. If you need a preformatted section, put it in + a |help-codeblock| starting with ">". + C docstrings ~ Nvim API documentation lives in the source code, as docstrings (Doxygen diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index ae28977556..6a9fb6d03c 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -4119,7 +4119,7 @@ This example sorts lines with a specific compare function. > As a one-liner: > :call setline(1, sort(getline(1, '$'), function("Strcmp"))) - +< scanf() replacement ~ *sscanf* diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt index 9f8ef248f8..ac54a6b6ca 100644 --- a/runtime/doc/filetype.txt +++ b/runtime/doc/filetype.txt @@ -178,7 +178,7 @@ If a file type that you want to use is not detected yet, there are a few ways to add it. In any way, it's better not to modify the $VIMRUNTIME/filetype.lua or $VIMRUNTIME/filetype.vim files. They will be overwritten when installing a new version of Nvim. The following explains the legacy Vim mechanism (enabled -if |do_legacy_filetype| is set). For Nvim's default mechanism, see +if |g:do_legacy_filetype| is set). For Nvim's default mechanism, see |vim.filetype.add()|. A. If you want to overrule all default file type checks. diff --git a/runtime/doc/helphelp.txt b/runtime/doc/helphelp.txt index 569995d319..4758cd37c6 100644 --- a/runtime/doc/helphelp.txt +++ b/runtime/doc/helphelp.txt @@ -212,12 +212,6 @@ This is done when viewing the file in Vim, the file itself is not changed. It is done by going through all help files and obtaining the first line of each file. The files in $VIMRUNTIME/doc are skipped. - *help-xterm-window* -If you want to have the help in another xterm window, you could use this -command: > - :!xterm -e vim +help & -< - *:helpt* *:helptags* *E150* *E151* *E152* *E153* *E154* *E670* *E856* :helpt[ags] [++t] {dir} @@ -372,6 +366,7 @@ To separate sections in a help file, place a series of '=' characters in a line starting from the first column. The section separator line is highlighted differently. + *help-codeblock* To quote a block of ex-commands verbatim, place a greater than (>) character at the end of the line before the block and a less than (<) character as the first non-blank on a line following the block. Any line starting in column 1 diff --git a/runtime/doc/luaref.txt b/runtime/doc/luaref.txt index ecb92d4bb6..0b04005e1a 100644 --- a/runtime/doc/luaref.txt +++ b/runtime/doc/luaref.txt @@ -55,7 +55,6 @@ Lua means "moon" in Portuguese and is pronounced LOO-ah. ============================================================================== 2 THE LANGUAGE *luaref-language* -============================================================================== This section describes the lexis, the syntax, and the semantics of Lua. In other words, this section describes which tokens are valid, how they can be @@ -450,21 +449,22 @@ through an arithmetic progression. It has the following syntax: < The `block` is repeated for `name` starting at the value of the first `exp`, until it passes the second `exp` by steps of the third `exp`. More precisely, -a `for` statement like +a `for` statement like > - `for var =` `e1, e2, e3` `do` `block` `end` + for var = e1, e2, e3 do block end -is equivalent to the code: +< is equivalent to the code: > - `do` - `local` `var, limit, step` `= tonumber(e1), tonumber(e2), tonumber(e3)` - `if not (` `var` `and` `limit` `and` `step` `) then error() end` - `while (` `step` `>0 and` `var` `<=` `limit` `)` - `or (` `step` `<=0 and` `var` `>=` `limit` `) do` - `block` - `var` `=` `var` `+` `step` - `end` - `end` + do + local var, limit, step = tonumber(e1), tonumber(e2), tonumber(e3) + if not ( var and limit and step ) then error() end + while ( step >0 and var <= limit ) + or ( step <=0 and var >= limit ) do + block + var = var + step + end + end +< Note the following: @@ -490,18 +490,18 @@ A `for` statement like `for` `var1, ..., varn` `in` `explist` `do` `block` `end` -is equivalent to the code: - - `do` - `local` `f, s, var` `=` `explist` - `while true do` - `local` `var1, ..., varn` `=` `f(s, var)` - `var` `=` `var1` - `if` `var` `== nil then break end` - `block` - `end` - `end` +is equivalent to the code: > + do + local f, s, var = explist + while true do + local var1, ..., varn = f(s, var) + var = var1 + if var == nil then break end + block + end + end +< Note the following: - `explist` is evaluated only once. Its results are an iterator function, @@ -1871,25 +1871,25 @@ lua_gc *lua_gc()* This function performs several tasks, according to the value of the parameter `what`: - `LUA_GCSTOP` stops the garbage collector. - `LUA_GCRESTART` restarts the garbage collector. - `LUA_GCCOLLECT` performs a full garbage-collection cycle. - `LUA_GCCOUNT` returns the current amount of memory (in Kbytes) in + - `LUA_GCSTOP` stops the garbage collector. + - `LUA_GCRESTART` restarts the garbage collector. + - `LUA_GCCOLLECT` performs a full garbage-collection cycle. + - `LUA_GCCOUNT` returns the current amount of memory (in Kbytes) in use by Lua. - `LUA_GCCOUNTB` returns the remainder of dividing the current + - `LUA_GCCOUNTB` returns the remainder of dividing the current amount of bytes of memory in use by Lua by 1024. - `LUA_GCSTEP` performs an incremental step of garbage collection. + - `LUA_GCSTEP` performs an incremental step of garbage collection. The step "size" is controlled by `data` (larger values mean more steps) in a non-specified way. If you want to control the step size you must experimentally tune the value of `data`. The function returns 1 if the step finished a garbage-collection cycle. - `LUA_GCSETPAUSE` sets `data` /100 as the new value for the + - `LUA_GCSETPAUSE` sets `data` /100 as the new value for the `pause` of the collector (see |luaref-langGC|). The function returns the previous value of the pause. - `LUA_GCSETSTEPMUL` sets `data` /100 as the new value for the + - `LUA_GCSETSTEPMUL`sets `data` /100 as the new value for the `step` `multiplier` of the collector (see |luaref-langGC|). The function returns the previous value of the step multiplier. @@ -2717,20 +2717,22 @@ need "inside information" from the interpreter. lua_Debug *lua_Debug()* - `typedef struct lua_Debug {` - `int event;` - `const char *name; /* (n) */` - `const char *namewhat; /* (n) */` - `const char *what; /* (S) */` - `const char *source; /* (S) */` - `int currentline; /* (l) */` - `int nups; /* (u) number of upvalues */` - `int linedefined; /* (S) */` - `int lastlinedefined; /* (S) */` - `char short_src[LUA_IDSIZE]; /* (S) */` - `/* private part */` - `other fields` - `} lua_Debug;` +> + typedef struct lua_Debug { + int event; + const char *name; /* (n) */ + const char *namewhat; /* (n) */ + const char *what; /* (S) */ + const char *source; /* (S) */ + int currentline; /* (l) */ + int nups; /* (u) number of upvalues */ + int linedefined; /* (S) */ + int lastlinedefined; /* (S) */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + other fields + } lua_Debug; +< A structure used to carry different pieces of information about an active function. `lua_getstack` (see |lua_getstack()|) fills only the private part @@ -2739,28 +2741,28 @@ useful information, call `lua_getinfo` (see |lua_getinfo()|). The fields of `lua_Debug` have the following meaning: - `source` If the function was defined in a string, then `source` is +- `source` If the function was defined in a string, then `source` is that string. If the function was defined in a file, then `source` starts with a `@` followed by the file name. - `short_src` a "printable" version of `source`, to be used in error messages. - `linedefined` the line number where the definition of the function starts. - `lastlinedefined` the line number where the definition of the function ends. - `what` the string `"Lua"` if the function is a Lua function, +- `short_src` a "printable" version of `source`, to be used in error messages. +- `linedefined` the line number where the definition of the function starts. +- `lastlinedefined` the line number where the definition of the function ends. +- `what` the string `"Lua"` if the function is a Lua function, `"C"` if it is a C function, `"main"` if it is the main part of a chunk, and `"tail"` if it was a function that did a tail call. In the latter case, Lua has no other information about the function. - `currentline` the current line where the given function is executing. +- `currentline` the current line where the given function is executing. When no line information is available, `currentline` is set to -1. - `name` a reasonable name for the given function. Because +- `name` a reasonable name for the given function. Because functions in Lua are first-class values, they do not have a fixed name: some functions may be the value of multiple global variables, while others may be stored only in a table field. The `lua_getinfo` function checks how the function was called to find a suitable name. If it cannot find a name, then `name` is set to `NULL`. - `namewhat` explains the `name` field. The value of `namewhat` can be +- `namewhat` explains the `name` field. The value of `namewhat` can be `"global"`, `"local"`, `"method"`, `"field"`, `"upvalue"`, or `""` (the empty string), according to how the function was called. (Lua uses the empty string when diff --git a/runtime/doc/quickref.txt b/runtime/doc/quickref.txt index 23ce16a40a..bdb0f7447c 100644 --- a/runtime/doc/quickref.txt +++ b/runtime/doc/quickref.txt @@ -3,7 +3,8 @@ VIM REFERENCE MANUAL by Bram Moolenaar - Quick reference guide +============================================================================== +Quick reference guide *quickref* *Contents* tag subject tag subject ~ @@ -29,11 +30,11 @@ |Q_to| Text objects |Q_gu| GUI commands |Q_fo| Folding ------------------------------------------------------------------------------- -N is used to indicate an optional count that can be given before the command. ------------------------------------------------------------------------------ *Q_lr* Left-right motions +N is used to indicate an optional count that can be given before the command. + |h| N h left (also: CTRL-H, , or key) |l| N l right (also: or key) |0| 0 to first character in the line (also: key) @@ -56,6 +57,7 @@ N is used to indicate an optional count that can be given before the command. |;| N ; repeat the last "f", "F", "t", or "T" N times |,| N , repeat the last "f", "F", "t", or "T" N times in opposite direction + ------------------------------------------------------------------------------ *Q_ud* Up-down motions @@ -73,6 +75,7 @@ N is used to indicate an optional count that can be given before the command. given, otherwise it is the |%| command |gk| N gk up N screen lines (differs from "k" when line wraps) |gj| N gj down N screen lines (differs from "j" when line wraps) + ------------------------------------------------------------------------------ *Q_tm* Text object motions @@ -105,6 +108,7 @@ N is used to indicate an optional count that can be given before the command. |]#| N ]# N times forward to unclosed "#else" or "#endif" |[star| N [* N times back to start of comment "/*" |]star| N ]* N times forward to end of comment "*/" + ------------------------------------------------------------------------------ *Q_pa* Pattern searches @@ -168,6 +172,7 @@ N is used to indicate an optional count that can be given before the command. b[+num] [num] identical to s[+num] above (mnemonic: begin) b[-num] [num] identical to s[-num] above (mnemonic: begin) ;{search-command} execute {search-command} next + ------------------------------------------------------------------------------ *Q_ma* Marks and motions @@ -188,6 +193,7 @@ N is used to indicate an optional count that can be given before the command. |CTRL-O| N CTRL-O go to Nth older position in jump list |CTRL-I| N CTRL-I go to Nth newer position in jump list |:ju| :ju[mps] print the jump list + ------------------------------------------------------------------------------ *Q_vm* Various motions @@ -202,6 +208,7 @@ N is used to indicate an optional count that can be given before the command. |go| N go go to Nth byte in the buffer |:go| :[range]go[to] [off] go to [off] byte in the buffer + ------------------------------------------------------------------------------ *Q_ta* Using tags @@ -229,6 +236,7 @@ N is used to indicate an optional count that can be given before the command. |:ptjump| :ptj[ump] like ":tjump" but show tag in preview window |:pclose| :pc[lose] close tag preview window |CTRL-W_z| CTRL-W z close tag preview window + ------------------------------------------------------------------------------ *Q_sc* Scrolling @@ -247,6 +255,7 @@ These only work when 'wrap' is off: |zl| N zl scroll screen N characters to the left |zH| N zH scroll screen half a screenwidth to the right |zL| N zL scroll screen half a screenwidth to the left + ------------------------------------------------------------------------------ *Q_in* Inserting text @@ -263,6 +272,7 @@ These only work when 'wrap' is off: in Visual block mode: |v_b_I| I insert the same text in front of all the selected lines |v_b_A| A append the same text after all the selected lines + ------------------------------------------------------------------------------ *Q_ai* Insert mode keys @@ -279,6 +289,7 @@ moving around: |i_| shift-up/down one screenful backward/forward |i_| cursor after last character in the line |i_| cursor to first character in the line + ------------------------------------------------------------------------------ *Q_ss* Special keys in Insert mode @@ -313,6 +324,7 @@ moving around: |i_0_CTRL-D| 0 CTRL-D delete all indent in the current line |i_^_CTRL-D| ^ CTRL-D delete all indent in the current line, restore indent in next line + ------------------------------------------------------------------------------ *Q_di* Digraphs @@ -325,12 +337,14 @@ In Insert or Command-line mode: enter digraph |i_digraph| {char1} {char2} enter digraph if 'digraph' option set + ------------------------------------------------------------------------------ *Q_si* Special inserts |:r| :r [file] insert the contents of [file] below the cursor |:r!| :r! {command} insert the standard output of {command} below the cursor + ------------------------------------------------------------------------------ *Q_de* Deleting text @@ -346,6 +360,7 @@ In Insert or Command-line mode: |gJ| N gJ like "J", but without inserting spaces |v_gJ| {visual}gJ like "{visual}J", but without inserting spaces |:d| :[range]d [x] delete [range] lines [into register x] + ------------------------------------------------------------------------------ *Q_cm* Copying and moving text @@ -363,6 +378,7 @@ In Insert or Command-line mode: |[p| N [p like P, but adjust indent to current line |gp| N gp like p, but leave cursor after the new text |gP| N gP like P, but leave cursor after the new text + ------------------------------------------------------------------------------ *Q_ch* Changing text @@ -418,6 +434,7 @@ In Insert or Command-line mode: left-align the lines in [range] (with [indent]) |:ri| :[range]ri[ght] [width] right-align the lines in [range] + ------------------------------------------------------------------------------ *Q_co* Complex changes @@ -444,6 +461,7 @@ In Insert or Command-line mode: |:ret| :[range]ret[ab][!] [tabstop] set 'tabstop' to new value and adjust white space accordingly + ------------------------------------------------------------------------------ *Q_vi* Visual mode @@ -457,6 +475,7 @@ In Insert or Command-line mode: |v_v| v highlight characters or stop highlighting |v_V| V highlight linewise or stop highlighting |v_CTRL-V| CTRL-V highlight blockwise or stop highlighting + ------------------------------------------------------------------------------ *Q_to* Text objects (only in Visual mode or after an operator) @@ -509,6 +528,7 @@ In Insert or Command-line mode: |:sl| :sl[eep] [sec] don't do anything for [sec] seconds |gs| N gs goto Sleep for N seconds + ------------------------------------------------------------------------------ *Q_km* Key mapping @@ -556,6 +576,7 @@ In Insert or Command-line mode: like ":mkvimrc", but store current files, windows, etc. too, to be able to continue this session later + ------------------------------------------------------------------------------ *Q_ab* Abbreviations @@ -570,6 +591,7 @@ In Insert or Command-line mode: |:abclear| :abc[lear] remove all abbreviations |:cabclear| :cabc[lear] remove all abbr's for Cmdline mode |:iabclear| :iabc[lear] remove all abbr's for Insert mode + ------------------------------------------------------------------------------ *Q_op* Options @@ -940,18 +962,21 @@ Short explanation of each option: *option-list* 'writeany' 'wa' write to file with no need for "!" override 'writebackup' 'wb' make a backup before overwriting a file 'writedelay' 'wd' delay this many msec for each char (for debug) + ------------------------------------------------------------------------------ *Q_ur* Undo/Redo commands |u| N u undo last N changes |CTRL-R| N CTRL-R redo last N undone changes |U| U restore last changed line + ------------------------------------------------------------------------------ *Q_et* External commands |:!| :!{command} execute {command} with a shell |K| K lookup keyword under the cursor with 'keywordprg' program (default: "man") + ------------------------------------------------------------------------------ *Q_qf* Quickfix commands @@ -975,6 +1000,7 @@ Short explanation of each option: *option-list* error |:grep| :gr[ep] [args] execute 'grepprg' to find matches and jump to the first one + ------------------------------------------------------------------------------ *Q_vc* Various commands @@ -1000,6 +1026,7 @@ Short explanation of each option: *option-list* unsaved changes or read-only files |:browse| :browse {command} open/read/write file, using a file selection dialog + ------------------------------------------------------------------------------ *Q_ce* Command-line editing @@ -1046,6 +1073,7 @@ Context-sensitive completion on the command-line: to next match |c_CTRL-P| CTRL-P after 'wildchar' with multiple matches: go to previous match + ------------------------------------------------------------------------------ *Q_ra* Ex ranges @@ -1066,6 +1094,7 @@ Context-sensitive completion on the command-line: (default: 1) |:range| -[num] subtract [num] from the preceding line number (default: 1) + ------------------------------------------------------------------------------ *Q_ex* Special Ex characters @@ -1098,6 +1127,7 @@ Context-sensitive completion on the command-line: |::r| :r root (extension removed) |::e| :e extension |::s| :s/{pat}/{repl}/ substitute {pat} with {repl} + ------------------------------------------------------------------------------ *Q_st* Starting Vim @@ -1134,6 +1164,7 @@ Context-sensitive completion on the command-line: |--help| --help show list of arguments and exit |--version| --version show version info and exit |--| - read file from stdin + ------------------------------------------------------------------------------ *Q_ed* Editing a file @@ -1153,6 +1184,7 @@ Context-sensitive completion on the command-line: position |:file| :f[ile] {name} set the current file name to {name} |:files| :files show alternate file names + ------------------------------------------------------------------------------ *Q_fl* Using the argument list |argument-list| @@ -1173,6 +1205,7 @@ Context-sensitive completion on the command-line: |:Next| :N[ext] :sN[ext] edit previous file |:first| :fir[st] :sfir[st] edit first file |:last| :la[st] :sla[st] edit last file + ------------------------------------------------------------------------------ *Q_wq* Writing and quitting @@ -1210,6 +1243,7 @@ Context-sensitive completion on the command-line: |:stop| :st[op][!] suspend Vim or start new shell; if 'aw' option is set and [!] not given write the buffer |CTRL-Z| CTRL-Z same as ":stop" + ------------------------------------------------------------------------------ *Q_ac* Automatic Commands @@ -1241,6 +1275,7 @@ Context-sensitive completion on the command-line: with {pat} |:autocmd| :au! {event} {pat} {cmd} remove all autocommands for {event} with {pat} and enter new one + ------------------------------------------------------------------------------ *Q_wi* Multi-window commands @@ -1286,6 +1321,7 @@ Context-sensitive completion on the command-line: |CTRL-W_>| CTRL-W > increase current window width |CTRL-W_bar| CTRL-W | set current window width (default: widest possible) + ------------------------------------------------------------------------------ *Q_bu* Buffer list commands @@ -1307,6 +1343,7 @@ Context-sensitive completion on the command-line: |:bfirst| :bfirst :sbfirst to first arg/buf |:blast| :blast :sblast to last arg/buf |:bmodified| :[N]bmod [N] :[N]sbmod [N] to Nth modified buf + ------------------------------------------------------------------------------ *Q_sy* Syntax Highlighting @@ -1333,6 +1370,7 @@ Context-sensitive completion on the command-line: |:filetype| :filetype plugin indent on switch on file type detection, with automatic indenting and settings + ------------------------------------------------------------------------------ *Q_gu* GUI commands @@ -1345,6 +1383,7 @@ Context-sensitive completion on the command-line: add toolbar item, giving {rhs} |:tmenu| :tmenu {mpath} {text} add tooltip to menu {mpath} |:unmenu| :unmenu {mpath} remove menu {mpath} + ------------------------------------------------------------------------------ *Q_fo* Folding diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt index 2d0c8d3b75..7ce6cd251f 100644 --- a/runtime/doc/ui.txt +++ b/runtime/doc/ui.txt @@ -23,40 +23,37 @@ screen grid with a size of width × height cells. This is typically done by an embedder at startup (see |ui-startup|), but UIs can also connect to a running Nvim instance and invoke nvim_ui_attach(). The `options` parameter is a map with these (optional) keys: + *ui-rgb* - `rgb` Decides the color format. - true: (default) 24-bit RGB colors - false: Terminal colors (8-bit, max 256) +- `rgb` Decides the color format. + - true: (default) 24-bit RGB colors + - false: Terminal colors (8-bit, max 256) *ui-override* - `override` Decides how UI capabilities are resolved. - true: Enable requested UI capabilities, even - if not supported by all connected UIs - (including |TUI|). - false: (default) Disable UI capabilities not - supported by all connected UIs - (including TUI). +- `override` Decides how UI capabilities are resolved. + - true: Enable requested UI capabilities, even if not + supported by all connected UIs (including |TUI|). + - false: (default) Disable UI capabilities not + supported by all connected UIs (including TUI). *ui-ext-options* - `ext_cmdline` Externalize the cmdline. |ui-cmdline| - `ext_hlstate` Detailed highlight state. |ui-hlstate| - Sets `ext_linegrid` implicitly. - `ext_linegrid` Line-based grid events. |ui-linegrid| - Deactivates |ui-grid-old| implicitly. - `ext_messages` Externalize messages. |ui-messages| - Sets `ext_linegrid` and `ext_cmdline` implicitly. - `ext_multigrid` Per-window grid events. |ui-multigrid| - Sets `ext_linegrid` implicitly. - `ext_popupmenu` Externalize |popupmenu-completion| and - 'wildmenu'. |ui-popupmenu| - `ext_tabline` Externalize the tabline. |ui-tabline| - `ext_termcolors` Use external default colors. - `term_name` Sets the name of the terminal 'term'. - `term_colors` Sets the number of supported colors 't_Co'. - `term_background` Sets the default value of 'background'. - `stdin_fd` Read buffer from `fd` as if it was a stdin pipe - This option can only used by |--embed| ui, - see |ui-startup-stdin|. - - +- `ext_cmdline` Externalize the cmdline. |ui-cmdline| +- `ext_hlstate` Detailed highlight state. |ui-hlstate| + Sets `ext_linegrid` implicitly. +- `ext_linegrid` Line-based grid events. |ui-linegrid| + Deactivates |ui-grid-old| implicitly. +- `ext_messages` Externalize messages. |ui-messages| + Sets `ext_linegrid` and `ext_cmdline` implicitly. +- `ext_multigrid` Per-window grid events. |ui-multigrid| + Sets `ext_linegrid` implicitly. +- `ext_popupmenu` Externalize |popupmenu-completion| and + 'wildmenu'. |ui-popupmenu| +- `ext_tabline` Externalize the tabline. |ui-tabline| +- `ext_termcolors` Use external default colors. +- `term_name` Sets the name of the terminal 'term'. +- `term_colors` Sets the number of supported colors 't_Co'. +- `term_background` Sets the default value of 'background'. +- `stdin_fd` Read buffer from `fd` as if it was a stdin pipe + This option can only used by |--embed| ui, + see |ui-startup-stdin|. Specifying an unknown option is an error; UIs can check the |api-metadata| `ui_options` key for supported options. @@ -164,13 +161,13 @@ Global Events *ui-global* The following UI events are always emitted, and describe global state of the editor. -["set_title", title] -["set_icon", icon] +["set_title", title] ~ +["set_icon", icon] ~ Set the window title, and icon (minimized) window title, respectively. In windowing systems not distinguishing between the two, "set_icon" can be ignored. -["mode_info_set", cursor_style_enabled, mode_info] +["mode_info_set", cursor_style_enabled, mode_info] ~ `cursor_style_enabled` is a boolean indicating if the UI should set the cursor style. `mode_info` is a list of mode property maps. The current mode is given by the `mode_idx` field of the `mode_change` @@ -197,21 +194,21 @@ the editor. `hl_id`: Use `attr_id` instead. `hl_lm`: Use `attr_id_lm` instead. -["option_set", name, value] +["option_set", name, value] ~ UI-related option changed, where `name` is one of: - 'arabicshape' - 'ambiwidth' - 'emoji' - 'guifont' - 'guifontwide' - 'linespace' - 'mousefocus' - 'mousemoveevent' - 'pumblend' - 'showtabline' - 'termguicolors' - "ext_*" (all |ui-ext-options|) + - 'arabicshape' + - 'ambiwidth' + - 'emoji' + - 'guifont' + - 'guifontwide' + - 'linespace' + - 'mousefocus' + - 'mousemoveevent' + - 'pumblend' + - 'showtabline' + - 'termguicolors' + - "ext_*" (all |ui-ext-options|) Triggered when the UI first connects to Nvim, and whenever an option is changed by the user or a plugin. @@ -224,7 +221,7 @@ the editor. however a UI might still use such options when rendering raw text sent from Nvim, like for |ui-cmdline|. -["mode_change", mode, mode_idx] +["mode_change", mode, mode_idx] ~ Editor mode changed. The `mode` parameter is a string representing the current mode. `mode_idx` is an index into the array emitted in the `mode_info_set` event. UIs should change the cursor style @@ -233,30 +230,30 @@ the editor. instance more submodes and temporary states might be represented as separate modes. -["mouse_on"] -["mouse_off"] +["mouse_on"] ~ +["mouse_off"] ~ 'mouse' was enabled/disabled in the current editor mode. Useful for a terminal UI, or embedding into an application where Nvim mouse would conflict with other usages of the mouse. Other UI:s may ignore this event. -["busy_start"] -["busy_stop"] +["busy_start"] ~ +["busy_stop"] ~ Indicates to the UI that it must stop rendering the cursor. This event is misnamed and does not actually have anything to do with busyness. -["suspend"] +["suspend"] ~ |:suspend| command or |CTRL-Z| mapping is used. A terminal client (or another client where it makes sense) could suspend itself. Other clients can safely ignore it. -["update_menu"] +["update_menu"] ~ The menu mappings changed. -["bell"] -["visual_bell"] +["bell"] ~ +["visual_bell"] ~ Notify the user with an audible or visual bell, respectively. -["flush"] +["flush"] ~ Nvim is done redrawing the screen. For an implementation that renders to an internal buffer, this is the time to display the redrawn parts to the user. @@ -279,11 +276,11 @@ be created; to enable per-window grids, activate |ui-multigrid|. Highlight attribute groups are predefined. UIs should maintain a table to map numerical highlight ids to the actual attributes. -["grid_resize", grid, width, height] +["grid_resize", grid, width, height] ~ Resize a `grid`. If `grid` wasn't seen by the client before, a new grid is being created with this size. -["default_colors_set", rgb_fg, rgb_bg, rgb_sp, cterm_fg, cterm_bg] +["default_colors_set", rgb_fg, rgb_bg, rgb_sp, cterm_fg, cterm_bg] ~ The first three arguments set the default foreground, background and special colors respectively. `cterm_fg` and `cterm_bg` specifies the default color codes to use in a 256-color terminal. @@ -300,7 +297,7 @@ numerical highlight ids to the actual attributes. screen with changed background color itself. *ui-event-hl_attr_define* -["hl_attr_define", id, rgb_attr, cterm_attr, info] +["hl_attr_define", id, rgb_attr, cterm_attr, info] ~ Add a highlight with `id` to the highlight table, with the attributes specified by the `rgb_attr` and `cterm_attr` dicts, with the following (all optional) keys. @@ -346,7 +343,7 @@ numerical highlight ids to the actual attributes. `info` is an empty array by default, and will be used by the |ui-hlstate| extension explained below. -["hl_group_set", name, hl_id] +["hl_group_set", name, hl_id] ~ The bulitin highlight group `name` was set to use the attributes `hl_id` defined by a previous `hl_attr_define` call. This event is not needed to render the grids which use attribute ids directly, but is useful @@ -355,7 +352,7 @@ numerical highlight ids to the actual attributes. use the |hl-Pmenu| family of builtin highlights. *ui-event-grid_line* -["grid_line", grid, row, col_start, cells] +["grid_line", grid, row, col_start, cells] ~ Redraw a continuous part of a `row` on a `grid`, starting at the column `col_start`. `cells` is an array of arrays each with 1 to 3 items: `[text(, hl_id, repeat)]` . `text` is the UTF-8 text that should be put in @@ -374,19 +371,19 @@ numerical highlight ids to the actual attributes. enough to cover the remaining line, will be sent when the rest of the line should be cleared. -["grid_clear", grid] +["grid_clear", grid] ~ Clear a `grid`. -["grid_destroy", grid] +["grid_destroy", grid] ~ `grid` will not be used anymore and the UI can free any data associated with it. -["grid_cursor_goto", grid, row, column] +["grid_cursor_goto", grid, row, column] ~ Makes `grid` the current grid and `row, column` the cursor position on this grid. This event will be sent at most once in a `redraw` batch and indicates the visible cursor position. -["grid_scroll", grid, top, bot, left, right, rows, cols] +["grid_scroll", grid, top, bot, left, right, rows, cols] ~ Scroll a region of `grid`. This is semantically unrelated to editor |scrolling|, rather this is an optimized way to say "copy these screen cells". @@ -439,30 +436,30 @@ Grid Events (cell-based) *ui-grid-old* This is the legacy representation of the screen grid, emitted if |ui-linegrid| is not active. New UIs should implement |ui-linegrid| instead. -["resize", width, height] +["resize", width, height] ~ The grid is resized to `width` and `height` cells. -["clear"] +["clear"] ~ Clear the grid. -["eol_clear"] +["eol_clear"] ~ Clear from the cursor position to the end of the current line. -["cursor_goto", row, col] +["cursor_goto", row, col] ~ Move the cursor to position (row, col). Currently, the same cursor is used to define the position for text insertion and the visible cursor. However, only the last cursor position, after processing the entire array in the "redraw" event, is intended to be a visible cursor position. -["update_fg", color] -["update_bg", color] -["update_sp", color] +["update_fg", color] ~ +["update_bg", color] ~ +["update_sp", color] ~ Set the default foreground, background and special colors respectively. *ui-event-highlight_set* -["highlight_set", attrs] +["highlight_set", attrs] ~ Set the attributes that the next text put on the grid will have. `attrs` is a dict with the keys below. Any absent key is reset to its default value. Color defaults are set by the `update_fg` etc @@ -482,18 +479,18 @@ is not active. New UIs should implement |ui-linegrid| instead. `underdotted`: underdotted text. The dots have `special` color. `underdashed`: underdashed text. The dashes have `special` color. -["put", text] +["put", text] ~ The (utf-8 encoded) string `text` is put at the cursor position (and the cursor is advanced), with the highlights as set by the last `highlight_set` update. -["set_scroll_region", top, bot, left, right] +["set_scroll_region", top, bot, left, right] ~ Define the scroll region used by `scroll` below. Note: ranges are end-inclusive, which is inconsistent with API conventions. -["scroll", count] +["scroll", count] ~ Scroll the text in the scroll region. The diagrams below illustrate what will happen, depending on the scroll direction. "=" is used to represent the SR(scroll region) boundaries and "-" the moved rectangles. @@ -588,29 +585,29 @@ A window can be hidden and redisplayed without its grid being deallocated. This can happen multiple times for the same window, for instance when switching tabs. -["win_pos", grid, win, start_row, start_col, width, height] +["win_pos", grid, win, start_row, start_col, width, height] ~ Set the position and size of the grid in Nvim (i.e. the outer grid size). If the window was previously hidden, it should now be shown again. -["win_float_pos", grid, win, anchor, anchor_grid, anchor_row, anchor_col, focusable] +["win_float_pos", grid, win, anchor, anchor_grid, anchor_row, anchor_col, focusable] ~ Display or reconfigure floating window `win`. The window should be displayed above another grid `anchor_grid` at the specified position `anchor_row` and `anchor_col`. For the meaning of `anchor` and more details of positioning, see |nvim_open_win()|. -["win_external_pos", grid, win] +["win_external_pos", grid, win] ~ Display or reconfigure external window `win`. The window should be displayed as a separate top-level window in the desktop environment, or something similar. -["win_hide", grid] +["win_hide", grid] ~ Stop displaying the window. The window can be shown again later. -["win_close", grid] +["win_close", grid] ~ Close the window. -["msg_set_pos", grid, row, scrolled, sep_char] +["msg_set_pos", grid, row, scrolled, sep_char] ~ Display messages on `grid`. The grid will be displayed at `row` on the default grid (grid=1), covering the full column width. `scrolled` indicates whether the message area has been scrolled to cover other @@ -621,13 +618,13 @@ tabs. When |ui-messages| is active, no message grid is used, and this event will not be sent. -["win_viewport", grid, win, topline, botline, curline, curcol] +["win_viewport", grid, win, topline, botline, curline, curcol] ~ Indicates the range of buffer text displayed in the window, as well as the cursor position in the buffer. All positions are zero-based. `botline` is set to one more than the line count of the buffer, if there are filler lines past the end. -["win_extmark", grid, win, ns_id, mark_id, row, col] +["win_extmark", grid, win, ns_id, mark_id, row, col] ~ Updates the position of an extmark which is currently visible in a window. Only emitted if the mark has the `ui_watched` attribute. @@ -639,7 +636,7 @@ Activated by the `ext_popupmenu` |ui-option|. This UI extension delegates presentation of the |popupmenu-completion| and command-line 'wildmenu'. -["popupmenu_show", items, selected, row, col, grid] +["popupmenu_show", items, selected, row, col, grid] ~ Show |popupmenu-completion|. `items` is an array of completion items to show; each item is an array of the form [word, kind, menu, info] as defined at |complete-items|, except that `word` is replaced by `abbr` @@ -651,12 +648,12 @@ command-line 'wildmenu'. set to -1 to indicate the popupmenu should be anchored to the external cmdline. Then `col` will be a byte position in the cmdline text. -["popupmenu_select", selected] +["popupmenu_select", selected] ~ Select an item in the current popupmenu. `selected` is a zero-based index into the array of items from the last popupmenu_show event, or -1 if no item is selected. -["popupmenu_hide"] +["popupmenu_hide"] ~ Hide the popupmenu. ============================================================================== @@ -664,7 +661,7 @@ Tabline Events *ui-tabline* Activated by the `ext_tabline` |ui-option|. -["tabline_update", curtab, tabs, curbuf, buffers] +["tabline_update", curtab, tabs, curbuf, buffers] ~ Tabline was updated. UIs should present this data in a custom tabline widget. Note: options `curbuf` + `buffers` were added in API7. curtab: Current Tabpage @@ -680,7 +677,7 @@ Activated by the `ext_cmdline` |ui-option|. This UI extension delegates presentation of the |cmdline| (except 'wildmenu'). For command-line 'wildmenu' UI events, activate |ui-popupmenu|. -["cmdline_show", content, pos, firstc, prompt, indent, level] +["cmdline_show", content, pos, firstc, prompt, indent, level] ~ content: List of [attrs, string] [[{}, "t"], [attrs, "est"], ...] @@ -703,10 +700,10 @@ For command-line 'wildmenu' UI events, activate |ui-popupmenu|. prompt has level 2. A command line invoked from the |cmdline-window| has a higher level than than the edited command line. -["cmdline_pos", pos, level] +["cmdline_pos", pos, level] ~ Change the cursor position in the cmdline. -["cmdline_special_char", c, shift, level] +["cmdline_special_char", c, shift, level] ~ Display a special char in the cmdline at the cursor position. This is typically used to indicate a pending state, e.g. after |c_CTRL-V|. If `shift` is true the text after the cursor should be shifted, otherwise @@ -714,10 +711,10 @@ For command-line 'wildmenu' UI events, activate |ui-popupmenu|. Should be hidden at next cmdline_show. -["cmdline_hide"] +["cmdline_hide"] ~ Hide the cmdline. -["cmdline_block_show", lines] +["cmdline_block_show", lines] ~ Show a block of context to the current command line. For example if the user defines a |:function| interactively: > :function Foo() @@ -727,10 +724,10 @@ For command-line 'wildmenu' UI events, activate |ui-popupmenu|. `lines` is a list of lines of highlighted chunks, in the same form as the "cmdline_show" `contents` parameter. -["cmdline_block_append", line] +["cmdline_block_append", line] ~ Append a line at the end of the currently shown block. -["cmdline_block_hide"] +["cmdline_block_hide"] ~ Hide the block. ============================================================================== @@ -747,7 +744,7 @@ Nvim will not allocate screen space for the cmdline or messages, and 'cmdheight' will be forced zero. Cmdline state is emitted as |ui-cmdline| events, which the UI must handle. -["msg_show", kind, content, replace_last] +["msg_show", kind, content, replace_last] ~ Display a message to the user. kind @@ -781,25 +778,25 @@ events, which the UI must handle. true: Replace the message in the most-recent `msg_show` call, but any other visible message should still remain. -["msg_clear"] +["msg_clear"] ~ Clear all messages currently displayed by "msg_show". (Messages sent by other "msg_" events below will not be affected). -["msg_showmode", content] +["msg_showmode", content] ~ Shows 'showmode' and |recording| messages. `content` has the same format as in "msg_show". This event is sent with empty `content` to hide the last message. -["msg_showcmd", content] +["msg_showcmd", content] ~ Shows 'showcmd' messages. `content` has the same format as in "msg_show". This event is sent with empty `content` to hide the last message. -["msg_ruler", content] +["msg_ruler", content] ~ Used to display 'ruler' when there is no space for the ruler in a statusline. `content` has the same format as in "msg_show". This event is sent with empty `content` to hide the last message. -["msg_history_show", entries] +["msg_history_show", entries] ~ Sent when |:messages| command is invoked. History is sent as a list of entries, where each entry is a `[kind, content]` tuple. diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index dbc18963f9..aea2a27f9e 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -907,8 +907,8 @@ function M.convert_signature_help_to_markdown_lines(signature_help, ft, triggers return end --The active signature. If omitted or the value lies outside the range of - --`signatures` the value defaults to zero or is ignored if `signatures.length - --=== 0`. Whenever possible implementors should make an active decision about + --`signatures` the value defaults to zero or is ignored if `signatures.length == 0`. + --Whenever possible implementors should make an active decision about --the active signature and shouldn't rely on a default value. local contents = {} local active_hl diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua index 6e297814b8..fdbf5f605a 100644 --- a/scripts/gen_help_html.lua +++ b/scripts/gen_help_html.lua @@ -1,5 +1,7 @@ -- Converts Vim :help files to HTML. Validates |tag| links and document syntax (parser errors). -- +-- NOTE: :helptags checks for duplicate tags, whereas this script checks _links_ (to tags). +-- -- USAGE (GENERATE HTML): -- 1. Run `make helptags` first; this script depends on vim.fn.taglist(). -- 2. nvim -V1 -es --clean +"lua require('scripts.gen_help_html').gen('./build/runtime/doc/', 'target/dir/')" @@ -20,37 +22,19 @@ -- * visit_node() is the core function used by gen() to traverse the document tree and produce HTML. -- * visit_validate() is the core function used by validate(). -- * Files in `new_layout` will be generated with a "flow" layout instead of preformatted/fixed-width layout. --- --- parser bugs: --- * Should NOT be code_block: --- tab:xy The 'x' is always used, then 'y' as many times as will --- fit. Thus "tab:>-" displays: --- > --- >- --- >-- --- etc. --- --- tab:xyz The 'z' is always used, then 'x' is prepended, and --- then 'y' is used as many times as will fit. Thus --- "tab:<->" displays: --- > --- <> --- <-> --- <--> --- etc. --- * Should NOT be a "headline". Perhaps a "table" (or just "line"). --- expr5 and expr6 *expr5* *expr6* --- --------------- --- expr6 + expr6 Number addition, |List| or |Blob| concatenation *expr-+* --- expr6 - expr6 Number subtraction *expr--* --- expr6 . expr6 String concatenation *expr-.* --- expr6 .. expr6 String concatenation *expr-..* local tagmap = nil local helpfiles = nil -local invalid_tags = {} +local invalid_links = {} +local invalid_urls = {} +local invalid_spelling = {} +local spell_dict = { + Neovim = 'Nvim', + NeoVim = 'Nvim', + neovim = 'Nvim', + lua = 'Lua', +} -local api = vim.api local M = {} -- These files are generated with "flow" layout (non fixed-width, wrapped text paragraphs). @@ -59,16 +43,31 @@ local new_layout = { ['api.txt'] = true, ['channel.txt'] = true, ['develop.txt'] = true, + ['luaref.txt'] = true, ['nvim.txt'] = true, ['pi_health.txt'] = true, ['provider.txt'] = true, ['ui.txt'] = true, } --- TODO: treesitter gets stuck on these files... -local exclude = { - ['filetype.txt'] = true, - ['usr_24.txt'] = true, +-- TODO: These known invalid |links| require an update to the relevant docs. +local exclude_invalid = { + ["'previewpopup'"] = "quickref.txt", + ["'pvp'"] = "quickref.txt", + ["'string'"] = "eval.txt", + Query = "treesitter.txt", + ["eq?"] = "treesitter.txt", + ["lsp-request"] = "lsp.txt", + matchit = "vim_diff.txt", + ["matchit.txt"] = "help.txt", + ["set!"] = "treesitter.txt", + ["v:_null_blob"] = "builtin.txt", + ["v:_null_dict"] = "builtin.txt", + ["v:_null_list"] = "builtin.txt", + ["v:_null_string"] = "builtin.txt", + ["vim.lsp.buf_request()"] = "lsp.txt", + ["vim.lsp.util.get_progress_messages()"] = "lsp.txt", + ["vim.treesitter.start()"] = "treesitter.txt" } local function tofile(fname, text) @@ -82,10 +81,6 @@ local function tofile(fname, text) end local function html_esc(s) - if s:find(']local%-additions[*<]') + ) then + -- table.insert(stats.noise_lines, getbuflinestr(root, opt.buf, 0)) + table.insert(noise_lines or {}, line) + return true + end + return false end --- Checks if a given line is a "noise" line that doesn't look good in HTML form. -local function is_noise(line) - return ( - line:find('Type .*gO.* to see the table of contents') - -- Title line of traditional :help pages. - -- Example: "NVIM REFERENCE MANUAL by ..." - or line:find('^%s*N?VIM REFERENCE MANUAL') - -- First line of traditional :help pages. - -- Example: "*api.txt* Nvim" - or line:find('%s*%*?[a-zA-Z]+%.txt%*?%s+N?[vV]im%s*$') - -- modeline - -- Example: "vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:" - or line:find('^%s*vi[m]%:.*ft=help') - or line:find('^%s*vi[m]%:.*filetype=help') - ) -end - --- Creates a github issue URL at vigoux/tree-sitter-vimdoc with prefilled content. +-- Creates a github issue URL at neovim/tree-sitter-vimdoc with prefilled content. local function get_bug_url_vimdoc(fname, to_fname, sample_text) local this_url = string.format('https://neovim.io/doc/user/%s', vim.fs.basename(to_fname)) - local bug_url = ('https://github.com/vigoux/tree-sitter-vimdoc/issues/new?labels=bug&title=parse+error%3A+' + local bug_url = ('https://github.com/neovim/tree-sitter-vimdoc/issues/new?labels=bug&title=parse+error%3A+' ..vim.fs.basename(fname) ..'+&body=Found+%60tree-sitter-vimdoc%60+parse+error+at%3A+' ..this_url @@ -237,31 +236,57 @@ local function getbuflinestr(node, bufnr, offset) return table.concat(lines, '\n') end --- Gets the whitespace just before `node` from the raw buffer text. --- Needed for preformatted `old` lines. -local function getws(node, bufnr) - local line1, c1, line2, _ = node:range() - local raw = vim.fn.getbufline(bufnr, line1 + 1, line2 + 1)[1] - local text_before = raw:sub(1, c1) - local leading_ws = text_before:match('%s+$') or '' - return leading_ws -end - -local function get_tagname(node, bufnr, link) - local node_name = (node.named and node:named()) and node:type() or nil +local function get_tagname(node, bufnr) local node_text = vim.treesitter.get_node_text(node, bufnr) - local tag = ((node_name == 'option' and node_text) - or (link and node_text:gsub('^|', ''):gsub('|$', '') or node_text:gsub('^%*', ''):gsub('%*$', ''))) - local helpfile = tag and vim.fs.basename(tagmap[tag]) or nil -- "api.txt" - local helppage = get_helppage(helpfile) -- "api.html" + local tag = (node:type() == 'optionlink' or node:parent():type() == 'optionlink') and ("'%s'"):format(node_text) or node_text + local helpfile = vim.fs.basename(tagmap[tag]) or nil -- "api.txt" + local helppage = get_helppage(helpfile) -- "api.html" return helppage, tag end +-- Returns true if the given invalid tagname is a false positive. +local function ignore_invalid(s) + -- Strings like |~/====| appear in various places and the parser thinks they are links, but they + -- are just table borders. + return not not (s:find('===') or exclude_invalid[s]) +end + +local function ignore_parse_error(s) + -- Ignore parse errors for unclosed codespan/optionlink/tag. + -- This is common in vimdocs and is treated as plaintext by :help. + return s:find("^[`'|*]") +end + +local function has_ancestor(node, ancestor_name) + local p = node + while true do + p = p:parent() + if not p or p:type() == 'help_file' then + break + elseif p:type() == ancestor_name then + return true + end + end + return false +end + +local function validate_link(node, bufnr, fname) + local helppage, tagname = get_tagname(node:child(1), bufnr, true) + if not has_ancestor(node, 'column_heading') and not node:has_error() and not tagmap[tagname] and not ignore_invalid(tagname) then + invalid_links[tagname] = vim.fs.basename(fname) + end + return helppage, tagname +end + -- Traverses the tree at `root` and checks that |tag| links point to valid helptags. local function visit_validate(root, level, lang_tree, opt, stats) level = level or 0 local node_name = (root.named and root:named()) and root:type() or nil local toplevel = level < 1 + local function node_text(node) + return vim.treesitter.get_node_text(node or root, opt.buf) + end + local text = trim(node_text()) if root:child_count() > 0 then for node, _ in root:iter_children() do @@ -272,14 +297,26 @@ local function visit_validate(root, level, lang_tree, opt, stats) end if node_name == 'ERROR' then + if ignore_parse_error(text) then + return + end -- Store the raw text to give context to the bug report. local sample_text = not toplevel and getbuflinestr(root, opt.buf, 3) or '[top level!]' table.insert(stats.parse_errors, sample_text) - elseif node_name == 'hotlink' or node_name == 'option' then - local _, tagname = get_tagname(root, opt.buf, true) - if not root:has_error() and not tagmap[tagname] then - invalid_tags[tagname] = vim.fs.basename(opt.fname) + elseif node_name == 'word' or node_name == 'uppercase_name' then + if spell_dict[text] then + if not invalid_spelling[text] then + invalid_spelling[text] = { vim.fs.basename(opt.fname) } + else + table.insert(invalid_spelling[text], vim.fs.basename(opt.fname)) + end end + elseif node_name == 'url' then + if text:find('http%:') then + invalid_urls[text] = vim.fs.basename(opt.fname) + end + elseif node_name == 'taglink' or node_name == 'optionlink' then + local _, _ = validate_link(root, opt.buf, opt.fname) end end @@ -296,19 +333,18 @@ local function visit_node(root, level, lang_tree, headings, opt, stats) local parent = root:parent() and root:parent():type() or nil local text = '' local toplevel = level < 1 - local function node_text() - return vim.treesitter.get_node_text(root, opt.buf) + local function node_text(node) + return vim.treesitter.get_node_text(node or root, opt.buf) end - if root:child_count() == 0 then + if root:child_count() == 0 or node_name == 'ERROR' then text = node_text() else -- Process children and join them with whitespace. for node, _ in root:iter_children() do if node:named() then local r = visit_node(node, level + 1, lang_tree, headings, opt, stats) - local ws = r == '' and '' or ((opt.old and (node:type() == 'word' or not node:named())) and getws(node, opt.buf) or ' ') - text = string.format('%s%s%s', text, ws, r) + text = string.format('%s%s', text, r) end end end @@ -316,82 +352,112 @@ local function visit_node(root, level, lang_tree, headings, opt, stats) if node_name == 'help_file' then -- root node return text + elseif node_name == 'url' then + return ('%s'):format(trimmed, trimmed) elseif node_name == 'word' or node_name == 'uppercase_name' then - if parent == 'headline' then - -- Start a new heading item, or update the current one. - local n = (prev == nil or #headings == 0) and #headings + 1 or #headings - headings[n] = string.format('%s%s', headings[n] and headings[n]..' ' or '', text) - end - return html_esc(text) - elseif node_name == 'headline' then - return ('

%s

\n'):format(to_heading_tag(headings[#headings]), text) + elseif node_name == 'h1' or node_name == 'h2' or node_name == 'h3' then + if is_noise(text, stats.noise_lines) then + return '' -- Discard common "noise" lines. + end + -- Remove "===" and tags from ToC text. + local hname = (node_text():gsub('%-%-%-%-+', ''):gsub('%=%=%=%=+', ''):gsub('%*.*%*', '')) + if node_name == 'h1' or #headings == 0 then + table.insert(headings, { name = hname, subheadings = {}, }) + else + table.insert(headings[#headings].subheadings, { name = hname, subheadings = {}, }) + end + local el = node_name == 'h1' and 'h2' or 'h3' + return ('<%s class="help-heading">%s\n'):format(to_heading_tag(hname), el, text, el) elseif node_name == 'column_heading' or node_name == 'column_name' then - return ('

%s

\n'):format(trimmed) - elseif node_name == 'line' then - -- TODO: remove these "sibling inspection" hacks once the parser provides structured info - -- about paragraphs and listitems: https://github.com/vigoux/tree-sitter-vimdoc/issues/12 - local next_text = root:next_sibling() and vim.treesitter.get_node_text(root:next_sibling(), opt.buf) or '' - local li = startswith_bullet(text) -- Listitem? - local next_li = startswith_bullet(next_text) -- Next is listitem? - -- Close the paragraph/listitem if the next sibling is not a line. - local close = (next_ ~= 'line' or next_li or is_blank(next_text)) and '\n' or '' - - -- HACK: discard common "noise" lines. - if is_noise(text) then - table.insert(stats.noise_lines, getbuflinestr(root, opt.buf, 0)) - return (opt.old or prev ~= 'line') and '' or close + if root:has_error() then + return text + end + return ('
%s
'):format(trimmed) + elseif node_name == 'block' then + if is_blank(text) then + return '' end - if opt.old then - -- XXX: Treat old docs as preformatted. Until those docs are "fixed" or we get better info - -- from tree-sitter-vimdoc, this avoids broken layout for legacy docs. - return ('
%s
\n'):format(text) + -- XXX: Treat old docs as preformatted; random indentation is used for layout there. + return ('
%s
\n'):format(text) end - - if li then - return string.format('
%s%s', trim_bullet(expandtabs(text)), close) + return string.format('
\n%s\n
\n', text) + elseif node_name == 'line' then + local sib = root:prev_sibling() + local sib_last = sib and sib:named_child(sib:named_child_count() - 1) + local in_li = false + + -- XXX: parser bug: (codeblock) without terminating "<" consumes first char of the next (line). Recover it here. + local recovered = (sib_last and sib_last:type() == 'codeblock') and node_text(root:prev_sibling()):sub(-1) or '' + recovered = recovered == '<' and '' or html_esc(recovered) + + -- XXX: see if we are currently "in" a listitem. + while sib ~= nil and not in_li do + in_li = (sib:type() == 'line_li') + sib = sib:prev_sibling() end - if prev ~= 'line' then -- Start a new paragraph. - return string.format('
%s%s', expandtabs(text), close) + + -- Close the current listitem. + local close = (in_li and next_ ~= 'line') and '
' or '' + + if is_blank(text) or is_noise(text, stats.noise_lines) then + return close -- Discard common "noise" lines. end - -- Continue in the current paragraph/listitem. - return string.format('%s%s', expandtabs(text), close) - elseif node_name == 'hotlink' or node_name == 'option' then - local helppage, tagname = get_tagname(root, opt.buf, true) - if not root:has_error() and not tagmap[tagname] then - invalid_tags[tagname] = vim.fs.basename(opt.fname) + local div = (root:child(0) and root:child(0):type() == 'column_heading') or close ~= '' + return string.format('%s%s%s%s', recovered, div and trim(text) or text, div and '' or '\n', close) + elseif node_name == 'line_li' then + -- Close the listitem immediately if the next sibling is not a line. + local close = (next_ ~= 'line') and '
' or '' + return string.format('
%s %s', trim_bullet(text), close) + elseif node_name == 'taglink' or node_name == 'optionlink' then + if root:has_error() then + return text + end + local helppage, tagname = validate_link(root, opt.buf, opt.fname) + return (' %s'):format(helppage, url_encode(tagname), html_esc(tagname)) + elseif node_name == 'codespan' then + if root:has_error() then + return text end - return ('%s'):format(helppage, url_encode(tagname), html_esc(tagname)) - elseif node_name == 'backtick' then - return ('%s'):format(html_esc(text)) + return (' %s'):format(text) elseif node_name == 'argument' then - return ('{%s}'):format(html_esc(trimmed)) - elseif node_name == 'code_block' then - return ('
\n%s
\n'):format(html_esc(trim_indent(trim_gt_lt(text)))) + return (' {%s}'):format(trimmed) + elseif node_name == 'codeblock' then + return ('
%s
'):format(html_esc(trim_indent(trim_gt_lt(text)))) elseif node_name == 'tag' then -- anchor - local _, tagname = get_tagname(root, opt.buf, false) - local s = ('%s'):format(url_encode(tagname), trimmed) - if parent == 'headline' and prev ~= 'tag' then + if root:has_error() then + return text + end + local in_heading = (parent == 'h1' or parent == 'h2') + local cssclass = (not in_heading and get_indent(node_text()) > 8) and 'help-tag-right' or 'help-tag' + local tagname = node_text(root:child(1)) + if vim.tbl_count(stats.first_tags) < 2 then + -- First 2 tags in the doc will be anchored at the main heading. + table.insert(stats.first_tags, tagname) + return '' + end + local s = (' %s'):format(url_encode(tagname), cssclass, trimmed) + if in_heading and prev ~= 'tag' then -- Start the container for tags in a heading. -- This makes "justify-content:space-between" right-align the tags. --

foo bartag1 tag2

return string.format('%s', s) - elseif parent == 'headline' and next_ == nil then + elseif in_heading and next_ == nil then -- End the container for tags in a heading. return string.format('%s', s) end return s elseif node_name == 'ERROR' then + if ignore_parse_error(trimmed) then + return text + end + -- Store the raw text to give context to the bug report. local sample_text = not toplevel and getbuflinestr(root, opt.buf, 3) or '[top level!]' table.insert(stats.parse_errors, sample_text) - if prev == 'ERROR' then - -- Avoid trashing the text with cascading errors. - return trimmed, ('parse-error:"%s"'):format(node_text()) - end - return ('%s'):format( + return ('%s'):format( get_bug_url_vimdoc(opt.fname, opt.to_fname, sample_text), trimmed) else -- Unknown token. local sample_text = not toplevel and getbuflinestr(root, opt.buf, 3) or '[top level!]' @@ -406,8 +472,7 @@ local function get_helpfiles(include) for f, type in vim.fs.dir(dir) do if (vim.endswith(f, '.txt') and type == 'file' - and (not include or vim.tbl_contains(include, f)) - and (not exclude[f])) then + and (not include or vim.tbl_contains(include, f))) then local fullpath = vim.fn.fnamemodify(('%s/%s'):format(dir, f), ':p') table.insert(rv, fullpath) end @@ -430,6 +495,13 @@ local function get_helptags(help_dir) return m end +-- Use the help.so parser defined in the build, not whatever happens to be installed on the system. +local function ensure_runtimepath() + if not vim.o.runtimepath:find('build/lib/nvim/') then + vim.cmd[[set runtimepath^=./build/lib/nvim/]] + end +end + -- Opens `fname` in a buffer and gets a treesitter parser for the buffer contents. -- -- @returns lang_tree, bufnr @@ -437,7 +509,7 @@ local function parse_buf(fname) local buf if type(fname) == 'string' then vim.cmd('split '..vim.fn.fnameescape(fname)) -- Filename. - buf = api.nvim_get_current_buf() + buf = vim.api.nvim_get_current_buf() else buf = fname vim.cmd('sbuffer '..tostring(fname)) -- Buffer number. @@ -451,10 +523,9 @@ end -- - checks that |tag| links point to valid helptags. -- - recursively counts parse errors ("ERROR" nodes) -- --- @returns { invalid_tags: number, parse_errors: number } +-- @returns { invalid_links: number, parse_errors: number } local function validate_one(fname) local stats = { - invalid_tags = {}, parse_errors = {}, } local lang_tree, buf = parse_buf(fname) @@ -463,10 +534,7 @@ local function validate_one(fname) end lang_tree:destroy() vim.cmd.close() - return { - invalid_tags = invalid_tags, - parse_errors = stats.parse_errors, - } + return stats end -- Generates HTML from one :help file `fname` and writes the result to `to_fname`. @@ -480,9 +548,10 @@ local function gen_one(fname, to_fname, old, commit) local stats = { noise_lines = {}, parse_errors = {}, + first_tags = {}, -- Track the first few tags in doc. } local lang_tree, buf = parse_buf(fname) - local headings = {} -- Headings (for ToC). + local headings = {} -- Headings (for ToC). 2-dimensional: h1 contains h2/h3. local title = to_titlecase(basename_noext(fname)) local html = ([[ @@ -555,7 +624,12 @@ local function gen_one(fname, to_fname, old, commit) ]] - local main = ([[ + local main = '' + for _, tree in ipairs(lang_tree:trees()) do + main = main .. (visit_node(tree:root(), 0, tree, headings, { buf = buf, old = old, fname = fname, to_fname = to_fname }, stats)) + end + + main = ([[