diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/api/autocmd.c | 92 | ||||
-rw-r--r-- | src/nvim/api/extmark.c | 18 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 2 | ||||
-rw-r--r-- | src/nvim/ex_getln.c | 5 | ||||
-rw-r--r-- | src/nvim/linematch.c | 6 | ||||
-rw-r--r-- | src/nvim/regexp_nfa.c | 23 | ||||
-rw-r--r-- | src/nvim/testdir/test_cmdline.vim | 24 | ||||
-rw-r--r-- | src/nvim/testdir/test_quickfix.vim | 1 |
8 files changed, 82 insertions, 89 deletions
diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c index db84ecb5d8..ada042e654 100644 --- a/src/nvim/api/autocmd.c +++ b/src/nvim/api/autocmd.c @@ -361,41 +361,20 @@ cleanup: return autocmd_list; } -/// Create an |autocommand| +/// Creates an |autocommand| event handler, defined by `callback` (Lua function or Vimscript +/// function _name_ string) or `command` (Ex command string). /// -/// The API allows for two (mutually exclusive) types of actions to be executed when the autocommand -/// triggers: a callback function (Lua or Vimscript), or a command (like regular autocommands). -/// -/// Example using callback: -/// <pre>lua -/// -- Lua function -/// local myluafun = function() print("This buffer enters") end -/// -/// -- Vimscript function name (as a string) -/// local myvimfun = "g:MyVimFunction" -/// -/// vim.api.nvim_create_autocmd({"BufEnter", "BufWinEnter"}, { -/// pattern = {"*.c", "*.h"}, -/// callback = myluafun, -- Or myvimfun -/// }) -/// </pre> -/// -/// Lua functions receive a table with information about the autocmd event as an argument. To use -/// a function which itself accepts another (optional) parameter, wrap the function -/// in a lambda: +/// Example using Lua callback: /// <pre>lua -/// -- Lua function with an optional parameter. -/// -- The autocmd callback would pass a table as argument but this -/// -- function expects number|nil -/// local myluafun = function(bufnr) bufnr = bufnr or vim.api.nvim_get_current_buf() end -/// /// vim.api.nvim_create_autocmd({"BufEnter", "BufWinEnter"}, { /// pattern = {"*.c", "*.h"}, -/// callback = function() myluafun() end, +/// callback = function(ev) +/// print(string.format('event fired: %s', vim.inspect(ev))) +/// end /// }) /// </pre> /// -/// Example using command: +/// Example using an Ex command as the handler: /// <pre>lua /// vim.api.nvim_create_autocmd({"BufEnter", "BufWinEnter"}, { /// pattern = {"*.c", "*.h"}, @@ -403,46 +382,28 @@ cleanup: /// }) /// </pre> /// -/// Example values for pattern: -/// <pre>lua -/// pattern = "*.py" -/// pattern = { "*.py", "*.pyi" } -/// </pre> -/// -/// Note: The `pattern` is passed to callbacks and commands as a literal string; environment -/// variables like `$HOME` and `~` are not automatically expanded as they are by |:autocmd|. -/// Instead, |expand()| such variables explicitly: +/// Note: `pattern` is NOT automatically expanded (unlike with |:autocmd|), thus names like "$HOME" +/// and "~" must be expanded explicitly: /// <pre>lua /// pattern = vim.fn.expand("~") .. "/some/path/*.py" /// </pre> /// -/// Example values for event: -/// <pre>lua -/// event = "BufWritePre" -/// event = {"CursorHold", "BufWritePre", "BufWritePost"} -/// </pre> -/// -/// @param event (string|array) The event or events to register this autocommand -/// @param opts Dictionary of autocommand options: -/// - group (string|integer) optional: the autocommand group name or -/// id to match against. -/// - pattern (string|array) optional: pattern or patterns to match literally -/// against |autocmd-pattern|. -/// - buffer (integer) optional: buffer number for buffer local autocommands +/// @param event (string|array) Event(s) that will trigger the handler (`callback` or `command`). +/// @param opts Options dict: +/// - group (string|integer) optional: autocommand group name or id to match against. +/// - pattern (string|array) optional: pattern(s) to match literally |autocmd-pattern|. +/// - buffer (integer) optional: buffer number for buffer-local autocommands /// |autocmd-buflocal|. Cannot be used with {pattern}. -/// - desc (string) optional: description of the autocommand. -/// - callback (function|string) optional: if a string, the name of a Vimscript function -/// to call when this autocommand is triggered. Otherwise, a Lua function which is -/// called when this autocommand is triggered. Cannot be used with {command}. Lua -/// callbacks can return true to delete the autocommand; in addition, they accept a -/// single table argument with the following keys: -/// - id: (number) the autocommand id -/// - event: (string) the name of the event that triggered the autocommand -/// |autocmd-events| -/// - group: (number|nil) the autocommand group id, if it exists -/// - match: (string) the expanded value of |<amatch>| -/// - buf: (number) the expanded value of |<abuf>| -/// - file: (string) the expanded value of |<afile>| +/// - desc (string) optional: description (for documentation and troubleshooting). +/// - callback (function|string) optional: Lua function (or Vimscript function name, if +/// string) called when the event(s) is triggered. Lua callback can return true to +/// delete the autocommand, and receives a table argument with these keys: +/// - id: (number) autocommand id +/// - event: (string) name of the triggered event |autocmd-events| +/// - group: (number|nil) autocommand group id, if any +/// - match: (string) expanded value of |<amatch>| +/// - buf: (number) expanded value of |<abuf>| +/// - file: (string) expanded value of |<afile>| /// - data: (any) arbitrary data passed to |nvim_exec_autocmds()| /// - command (string) optional: Vim command to execute on event. Cannot be used with /// {callback} @@ -451,7 +412,7 @@ cleanup: /// - nested (boolean) optional: defaults to false. Run nested /// autocommands |autocmd-nested|. /// -/// @return Integer id of the created autocommand. +/// @return Autocommand id (number) /// @see |autocommand| /// @see |nvim_del_autocmd()| Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autocmd) *opts, @@ -472,8 +433,7 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc } if (opts->callback.type != kObjectTypeNil && opts->command.type != kObjectTypeNil) { - api_set_error(err, kErrorTypeValidation, - "cannot pass both: 'callback' and 'command' for the same autocmd"); + api_set_error(err, kErrorTypeValidation, "specify either 'callback' or 'command', not both"); goto cleanup; } else if (opts->callback.type != kObjectTypeNil) { // TODO(tjdevries): It's possible we could accept callable tables, diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index b406672aa5..bdc0900dd9 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -66,7 +66,7 @@ Integer nvim_create_namespace(String name) return (Integer)id; } -/// Gets existing, non-anonymous namespaces. +/// Gets existing, non-anonymous |namespace|s. /// /// @return dict that maps from names to namespace ids. Dictionary nvim_get_namespaces(void) @@ -195,7 +195,7 @@ static Array extmark_to_array(const ExtmarkInfo *extmark, bool id, bool add_dict return rv; } -/// Gets the position (0-indexed) of an extmark. +/// Gets the position (0-indexed) of an |extmark|. /// /// @param buffer Buffer handle, or 0 for current buffer /// @param ns_id Namespace id from |nvim_create_namespace()| @@ -249,7 +249,7 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id, return extmark_to_array(&extmark, false, details); } -/// Gets extmarks in "traversal order" from a |charwise| region defined by +/// Gets |extmarks| in "traversal order" from a |charwise| region defined by /// buffer positions (inclusive, 0-indexed |api-indexing|). /// /// Region can be given as (row,col) tuples, or valid extmark ids (whose @@ -368,7 +368,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e return rv; } -/// Creates or updates an extmark. +/// Creates or updates an |extmark|. /// /// By default a new extmark is created when no id is passed in, but it is also /// possible to create a new mark by passing in a previously unused id or move @@ -814,7 +814,7 @@ error: return 0; } -/// Removes an extmark. +/// Removes an |extmark|. /// /// @param buffer Buffer handle, or 0 for current buffer /// @param ns_id Namespace id from |nvim_create_namespace()| @@ -929,7 +929,7 @@ Integer nvim_buf_add_highlight(Buffer buffer, Integer ns_id, String hl_group, In return ns_id; } -/// Clears namespaced objects (highlights, extmarks, virtual text) from +/// Clears |namespace|d objects (highlights, |extmarks|, virtual text) from /// a region. /// /// Lines are 0-indexed. |api-indexing| To clear the namespace in the entire @@ -962,12 +962,12 @@ void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start, (int)line_end - 1, MAXCOL); } -/// Set or change decoration provider for a namespace +/// Set or change decoration provider for a |namespace| /// /// This is a very general purpose interface for having lua callbacks /// being triggered during the redraw code. /// -/// The expected usage is to set extmarks for the currently +/// 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 per-lines basis. Use the `ephemeral` key to only /// use the mark for the current screen redraw (the callback will be called @@ -1051,7 +1051,7 @@ error: decor_provider_clear(p); } -/// Gets the line and column of an extmark. +/// Gets the line and column of an |extmark|. /// /// Extmarks may be queried by position, name or even special names /// in the future such as "cursor". diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 857c03eb27..70b07dabe8 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1825,7 +1825,7 @@ Dictionary nvim__stats(void) /// - "width" Requested width of the UI /// - "rgb" true if the UI uses RGB colors (false implies |cterm-colors|) /// - "ext_..." Requested UI extensions, see |ui-option| -/// - "chan" Channel id of remote UI (not present for TUI) +/// - "chan" Channel id of remote UI or 0 for TUI Array nvim_list_uis(void) FUNC_API_SINCE(4) { diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 8fd7cb08f0..bd77df1704 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1609,7 +1609,8 @@ static int command_line_insert_reg(CommandLineState *s) ccline.special_char = NUL; redrawcmd(); - return CMDLINE_CHANGED; + // The text has been stuffed, the command line didn't change yet. + return CMDLINE_NOT_CHANGED; } /// Handle the Left and Right mouse clicks in the command-line mode. @@ -1690,7 +1691,7 @@ static void command_line_next_histidx(CommandLineState *s, bool next_match) } /// Handle the Up, Down, Page Up, Page down, CTRL-N and CTRL-P key in the -/// command-line mode. The pressed key is in 'c'. +/// command-line mode. static int command_line_browse_history(CommandLineState *s) { if (s->histype == HIST_INVALID || get_hislen() == 0 || s->firstc == NUL) { diff --git a/src/nvim/linematch.c b/src/nvim/linematch.c index ebedda9b4d..629a31c913 100644 --- a/src/nvim/linematch.c +++ b/src/nvim/linematch.c @@ -85,7 +85,7 @@ static void update_path_flat(diffcmppath_T *diffcmppath, int score, size_t to, s diffcmppath[to].df_path_idx = path_idx + 1; } -#define MATCH_CHAR_MAX_LEN 500 +#define MATCH_CHAR_MAX_LEN 800 /// Return matching characters between "s1" and "s2" whilst respecting sequence order. /// Consider the case of two strings 'AAACCC' and 'CCCAAA', the @@ -102,8 +102,8 @@ static void update_path_flat(diffcmppath_T *diffcmppath, int score, size_t to, s /// @param s2 static int matching_chars(const char *s1, const char *s2) { - size_t s1len = MIN(MATCH_CHAR_MAX_LEN, line_len(s1)); - size_t s2len = MIN(MATCH_CHAR_MAX_LEN, line_len(s2)); + size_t s1len = MIN(MATCH_CHAR_MAX_LEN - 1, line_len(s1)); + size_t s2len = MIN(MATCH_CHAR_MAX_LEN - 1, line_len(s2)); int matrix[2][MATCH_CHAR_MAX_LEN] = { 0 }; bool icur = 1; // save space by storing only two rows for i axis for (size_t i = 0; i < s1len; i++) { diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c index 25a99c58ba..dfb4cc2625 100644 --- a/src/nvim/regexp_nfa.c +++ b/src/nvim/regexp_nfa.c @@ -280,6 +280,7 @@ typedef struct { char_u *end; } line[NSUBEXP]; } list; + colnr_T orig_start_col; // list.multi[0].start_col without \zs } regsub_T; typedef struct { @@ -4431,6 +4432,7 @@ static void copy_sub(regsub_T *to, regsub_T *from) if (REG_MULTI) { memmove(&to->list.multi[0], &from->list.multi[0], sizeof(struct multipos) * (size_t)from->in_use); + to->orig_start_col = from->orig_start_col; } else { memmove(&to->list.line[0], &from->list.line[0], sizeof(struct linepos) * (size_t)from->in_use); @@ -5781,12 +5783,12 @@ static int skip_to_start(int c, colnr_T *colp) // Check for a match with match_text. // Called after skip_to_start() has found regstart. // Returns zero for no match, 1 for a match. -static long find_match_text(colnr_T startcol, int regstart, char_u *match_text) +static long find_match_text(colnr_T *startcol, int regstart, char_u *match_text) { #define PTR2LEN(x) utf_ptr2len(x) - colnr_T col = startcol; - int regstart_len = PTR2LEN((char *)rex.line + startcol); + colnr_T col = *startcol; + int regstart_len = PTR2LEN((char *)rex.line + col); for (;;) { bool match = true; @@ -5819,6 +5821,7 @@ static long find_match_text(colnr_T startcol, int regstart, char_u *match_text) rex.reg_startp[0] = rex.line + col; rex.reg_endp[0] = s2; } + *startcol = col; return 1L; } @@ -5828,6 +5831,8 @@ static long find_match_text(colnr_T startcol, int regstart, char_u *match_text) break; } } + + *startcol = col; return 0L; #undef PTR2LEN @@ -5931,6 +5936,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm if (REG_MULTI) { m->norm.list.multi[0].start_lnum = rex.lnum; m->norm.list.multi[0].start_col = (colnr_T)(rex.input - rex.line); + m->norm.orig_start_col = m->norm.list.multi[0].start_col; } else { m->norm.list.line[0].start = rex.input; } @@ -7110,6 +7116,8 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm if (REG_MULTI) { m->norm.list.multi[0].start_col = (colnr_T)(rex.input - rex.line) + clen; + m->norm.orig_start_col = + m->norm.list.multi[0].start_col; } else { m->norm.list.line[0].start = rex.input + clen; } @@ -7243,6 +7251,9 @@ static long nfa_regtry(nfa_regprog_T *prog, colnr_T col, proftime_T *tm, int *ti rex.reg_endpos[i].lnum = subs.norm.list.multi[i].end_lnum; rex.reg_endpos[i].col = subs.norm.list.multi[i].end_col; } + if (rex.reg_mmatch != NULL) { + rex.reg_mmatch->rmm_matchcol = subs.norm.orig_start_col; + } if (rex.reg_startpos[0].lnum < 0) { rex.reg_startpos[0].lnum = 0; @@ -7385,7 +7396,7 @@ static long nfa_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm, int // If match_text is set it contains the full text that must match. // Nothing else to try. Doesn't handle combining chars well. if (prog->match_text != NULL && !rex.reg_icombine) { - retval = find_match_text(col, prog->regstart, prog->match_text); + retval = find_match_text(&col, prog->regstart, prog->match_text); if (REG_MULTI) { rex.reg_mmatch->rmm_matchcol = col; } else { @@ -7427,10 +7438,6 @@ theend: || (end->lnum == start->lnum && end->col < start->col)) { rex.reg_mmatch->endpos[0] = rex.reg_mmatch->startpos[0]; } - - // startpos[0] may be set by "\zs", also return the column where - // the whole pattern matched. - rex.reg_mmatch->rmm_matchcol = col; } else { if (rex.reg_match->endp[0] < rex.reg_match->startp[0]) { rex.reg_match->endp[0] = rex.reg_match->startp[0]; diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim index 0ab82e6bcd..b9f32b2db9 100644 --- a/src/nvim/testdir/test_cmdline.vim +++ b/src/nvim/testdir/test_cmdline.vim @@ -2235,6 +2235,30 @@ func Test_recalling_cmdline() cunmap <Plug>(save-cmdline) endfunc +func Test_cmd_map_cmdlineChanged() + let g:log = [] + cnoremap <F1> l<Cmd><CR>s + augroup test + autocmd! + autocmd CmdlineChanged : let g:log += [getcmdline()] + augroup END + + call feedkeys(":\<F1>\<CR>", 'xt') + call assert_equal(['l', 'ls'], g:log) + + let @b = 'b' + cnoremap <F1> a<C-R>b + let g:log = [] + call feedkeys(":\<F1>\<CR>", 'xt') + call assert_equal(['a', 'ab'], g:log) + + unlet g:log + cunmap <F1> + augroup test + autocmd! + augroup END +endfunc + " Test for the 'suffixes' option func Test_suffixes_opt() call writefile([], 'Xfile') diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index e13ff77705..8dc4173d60 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -2959,6 +2959,7 @@ func Test_cwindow_highlight() call writefile(lines, 'XtestCwindow') let buf = RunVimInTerminal('-S XtestCwindow', #{rows: 12}) call VerifyScreenDump(buf, 'Test_quickfix_cwindow_1', {}) + call term_sendkeys(buf, ":cnext\<CR>") call VerifyScreenDump(buf, 'Test_quickfix_cwindow_2', {}) |