diff options
125 files changed, 2277 insertions, 1513 deletions
diff --git a/runtime/autoload/zip.vim b/runtime/autoload/zip.vim index 9588bbf4a2..bc9b62ddb0 100644 --- a/runtime/autoload/zip.vim +++ b/runtime/autoload/zip.vim @@ -1,7 +1,7 @@ " zip.vim: Handles browsing zipfiles " AUTOLOAD PORTION -" Date: Jan 07, 2020 -" Version: 31 +" Date: Nov 08, 2021 +" Version: 32 " Maintainer: Charles E Campbell <NcampObell@SdrPchip.AorgM-NOSPAM> " License: Vim License (see vim's :help license) " Copyright: Copyright (C) 2005-2019 Charles E. Campbell {{{1 @@ -20,7 +20,7 @@ if &cp || exists("g:loaded_zip") finish endif -let g:loaded_zip= "v31" +let g:loaded_zip= "v32" if v:version < 702 echohl WarningMsg echo "***warning*** this version of zip needs vim 7.2 or later" @@ -115,7 +115,13 @@ fun! zip#Browse(zipfile) setlocal bufhidden=hide setlocal nobuflisted setlocal nowrap - set ft=tar + + " Oct 12, 2021: need to re-use Bram's syntax/tar.vim. + " Setting the filetype to zip doesn't do anything (currently), + " but it is perhaps less confusing to curious perusers who do + " a :echo &ft + setf zip + run! syntax/tar.vim " give header call append(0, ['" zip.vim version '.g:loaded_zip, @@ -187,8 +193,8 @@ fun! s:ZipBrowseSelect() wincmd _ endif let s:zipfile_{winnr()}= curfile -" call Decho("exe e ".fnameescape("zipfile:".zipfile.'::'.fname)) - exe "noswapfile e ".fnameescape("zipfile:".zipfile.'::'.fname) +" call Decho("exe e ".fnameescape("zipfile://".zipfile.'::'.fname)) + exe "noswapfile e ".fnameescape("zipfile://".zipfile.'::'.fname) filetype detect let &report= repkeep @@ -203,11 +209,11 @@ fun! zip#Read(fname,mode) set report=10 if has("unix") - let zipfile = substitute(a:fname,'zipfile:\(.\{-}\)::[^\\].*$','\1','') - let fname = substitute(a:fname,'zipfile:.\{-}::\([^\\].*\)$','\1','') + let zipfile = substitute(a:fname,'zipfile://\(.\{-}\)::[^\\].*$','\1','') + let fname = substitute(a:fname,'zipfile://.\{-}::\([^\\].*\)$','\1','') else - let zipfile = substitute(a:fname,'^.\{-}zipfile:\(.\{-}\)::[^\\].*$','\1','') - let fname = substitute(a:fname,'^.\{-}zipfile:.\{-}::\([^\\].*\)$','\1','') + let zipfile = substitute(a:fname,'^.\{-}zipfile://\(.\{-}\)::[^\\].*$','\1','') + let fname = substitute(a:fname,'^.\{-}zipfile://.\{-}::\([^\\].*\)$','\1','') let fname = substitute(fname, '[', '[[]', 'g') endif " call Decho("zipfile<".zipfile.">") @@ -224,7 +230,7 @@ fun! zip#Read(fname,mode) " the following code does much the same thing as " exe "keepj sil! r! ".g:zip_unzipcmd." -p -- ".s:Escape(zipfile,1)." ".s:Escape(fnameescape(fname),1) - " but allows zipfile:... entries in quickfix lists + " but allows zipfile://... entries in quickfix lists let temp = tempname() " call Decho("using temp file<".temp.">") let fn = expand('%:p') @@ -296,11 +302,11 @@ fun! zip#Write(fname) " call Decho("current directory now: ".getcwd()) if has("unix") - let zipfile = substitute(a:fname,'zipfile:\(.\{-}\)::[^\\].*$','\1','') - let fname = substitute(a:fname,'zipfile:.\{-}::\([^\\].*\)$','\1','') + let zipfile = substitute(a:fname,'zipfile://\(.\{-}\)::[^\\].*$','\1','') + let fname = substitute(a:fname,'zipfile://.\{-}::\([^\\].*\)$','\1','') else - let zipfile = substitute(a:fname,'^.\{-}zipfile:\(.\{-}\)::[^\\].*$','\1','') - let fname = substitute(a:fname,'^.\{-}zipfile:.\{-}::\([^\\].*\)$','\1','') + let zipfile = substitute(a:fname,'^.\{-}zipfile://\(.\{-}\)::[^\\].*$','\1','') + let fname = substitute(a:fname,'^.\{-}zipfile://.\{-}::\([^\\].*\)$','\1','') endif " call Decho("zipfile<".zipfile.">") " call Decho("fname <".fname.">") diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index bb8e83f84a..166fef028d 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -652,35 +652,6 @@ nvim_call_atomic({calls}) *nvim_call_atomic()* occurred, the values from all preceding calls will still be returned. - *nvim_call_dict_function()* -nvim_call_dict_function({dict}, {fn}, {args}) - Calls a VimL |Dictionary-function| with the given arguments. - - On execution error: fails with VimL error, does not update - v:errmsg. - - Parameters: ~ - {dict} Dictionary, or String evaluating to a VimL |self| - dict - {fn} Name of the function defined on the VimL dict - {args} Function arguments packed in an Array - - Return: ~ - Result of the function call - -nvim_call_function({fn}, {args}) *nvim_call_function()* - Calls a VimL function with the given arguments. - - On execution error: fails with VimL error, does not update - v:errmsg. - - Parameters: ~ - {fn} Function to call - {args} Function arguments packed in an Array - - Return: ~ - Result of the function call - nvim_chan_send({chan}, {data}) *nvim_chan_send()* Send data to channel `id` . For a job, it writes it to the stdin of the process. For the stdio channel |channel-stdio|, @@ -697,18 +668,6 @@ nvim_chan_send({chan}, {data}) *nvim_chan_send()* {chan} id of the channel {data} data to write. 8-bit clean: can contain NUL bytes. -nvim_command({command}) *nvim_command()* - Executes an ex-command. - - On execution error: fails with VimL error, does not update - v:errmsg. - - Parameters: ~ - {command} Ex-command string - - See also: ~ - |nvim_exec()| - nvim_create_buf({listed}, {scratch}) *nvim_create_buf()* Creates a new, empty, unnamed buffer. @@ -724,22 +683,6 @@ nvim_create_buf({listed}, {scratch}) *nvim_create_buf()* See also: ~ buf_open_scratch -nvim_create_namespace({name}) *nvim_create_namespace()* - Creates a new *namespace* or gets an existing one. - - Namespaces are used for buffer highlights and virtual text, - see |nvim_buf_add_highlight()| and |nvim_buf_set_extmark()|. - - Namespaces can be named or anonymous. If `name` matches an - existing namespace, the associated id is returned. If `name` - is an empty string a new, anonymous namespace is created. - - Parameters: ~ - {name} Namespace name or empty string - - Return: ~ - Namespace id - nvim_del_current_line() *nvim_del_current_line()* Deletes the current line. @@ -806,19 +749,6 @@ nvim_err_writeln({str}) *nvim_err_writeln()* See also: ~ nvim_err_write() -nvim_eval({expr}) *nvim_eval()* - Evaluates a VimL |expression|. Dictionaries and Lists are - recursively expanded. - - On execution error: fails with VimL error, does not update - v:errmsg. - - Parameters: ~ - {expr} VimL expression string - - Return: ~ - Evaluation result or expanded object - nvim_eval_statusline({str}, {*opts}) *nvim_eval_statusline()* Evaluates statusline string. @@ -852,29 +782,6 @@ nvim_eval_statusline({str}, {*opts}) *nvim_eval_statusline()* character that uses the highlight. • group: (string) Name of highlight group. -nvim_exec({src}, {output}) *nvim_exec()* - Executes Vimscript (multiline block of Ex-commands), like - anonymous |:source|. - - Unlike |nvim_command()| this function supports heredocs, - script-scope (s:), etc. - - On execution error: fails with VimL error, does not update - v:errmsg. - - Parameters: ~ - {src} Vimscript code - {output} Capture and return all (non-error, non-shell - |:!|) output - - Return: ~ - Output (non-error, non-shell |:!|) if `output` is true, - else empty string. - - See also: ~ - |execute()| - |nvim_command()| - nvim_exec_lua({code}, {args}) *nvim_exec_lua()* Execute Lua code. Parameters (if any) are available as `...` inside the chunk. The chunk can return a value. @@ -1110,12 +1017,6 @@ nvim_get_mode() *nvim_get_mode()* Attributes: ~ {fast} -nvim_get_namespaces() *nvim_get_namespaces()* - Gets existing, non-anonymous namespaces. - - Return: ~ - dict that maps from names to namespace ids. - nvim_get_option({name}) *nvim_get_option()* Gets an option value string. @@ -1344,7 +1245,15 @@ nvim_open_term({buffer}, {opts}) *nvim_open_term()* Parameters: ~ {buffer} the buffer to use (expected to be empty) - {opts} Optional parameters. Reserved for future use. + {opts} Optional parameters. + • on_input: lua callback for input sent, i e + keypresses in 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 callback + however. ["input", term, bufnr, data] Return: ~ Channel id, or 0 on error @@ -1357,104 +1266,6 @@ nvim_out_write({str}) *nvim_out_write()* Parameters: ~ {str} Message - *nvim_parse_expression()* -nvim_parse_expression({expr}, {flags}, {highlight}) - Parse a VimL expression. - - Attributes: ~ - {fast} - - Parameters: ~ - {expr} Expression to parse. Always treated as a - single line. - {flags} Flags: - • "m" if multiple expressions in a row are - allowed (only the first one will be - parsed), - • "E" if EOC tokens are not allowed - (determines whether they will stop parsing - process or be recognized as an - operator/space, though also yielding an - error). - • "l" when needing to start parsing with - lvalues for ":let" or ":for". Common flag - sets: - • "m" to parse like for ":echo". - • "E" to parse like for "<C-r>=". - • empty string for ":call". - • "lm" to parse for ":let". - {highlight} If true, return value will also include - "highlight" key containing array of 4-tuples - (arrays) (Integer, Integer, Integer, String), - where first three numbers define the - highlighted region and represent line, - starting column and ending column (latter - exclusive: one should highlight region - [start_col, end_col)). - - Return: ~ - - • AST: top-level dictionary with these keys: - • "error": Dictionary with error, present only if parser - saw some error. Contains the following keys: - • "message": String, error message in printf format, - translated. Must contain exactly one "%.*s". - • "arg": String, error message argument. - - • "len": Amount of bytes successfully parsed. With flags - equal to "" that should be equal to the length of expr - string. (“Successfully parsed” here means - “participated in AST creation”, not “till the first - error”.) - • "ast": AST, either nil or a dictionary with these - keys: - • "type": node type, one of the value names from - ExprASTNodeType stringified without "kExprNode" - prefix. - • "start": a pair [line, column] describing where node - is "started" where "line" is always 0 (will not be 0 - if you will be using nvim_parse_viml() on e.g. - ":let", but that is not present yet). Both elements - are Integers. - • "len": “length” of the node. This and "start" are - there for debugging purposes primary (debugging - parser and providing debug information). - • "children": a list of nodes described in top/"ast". - There always is zero, one or two children, key will - not be present if node has no children. Maximum - number of children may be found in node_maxchildren - array. - - • Local values (present only for certain nodes): - • "scope": a single Integer, specifies scope for - "Option" and "PlainIdentifier" nodes. For "Option" it - is one of ExprOptScope values, for "PlainIdentifier" - it is one of ExprVarScope values. - • "ident": identifier (without scope, if any), present - for "Option", "PlainIdentifier", "PlainKey" and - "Environment" nodes. - • "name": Integer, register name (one character) or -1. - Only present for "Register" nodes. - • "cmp_type": String, comparison type, one of the value - names from ExprComparisonType, stringified without - "kExprCmp" prefix. Only present for "Comparison" - nodes. - • "ccs_strategy": String, case comparison strategy, one - of the value names from ExprCaseCompareStrategy, - stringified without "kCCStrategy" prefix. Only present - for "Comparison" nodes. - • "augmentation": String, augmentation type for - "Assignment" nodes. Is either an empty string, "Add", - "Subtract" or "Concat" for "=", "+=", "-=" or ".=" - respectively. - • "invert": Boolean, true if result of comparison needs - to be inverted. Only present for "Comparison" nodes. - • "ivalue": Integer, integer value for "Integer" nodes. - • "fvalue": Float, floating-point value for "Float" - nodes. - • "svalue": String, value for "SingleQuotedString" and - "DoubleQuotedString" nodes. - nvim_paste({data}, {crlf}, {phase}) *nvim_paste()* Pastes at cursor, in any mode. @@ -1650,53 +1461,6 @@ nvim_set_current_win({window}) *nvim_set_current_win()* Parameters: ~ {window} Window handle - *nvim_set_decoration_provider()* -nvim_set_decoration_provider({ns_id}, {opts}) - 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 - 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 ). - - Note: this function should not be called often. Rather, the - callbacks themselves can be used to throttle unneeded - callbacks. the `on_start` callback can return `false` to - disable the provider until the next redraw. Similarly, return - `false` in `on_win` will skip the `on_lines` calls for that - window (but any extmarks set in `on_win` will still be used). - A plugin managing multiple sources of decoration should - ideally only set one provider, and merge the sources - internally. You can use multiple `ns_id` for the extmarks - set/modified inside the callback anyway. - - Note: doing anything other than setting extmarks is considered - experimental. Doing things like changing options are not - expliticly forbidden, but is likely to have unexpected - consequences (such as 100% CPU consumption). doing - `vim.rpcnotify` should be OK, but `vim.rpcrequest` is quite - dubious for the moment. - - Parameters: ~ - {ns_id} Namespace id from |nvim_create_namespace()| - {opts} Callbacks invoked during redraw: - • on_start: called first on each screen redraw - ["start", tick] - • on_buf: called for each buffer being redrawn - (before window callbacks) ["buf", bufnr, tick] - • on_win: called when starting to redraw a - specific window. ["win", winid, bufnr, topline, - botline_guess] - • on_line: called for each buffer line being - redrawn. (The interation with fold lines is - subject to change) ["win", winid, bufnr, row] - • on_end: called at the end of a redraw cycle - ["end", tick] - nvim_set_hl({ns_id}, {name}, {val}) *nvim_set_hl()* Set a highlight group. @@ -1790,6 +1554,185 @@ nvim_unsubscribe({event}) *nvim_unsubscribe()* ============================================================================== +Vimscript Functions *api-vimscript* + + *nvim_call_dict_function()* +nvim_call_dict_function({dict}, {fn}, {args}) + Calls a VimL |Dictionary-function| with the given arguments. + + On execution error: fails with VimL error, does not update + v:errmsg. + + Parameters: ~ + {dict} Dictionary, or String evaluating to a VimL |self| + dict + {fn} Name of the function defined on the VimL dict + {args} Function arguments packed in an Array + + Return: ~ + Result of the function call + +nvim_call_function({fn}, {args}) *nvim_call_function()* + Calls a VimL function with the given arguments. + + On execution error: fails with VimL error, does not update + v:errmsg. + + Parameters: ~ + {fn} Function to call + {args} Function arguments packed in an Array + + Return: ~ + Result of the function call + +nvim_command({command}) *nvim_command()* + Executes an ex-command. + + On execution error: fails with VimL error, does not update + v:errmsg. + + Parameters: ~ + {command} Ex-command string + + See also: ~ + |nvim_exec()| + +nvim_eval({expr}) *nvim_eval()* + Evaluates a VimL |expression|. Dictionaries and Lists are + recursively expanded. + + On execution error: fails with VimL error, does not update + v:errmsg. + + Parameters: ~ + {expr} VimL expression string + + Return: ~ + Evaluation result or expanded object + +nvim_exec({src}, {output}) *nvim_exec()* + Executes Vimscript (multiline block of Ex-commands), like + anonymous |:source|. + + Unlike |nvim_command()| this function supports heredocs, + script-scope (s:), etc. + + On execution error: fails with VimL error, does not update + v:errmsg. + + Parameters: ~ + {src} Vimscript code + {output} Capture and return all (non-error, non-shell + |:!|) output + + Return: ~ + Output (non-error, non-shell |:!|) if `output` is true, + else empty string. + + See also: ~ + |execute()| + |nvim_command()| + + *nvim_parse_expression()* +nvim_parse_expression({expr}, {flags}, {highlight}) + Parse a VimL expression. + + Attributes: ~ + {fast} + + Parameters: ~ + {expr} Expression to parse. Always treated as a + single line. + {flags} Flags: + • "m" if multiple expressions in a row are + allowed (only the first one will be + parsed), + • "E" if EOC tokens are not allowed + (determines whether they will stop parsing + process or be recognized as an + operator/space, though also yielding an + error). + • "l" when needing to start parsing with + lvalues for ":let" or ":for". Common flag + sets: + • "m" to parse like for ":echo". + • "E" to parse like for "<C-r>=". + • empty string for ":call". + • "lm" to parse for ":let". + {highlight} If true, return value will also include + "highlight" key containing array of 4-tuples + (arrays) (Integer, Integer, Integer, String), + where first three numbers define the + highlighted region and represent line, + starting column and ending column (latter + exclusive: one should highlight region + [start_col, end_col)). + + Return: ~ + + • AST: top-level dictionary with these keys: + • "error": Dictionary with error, present only if parser + saw some error. Contains the following keys: + • "message": String, error message in printf format, + translated. Must contain exactly one "%.*s". + • "arg": String, error message argument. + + • "len": Amount of bytes successfully parsed. With flags + equal to "" that should be equal to the length of expr + string. (“Successfully parsed” here means + “participated in AST creation”, not “till the first + error”.) + • "ast": AST, either nil or a dictionary with these + keys: + • "type": node type, one of the value names from + ExprASTNodeType stringified without "kExprNode" + prefix. + • "start": a pair [line, column] describing where node + is "started" where "line" is always 0 (will not be 0 + if you will be using nvim_parse_viml() on e.g. + ":let", but that is not present yet). Both elements + are Integers. + • "len": “length” of the node. This and "start" are + there for debugging purposes primary (debugging + parser and providing debug information). + • "children": a list of nodes described in top/"ast". + There always is zero, one or two children, key will + not be present if node has no children. Maximum + number of children may be found in node_maxchildren + array. + + • Local values (present only for certain nodes): + • "scope": a single Integer, specifies scope for + "Option" and "PlainIdentifier" nodes. For "Option" it + is one of ExprOptScope values, for "PlainIdentifier" + it is one of ExprVarScope values. + • "ident": identifier (without scope, if any), present + for "Option", "PlainIdentifier", "PlainKey" and + "Environment" nodes. + • "name": Integer, register name (one character) or -1. + Only present for "Register" nodes. + • "cmp_type": String, comparison type, one of the value + names from ExprComparisonType, stringified without + "kExprCmp" prefix. Only present for "Comparison" + nodes. + • "ccs_strategy": String, case comparison strategy, one + of the value names from ExprCaseCompareStrategy, + stringified without "kCCStrategy" prefix. Only present + for "Comparison" nodes. + • "augmentation": String, augmentation type for + "Assignment" nodes. Is either an empty string, "Add", + "Subtract" or "Concat" for "=", "+=", "-=" or ".=" + respectively. + • "invert": Boolean, true if result of comparison needs + to be inverted. Only present for "Comparison" nodes. + • "ivalue": Integer, integer value for "Integer" nodes. + • "fvalue": Float, floating-point value for "Float" + nodes. + • "svalue": String, value for "SingleQuotedString" and + "DoubleQuotedString" nodes. + + +============================================================================== Buffer Functions *api-buffer* @@ -1815,48 +1758,6 @@ nvim__buf_redraw_range({buffer}, {first}, {last}) nvim__buf_stats({buffer}) *nvim__buf_stats()* TODO: Documentation - *nvim_buf_add_highlight()* -nvim_buf_add_highlight({buffer}, {ns_id}, {hl_group}, {line}, {col_start}, - {col_end}) - Adds a highlight to buffer. - - Useful for plugins that dynamically generate highlights to a - buffer (like a semantic highlighter or linter). The function - adds a single highlight to a buffer. Unlike |matchaddpos()| - highlights follow changes to line numbering (as lines are - inserted/removed above the highlighted line), like signs and - marks do. - - Namespaces are used for batch deletion/updating of a set of - highlights. To create a namespace, use - |nvim_create_namespace()| which returns a namespace id. Pass - it in to this function as `ns_id` to add highlights to the - namespace. All highlights in the same namespace can then be - cleared with single call to |nvim_buf_clear_namespace()|. If - the highlight never will be deleted by an API call, pass - `ns_id = -1` . - - As a shorthand, `ns_id = 0` can be used to create a new - namespace for the highlight, the allocated id is then - returned. If `hl_group` is the empty string no highlight is - added, but a new `ns_id` is still returned. This is supported - for backwards compatibility, new code should use - |nvim_create_namespace()| to create a new empty namespace. - - Parameters: ~ - {buffer} Buffer handle, or 0 for current buffer - {ns_id} namespace to use or -1 for ungrouped - highlight - {hl_group} Name of the highlight group to use - {line} Line to highlight (zero-indexed) - {col_start} Start of (byte-indexed) column range to - highlight - {col_end} End of (byte-indexed) column range to - highlight, or -1 to highlight to end of line - - Return: ~ - The ns_id that was used - nvim_buf_attach({buffer}, {send_buffer}, {opts}) *nvim_buf_attach()* Activates buffer-update events on a channel, or as Lua callbacks. @@ -1965,33 +1866,6 @@ nvim_buf_call({buffer}, {fun}) *nvim_buf_call()* Return value of function. NB: will deepcopy lua values currently, use upvalues to send lua references in and out. - *nvim_buf_clear_namespace()* -nvim_buf_clear_namespace({buffer}, {ns_id}, {line_start}, {line_end}) - Clears namespaced objects (highlights, extmarks, virtual text) - from a region. - - Lines are 0-indexed. |api-indexing| To clear the namespace in - the entire buffer, specify line_start=0 and line_end=-1. - - Parameters: ~ - {buffer} Buffer handle, or 0 for current buffer - {ns_id} Namespace to clear, or -1 to clear all - namespaces. - {line_start} Start of range of lines to clear - {line_end} End of range of lines to clear (exclusive) - or -1 to clear to end of buffer. - -nvim_buf_del_extmark({buffer}, {ns_id}, {id}) *nvim_buf_del_extmark()* - Removes an extmark. - - Parameters: ~ - {buffer} Buffer handle, or 0 for current buffer - {ns_id} Namespace id from |nvim_create_namespace()| - {id} Extmark id - - Return: ~ - true if the extmark was found, else false - nvim_buf_del_keymap({buffer}, {mode}, {lhs}) *nvim_buf_del_keymap()* Unmaps a buffer-local |mapping| for the given mode. @@ -2073,73 +1947,6 @@ nvim_buf_get_commands({buffer}, {*opts}) *nvim_buf_get_commands()* Return: ~ Map of maps describing commands. - *nvim_buf_get_extmark_by_id()* -nvim_buf_get_extmark_by_id({buffer}, {ns_id}, {id}, {opts}) - Gets the position (0-indexed) of an extmark. - - Parameters: ~ - {buffer} Buffer handle, or 0 for current buffer - {ns_id} Namespace id from |nvim_create_namespace()| - {id} Extmark id - {opts} Optional parameters. Keys: - • details: Whether to include the details dict - - Return: ~ - 0-indexed (row, col) tuple or empty list () if extmark id - was absent - - *nvim_buf_get_extmarks()* -nvim_buf_get_extmarks({buffer}, {ns_id}, {start}, {end}, {opts}) - 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 positions define the bounds). 0 and -1 are understood - as (0,0) and (-1,-1) respectively, thus the following are - equivalent: -> - nvim_buf_get_extmarks(0, my_ns, 0, -1, {}) - nvim_buf_get_extmarks(0, my_ns, [0,0], [-1,-1], {}) -< - - If `end` is less than `start` , traversal works backwards. - (Useful with `limit` , to get the first marks prior to a given - position.) - - Example: -> - local a = vim.api - local pos = a.nvim_win_get_cursor(0) - local ns = a.nvim_create_namespace('my-plugin') - -- Create new extmark at line 1, column 1. - local m1 = a.nvim_buf_set_extmark(0, ns, 0, 0, 0, {}) - -- Create new extmark at line 3, column 1. - local m2 = a.nvim_buf_set_extmark(0, ns, 0, 2, 0, {}) - -- Get extmarks only from line 3. - local ms = a.nvim_buf_get_extmarks(0, ns, {2,0}, {2,0}, {}) - -- Get all marks in this buffer + namespace. - local all = a.nvim_buf_get_extmarks(0, ns, 0, -1, {}) - print(vim.inspect(ms)) -< - - Parameters: ~ - {buffer} Buffer handle, or 0 for current buffer - {ns_id} Namespace id from |nvim_create_namespace()| - {start} Start of range: a 0-indexed (row, col) or valid - extmark id (whose position defines the bound). - |api-indexing| - {end} End of range (inclusive): a 0-indexed (row, col) - or valid extmark id (whose position defines the - bound). |api-indexing| - {opts} Optional parameters. Keys: - • limit: Maximum number of marks to return - • details Whether to include the details dict - - Return: ~ - List of [extmark_id, row, col] tuples in "traversal - order". - nvim_buf_get_keymap({buffer}, {mode}) *nvim_buf_get_keymap()* Gets a list of buffer-local |mapping| definitions. @@ -2270,6 +2077,257 @@ nvim_buf_line_count({buffer}) *nvim_buf_line_count()* Return: ~ Line count, or 0 for unloaded buffer. |api-buffer| + *nvim_buf_set_keymap()* +nvim_buf_set_keymap({buffer}, {mode}, {lhs}, {rhs}, {*opts}) + Sets a buffer-local |mapping| for the given mode. + + Parameters: ~ + {buffer} Buffer handle, or 0 for current buffer + + See also: ~ + |nvim_set_keymap()| + + *nvim_buf_set_lines()* +nvim_buf_set_lines({buffer}, {start}, {end}, {strict_indexing}, {replacement}) + Sets (replaces) a line-range in the buffer. + + Indexing is zero-based, end-exclusive. Negative indices are + interpreted as length+1+index: -1 refers to the index past the + end. So to change or delete the last element use start=-2 and + end=-1. + + To insert lines at a given index, set `start` and `end` to the + same index. To delete a range of lines, set `replacement` to + an empty array. + + Out-of-bounds indices are clamped to the nearest valid value, + unless `strict_indexing` is set. + + Attributes: ~ + not allowed when |textlock| is active + + Parameters: ~ + {buffer} Buffer handle, or 0 for current buffer + {start} First line index + {end} Last line index (exclusive) + {strict_indexing} Whether out-of-bounds should be an + error. + {replacement} Array of lines to use as replacement + + *nvim_buf_set_mark()* +nvim_buf_set_mark({buffer}, {name}, {line}, {col}, {opts}) + Sets a named mark in the given buffer, all marks are allowed + file/uppercase, visual, last change, etc. See |mark-motions|. + + Marks are (1,0)-indexed. |api-indexing| + + Note: + Passing 0 as line deletes the mark + + Parameters: ~ + {buffer} Buffer to set the mark on + {name} Mark name + {line} Line number + {col} Column/row number + {opts} Optional parameters. Reserved for future use. + + Return: ~ + true if the mark was set, else false. + + See also: ~ + |nvim_buf_del_mark()| + |nvim_buf_get_mark()| + +nvim_buf_set_name({buffer}, {name}) *nvim_buf_set_name()* + Sets the full file name for a buffer + + Parameters: ~ + {buffer} Buffer handle, or 0 for current buffer + {name} Buffer name + +nvim_buf_set_option({buffer}, {name}, {value}) *nvim_buf_set_option()* + Sets a buffer option value. Passing 'nil' as value deletes the + option (only works if there's a global fallback) + + Parameters: ~ + {buffer} Buffer handle, or 0 for current buffer + {name} Option name + {value} Option value + + *nvim_buf_set_text()* +nvim_buf_set_text({buffer}, {start_row}, {start_col}, {end_row}, {end_col}, + {replacement}) + Sets (replaces) a range in the buffer + + This is recommended over nvim_buf_set_lines when only + modifying parts of a line, as extmarks will be preserved on + non-modified parts of the touched lines. + + Indexing is zero-based and end-exclusive. + + To insert text at a given index, set `start` and `end` ranges + to the same index. To delete a range, set `replacement` to an + array containing an empty string, or simply an empty array. + + Prefer nvim_buf_set_lines when adding or deleting entire lines + only. + + Parameters: ~ + {buffer} Buffer handle, or 0 for current buffer + {start_row} First line index + {start_column} Last column + {end_row} Last line index + {end_column} Last column + {replacement} Array of lines to use as replacement + +nvim_buf_set_var({buffer}, {name}, {value}) *nvim_buf_set_var()* + Sets a buffer-scoped (b:) variable + + Parameters: ~ + {buffer} Buffer handle, or 0 for current buffer + {name} Variable name + {value} Variable value + + +============================================================================== +Extmark Functions *api-extmark* + + *nvim_buf_add_highlight()* +nvim_buf_add_highlight({buffer}, {ns_id}, {hl_group}, {line}, {col_start}, + {col_end}) + Adds a highlight to buffer. + + Useful for plugins that dynamically generate highlights to a + buffer (like a semantic highlighter or linter). The function + adds a single highlight to a buffer. Unlike |matchaddpos()| + highlights follow changes to line numbering (as lines are + inserted/removed above the highlighted line), like signs and + marks do. + + Namespaces are used for batch deletion/updating of a set of + highlights. To create a namespace, use + |nvim_create_namespace()| which returns a namespace id. Pass + it in to this function as `ns_id` to add highlights to the + namespace. All highlights in the same namespace can then be + cleared with single call to |nvim_buf_clear_namespace()|. If + the highlight never will be deleted by an API call, pass + `ns_id = -1` . + + As a shorthand, `ns_id = 0` can be used to create a new + namespace for the highlight, the allocated id is then + returned. If `hl_group` is the empty string no highlight is + added, but a new `ns_id` is still returned. This is supported + for backwards compatibility, new code should use + |nvim_create_namespace()| to create a new empty namespace. + + Parameters: ~ + {buffer} Buffer handle, or 0 for current buffer + {ns_id} namespace to use or -1 for ungrouped + highlight + {hl_group} Name of the highlight group to use + {line} Line to highlight (zero-indexed) + {col_start} Start of (byte-indexed) column range to + highlight + {col_end} End of (byte-indexed) column range to + highlight, or -1 to highlight to end of line + + Return: ~ + The ns_id that was used + + *nvim_buf_clear_namespace()* +nvim_buf_clear_namespace({buffer}, {ns_id}, {line_start}, {line_end}) + Clears namespaced objects (highlights, extmarks, virtual text) + from a region. + + Lines are 0-indexed. |api-indexing| To clear the namespace in + the entire buffer, specify line_start=0 and line_end=-1. + + Parameters: ~ + {buffer} Buffer handle, or 0 for current buffer + {ns_id} Namespace to clear, or -1 to clear all + namespaces. + {line_start} Start of range of lines to clear + {line_end} End of range of lines to clear (exclusive) + or -1 to clear to end of buffer. + +nvim_buf_del_extmark({buffer}, {ns_id}, {id}) *nvim_buf_del_extmark()* + Removes an extmark. + + Parameters: ~ + {buffer} Buffer handle, or 0 for current buffer + {ns_id} Namespace id from |nvim_create_namespace()| + {id} Extmark id + + Return: ~ + true if the extmark was found, else false + + *nvim_buf_get_extmark_by_id()* +nvim_buf_get_extmark_by_id({buffer}, {ns_id}, {id}, {opts}) + Gets the position (0-indexed) of an extmark. + + Parameters: ~ + {buffer} Buffer handle, or 0 for current buffer + {ns_id} Namespace id from |nvim_create_namespace()| + {id} Extmark id + {opts} Optional parameters. Keys: + • details: Whether to include the details dict + + Return: ~ + 0-indexed (row, col) tuple or empty list () if extmark id + was absent + + *nvim_buf_get_extmarks()* +nvim_buf_get_extmarks({buffer}, {ns_id}, {start}, {end}, {opts}) + 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 positions define the bounds). 0 and -1 are understood + as (0,0) and (-1,-1) respectively, thus the following are + equivalent: +> + nvim_buf_get_extmarks(0, my_ns, 0, -1, {}) + nvim_buf_get_extmarks(0, my_ns, [0,0], [-1,-1], {}) +< + + If `end` is less than `start` , traversal works backwards. + (Useful with `limit` , to get the first marks prior to a given + position.) + + Example: +> + local a = vim.api + local pos = a.nvim_win_get_cursor(0) + local ns = a.nvim_create_namespace('my-plugin') + -- Create new extmark at line 1, column 1. + local m1 = a.nvim_buf_set_extmark(0, ns, 0, 0, 0, {}) + -- Create new extmark at line 3, column 1. + local m2 = a.nvim_buf_set_extmark(0, ns, 0, 2, 0, {}) + -- Get extmarks only from line 3. + local ms = a.nvim_buf_get_extmarks(0, ns, {2,0}, {2,0}, {}) + -- Get all marks in this buffer + namespace. + local all = a.nvim_buf_get_extmarks(0, ns, 0, -1, {}) + print(vim.inspect(ms)) +< + + Parameters: ~ + {buffer} Buffer handle, or 0 for current buffer + {ns_id} Namespace id from |nvim_create_namespace()| + {start} Start of range: a 0-indexed (row, col) or valid + extmark id (whose position defines the bound). + |api-indexing| + {end} End of range (inclusive): a 0-indexed (row, col) + or valid extmark id (whose position defines the + bound). |api-indexing| + {opts} Optional parameters. Keys: + • limit: Maximum number of marks to return + • details Whether to include the details dict + + Return: ~ + List of [extmark_id, row, col] tuples in "traversal + order". + *nvim_buf_set_extmark()* nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts}) Creates or updates an extmark. @@ -2351,12 +2409,7 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts}) of the array. However the 'tabstop' buffer option is still used for hard tabs. By default lines are placed below the buffer line - containing the mark. • Note: currently virtual lines are limited to - one block per buffer. Thus setting a new mark - disables any previous `virt_lines` decoration. - However plugins should not rely on this - behaviour, as this limitation is planned to be - removed. + containing the mark. • virt_lines_above: place virtual lines above instead. • virt_lines_leftcol: Place extmarks in the @@ -2383,116 +2436,74 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts}) Return: ~ Id of the created/updated extmark - *nvim_buf_set_keymap()* -nvim_buf_set_keymap({buffer}, {mode}, {lhs}, {rhs}, {*opts}) - Sets a buffer-local |mapping| for the given mode. - - Parameters: ~ - {buffer} Buffer handle, or 0 for current buffer - - See also: ~ - |nvim_set_keymap()| - - *nvim_buf_set_lines()* -nvim_buf_set_lines({buffer}, {start}, {end}, {strict_indexing}, {replacement}) - Sets (replaces) a line-range in the buffer. - - Indexing is zero-based, end-exclusive. Negative indices are - interpreted as length+1+index: -1 refers to the index past the - end. So to change or delete the last element use start=-2 and - end=-1. - - To insert lines at a given index, set `start` and `end` to the - same index. To delete a range of lines, set `replacement` to - an empty array. - - Out-of-bounds indices are clamped to the nearest valid value, - unless `strict_indexing` is set. - - Attributes: ~ - not allowed when |textlock| is active - - Parameters: ~ - {buffer} Buffer handle, or 0 for current buffer - {start} First line index - {end} Last line index (exclusive) - {strict_indexing} Whether out-of-bounds should be an - error. - {replacement} Array of lines to use as replacement - - *nvim_buf_set_mark()* -nvim_buf_set_mark({buffer}, {name}, {line}, {col}, {opts}) - Sets a named mark in the given buffer, all marks are allowed - file/uppercase, visual, last change, etc. See |mark-motions|. +nvim_create_namespace({name}) *nvim_create_namespace()* + Creates a new *namespace* or gets an existing one. - Marks are (1,0)-indexed. |api-indexing| + Namespaces are used for buffer highlights and virtual text, + see |nvim_buf_add_highlight()| and |nvim_buf_set_extmark()|. - Note: - Passing 0 as line deletes the mark + Namespaces can be named or anonymous. If `name` matches an + existing namespace, the associated id is returned. If `name` + is an empty string a new, anonymous namespace is created. Parameters: ~ - {buffer} Buffer to set the mark on - {name} Mark name - {line} Line number - {col} Column/row number - {opts} Optional parameters. Reserved for future use. + {name} Namespace name or empty string Return: ~ - true if the mark was set, else false. - - See also: ~ - |nvim_buf_del_mark()| - |nvim_buf_get_mark()| - -nvim_buf_set_name({buffer}, {name}) *nvim_buf_set_name()* - Sets the full file name for a buffer - - Parameters: ~ - {buffer} Buffer handle, or 0 for current buffer - {name} Buffer name - -nvim_buf_set_option({buffer}, {name}, {value}) *nvim_buf_set_option()* - Sets a buffer option value. Passing 'nil' as value deletes the - option (only works if there's a global fallback) - - Parameters: ~ - {buffer} Buffer handle, or 0 for current buffer - {name} Option name - {value} Option value + Namespace id - *nvim_buf_set_text()* -nvim_buf_set_text({buffer}, {start_row}, {start_col}, {end_row}, {end_col}, - {replacement}) - Sets (replaces) a range in the buffer +nvim_get_namespaces() *nvim_get_namespaces()* + Gets existing, non-anonymous namespaces. - This is recommended over nvim_buf_set_lines when only - modifying parts of a line, as extmarks will be preserved on - non-modified parts of the touched lines. + Return: ~ + dict that maps from names to namespace ids. - Indexing is zero-based and end-exclusive. + *nvim_set_decoration_provider()* +nvim_set_decoration_provider({ns_id}, {opts}) + Set or change decoration provider for a namespace - To insert text at a given index, set `start` and `end` ranges - to the same index. To delete a range, set `replacement` to an - array containing an empty string, or simply an empty array. + This is a very general purpose interface for having lua + callbacks being triggered during the redraw code. - Prefer nvim_buf_set_lines when adding or deleting entire lines - only. + 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 again for the next redraw ). - Parameters: ~ - {buffer} Buffer handle, or 0 for current buffer - {start_row} First line index - {start_column} Last column - {end_row} Last line index - {end_column} Last column - {replacement} Array of lines to use as replacement + Note: this function should not be called often. Rather, the + callbacks themselves can be used to throttle unneeded + callbacks. the `on_start` callback can return `false` to + disable the provider until the next redraw. Similarly, return + `false` in `on_win` will skip the `on_lines` calls for that + window (but any extmarks set in `on_win` will still be used). + A plugin managing multiple sources of decoration should + ideally only set one provider, and merge the sources + internally. You can use multiple `ns_id` for the extmarks + set/modified inside the callback anyway. -nvim_buf_set_var({buffer}, {name}, {value}) *nvim_buf_set_var()* - Sets a buffer-scoped (b:) variable + Note: doing anything other than setting extmarks is considered + experimental. Doing things like changing options are not + expliticly forbidden, but is likely to have unexpected + consequences (such as 100% CPU consumption). doing + `vim.rpcnotify` should be OK, but `vim.rpcrequest` is quite + dubious for the moment. Parameters: ~ - {buffer} Buffer handle, or 0 for current buffer - {name} Variable name - {value} Variable value + {ns_id} Namespace id from |nvim_create_namespace()| + {opts} Callbacks invoked during redraw: + • on_start: called first on each screen redraw + ["start", tick] + • on_buf: called for each buffer being redrawn + (before window callbacks) ["buf", bufnr, tick] + • on_win: called when starting to redraw a + specific window. ["win", winid, bufnr, topline, + botline_guess] + • on_line: called for each buffer line being + redrawn. (The interation with fold lines is + subject to change) ["win", winid, bufnr, row] + • on_end: called at the end of a redraw cycle + ["end", tick] ============================================================================== diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt index 6c41dd3b10..2737ac9b9f 100644 --- a/runtime/doc/autocmd.txt +++ b/runtime/doc/autocmd.txt @@ -1002,8 +1002,9 @@ VimResume After Nvim resumes from |suspend| state. *VimSuspend* VimSuspend Before Nvim enters |suspend| state. *WinClosed* -WinClosed After closing a window. <afile> expands to the - |window-ID|. +WinClosed After closing a window. The pattern is + matched against the |window-ID|. Both + <amatch> and <afile> are set to the |window-ID|. After WinLeave. Non-recursive (event cannot trigger itself). See also |ExitPre|, |QuitPre|. diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 1b949d749c..58d5d30146 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -5001,11 +5001,11 @@ getcurpos() Get the position of the cursor. This is like getpos('.'), but getcwd([{winnr}[, {tabnr}]]) *getcwd()* With no arguments, returns the name of the effective |current-directory|. With {winnr} or {tabnr} the working - directory of that scope is returned. + directory of that scope is returned, and 'autochdir' is + ignored. Tabs and windows are identified by their respective numbers, - 0 means current tab or window. Missing argument implies 0. + 0 means current tab or window. Missing tab number implies 0. Thus the following are equivalent: > - getcwd() getcwd(0) getcwd(0, 0) < If {winnr} is -1 it is ignored, only the tab is resolved. @@ -5562,6 +5562,9 @@ getwininfo([{winid}]) *getwininfo()* otherwise wincol leftmost screen column of the window; "col" from |win_screenpos()| + textoff number of columns occupied by any + 'foldcolumn', 'signcolumn' and line + number in front of the text winid |window-ID| winnr window number winrow topmost screen line of the window; @@ -10291,7 +10294,9 @@ wildmenumode() *wildmenumode()* win_execute({id}, {command} [, {silent}]) *win_execute()* Like `execute()` but in the context of window {id}. The window will temporarily be made the current window, - without triggering autocommands. + without triggering autocommands or changing directory. When + executing {command} autocommands will be triggered, this may + have unexpected side effects. Use |:noautocmd| if needed. Example: > call win_execute(winid, 'syntax enable') diff --git a/runtime/doc/helphelp.txt b/runtime/doc/helphelp.txt index aaa2a35fe1..c884eea54f 100644 --- a/runtime/doc/helphelp.txt +++ b/runtime/doc/helphelp.txt @@ -319,21 +319,25 @@ Hints for translators: 3. Writing help files *help-writing* For ease of use, a Vim help file for a plugin should follow the format of the -standard Vim help files. If you are writing a new help file it's best to copy -one of the existing files and use it as a template. +standard Vim help files, except fot the fist line. If you are writing a new +help file it's best to copy one of the existing files and use it as a +template. The first line in a help file should have the following format: -*helpfile_name.txt* For Vim version 7.3 Last change: 2010 June 4 +*plugin_name.txt* {short description of the plugin} -The first field is a link to the help file name. The second field describes -the applicable Vim version. The last field specifies the last modification -date of the file. Each field is separated by a tab. +The first field is a help tag where ":help plugin_name" will jump to. The +remainder of the line, after a Tab, describes the plugin purpose in a short +way. This will show up in the "LOCAL ADDITIONS" section of the main help +file. Check there that it shows up properly: |local-additions|. + +If you want to add a version number of last modification date, put it in the +second line, right aligned. At the bottom of the help file, place a Vim modeline to set the 'textwidth' and 'tabstop' options and the 'filetype' to "help". Never set a global option -in such a modeline, that can have consequences undesired by whoever reads that -help. +in such a modeline, that can have undesired consequences. TAGS diff --git a/runtime/doc/if_pyth.txt b/runtime/doc/if_pyth.txt index dc46fa515a..fea47de220 100644 --- a/runtime/doc/if_pyth.txt +++ b/runtime/doc/if_pyth.txt @@ -45,6 +45,11 @@ To see what version of Python you have: > There is no need to "import sys", it's done by default. + *python-environment* +Environment variables set in Vim are not always available in Python. This +depends on how Vim and Python were build. Also see +https://docs.python.org/3/library/os.html#os.environ + Note: Python is very sensitive to indenting. Make sure the "class" line and "EOF" do not have any indent. diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index 83d201c23a..1e84402a9f 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -573,6 +573,9 @@ buf_request_sync({bufnr}, {method}, {params}, {timeout_ms}) error, returns `(nil, err)` where `err` is a string describing the failure reason. +check_clients_closed() *vim.lsp.check_clients_closed()* + TODO: Documentation + client() *vim.lsp.client* LSP client object. You can get an active client object via |vim.lsp.get_client_by_id()| or @@ -628,11 +631,6 @@ client() *vim.lsp.client* server. • {handlers} (table): The handlers used by the client as described in |lsp-handler|. - • {requests} (table): The current pending requests in flight - to the server. Entries are key-value pairs with the key - being the request ID while the value is a table with `type`, - `bufnr`, and `method` key-value pairs. `type` is either "pending" - for an active request, or "cancel" for a cancel request. • {config} (table): copy of the table that was passed by the user to |vim.lsp.start_client()|. • {server_capabilities} (table): Response from the server @@ -657,6 +655,19 @@ flush({client}) *vim.lsp.flush()* for_each_buffer_client({bufnr}, {fn}) TODO: Documentation +formatexpr({opts}) *vim.lsp.formatexpr()* + Provides an interface between the built-in client and a + `formatexpr` function. + + Currently only supports a single client. This can be set via `setlocal formatexpr=v:lua.vim.lsp.formatexpr()` but will typically or in `on_attach` via vim.api.nvim_buf_set_option(bufnr, 'formatexpr , 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})')`. + + Parameters: ~ + {opts} table options for customizing the formatting + expression which takes the following optional + keys: + • timeout_ms (default 500ms). The timeout period + for the formatting request. + get_active_clients() *vim.lsp.get_active_clients()* Gets all active clients. @@ -666,7 +677,7 @@ get_active_clients() *vim.lsp.get_active_clients()* *vim.lsp.get_buffers_by_client_id()* get_buffers_by_client_id({client_id}) Parameters: ~ - {client_id} client id + {client_id} number client id Return: ~ list of buffer ids @@ -676,7 +687,7 @@ get_client_by_id({client_id}) *vim.lsp.get_client_by_id()* client may not yet be fully initialized. Parameters: ~ - {client_id} client id number + {client_id} number client id Return: ~ |vim.lsp.client| object, or nil @@ -707,7 +718,7 @@ omnifunc({findstart}, {base}) *vim.lsp.omnifunc()* |CompleteDone| *vim.lsp.prepare()* -prepare({bufnr}, {firstline}, {new_lastline}, {changedtick}) +prepare({bufnr}, {firstline}, {lastline}, {new_lastline}, {changedtick}) TODO: Documentation reset({client_id}) *vim.lsp.reset()* @@ -734,15 +745,12 @@ set_log_level({level}) *vim.lsp.set_log_level()* start_client({config}) *vim.lsp.start_client()* Starts and initializes a client with the given configuration. - Parameters `cmd` and `root_dir` are required. + Parameter `cmd` is required. The following parameters describe fields in the {config} table. Parameters: ~ - {root_dir} (string) Directory where the LSP - server will base its rootUri on - initialization. {cmd} (required, string or list treated like |jobstart()|) Base command that initiates the LSP client. @@ -757,6 +765,13 @@ start_client({config}) *vim.lsp.start_client()* { "PRODUCTION=true"; "TEST=123"; PORT = 8080; HOST = "0.0.0.0"; } < + {workspace_folders} (table) List of workspace folders + passed to the language server. For + backwards compatibility rootUri and + rootPath will be derived from the + first workspace folder in this list. + See `workspaceFolders` in the LSP + spec. {capabilities} Map overriding the default capabilities defined by |vim.lsp.protocol.make_client_capabilities()|, @@ -776,15 +791,20 @@ start_client({config}) *vim.lsp.start_client()* language server if requested via `workspace/configuration` . Keys are case-sensitive. + {commands} table Table that maps string of + clientside commands to user-defined + functions. Commands passed to + start_client take precedence over the + global command registry. Each key + must be a unique comand name, and the + value is a function which is called + if any LSP action (code action, code + lenses, ...) triggers the command. {init_options} Values to pass in the initialization request as `initializationOptions` . See `initialize` in the LSP spec. {name} (string, default=client-id) Name in log messages. - {workspace_folders} (table) List of workspace folders - passed to the language server. - Defaults to root_dir if not set. See - `workspaceFolders` in the LSP spec {get_language_id} function(bufnr, filetype) -> language ID as string. Defaults to the filetype. @@ -851,6 +871,12 @@ start_client({config}) *vim.lsp.start_client()* notifications to the server by the given number in milliseconds. No debounce occurs if nil + • exit_timeout (number, default 500): + Milliseconds to wait for server to + {root_dir} string Directory where the LSP server + will base its workspaceFolders, + rootUri, and rootPath on + initialization. Return: ~ Client id. |vim.lsp.get_client_by_id()| Note: client may @@ -876,6 +902,23 @@ stop_client({client_id}, {force}) *vim.lsp.stop_client()* thereof {force} boolean (optional) shutdown forcefully +tagfunc({...}) *vim.lsp.tagfunc()* + Provides an interface between the built-in client and + 'tagfunc'. + + When used with normal mode commands (e.g. |CTRL-]|) this will + invoke the "textDocument/definition" LSP method to find the + tag under the cursor. Otherwise, uses "workspace/symbol". If + no results are returned from any LSP servers, falls back to + using built-in tags. + + Parameters: ~ + {pattern} Pattern used to find a workspace symbol + {flags} See |tag-function| + + Return: ~ + A list of matching tags + with({handler}, {override_config}) *vim.lsp.with()* Function to manage overriding defaults for LSP handlers. @@ -1304,13 +1347,15 @@ buf_clear_references({bufnr}) *vim.lsp.util.buf_clear_references()* {bufnr} buffer id *vim.lsp.util.buf_highlight_references()* -buf_highlight_references({bufnr}, {references}) +buf_highlight_references({bufnr}, {references}, {offset_encoding}) Shows a list of document highlights for a certain buffer. Parameters: ~ - {bufnr} buffer id - {references} List of `DocumentHighlight` objects to - highlight + {bufnr} buffer id + {references} List of `DocumentHighlight` objects to + highlight + {offset_encoding} string utf-8|utf-16|utf-32|nil defaults + to utf-16 See also: ~ https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#documentHighlight @@ -1344,25 +1389,6 @@ close_preview_autocmd({events}, {winnr}) See also: ~ |autocmd-events| - *vim.lsp.util.compute_diff()* -compute_diff({old_lines}, {new_lines}, {start_line_idx}, {end_line_idx}, - {offset_encoding}) - Returns the range table for the difference between old and new - lines - - Parameters: ~ - {old_lines} table list of lines - {new_lines} table list of lines - {start_line_idx} int line to begin search for first - difference - {end_line_idx} int line to begin search for last - difference - {offset_encoding} string encoding requested by language - server - - Return: ~ - table start_line_idx and start_col_idx of range - *vim.lsp.util.convert_input_to_markdown_lines()* convert_input_to_markdown_lines({input}, {contents}) Converts any of `MarkedString` | `MarkedString[]` | @@ -1800,14 +1826,19 @@ notify({method}, {params}) *vim.lsp.rpc.notify()* (bool) `true` if notification could be sent, `false` if not -request({method}, {params}, {callback}) *vim.lsp.rpc.request()* + *vim.lsp.rpc.request()* +request({method}, {params}, {callback}, {notify_reply_callback}) Sends a request to the LSP server and runs {callback} upon response. Parameters: ~ - {method} (string) The invoked LSP method - {params} (table) Parameters for the invoked LSP method - {callback} (function) Callback to invoke + {method} (string) The invoked LSP method + {params} (table) Parameters for the + invoked LSP method + {callback} (function) Callback to invoke + {notify_reply_callback} (function) Callback to invoke as + soon as a request is no longer + pending Return: ~ (bool, number) `(true, message_id)` if request could be @@ -1862,6 +1893,35 @@ start({cmd}, {cmd_args}, {dispatchers}, {extra_spawn_params}) ============================================================================== +Lua module: vim.lsp.sync *lsp-sync* + + *vim.lsp.sync.compute_diff()* +compute_diff({prev_lines}, {curr_lines}, {firstline}, {lastline}, + {new_lastline}, {offset_encoding}, {line_ending}) + Returns the range table for the difference between prev and + curr lines + + Parameters: ~ + {prev_lines} table list of lines + {curr_lines} table list of lines + {firstline} number line to begin search for first + difference + {lastline} number line to begin search in + old_lines for last difference + {new_lastline} number line to begin search in + new_lines for last difference + {offset_encoding} string encoding requested by language + server + + Return: ~ + table TextDocumentContentChangeEvent see https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#textDocumentContentChangeEvent + + *vim.lsp.sync.compute_line_length()* +compute_line_length({line}, {offset_encoding}) + TODO: Documentation + + +============================================================================== Lua module: vim.lsp.protocol *lsp-protocol* *vim.lsp.protocol.make_client_capabilities()* diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index ef2d87949d..5e9189158a 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -1200,7 +1200,7 @@ inspect({object}, {options}) *vim.inspect()* https://github.com/kikito/inspect.lua https://github.com/mpeterv/vinspect -make_dict_accessor({scope}) *vim.make_dict_accessor()* +make_dict_accessor({scope}, {handle}) *vim.make_dict_accessor()* TODO: Documentation notify({msg}, {log_level}, {_opts}) *vim.notify()* @@ -1617,14 +1617,12 @@ validate({opt}) *vim.validate()* vim.validate{arg1={{'foo'}, 'table'}, arg2={'foo', 'string'}} => NOP (success) -< -> - vim.validate{arg1={1, 'table'}} - => error('arg1: expected table, got number') -< -> - vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}} - => error('arg1: expected even number, got 3') + + vim.validate{arg1={1, 'table'}} + => error('arg1: expected table, got number') + + vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}} + => error('arg1: expected even number, got 3') < Parameters: ~ @@ -1658,40 +1656,38 @@ uri_from_bufnr({bufnr}) *vim.uri_from_bufnr()* Get a URI from a bufnr Parameters: ~ - {bufnr} (number): Buffer number + {bufnr} number Return: ~ - URI + string URI uri_from_fname({path}) *vim.uri_from_fname()* Get a URI from a file path. Parameters: ~ - {path} (string): Path to file + {path} string Path to file Return: ~ - URI + string URI uri_to_bufnr({uri}) *vim.uri_to_bufnr()* - Return or create a buffer for a uri. + Get the buffer for a uri. Creates a new unloaded buffer if no + buffer for the uri already exists. Parameters: ~ - {uri} (string): The URI + {uri} string Return: ~ - bufnr. - - Note: - Creates buffer but does not load it + number bufnr uri_to_fname({uri}) *vim.uri_to_fname()* Get a filename from a URI Parameters: ~ - {uri} (string): The URI + {uri} string Return: ~ - Filename + string filename or unchanged URI for non-file URIs ============================================================================== @@ -1731,6 +1727,12 @@ select({items}, {opts}, {on_choice}) *vim.ui.select()* • format_item (function item -> text) Function to format an individual item from `items` . Defaults to `tostring` . + • kind (string|nil) Arbitrary hint string + indicating the item shape. Plugins + reimplementing `vim.ui.select` may wish to + use this to infer the structure or + semantics of `items` , or the context in + which select() was called. {on_choice} function ((item|nil, idx|nil) -> ()) Called once the user made a choice. `idx` is the 1-based index of `item` within `item` . `nil` diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index 90d4c4de93..0b9ac42898 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -46,6 +46,8 @@ modes. where the map command applies. The result, including {rhs}, is then further scanned for mappings. This allows for nested and recursive use of mappings. + Note: Trailing spaces are included in the {rhs}, + because space is a valid Normal mode command. *:nore* *:norem* :no[remap] {lhs} {rhs} |mapmode-nvo| *:no* *:noremap* *:nor* @@ -1419,6 +1421,7 @@ Possible values are (second column is the short name used in listing): Special cases ~ *:command-bang* *:command-bar* *:command-register* *:command-buffer* + *:command-keepscript* There are some special cases as well: -bang The command can take a ! modifier (like :q or :w) diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 399a59251a..038808b760 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -3792,6 +3792,13 @@ A jump table for the options with a short description can be found at |Q_op|. The characters ':' and ',' should not be used. UTF-8 characters can be used. All characters must be single width. + Each character can be specified as hex: > + set listchars=eol:\\x24 + set listchars=eol:\\u21b5 + set listchars=eol:\\U000021b5 +< Note that a double backslash is used. The number of hex characters + must be exactly 2 for \\x, 4 for \\u and 8 for \\U. + Examples: > :set lcs=tab:>-,trail:- :set lcs=tab:>-,eol:<,nbsp:% diff --git a/runtime/doc/pi_zip.txt b/runtime/doc/pi_zip.txt index c715644847..2bbd6eea06 100644 --- a/runtime/doc/pi_zip.txt +++ b/runtime/doc/pi_zip.txt @@ -102,6 +102,9 @@ Copyright: Copyright (C) 2005-2015 Charles E Campbell *zip-copyright* ============================================================================== 4. History *zip-history* {{{1 + v32 Oct 22, 2021 * to avoid an issue with a vim 8.2 patch, zipfile: has + been changed to zipfile:// . This often shows up + as zipfile:/// with zipped files that are root-based. v29 Apr 02, 2017 * (Klartext) reported that an encrypted zip file could opened but the swapfile held unencrypted contents. The solution is to edit the contents of a zip file diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index 441ae13df4..ac10aeec88 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -531,11 +531,9 @@ Query:iter_matches({self}, {node}, {source}, {start}, {stop}) for id, node in pairs(match) do local name = query.captures[id] -- `node` was captured by the `name` capture in the match -< -> - local node_data = metadata[id] -- Node level metadata -< -> + + local node_data = metadata[id] -- Node level metadata + ... use the info here ... end end diff --git a/runtime/doc/usr_20.txt b/runtime/doc/usr_20.txt index 29252705d6..cff5c7d2f2 100644 --- a/runtime/doc/usr_20.txt +++ b/runtime/doc/usr_20.txt @@ -289,11 +289,11 @@ In chapter 3 we briefly mentioned the history. The basics are that you can use the <Up> key to recall an older command line. <Down> then takes you back to newer commands. -There are actually four histories. The ones we will mention here are for ":" +There are actually five histories. The ones we will mention here are for ":" commands and for "/" and "?" search commands. The "/" and "?" commands share -the same history, because they are both search commands. The two other -histories are for expressions and input lines for the input() function. -|cmdline-history| +the same history, because they are both search commands. The three other +histories are for expressions, debug more commands and input lines for the +input() function. |cmdline-history| Suppose you have done a ":set" command, typed ten more colon commands and then want to repeat that ":set" command again. You could press ":" and then ten diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index 77bf1d29eb..d88f4f42e8 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -186,7 +186,6 @@ Events: |TermOpen| |UIEnter| |UILeave| - |WinClosed| Functions: |dictwatcheradd()| notifies a callback whenever a |Dict| is modified diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 13d8c72e76..1b48070128 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1,7 +1,7 @@ " Vim support file to detect file types " " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2021 Oct 03 +" Last Change: 2021 Nov 16 " Listen very carefully, I will say this only once if exists("did_load_filetypes") diff --git a/runtime/ftplugin/aap.vim b/runtime/ftplugin/aap.vim index 9b20ec4766..b5065e5157 100644 --- a/runtime/ftplugin/aap.vim +++ b/runtime/ftplugin/aap.vim @@ -1,7 +1,7 @@ " Vim filetype plugin file " Language: Aap recipe " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2013 Apr 05 +" Last Change: 2021 Nov 14 " Only do this when not done yet for this buffer if exists("b:did_ftplugin") @@ -11,8 +11,9 @@ endif " Don't load another plugin for this buffer let b:did_ftplugin = 1 -" Reset 'formatoptions', 'comments' and 'expandtab' to undo this plugin. -let b:undo_ftplugin = "setl fo< com< et<" +" Reset 'formatoptions', 'comments', 'commentstring' and 'expandtab' to undo +" this plugin. +let b:undo_ftplugin = "setl fo< com< cms< et<" " Set 'formatoptions' to break comment lines but not other lines, " and insert the comment leader when hitting <CR> or using "o". @@ -20,6 +21,12 @@ setlocal fo-=t fo+=croql " Set 'comments' to format dashed lists in comments. setlocal comments=s:#\ -,m:#\ \ ,e:#,n:#,fb:- +setlocal commentstring=#\ %s " Expand tabs to spaces to avoid trouble. setlocal expandtab + +if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") + let b:browsefilter = "Aap Recipe Files (*.aap)\t*.aap\nAll Files (*.*)\t*.*\n" + let b:undo_ftplugin ..= " | unlet! b:browsefilter" +endif diff --git a/runtime/ftplugin/diff.vim b/runtime/ftplugin/diff.vim index 0464290475..bf37d464c0 100644 --- a/runtime/ftplugin/diff.vim +++ b/runtime/ftplugin/diff.vim @@ -1,7 +1,7 @@ " Vim filetype plugin file " Language: Diff " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2020 Jul 18 +" Last Change: 2021 Nov 14 " Only do this when not done yet for this buffer if exists("b:did_ftplugin") @@ -9,10 +9,15 @@ if exists("b:did_ftplugin") endif let b:did_ftplugin = 1 -let b:undo_ftplugin = "setl modeline<" +let b:undo_ftplugin = "setl modeline< commentstring<" " Don't use modelines in a diff, they apply to the diffed file setlocal nomodeline " If there are comments they start with # -let &commentstring = "# %s" +let &l:commentstring = "# %s" + +if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") + let b:browsefilter = "Diff Files (*.diff)\t*.diff\nPatch Files (*.patch)\t*.h\nAll Files (*.*)\t*.*\n" + let b:undo_ftplugin ..= " | unlet! b:browsefilter" +endif diff --git a/runtime/ftplugin/lua.vim b/runtime/ftplugin/lua.vim index 3454a4d694..2604257594 100644 --- a/runtime/ftplugin/lua.vim +++ b/runtime/ftplugin/lua.vim @@ -1,7 +1,8 @@ " Vim filetype plugin file. -" Language: Lua 4.0+ -" Maintainer: Max Ischenko <mfi@ukr.net> -" Last Change: 2012 Mar 07 +" Language: Lua +" Maintainer: Doug Kearns <dougkearns@gmail.com> +" Previous Maintainer: Max Ischenko <mfi@ukr.net> +" Last Change: 2021 Nov 15 " Only do this when not done yet for this buffer if exists("b:did_ftplugin") @@ -16,27 +17,30 @@ set cpo&vim " Set 'formatoptions' to break comment lines but not other lines, and insert " the comment leader when hitting <CR> or using "o". -setlocal fo-=t fo+=croql +setlocal formatoptions-=t formatoptions+=croql -setlocal com=:-- -setlocal cms=--%s +setlocal comments=:-- +setlocal commentstring=--%s setlocal suffixesadd=.lua +let b:undo_ftplugin = "setlocal fo< com< cms< sua<" -" The following lines enable the macros/matchit.vim plugin for -" extended matching with the % key. -if exists("loaded_matchit") - +if exists("loaded_matchit") && !exists("b:match_words") let b:match_ignorecase = 0 let b:match_words = - \ '\<\%(do\|function\|if\)\>:' . - \ '\<\%(return\|else\|elseif\)\>:' . - \ '\<end\>,' . - \ '\<repeat\>:\<until\>' + \ '\<\%(do\|function\|if\)\>:' . + \ '\<\%(return\|else\|elseif\)\>:' . + \ '\<end\>,' . + \ '\<repeat\>:\<until\>,' . + \ '\%(--\)\=\[\(=*\)\[:]\1]' + let b:undo_ftplugin .= " | unlet! b:match_words b:match_ignorecase" +endif -endif " exists("loaded_matchit") +if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") + let b:browsefilter = "Lua Source Files (*.lua)\t*.lua\n" . + \ "All Files (*.*)\t*.*\n" + let b:undo_ftplugin .= " | unlet! b:browsefilter" +endif let &cpo = s:cpo_save unlet s:cpo_save - -let b:undo_ftplugin = "setlocal fo< com< cms< suffixesadd<" diff --git a/runtime/ftplugin/routeros.vim b/runtime/ftplugin/routeros.vim new file mode 100644 index 0000000000..c6e4799aa2 --- /dev/null +++ b/runtime/ftplugin/routeros.vim @@ -0,0 +1,29 @@ +" Vim filetype plugin file +" Language: MikroTik RouterOS Script +" Maintainer: zainin <z@wintr.dev> +" Last Change: 2021 Nov 14 + +if exists("b:did_ftplugin") + finish +endif +let b:did_ftplugin = 1 + +let s:save_cpo = &cpo +set cpo-=C + +setlocal comments=:# +setlocal commentstring=#\ %s +setlocal formatoptions-=t formatoptions+=croql + +let b:undo_ftplugin = "setlocal com< cms< fo<" + +if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") + let b:browsefilter = "RouterOS Script Files (*.rsc)\t*.rsc\n" .. + \ "All Files (*.*)\t*.*\n" + let b:undo_ftplugin ..= " | unlet! b:browsefilter" +endif + +let &cpo = s:save_cpo +unlet! s:save_cpo + +" vim: nowrap sw=2 sts=2 ts=8 noet: diff --git a/runtime/ftplugin/zimbu.vim b/runtime/ftplugin/zimbu.vim index 24674776cb..e365ccf07e 100644 --- a/runtime/ftplugin/zimbu.vim +++ b/runtime/ftplugin/zimbu.vim @@ -1,7 +1,7 @@ " Vim filetype plugin file " Language: Zimbu " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2017 Dec 05 +" Last Change: 2021 Nov 12 " Only do this when not done yet for this buffer if exists("b:did_ftplugin") @@ -34,9 +34,11 @@ setlocal errorformat^=%f\ line\ %l\ col\ %c:\ %m,ERROR:\ %m " When the matchit plugin is loaded, this makes the % command skip parens and " braces in comments. -let b:match_words = '\(^\s*\)\@<=\(MODULE\|CLASS\|INTERFACE\|BITS\|ENUM\|SHARED\|FUNC\|REPLACE\|DEFINE\|PROC\|EQUAL\|MAIN\|IF\|GENERATE_IF\|WHILE\|REPEAT\|WITH\|DO\|FOR\|SWITCH\|TRY\)\>\|{\s*$:\(^\s*\)\@<=\(ELSE\|ELSEIF\|GENERATE_ELSE\|GENERATE_ELSEIF\|CATCH\|FINALLY\)\>:\(^\s*\)\@<=\(}\|\<UNTIL\>\)' - -let b:match_skip = 's:comment\|string\|zimbuchar' +if exists("loaded_matchit") && !exists("b:match_words") + let b:match_words = '\(^\s*\)\@<=\(MODULE\|CLASS\|INTERFACE\|BITS\|ENUM\|SHARED\|FUNC\|REPLACE\|DEFINE\|PROC\|EQUAL\|MAIN\|IF\|GENERATE_IF\|WHILE\|REPEAT\|WITH\|DO\|FOR\|SWITCH\|TRY\)\>\|{\s*$:\(^\s*\)\@<=\(ELSE\|ELSEIF\|GENERATE_ELSE\|GENERATE_ELSEIF\|CATCH\|FINALLY\)\>:\(^\s*\)\@<=\(}\|\<UNTIL\>\)' + let b:match_skip = 's:comment\|string\|zimbuchar' + let b:undo_ftplugin ..= " | unlet! b:match_words b:match_skip" +endif setlocal tw=78 setlocal et sts=2 sw=2 @@ -135,9 +137,60 @@ iabbr <buffer> <expr> until GCUpperSpace("until") iabbr <buffer> <expr> while GCUpperSpace("while") iabbr <buffer> <expr> repeat GCUpper("repeat") +let b:undo_ftplugin ..= + \ " | iunabbr <buffer> alias" .. + \ " | iunabbr <buffer> arg" .. + \ " | iunabbr <buffer> break" .. + \ " | iunabbr <buffer> case" .. + \ " | iunabbr <buffer> catch" .. + \ " | iunabbr <buffer> check" .. + \ " | iunabbr <buffer> class" .. + \ " | iunabbr <buffer> interface" .. + \ " | iunabbr <buffer> implements" .. + \ " | iunabbr <buffer> shared" .. + \ " | iunabbr <buffer> continue" .. + \ " | iunabbr <buffer> default" .. + \ " | iunabbr <buffer> extends" .. + \ " | iunabbr <buffer> do" .. + \ " | iunabbr <buffer> else" .. + \ " | iunabbr <buffer> elseif" .. + \ " | iunabbr <buffer> enum" .. + \ " | iunabbr <buffer> exit" .. + \ " | iunabbr <buffer> false" .. + \ " | iunabbr <buffer> fail" .. + \ " | iunabbr <buffer> finally" .. + \ " | iunabbr <buffer> for" .. + \ " | iunabbr <buffer> func" .. + \ " | iunabbr <buffer> if" .. + \ " | iunabbr <buffer> import" .. + \ " | iunabbr <buffer> in" .. + \ " | iunabbr <buffer> io" .. + \ " | iunabbr <buffer> main" .. + \ " | iunabbr <buffer> module" .. + \ " | iunabbr <buffer> new" .. + \ " | iunabbr <buffer> nil" .. + \ " | iunabbr <buffer> ok" .. + \ " | iunabbr <buffer> proc" .. + \ " | iunabbr <buffer> proceed" .. + \ " | iunabbr <buffer> return" .. + \ " | iunabbr <buffer> step" .. + \ " | iunabbr <buffer> switch" .. + \ " | iunabbr <buffer> sys" .. + \ " | iunabbr <buffer> this" .. + \ " | iunabbr <buffer> throw" .. + \ " | iunabbr <buffer> try" .. + \ " | iunabbr <buffer> to" .. + \ " | iunabbr <buffer> true" .. + \ " | iunabbr <buffer> until" .. + \ " | iunabbr <buffer> while" .. + \ " | iunabbr <buffer> repeat" + if !exists("no_plugin_maps") && !exists("no_zimbu_maps") nnoremap <silent> <buffer> [[ m`:call ZimbuGoStartBlock()<CR> nnoremap <silent> <buffer> ]] m`:call ZimbuGoEndBlock()<CR> + let b:undo_ftplugin ..= + \ " | silent! exe 'nunmap <buffer> [['" .. + \ " | silent! exe 'nunmap <buffer> ]]'" endif " Using a function makes sure the search pattern is restored diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index 191b9b9145..9b57467a52 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -36,7 +36,51 @@ M.handlers = setmetatable({}, { end, }) --- Local functions {{{ +-- Metatable that automatically creates an empty table when assigning to a missing key +local bufnr_and_namespace_cacher_mt = { + __index = function(t, bufnr) + if not bufnr or bufnr == 0 then + bufnr = vim.api.nvim_get_current_buf() + end + + rawset(t, bufnr, {}) + + return rawget(t, bufnr) + end, + + __newindex = function(t, bufnr, v) + if not bufnr or bufnr == 0 then + bufnr = vim.api.nvim_get_current_buf() + end + + rawset(t, bufnr, v) + end, +} + +local diagnostic_cache = setmetatable({}, { + __index = function(t, bufnr) + if not bufnr or bufnr == 0 then + bufnr = vim.api.nvim_get_current_buf() + end + + vim.api.nvim_buf_attach(bufnr, false, { + on_detach = function() + rawset(t, bufnr, nil) -- clear cache + end + }) + + rawset(t, bufnr, {}) + + return rawget(t, bufnr) + end, +}) + +local diagnostic_cache_extmarks = setmetatable({}, bufnr_and_namespace_cacher_mt) +local diagnostic_attached_buffers = {} +local diagnostic_disabled = {} +local bufs_waiting_to_update = setmetatable({}, bufnr_and_namespace_cacher_mt) + +local all_namespaces = {} ---@private local function to_severity(severity) @@ -106,8 +150,6 @@ local function reformat_diagnostics(format, diagnostics) return formatted end -local all_namespaces = {} - ---@private local function enabled_value(option, namespace) local ns = namespace and M.get_namespace(namespace) or {} @@ -213,36 +255,6 @@ local function get_bufnr(bufnr) return bufnr end --- Metatable that automatically creates an empty table when assigning to a missing key -local bufnr_and_namespace_cacher_mt = { - __index = function(t, bufnr) - if not bufnr or bufnr == 0 then - bufnr = vim.api.nvim_get_current_buf() - end - - if rawget(t, bufnr) == nil then - rawset(t, bufnr, {}) - end - - return rawget(t, bufnr) - end, - - __newindex = function(t, bufnr, v) - if not bufnr or bufnr == 0 then - bufnr = vim.api.nvim_get_current_buf() - end - - rawset(t, bufnr, v) - end, -} - -local diagnostic_cleanup = setmetatable({}, bufnr_and_namespace_cacher_mt) -local diagnostic_cache = setmetatable({}, bufnr_and_namespace_cacher_mt) -local diagnostic_cache_extmarks = setmetatable({}, bufnr_and_namespace_cacher_mt) -local diagnostic_attached_buffers = {} -local diagnostic_disabled = {} -local bufs_waiting_to_update = setmetatable({}, bufnr_and_namespace_cacher_mt) - ---@private local function is_disabled(namespace, bufnr) local ns = M.get_namespace(namespace) @@ -287,11 +299,6 @@ local function set_diagnostic_cache(namespace, bufnr, diagnostics) end ---@private -local function clear_diagnostic_cache(namespace, bufnr) - diagnostic_cache[bufnr][namespace] = nil -end - ----@private local function restore_extmarks(bufnr, last) for ns, extmarks in pairs(diagnostic_cache_extmarks[bufnr]) do local extmarks_current = vim.api.nvim_buf_get_extmarks(bufnr, ns, 0, -1, {details = true}) @@ -377,6 +384,59 @@ local function clear_scheduled_display(namespace, bufnr) end ---@private +local function get_diagnostics(bufnr, opts, clamp) + opts = opts or {} + + local namespace = opts.namespace + local diagnostics = {} + local buf_line_count = clamp and vim.api.nvim_buf_line_count(bufnr) or math.huge + + ---@private + local function add(d) + if not opts.lnum or d.lnum == opts.lnum then + if clamp and (d.lnum >= buf_line_count or d.end_lnum >= buf_line_count) then + d = vim.deepcopy(d) + d.lnum = math.max(math.min(d.lnum, buf_line_count - 1), 0) + d.end_lnum = math.max(math.min(d.end_lnum, buf_line_count - 1), 0) + end + table.insert(diagnostics, d) + end + end + + if namespace == nil and bufnr == nil then + for _, t in pairs(diagnostic_cache) do + for _, v in pairs(t) do + for _, diagnostic in pairs(v) do + add(diagnostic) + end + end + end + elseif namespace == nil then + for iter_namespace in pairs(diagnostic_cache[bufnr]) do + for _, diagnostic in pairs(diagnostic_cache[bufnr][iter_namespace]) do + add(diagnostic) + end + end + elseif bufnr == nil then + for _, t in pairs(diagnostic_cache) do + for _, diagnostic in pairs(t[namespace] or {}) do + add(diagnostic) + end + end + else + for _, diagnostic in pairs(diagnostic_cache[bufnr][namespace] or {}) do + add(diagnostic) + end + end + + if opts.severity then + diagnostics = filter_by_severity(opts.severity, diagnostics) + end + + return diagnostics +end + +---@private local function set_list(loclist, opts) opts = opts or {} local open = vim.F.if_nil(opts.open, true) @@ -386,7 +446,7 @@ local function set_list(loclist, opts) if loclist then bufnr = vim.api.nvim_win_get_buf(winnr) end - local diagnostics = M.get(bufnr, opts) + local diagnostics = get_diagnostics(bufnr, opts, true) local items = M.toqflist(diagnostics) if loclist then vim.fn.setloclist(winnr, {}, ' ', { title = title, items = items }) @@ -399,27 +459,12 @@ local function set_list(loclist, opts) end ---@private ---- To (slightly) improve performance, modifies diagnostics in place. -local function clamp_line_numbers(bufnr, diagnostics) - local buf_line_count = vim.api.nvim_buf_line_count(bufnr) - if buf_line_count == 0 then - return - end - - for _, diagnostic in ipairs(diagnostics) do - diagnostic.lnum = math.max(math.min(diagnostic.lnum, buf_line_count - 1), 0) - diagnostic.end_lnum = math.max(math.min(diagnostic.end_lnum, buf_line_count - 1), 0) - end -end - ----@private local function next_diagnostic(position, search_forward, bufnr, opts, namespace) position[1] = position[1] - 1 bufnr = get_bufnr(bufnr) local wrap = vim.F.if_nil(opts.wrap, true) local line_count = vim.api.nvim_buf_line_count(bufnr) - local diagnostics = M.get(bufnr, vim.tbl_extend("keep", opts, {namespace = namespace})) - clamp_line_numbers(bufnr, diagnostics) + local diagnostics = get_diagnostics(bufnr, vim.tbl_extend("keep", opts, {namespace = namespace}), true) local line_diagnostics = diagnostic_lines(diagnostics) for i = 0, line_count do local offset = i * (search_forward and 1 or -1) @@ -431,13 +476,14 @@ local function next_diagnostic(position, search_forward, bufnr, opts, namespace) lnum = (lnum + line_count) % line_count end if line_diagnostics[lnum] and not vim.tbl_isempty(line_diagnostics[lnum]) then + local line_length = #vim.api.nvim_buf_get_lines(bufnr, lnum, lnum + 1, true)[1] local sort_diagnostics, is_next if search_forward then sort_diagnostics = function(a, b) return a.col < b.col end - is_next = function(diagnostic) return diagnostic.col > position[2] end + is_next = function(d) return math.min(d.col, line_length - 1) > position[2] end else sort_diagnostics = function(a, b) return a.col > b.col end - is_next = function(diagnostic) return diagnostic.col < position[2] end + is_next = function(d) return math.min(d.col, line_length - 1) < position[2] end end table.sort(line_diagnostics[lnum], sort_diagnostics) if i == 0 then @@ -481,10 +527,6 @@ local function diagnostic_move_pos(opts, pos) end end --- }}} - --- Public API {{{ - --- Configure diagnostic options globally or for a specific diagnostic --- namespace. --- @@ -618,19 +660,8 @@ function M.set(namespace, bufnr, diagnostics, opts) } if vim.tbl_isempty(diagnostics) then - clear_diagnostic_cache(namespace, bufnr) + diagnostic_cache[bufnr][namespace] = nil else - if not diagnostic_cleanup[bufnr][namespace] then - diagnostic_cleanup[bufnr][namespace] = true - - -- Clean up our data when the buffer unloads. - vim.api.nvim_buf_attach(bufnr, false, { - on_detach = function(_, b) - clear_diagnostic_cache(namespace, b) - diagnostic_cleanup[b][namespace] = nil - end - }) - end set_diagnostic_cache(namespace, bufnr, diagnostics) end @@ -689,49 +720,7 @@ function M.get(bufnr, opts) opts = { opts, 't', true }, } - opts = opts or {} - - local namespace = opts.namespace - local diagnostics = {} - - ---@private - local function add(d) - if not opts.lnum or d.lnum == opts.lnum then - table.insert(diagnostics, d) - end - end - - if namespace == nil and bufnr == nil then - for _, t in pairs(diagnostic_cache) do - for _, v in pairs(t) do - for _, diagnostic in pairs(v) do - add(diagnostic) - end - end - end - elseif namespace == nil then - for iter_namespace in pairs(diagnostic_cache[bufnr]) do - for _, diagnostic in pairs(diagnostic_cache[bufnr][iter_namespace]) do - add(diagnostic) - end - end - elseif bufnr == nil then - for _, t in pairs(diagnostic_cache) do - for _, diagnostic in pairs(t[namespace] or {}) do - add(diagnostic) - end - end - else - for _, diagnostic in pairs(diagnostic_cache[bufnr][namespace] or {}) do - add(diagnostic) - end - end - - if opts.severity then - diagnostics = filter_by_severity(opts.severity, diagnostics) - end - - return diagnostics + return get_diagnostics(bufnr, opts, false) end --- Get the previous diagnostic closest to the cursor position. @@ -1115,7 +1104,7 @@ function M.show(namespace, bufnr, diagnostics, opts) M.hide(namespace, bufnr) - diagnostics = diagnostics or M.get(bufnr, {namespace=namespace}) + diagnostics = diagnostics or get_diagnostics(bufnr, {namespace=namespace}, true) if not diagnostics or vim.tbl_isempty(diagnostics) then return @@ -1141,8 +1130,6 @@ function M.show(namespace, bufnr, diagnostics, opts) end end - clamp_line_numbers(bufnr, diagnostics) - for handler_name, handler in pairs(M.handlers) do if handler.show and opts[handler_name] then handler.show(namespace, bufnr, diagnostics, opts) @@ -1213,8 +1200,7 @@ function M.open_float(bufnr, opts) opts = get_resolved_options({ float = float_opts }, nil, bufnr).float end - local diagnostics = M.get(bufnr, opts) - clamp_line_numbers(bufnr, diagnostics) + local diagnostics = get_diagnostics(bufnr, opts, true) if scope == "line" then diagnostics = vim.tbl_filter(function(d) @@ -1338,7 +1324,7 @@ function M.reset(namespace, bufnr) for _, iter_bufnr in ipairs(buffers) do local namespaces = namespace and {namespace} or vim.tbl_keys(diagnostic_cache[iter_bufnr]) for _, iter_namespace in ipairs(namespaces) do - clear_diagnostic_cache(iter_namespace, iter_bufnr) + diagnostic_cache[iter_bufnr][iter_namespace] = nil M.hide(iter_namespace, iter_bufnr) end end @@ -1545,7 +1531,7 @@ function M.fromqflist(list) for _, item in ipairs(list) do if item.valid == 1 then local lnum = math.max(0, item.lnum - 1) - local col = item.col > 0 and (item.col - 1) or nil + local col = math.max(0, item.col - 1) local end_lnum = item.end_lnum > 0 and (item.end_lnum - 1) or lnum local end_col = item.end_col > 0 and (item.end_col - 1) or col local severity = item.type ~= "" and M.severity[item.type] or M.severity.ERROR @@ -1563,6 +1549,4 @@ function M.fromqflist(list) return diagnostics end --- }}} - return M diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 0fc0a7a7aa..7433e7c04d 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -115,6 +115,13 @@ local format_line_ending = { ["mac"] = '\r', } +---@private +---@param bufnr (number) +---@returns (string) +local function buf_get_line_ending(bufnr) + return format_line_ending[nvim_buf_get_option(bufnr, 'fileformat')] or '\n' +end + local client_index = 0 ---@private --- Returns a new, unused client id. @@ -236,7 +243,6 @@ local function validate_client_config(config) config = { config, 't' }; } validate { - root_dir = { config.root_dir, optional_validator(is_dir), "directory" }; handlers = { config.handlers, "t", true }; capabilities = { config.capabilities, "t", true }; cmd_cwd = { config.cmd_cwd, optional_validator(is_dir), "directory" }; @@ -278,9 +284,10 @@ end ---@param bufnr (number) Buffer handle, or 0 for current. ---@returns Buffer text as string. local function buf_get_full_text(bufnr) - local text = table.concat(nvim_buf_get_lines(bufnr, 0, -1, true), '\n') + local line_ending = buf_get_line_ending(bufnr) + local text = table.concat(nvim_buf_get_lines(bufnr, 0, -1, true), line_ending) if nvim_buf_get_option(bufnr, 'eol') then - text = text .. '\n' + text = text .. line_ending end return text end @@ -362,9 +369,9 @@ do local incremental_changes = function(client) local cached_buffers = state_by_client[client.id].buffers local curr_lines = nvim_buf_get_lines(bufnr, 0, -1, true) - local line_ending = format_line_ending[vim.api.nvim_buf_get_option(0, 'fileformat')] + local line_ending = buf_get_line_ending(bufnr) local incremental_change = sync.compute_diff( - cached_buffers[bufnr], curr_lines, firstline, lastline, new_lastline, client.offset_encoding or 'utf-16', line_ending or '\n') + cached_buffers[bufnr], curr_lines, firstline, lastline, new_lastline, client.offset_encoding or 'utf-16', line_ending) cached_buffers[bufnr] = curr_lines return incremental_change end @@ -566,12 +573,10 @@ end -- --- Starts and initializes a client with the given configuration. --- ---- Parameters `cmd` and `root_dir` are required. +--- Parameter `cmd` is required. --- --- The following parameters describe fields in the {config} table. --- ----@param root_dir: (string) Directory where the LSP server will base ---- its rootUri on initialization. --- ---@param cmd: (required, string or list treated like |jobstart()|) Base command --- that initiates the LSP client. @@ -587,6 +592,11 @@ end --- { "PRODUCTION=true"; "TEST=123"; PORT = 8080; HOST = "0.0.0.0"; } --- </pre> --- +---@param workspace_folders (table) List of workspace folders passed to the +--- language server. For backwards compatibility rootUri and rootPath will be +--- derived from the first workspace folder in this list. See `workspaceFolders` in +--- the LSP spec. +--- ---@param capabilities Map overriding the default capabilities defined by --- |vim.lsp.protocol.make_client_capabilities()|, passed to the language --- server on initialization. Hint: use make_client_capabilities() and modify @@ -610,10 +620,6 @@ end --- as `initializationOptions`. See `initialize` in the LSP spec. --- ---@param name (string, default=client-id) Name in log messages. --- ----@param workspace_folders (table) List of workspace folders passed to the ---- language server. Defaults to root_dir if not set. See `workspaceFolders` in ---- the LSP spec --- ---@param get_language_id function(bufnr, filetype) -> language ID as string. --- Defaults to the filetype. @@ -663,6 +669,11 @@ end --- - exit_timeout (number, default 500): 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. +--- +---@param root_dir string Directory where the LSP +--- server will base its workspaceFolders, rootUri, and rootPath +--- on initialization. +--- ---@returns Client id. |vim.lsp.get_client_by_id()| Note: client may not be --- fully initialized. Use `on_init` to do any actions once --- the client has been initialized. @@ -805,11 +816,24 @@ function lsp.start_client(config) } local version = vim.version() - if config.root_dir and not config.workspace_folders then - config.workspace_folders = {{ - uri = vim.uri_from_fname(config.root_dir); - name = string.format("%s", config.root_dir); - }}; + local workspace_folders + local root_uri + local root_path + if config.workspace_folders or config.root_dir then + if config.root_dir and not config.workspace_folders then + workspace_folders = {{ + uri = vim.uri_from_fname(config.root_dir); + name = string.format("%s", config.root_dir); + }}; + else + workspace_folders = config.workspace_folders + end + root_uri = workspace_folders[1].uri + root_path = vim.uri_to_fname(root_uri) + else + workspace_folders = vim.NIL + root_uri = vim.NIL + root_path = vim.NIL end local initialize_params = { @@ -827,10 +851,15 @@ function lsp.start_client(config) -- The rootPath of the workspace. Is null if no folder is open. -- -- @deprecated in favour of rootUri. - rootPath = config.root_dir; + rootPath = root_path; -- The rootUri of the workspace. Is null if no folder is open. If both -- `rootPath` and `rootUri` are set `rootUri` wins. - rootUri = config.root_dir and vim.uri_from_fname(config.root_dir); + rootUri = root_uri; + -- The workspace folders configured in the client when the server starts. + -- This property is only available if the client supports workspace folders. + -- It can be `null` if the client supports workspace folders but none are + -- configured. + workspaceFolders = workspace_folders; -- User provided initialization options. initializationOptions = config.init_options; -- The capabilities provided by the client (editor or tool) @@ -838,21 +867,6 @@ function lsp.start_client(config) -- The initial trace setting. If omitted trace is disabled ("off"). -- trace = "off" | "messages" | "verbose"; trace = valid_traces[config.trace] or 'off'; - -- The workspace folders configured in the client when the server starts. - -- This property is only available if the client supports workspace folders. - -- It can be `null` if the client supports workspace folders but none are - -- configured. - -- - -- Since 3.6.0 - -- workspaceFolders?: WorkspaceFolder[] | null; - -- export interface WorkspaceFolder { - -- -- The associated URI for this workspace folder. - -- uri - -- -- The name of the workspace folder. Used to refer to this - -- -- workspace folder in the user interface. - -- name - -- } - workspaceFolders = config.workspace_folders, } if config.before_init then -- TODO(ashkan) handle errors here. @@ -1587,6 +1601,21 @@ function lsp.formatexpr(opts) return 0 end +--- Provides an interface between the built-in client and 'tagfunc'. +--- +--- When used with normal mode commands (e.g. |CTRL-]|) this will invoke +--- the "textDocument/definition" LSP method to find the tag under the cursor. +--- Otherwise, uses "workspace/symbol". If no results are returned from +--- any LSP servers, falls back to using built-in tags. +--- +---@param pattern Pattern used to find a workspace symbol +---@param flags See |tag-function| +--- +---@returns A list of matching tags +function lsp.tagfunc(...) + return require('vim.lsp.tagfunc')(...) +end + ---Checks whether a client is stopped. --- ---@param client_id (Number) diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua index 1e6f83c1ba..76a4dc30b7 100644 --- a/runtime/lua/vim/lsp/diagnostic.lua +++ b/runtime/lua/vim/lsp/diagnostic.lua @@ -717,5 +717,3 @@ end -- }}} return M - --- vim: fdm=marker diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index a561630c2b..fa4f2b22a5 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -350,7 +350,10 @@ M['textDocument/signatureHelp'] = M.signature_help --see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentHighlight M['textDocument/documentHighlight'] = function(_, result, ctx, _) if not result then return end - util.buf_highlight_references(ctx.bufnr, result, ctx.client_id) + local client_id = ctx.client_id + local client = vim.lsp.get_client_by_id(client_id) + if not client then return end + util.buf_highlight_references(ctx.bufnr, result, client.offset_encoding) end ---@private diff --git a/runtime/lua/vim/lsp/sync.lua b/runtime/lua/vim/lsp/sync.lua index 585c14a00f..f185e3973f 100644 --- a/runtime/lua/vim/lsp/sync.lua +++ b/runtime/lua/vim/lsp/sync.lua @@ -74,43 +74,45 @@ local function byte_to_utf(line, byte, offset_encoding) return utf_idx + 1 end +local function compute_line_length(line, offset_encoding) + local length + local _ + if offset_encoding == 'utf-16' then + _, length = str_utfindex(line) + elseif offset_encoding == 'utf-32' then + length, _ = str_utfindex(line) + else + length = #line + end + return length +end + ---@private -- Given a line, byte idx, alignment, and offset_encoding convert to the aligned -- utf-8 index and either the utf-16, or utf-32 index. ---@param line string the line to index into ---@param byte integer the byte idx ----@param align string when dealing with multibyte characters, --- to choose the start of the current character or the beginning of the next. --- Used for incremental sync for start/end range respectively ---@param offset_encoding string utf-8|utf-16|utf-32|nil (default: utf-8) ---@returns table<string, int> byte_idx and char_idx of first change position -local function align_position(line, byte, align, offset_encoding) +local function align_end_position(line, byte, offset_encoding) local char -- If on the first byte, or an empty string: the trivial case if byte == 1 or #line == 0 then char = byte -- Called in the case of extending an empty line "" -> "a" elseif byte == #line + 1 then - byte = byte + str_utf_end(line, #line) - char = byte_to_utf(line, byte, offset_encoding) + char = compute_line_length(line, offset_encoding) + 1 else -- Modifying line, find the nearest utf codepoint - if align == 'start' then - byte = byte + str_utf_start(line, byte) - char = byte_to_utf(line, byte, offset_encoding) - elseif align == 'end' then - local offset = str_utf_end(line, byte) - -- If the byte does not fall on the start of the character, then - -- align to the start of the next character. - if offset > 0 then - char = byte_to_utf(line, byte, offset_encoding) + 1 - byte = byte + offset - else - char = byte_to_utf(line, byte, offset_encoding) - byte = byte + offset - end + local offset = str_utf_end(line, byte) + -- If the byte does not fall on the start of the character, then + -- align to the start of the next character. + if offset > 0 then + char = byte_to_utf(line, byte, offset_encoding) + 1 + byte = byte + offset else - error('`align` must be start or end.') + char = byte_to_utf(line, byte, offset_encoding) + byte = byte + offset end -- Extending line, find the nearest utf codepoint for the last valid character end @@ -154,7 +156,18 @@ local function compute_start_range(prev_lines, curr_lines, firstline, lastline, end -- Convert byte to codepoint if applicable - local byte_idx, char_idx = align_position(prev_line, start_byte_idx, 'start', offset_encoding) + local char_idx + local byte_idx + if start_byte_idx == 1 or (#prev_line == 0 and start_byte_idx == 1)then + byte_idx = start_byte_idx + char_idx = 1 + elseif start_byte_idx == #prev_line + 1 then + byte_idx = start_byte_idx + char_idx = compute_line_length(prev_line, offset_encoding) + 1 + else + byte_idx = start_byte_idx + str_utf_start(prev_line, start_byte_idx) + char_idx = byte_to_utf(prev_line, start_byte_idx, offset_encoding) + end -- Return the start difference (shared for new and prev lines) return { line_idx = firstline, byte_idx = byte_idx, char_idx = char_idx } @@ -219,11 +232,12 @@ local function compute_end_range(prev_lines, curr_lines, start_range, firstline, -- Iterate from end to beginning of shortest line local prev_end_byte_idx = prev_line_length - byte_offset + 1 + -- Handle case where lines match if prev_end_byte_idx == 0 then prev_end_byte_idx = 1 end - local prev_byte_idx, prev_char_idx = align_position(prev_line, prev_end_byte_idx, 'start', offset_encoding) + local prev_byte_idx, prev_char_idx = align_end_position(prev_line, prev_end_byte_idx, offset_encoding) local prev_end_range = { line_idx = prev_line_idx, byte_idx = prev_byte_idx, char_idx = prev_char_idx } local curr_end_range @@ -236,7 +250,7 @@ local function compute_end_range(prev_lines, curr_lines, start_range, firstline, if curr_end_byte_idx == 0 then curr_end_byte_idx = 1 end - local curr_byte_idx, curr_char_idx = align_position(curr_line, curr_end_byte_idx, 'start', offset_encoding) + local curr_byte_idx, curr_char_idx = align_end_position(curr_line, curr_end_byte_idx, offset_encoding) curr_end_range = { line_idx = curr_line_idx, byte_idx = curr_byte_idx, char_idx = curr_char_idx } end @@ -280,18 +294,6 @@ local function extract_text(lines, start_range, end_range, line_ending) end end -local function compute_line_length(line, offset_encoding) - local length - local _ - if offset_encoding == 'utf-16' then - _, length = str_utfindex(line) - elseif offset_encoding == 'utf-32' then - length, _ = str_utfindex(line) - else - length = #line - end - return length -end ---@private -- rangelength depends on the offset encoding -- bytes for utf-8 (clangd with extenion) diff --git a/runtime/lua/vim/lsp/tagfunc.lua b/runtime/lua/vim/lsp/tagfunc.lua new file mode 100644 index 0000000000..5c55e8559f --- /dev/null +++ b/runtime/lua/vim/lsp/tagfunc.lua @@ -0,0 +1,76 @@ +local lsp = vim.lsp +local util = vim.lsp.util + +---@private +local function mk_tag_item(name, range, uri, offset_encoding) + local bufnr = vim.uri_to_bufnr(uri) + -- This is get_line_byte_from_position is 0-indexed, call cursor expects a 1-indexed position + local byte = util._get_line_byte_from_position(bufnr, range.start, offset_encoding) + 1 + return { + name = name, + filename = vim.uri_to_fname(uri), + cmd = string.format('call cursor(%d, %d)|', range.start.line + 1, byte), + } +end + +---@private +local function query_definition(pattern) + local params = lsp.util.make_position_params() + local results_by_client, err = lsp.buf_request_sync(0, 'textDocument/definition', params, 1000) + if err then + return {} + end + local results = {} + local add = function(range, uri, offset_encoding) + table.insert(results, mk_tag_item(pattern, range, uri, offset_encoding)) + end + for client_id, lsp_results in pairs(results_by_client) do + local client = lsp.get_client_by_id(client_id) + local result = lsp_results.result or {} + if result.range then -- Location + add(result.range, result.uri) + else -- Location[] or LocationLink[] + for _, item in pairs(result) do + if item.range then -- Location + add(item.range, item.uri, client.offset_encoding) + else -- LocationLink + add(item.targetSelectionRange, item.targetUri, client.offset_encoding) + end + end + end + end + return results +end + +---@private +local function query_workspace_symbols(pattern) + local results_by_client, err = lsp.buf_request_sync(0, 'workspace/symbol', { query = pattern }, 1000) + if err then + return {} + end + local results = {} + for client_id, symbols in pairs(results_by_client) do + local client = lsp.get_client_by_id(client_id) + for _, symbol in pairs(symbols.result or {}) do + local loc = symbol.location + local item = mk_tag_item(symbol.name, loc.range, loc.uri, client.offset_encoding) + item.kind = lsp.protocol.SymbolKind[symbol.kind] or 'Unknown' + table.insert(results, item) + end + end + return results +end + +---@private +local function tagfunc(pattern, flags) + local matches + if string.match(flags, 'c') then + matches = query_definition(pattern) + else + matches = query_workspace_symbols(pattern) + end + -- fall back to tags if no matches + return #matches > 0 and matches or vim.NIL +end + +return tagfunc diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index a4b7b9922b..ba5c20ef9f 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -1341,19 +1341,17 @@ do --[[ References ]] --- ---@param bufnr buffer id ---@param references List of `DocumentHighlight` objects to highlight + ---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to utf-16 ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#documentHighlight - function M.buf_highlight_references(bufnr, references, client_id) + function M.buf_highlight_references(bufnr, references, offset_encoding) validate { bufnr = {bufnr, 'n', true} } - local client = vim.lsp.get_client_by_id(client_id) - if not client then - return - end + offset_encoding = offset_encoding or 'utf-16' for _, reference in ipairs(references) do local start_line, start_char = reference["range"]["start"]["line"], reference["range"]["start"]["character"] local end_line, end_char = reference["range"]["end"]["line"], reference["range"]["end"]["character"] - local start_idx = get_line_byte_from_position(bufnr, { line = start_line, character = start_char }, client.offset_encoding) - local end_idx = get_line_byte_from_position(bufnr, { line = start_line, character = end_char }, client.offset_encoding) + local start_idx = get_line_byte_from_position(bufnr, { line = start_line, character = start_char }, offset_encoding) + local end_idx = get_line_byte_from_position(bufnr, { line = start_line, character = end_char }, offset_encoding) local document_highlight_kind = { [protocol.DocumentHighlightKind.Text] = "LspReferenceText"; diff --git a/runtime/lua/vim/uri.lua b/runtime/lua/vim/uri.lua index 5d8d4fa169..d08d2a3ee3 100644 --- a/runtime/lua/vim/uri.lua +++ b/runtime/lua/vim/uri.lua @@ -56,8 +56,8 @@ local function is_windows_file_uri(uri) end --- Get a URI from a file path. ----@param path (string): Path to file ----@return URI +---@param path string Path to file +---@return string URI local function uri_from_fname(path) local volume_path, fname = path:match("^([a-zA-Z]:)(.*)") local is_windows = volume_path ~= nil @@ -78,8 +78,8 @@ local URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9+-.]*):.*' local WINDOWS_URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9+-.]*):[a-zA-Z]:.*' --- Get a URI from a bufnr ----@param bufnr (number): Buffer number ----@return URI +---@param bufnr number +---@return string URI local function uri_from_bufnr(bufnr) local fname = vim.api.nvim_buf_get_name(bufnr) local volume_path = fname:match("^([a-zA-Z]:).*") @@ -99,8 +99,8 @@ local function uri_from_bufnr(bufnr) end --- Get a filename from a URI ----@param uri (string): The URI ----@return Filename +---@param uri string +---@return string filename or unchanged URI for non-file URIs local function uri_to_fname(uri) local scheme = assert(uri:match(URI_SCHEME_PATTERN), 'URI must contain a scheme: ' .. uri) if scheme ~= 'file' then @@ -117,17 +117,13 @@ local function uri_to_fname(uri) return uri end ---- Return or create a buffer for a uri. ----@param uri (string): The URI ----@return bufnr. ----@note Creates buffer but does not load it +--- Get the buffer for a uri. +--- Creates a new unloaded buffer if no buffer for the uri already exists. +-- +---@param uri string +---@return number bufnr local function uri_to_bufnr(uri) - local scheme = assert(uri:match(URI_SCHEME_PATTERN), 'URI must contain a scheme: ' .. uri) - if scheme == 'file' then - return vim.fn.bufadd(uri_to_fname(uri)) - else - return vim.fn.bufadd(uri) - end + return vim.fn.bufadd(uri_to_fname(uri)) end return { diff --git a/runtime/pack/dist/opt/matchit/doc/matchit.txt b/runtime/pack/dist/opt/matchit/doc/matchit.txt index 58a47780ef..b719fae730 100644 --- a/runtime/pack/dist/opt/matchit/doc/matchit.txt +++ b/runtime/pack/dist/opt/matchit/doc/matchit.txt @@ -1,10 +1,10 @@ -*matchit.txt* Extended "%" matching +*matchit.txt* Extended "%" matching For instructions on installing this file, type `:help matchit-install` inside Vim. -For Vim version 8.1. Last change: 2021 May 17 +For Vim version 8.1. Last change: 2021 Nov 13 VIM REFERENCE MANUAL by Benji Fisher et al diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim index 8de03dfab7..ae0242a312 100644 --- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim +++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim @@ -2,7 +2,7 @@ " " Author: Bram Moolenaar " Copyright: Vim license applies, see ":help license" -" Last Change: 2021 Oct 26 +" Last Change: 2021 Nov 14 " " WORK IN PROGRESS - Only the basics work " Note: On MS-Windows you need a recent version of gdb. The one included with @@ -1191,6 +1191,7 @@ func s:GotoAsmwinOrCreateIt() setlocal number setlocal noswapfile setlocal buftype=nofile + setlocal modifiable let asmbuf = bufnr('Termdebug-asm-listing') if asmbuf > 0 @@ -1273,6 +1274,7 @@ func s:HandleCursor(msg) endif endif exe lnum + normal! zv exe 'sign unplace ' . s:pc_id exe 'sign place ' . s:pc_id . ' line=' . lnum . ' name=debugPC file=' . fname if !exists('b:save_signcolumn') diff --git a/runtime/plugin/zipPlugin.vim b/runtime/plugin/zipPlugin.vim index b9e334fb98..edc52713a8 100644 --- a/runtime/plugin/zipPlugin.vim +++ b/runtime/plugin/zipPlugin.vim @@ -20,7 +20,7 @@ if &cp || exists("g:loaded_zipPlugin") finish endif -let g:loaded_zipPlugin = "v31" +let g:loaded_zipPlugin = "v32" let s:keepcpo = &cpo set cpo&vim diff --git a/runtime/syntax/autoit.vim b/runtime/syntax/autoit.vim index 1b9ab7458e..6b6048aadc 100644 --- a/runtime/syntax/autoit.vim +++ b/runtime/syntax/autoit.vim @@ -5,6 +5,7 @@ " Authored By: Riccardo Casini <ric@libero.it> " Script URL: http://www.vim.org/scripts/script.php?script_id=1239 " ChangeLog: Please visit the script URL for detailed change information +" Included change from #970. " Quit when a syntax file was already loaded. if exists("b:current_syntax") @@ -932,7 +933,7 @@ syn match autoitConst "\$SD_POWERDOWN" " constants - string syn match autoitConst "\$STR_NOCASESENSE" syn match autoitConst "\$STR_CASESENSE" -syn match autoitConst "\STR_STRIPLEADING" +syn match autoitConst "\$STR_STRIPLEADING" syn match autoitConst "\$STR_STRIPTRAILING" syn match autoitConst "\$STR_STRIPSPACES" syn match autoitConst "\$STR_STRIPALL" diff --git a/runtime/syntax/gdb.vim b/runtime/syntax/gdb.vim index 25a21d184e..c820ba40a9 100644 --- a/runtime/syntax/gdb.vim +++ b/runtime/syntax/gdb.vim @@ -2,7 +2,8 @@ " Language: GDB command files " Maintainer: Claudio Fleiner <claudio@fleiner.com> " URL: http://www.fleiner.com/vim/syntax/gdb.vim -" Last Change: 2012 Oct 05 +" Last Change: 2021 Nov 15 +" Additional changes by Simon Sobisch " quit when a syntax file was already loaded if exists("b:current_syntax") @@ -21,19 +22,19 @@ syn match gdbInfo contained "all-registers" syn keyword gdbStatement contained actions apply attach awatch backtrace break bt call catch cd clear collect commands -syn keyword gdbStatement contained complete condition continue delete detach directory disable disassemble display down +syn keyword gdbStatement contained complete condition continue delete detach directory disable disas[semble] disp[lay] down syn keyword gdbStatement contained echo else enable end file finish frame handle hbreak help if ignore syn keyword gdbStatement contained inspect jump kill list load maintenance make next nexti ni output overlay -syn keyword gdbStatement contained passcount path print printf ptype pwd quit rbreak remote return run rwatch -syn keyword gdbStatement contained search section set sharedlibrary shell show si signal source step stepi stepping +syn keyword gdbStatement contained passcount path print printf ptype python pwd quit rbreak remote return run rwatch +syn keyword gdbStatement contained search section set sharedlibrary shell show si signal skip source step stepi stepping syn keyword gdbStatement contained stop target tbreak tdump tfind thbreak thread tp trace tstart tstatus tstop -syn keyword gdbStatement contained tty undisplay unset until up watch whatis where while ws x +syn keyword gdbStatement contained tty und[isplay] unset until up watch whatis where while ws x syn match gdbFuncDef "\<define\>.*" syn match gdbStatmentContainer "^\s*\S\+" contains=gdbStatement,gdbFuncDef syn match gdbStatement "^\s*info" nextgroup=gdbInfo skipwhite skipempty " some commonly used abbreviations -syn keyword gdbStatement c disp undisp disas p +syn keyword gdbStatement c cont p py syn region gdbDocument matchgroup=gdbFuncDef start="\<document\>.*$" matchgroup=gdbFuncDef end="^end\s*$" diff --git a/runtime/syntax/gnuplot.vim b/runtime/syntax/gnuplot.vim index 9c98e67e58..b5092d7555 100644 --- a/runtime/syntax/gnuplot.vim +++ b/runtime/syntax/gnuplot.vim @@ -3,7 +3,8 @@ " Maintainer: Josh Wainwright <wainwright DOT ja AT gmail DOT com> " Last Maintainer: Andrew Rasmussen andyras@users.sourceforge.net " Original Maintainer: John Hoelzel johnh51@users.sourceforge.net -" Last Change: 2020 May 12 +" Last Change: 2021 Nov 16 +" additional changes from PR #8949 " Filenames: *.gnu *.plt *.gpi *.gih *.gp *.gnuplot scripts: #!*gnuplot " URL: http://www.vim.org/scripts/script.php?script_id=4873 " Original URL: http://johnh51.get.to/vim/syntax/gnuplot.vim @@ -32,22 +33,22 @@ syn match gnuplotSpecial "\\." contained " syn match gnuplotSpecial "\\\o\o\o\|\\x\x\x\|\\c[^"]\|\\[a-z\\]" contained " measurements in the units in, cm and pt are special -syn match gnuplotUnit "[0-9]+in" -syn match gnuplotUnit "[0-9]+cm" -syn match gnuplotUnit "[0-9]+pt" +syn match gnuplotUnit "\d+in" +syn match gnuplotUnit "\d+cm" +syn match gnuplotUnit "\d+pt" " external (shell) commands are special -syn region gnuplotExternal start="!" end="$" +syn region gnuplotExternal start="^\s*!" end="$" " ---- Comments ---- " -syn region gnuplotComment start="#" end="$" contains=gnuplotTodo +syn region gnuplotComment start="#" end="$" contains=gnuplotTodo,@Spell " ---- Constants ---- " " strings -syn region gnuplotString start=+"+ skip=+\\"+ end=+"+ contains=gnuplotSpecial -syn region gnuplotString start="'" end="'" +syn region gnuplotString start=+"+ skip=+\\"+ end=+"+ contains=gnuplotSpecial,@Spell +syn region gnuplotString start="'" end="'" contains=@Spell " built-in variables syn keyword gnuplotNumber GNUTERM GPVAL_TERM GPVAL_TERMOPTIONS GPVAL_SPLOT @@ -76,7 +77,7 @@ syn keyword gnuplotNumber GPVAL_TERM_YSIZE GPVAL_VIEW_MAP GPVAL_VIEW_ROT_X syn keyword gnuplotNumber GPVAL_VIEW_ROT_Z GPVAL_VIEW_SCALE " function name variables -syn match gnuplotNumber "GPFUN_[a-zA-Z_]*" +syn match gnuplotNumber "GPFUN_\h*" " stats variables syn keyword gnuplotNumber STATS_records STATS_outofrange STATS_invalid @@ -104,23 +105,23 @@ syn keyword gnuplotError FIT_LAMBDA_FACTOR FIT_LOG FIT_SCRIPT " integer number, or floating point number without a dot and with "f". syn case ignore -syn match gnuplotNumber "\<[0-9]\+\(u\=l\=\|lu\|f\)\>" +syn match gnuplotNumber "\<\d\+\(u\=l\=\|lu\|f\)\>" " floating point number, with dot, optional exponent -syn match gnuplotFloat "\<[0-9]\+\.[0-9]*\(e[-+]\=[0-9]\+\)\=[fl]\=\>" +syn match gnuplotFloat "\<\d\+\.\d*\(e[-+]\=\d\+\)\=[fl]\=\>" " floating point number, starting with a dot, optional exponent -syn match gnuplotFloat "\.[0-9]\+\(e[-+]\=[0-9]\+\)\=[fl]\=\>" +syn match gnuplotFloat "\.\d\+\(e[-+]\=\d\+\)\=[fl]\=\>" " floating point number, without dot, with exponent -syn match gnuplotFloat "\<[0-9]\+e[-+]\=[0-9]\+[fl]\=\>" +syn match gnuplotFloat "\<\d\+e[-+]\=\d\+[fl]\=\>" " hex number -syn match gnuplotNumber "\<0x[0-9a-f]\+\(u\=l\=\|lu\)\>" +syn match gnuplotNumber "\<0x\x\+\(u\=l\=\|lu\)\>" syn case match " flag an octal number with wrong digits by not highlighting -syn match gnuplotOctalError "\<0[0-7]*[89]" +syn match gnuplotOctalError "\<0\o*[89]" " ---- Identifiers: Functions ---- " @@ -374,8 +375,8 @@ syn keyword gnuplotKeyword nohead nooutliers nowedge off opaque outliers syn keyword gnuplotKeyword palette pattern pi pointinterval pointsize syn keyword gnuplotKeyword pointtype ps pt radius range rectangle syn keyword gnuplotKeyword rowstacked screen separation size solid sorted -syn keyword gnuplotKeyword textbox transparent units unsorted userstyles -syn keyword gnuplotKeyword wedge x x2 xx xy yy +syn keyword gnuplotKeyword textbox units unsorted userstyles wedge +syn keyword gnuplotKeyword x x2 xx xy yy " set surface syn keyword gnuplotKeyword surface implicit explicit " set table @@ -477,9 +478,13 @@ syn keyword gnuplotKeyword nooutput " keywords for 'test' command syn keyword gnuplotKeyword terminal palette rgb rbg grb gbr brg bgr +" The transparent gnuplot keyword cannot use 'syn keyword' as transparent +" has a special meaning in :syntax commands. +syn match gnuplotKeyword "\<transparent\>" + " ---- Macros ---- " -syn match gnuplotMacro "@[a-zA-Z0-9_]*" +syn match gnuplotMacro "@\w*" " ---- Todos ---- " diff --git a/runtime/syntax/lisp.vim b/runtime/syntax/lisp.vim index 434150ab26..90513e3a00 100644 --- a/runtime/syntax/lisp.vim +++ b/runtime/syntax/lisp.vim @@ -1,8 +1,8 @@ " Vim syntax file " Language: Lisp " Maintainer: Charles E. Campbell <NcampObell@SdrPchip.AorgM-NOSPAM> -" Last Change: Jul 11, 2019 -" Version: 30 +" Last Change: Nov 10, 2021 +" Version: 31 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_LISP " " Thanks to F Xavier Noria for a list of 978 Common Lisp symbols taken from HyperSpec @@ -54,20 +54,20 @@ if exists("g:lisp_rainbow") && g:lisp_rainbow != 0 syn region lispParen8 contained matchgroup=hlLevel8 start="`\=(" end=")" skip="|.\{-}|" contains=@lispListCluster,lispParen9 syn region lispParen9 contained matchgroup=hlLevel9 start="`\=(" end=")" skip="|.\{-}|" contains=@lispListCluster,lispParen0 else - syn region lispList matchgroup=lispParen start="(" skip="|.\{-}|" matchgroup=lispParen end=")" contains=@lispListCluster - syn region lispBQList matchgroup=PreProc start="`(" skip="|.\{-}|" matchgroup=PreProc end=")" contains=@lispListCluster + syn region lispList matchgroup=lispParen start="(" skip="|.\{-}|" matchgroup=lispParen end=")" contains=@lispListCluster + syn region lispBQList matchgroup=PreProc start="`(" skip="|.\{-}|" matchgroup=PreProc end=")" contains=@lispListCluster endif " --------------------------------------------------------------------- " Atoms: {{{1 -syn match lispAtomMark "'" -syn match lispAtom "'("me=e-1 contains=lispAtomMark nextgroup=lispAtomList -syn match lispAtom "'[^ \t()]\+" contains=lispAtomMark -syn match lispAtomBarSymbol !'|..\{-}|! contains=lispAtomMark -syn region lispAtom start=+'"+ skip=+\\"+ end=+"+ -syn region lispAtomList contained matchgroup=Special start="(" skip="|.\{-}|" matchgroup=Special end=")" contains=@lispAtomCluster,lispString,lispEscapeSpecial -syn match lispAtomNmbr contained "\<\d\+" -syn match lispLeadWhite contained "^\s\+" +syn match lispAtomMark "'" +syn match lispAtom "'("me=e-1 contains=lispAtomMark nextgroup=lispAtomList +syn match lispAtom "'[^ \t()]\+" contains=lispAtomMark +syn match lispAtomBarSymbol !'|..\{-}|! contains=lispAtomMark +syn region lispAtom start=+'"+ skip=+\\"+ end=+"+ +syn region lispAtomList contained matchgroup=Special start="(" skip="|.\{-}|" matchgroup=Special end=")" contains=@lispAtomCluster,lispString,lispEscapeSpecial +syn match lispAtomNmbr contained "\<\d\+" +syn match lispLeadWhite contained "^\s\+" " --------------------------------------------------------------------- " Standard Lisp Functions and Macros: {{{1 @@ -553,6 +553,8 @@ syn match lispParenError ")" syn cluster lispCommentGroup contains=lispTodo,@Spell syn match lispComment ";.*$" contains=@lispCommentGroup syn region lispCommentRegion start="#|" end="|#" contains=lispCommentRegion,@lispCommentGroup +syn region lispComment start="#+nil" end="\ze)" contains=@lispCommentGroup +syn match lispComment '^\s*#+nil.*$' contains=@lispCommentGroup syn keyword lispTodo contained combak combak: todo todo: " --------------------------------------------------------------------- diff --git a/runtime/syntax/routeros.vim b/runtime/syntax/routeros.vim new file mode 100644 index 0000000000..b6effc9b62 --- /dev/null +++ b/runtime/syntax/routeros.vim @@ -0,0 +1,91 @@ +" Vim syntax file +" Language: MikroTik RouterOS Script +" Maintainer: zainin <z@wintr.dev> +" Original Author: ndbjorne @ MikroTik forums +" Last Change: 2021 Nov 14 + +" quit when a syntax file was already loaded +if exists("b:current_syntax") + finish +endif + +syn case ignore + +syn iskeyword @,48-57,- + +" comments +syn match routerosComment /^\s*\zs#.*/ + +" options submenus: /interface ether1 etc +syn match routerosSubMenu "\([a-z]\)\@<!/[a-zA-Z0-9-]*" + +" variables are matched by looking at strings ending with "=", e.g. var= +syn match routerosVariable "[a-zA-Z0-9-/]*\(=\)\@=" +syn match routerosVariable "$[a-zA-Z0-9-]*" + +" colored for clarity +syn match routerosDelimiter "[,=]" +" match slash in CIDR notation (1.2.3.4/24, 2001:db8::/48, ::1/128) +syn match routerosDelimiter "\(\x\|:\)\@<=\/\(\d\)\@=" +" dash in IP ranges +syn match routerosDelimiter "\(\x\|:\)\@<=-\(\x\|:\)\@=" + +" match service names after "set", like in original routeros syntax +syn match routerosService "\(set\)\@<=\s\(api-ssl\|api\|dns\|ftp\|http\|https\|pim\|ntp\|smb\|ssh\|telnet\|winbox\|www\|www-ssl\)" + +" colors various interfaces +syn match routerosInterface "bridge\d\+\|ether\d\+\|wlan\d\+\|pppoe-\(out\|in\)\d\+" + +syn keyword routerosBoolean yes no true false + +syn keyword routerosConditional if + +" operators +syn match routerosOperator " \zs[-+*<>=!~^&.,]\ze " +syn match routerosOperator "[<>!]=" +syn match routerosOperator "<<\|>>" +syn match routerosOperator "[+-]\d\@=" + +syn keyword routerosOperator and or in + +" commands +syn keyword routerosCommands beep delay put len typeof pick log time set find environment +syn keyword routerosCommands terminal error parse resolve toarray tobool toid toip toip6 +syn keyword routerosCommands tonum tostr totime add remove enable disable where get print +syn keyword routerosCommands export edit find append as-value brief detail count-only file +syn keyword routerosCommands follow follow-only from interval terse value-list without-paging +syn keyword routerosCommands return + +" variable types +syn keyword routerosType global local + +" loop keywords +syn keyword routerosRepeat do while for foreach + +syn match routerosSpecial "[():[\]{|}]" + +syn match routerosLineContinuation "\\$" + +syn match routerosEscape "\\["\\nrt$?_abfv]" contained display +syn match routerosEscape "\\\x\x" contained display + +syn region routerosString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=routerosEscape,routerosLineContinuation + +hi link routerosComment Comment +hi link routerosSubMenu Function +hi link routerosVariable Identifier +hi link routerosDelimiter Operator +hi link routerosEscape Special +hi link routerosService Type +hi link routerosInterface Type +hi link routerosBoolean Boolean +hi link routerosConditional Conditional +hi link routerosOperator Operator +hi link routerosCommands Operator +hi link routerosType Type +hi link routerosRepeat Repeat +hi link routerosSpecial Delimiter +hi link routerosString String +hi link routerosLineContinuation Special + +let b:current_syntax = "routeros" diff --git a/runtime/syntax/tcl.vim b/runtime/syntax/tcl.vim index 73b2b3fa11..59cb04f70f 100644 --- a/runtime/syntax/tcl.vim +++ b/runtime/syntax/tcl.vim @@ -6,8 +6,8 @@ " (previously Matt Neumann <mattneu@purpleturtle.com>) " (previously Allan Kelly <allan@fruitloaf.co.uk>) " Original: Robin Becker <robin@jessikat.demon.co.uk> -" Last Change: 2021 Oct 03 -" Version: 1.14 +" Last Change: 2021 Nov 16 +" Version: 1.14 plus improvements from PR #8948 " URL: (removed, no longer worked) " quit when a syntax file was already loaded @@ -192,18 +192,18 @@ syn region tcltkCommand matchgroup=tcltkCommandColor start="\<lsort\>" matchgrou syn keyword tclTodo contained TODO " Sequences which are backslash-escaped: http://www.tcl.tk/man/tcl8.5/TclCmd/Tcl.htm#M16 -" Octal, hexadecimal, unicode codepoints, and the classics. +" Octal, hexadecimal, Unicode codepoints, and the classics. " Tcl takes as many valid characters in a row as it can, so \xAZ in a string is newline followed by 'Z'. -syn match tclSpecial contained '\\\([0-7]\{1,3}\|x\x\{1,2}\|u\x\{1,4}\|[abfnrtv]\)' +syn match tclSpecial contained '\\\(\o\{1,3}\|x\x\{1,2}\|u\x\{1,4}\|[abfnrtv]\)' syn match tclSpecial contained '\\[\[\]\{\}\"\$]' " Command appearing inside another command or inside a string. syn region tclEmbeddedStatement start='\[' end='\]' contained contains=tclCommand,tclNumber,tclLineContinue,tclString,tclVarRef,tclEmbeddedStatement " A string needs the skip argument as it may legitimately contain \". " Match at start of line -syn region tclString start=+^"+ end=+"+ contains=@tclSpecialC skip=+\\\\\|\\"+ +syn region tclString start=+^"+ end=+"+ contains=@tclSpecialC,@Spell skip=+\\\\\|\\"+ "Match all other legal strings. -syn region tclString start=+[^\\]"+ms=s+1 end=+"+ contains=@tclSpecialC,@tclVarRefC,tclEmbeddedStatement skip=+\\\\\|\\"+ +syn region tclString start=+[^\\]"+ms=s+1 end=+"+ contains=@tclSpecialC,@tclVarRefC,tclEmbeddedStatement,@Spell skip=+\\\\\|\\"+ " Line continuation is backslash immediately followed by newline. syn match tclLineContinue '\\$' @@ -222,12 +222,12 @@ syn match tclNumber "\.\d\+\(e[-+]\=\d\+\)\=[fl]\=\>" "floating point number, without dot, with exponent syn match tclNumber "\<\d\+e[-+]\=\d\+[fl]\=\>" "hex number -syn match tclNumber "0x[0-9a-f]\+\(u\=l\=\|lu\)\>" -"syn match tclIdentifier "\<[a-z_][a-z0-9_]*\>" +syn match tclNumber "0x\x\+\(u\=l\=\|lu\)\>" +"syn match tclIdentifier "\<\h\w*\>" syn case match -syn region tclComment start="^\s*\#" skip="\\$" end="$" contains=tclTodo -syn region tclComment start=/;\s*\#/hs=s+1 skip="\\$" end="$" contains=tclTodo +syn region tclComment start="^\s*\#" skip="\\$" end="$" contains=tclTodo,@Spell +syn region tclComment start=/;\s*\#/hs=s+1 skip="\\$" end="$" contains=tclTodo,@Spell "syn match tclComment /^\s*\#.*$/ "syn match tclComment /;\s*\#.*$/hs=s+1 diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim index 67756fa320..f7b5ce0f63 100644 --- a/runtime/syntax/vim.vim +++ b/runtime/syntax/vim.vim @@ -161,10 +161,13 @@ syn match vimFBVar contained "\<[bwglstav]:\h[a-zA-Z0-9#_]*\>" syn keyword vimCommand contained in " Insertions And Appends: insert append {{{2 +" (buftype != nofile test avoids having append, change, insert show up in the command window) " ======================= -syn region vimInsert matchgroup=vimCommand start="^[: \t]*\(\d\+\(,\d\+\)\=\)\=a\%[ppend]$" matchgroup=vimCommand end="^\.$"" -syn region vimInsert matchgroup=vimCommand start="^[: \t]*\(\d\+\(,\d\+\)\=\)\=c\%[hange]$" matchgroup=vimCommand end="^\.$"" -syn region vimInsert matchgroup=vimCommand start="^[: \t]*\(\d\+\(,\d\+\)\=\)\=i\%[nsert]$" matchgroup=vimCommand end="^\.$"" +if &buftype != 'nofile' + syn region vimInsert matchgroup=vimCommand start="^[: \t]*\(\d\+\(,\d\+\)\=\)\=a\%[ppend]$" matchgroup=vimCommand end="^\.$"" + syn region vimInsert matchgroup=vimCommand start="^[: \t]*\(\d\+\(,\d\+\)\=\)\=c\%[hange]$" matchgroup=vimCommand end="^\.$"" + syn region vimInsert matchgroup=vimCommand start="^[: \t]*\(\d\+\(,\d\+\)\=\)\=i\%[nsert]$" matchgroup=vimCommand end="^\.$"" +endif " Behave! {{{2 " ======= diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index 2d2d46d1bd..89fc14121e 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -162,6 +162,7 @@ CONFIG = { 'buf.lua', 'diagnostic.lua', 'codelens.lua', + 'tagfunc.lua', 'handlers.lua', 'util.lua', 'log.lua', diff --git a/src/nvim/api/vimscript.c b/src/nvim/api/vimscript.c index c516cedaf4..640144b234 100644 --- a/src/nvim/api/vimscript.c +++ b/src/nvim/api/vimscript.c @@ -390,7 +390,7 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, E FUNC_API_SINCE(4) FUNC_API_FAST { int pflags = 0; - for (size_t i = 0 ; i < flags.size ; i++) { + for (size_t i = 0; i < flags.size; i++) { switch (flags.data[i]) { case 'm': pflags |= kExprFlagsMulti; break; @@ -478,7 +478,7 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, E .capacity = kv_size(colors), .size = kv_size(colors), }; - for (size_t i = 0 ; i < kv_size(colors) ; i++) { + for (size_t i = 0; i < kv_size(colors); i++) { const ParserHighlightChunk chunk = kv_A(colors, i); Array chunk_arr = (Array) { .items = xmalloc(4 * sizeof(chunk_arr.items[0])), diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 88938d5099..f2f4950e58 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -1305,7 +1305,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit) if (buf == NULL) { // No previous buffer, Try 2'nd approach forward = true; buf = curbuf->b_next; - for (;; ) { + for (;;) { if (buf == NULL) { if (!forward) { // tried both directions break; @@ -1587,7 +1587,7 @@ void do_autochdir(void) if (starting == 0 && curbuf->b_ffname != NULL && vim_chdirfile(curbuf->b_ffname, kCdCauseAuto) == OK) { - post_chdir(kCdScopeGlobal, false); + last_chdir_reason = "autochdir"; shorten_fnames(true); } } @@ -2163,7 +2163,7 @@ int buflist_findpat(const char_u *pattern, const char_u *pattern_end, bool unlis // First try finding a listed buffer. If not found and "unlisted" // is true, try finding an unlisted buffer. find_listed = true; - for (;; ) { + for (;;) { for (attempt = 0; attempt <= 3; attempt++) { // may add '^' and '$' if (toggledollar) { @@ -3511,7 +3511,7 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use // Proceed character by character through the statusline format string // fmt_p is the current position in the input buffer - for (char_u *fmt_p = usefmt; *fmt_p; ) { + for (char_u *fmt_p = usefmt; *fmt_p;) { if (curitem == (int)stl_items_len) { size_t new_len = stl_items_len * 3 / 2; @@ -4407,7 +4407,7 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use // string to find the last character that will fit. trunc_p = out; width = 0; - for (;; ) { + for (;;) { width += ptr2cells(trunc_p); if (width >= maxwidth) { break; @@ -4758,7 +4758,7 @@ void do_arg_all(int count, int forceit, int keep_tabs) if (had_tab > 0) { goto_tabpage_tp(first_tabpage, true, true); } - for (;; ) { + for (;;) { win_T *wpnext = NULL; tpnext = curtab->tp_next; for (win_T *wp = firstwin; wp != NULL; wp = wpnext) { @@ -5009,7 +5009,7 @@ void ex_buffer_all(exarg_T *eap) if (had_tab > 0) { goto_tabpage_tp(first_tabpage, true, true); } - for (;; ) { + for (;;) { tpnext = curtab->tp_next; for (wp = firstwin; wp != NULL; wp = wpnext) { wpnext = wp->w_next; @@ -5020,8 +5020,8 @@ void ex_buffer_all(exarg_T *eap) : wp->w_width != Columns) || (had_tab > 0 && wp != firstwin)) && !ONE_WINDOW - && !(wp->w_closing || - wp->w_buffer->b_locked > 0)) { + && !(wp->w_closing + || wp->w_buffer->b_locked > 0)) { win_close(wp, false); wpnext = firstwin; // just in case an autocommand does // something strange with windows @@ -5138,7 +5138,7 @@ void ex_buffer_all(exarg_T *eap) /* * Close superfluous windows. */ - for (wp = lastwin; open_wins > count; ) { + for (wp = lastwin; open_wins > count;) { r = (buf_hide(wp->w_buffer) || !bufIsChanged(wp->w_buffer) || autowrite(wp->w_buffer, false) == OK); if (!win_valid(wp)) { diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index bd9c5efa44..49e527e98b 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1121,14 +1121,14 @@ typedef struct { /// @{ enum { MENU_INDEX_INVALID = -1, - MENU_INDEX_NORMAL = 0, - MENU_INDEX_VISUAL = 1, - MENU_INDEX_SELECT = 2, - MENU_INDEX_OP_PENDING = 3, - MENU_INDEX_INSERT = 4, - MENU_INDEX_CMDLINE = 5, - MENU_INDEX_TIP = 6, - MENU_MODES = 7, + MENU_INDEX_NORMAL = 0, + MENU_INDEX_VISUAL = 1, + MENU_INDEX_SELECT = 2, + MENU_INDEX_OP_PENDING = 3, + MENU_INDEX_INSERT = 4, + MENU_INDEX_CMDLINE = 5, + MENU_INDEX_TIP = 6, + MENU_MODES = 7, }; typedef struct VimMenu vimmenu_T; diff --git a/src/nvim/change.c b/src/nvim/change.c index 6ec4979dac..c52d992fbe 100644 --- a/src/nvim/change.c +++ b/src/nvim/change.c @@ -1355,7 +1355,7 @@ int open_line(int dir, int flags, int second_line_indent) int c = 0; int off = 0; - for (p = lead_flags; *p != NUL && *p != ':'; ) { + for (p = lead_flags; *p != NUL && *p != ':';) { if (*p == COM_RIGHT || *p == COM_LEFT) { c = *p++; } else if (ascii_isdigit(*p) || *p == '-') { @@ -1841,7 +1841,7 @@ void del_lines(long nlines, bool undo) return; } - for (n = 0; n < nlines; ) { + for (n = 0; n < nlines;) { if (curbuf->b_ml.ml_flags & ML_EMPTY) { // nothing to delete break; } diff --git a/src/nvim/charset.c b/src/nvim/charset.c index 5e18f9d86e..eb0903b594 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -1642,6 +1642,16 @@ int hex2nr(int c) return c - '0'; } +/// Convert two hex characters to a byte. +/// Return -1 if one of the characters is not hex. +int hexhex2nr(char_u *p) +{ + if (!ascii_isxdigit(p[0]) || !ascii_isxdigit(p[1])) { + return -1; + } + return (hex2nr(p[0]) << 4) + hex2nr(p[1]); +} + /// Check that "str" starts with a backslash that should be removed. /// For Windows this is only done when the character after the /// backslash is not a normal file name character. diff --git a/src/nvim/cursor_shape.c b/src/nvim/cursor_shape.c index 644bb2c324..6b0a5dfe12 100644 --- a/src/nvim/cursor_shape.c +++ b/src/nvim/cursor_shape.c @@ -168,7 +168,7 @@ char *parse_shape_opt(int what) } // Parse the part after the colon - for (p = colonp + 1; *p && *p != ','; ) { + for (p = colonp + 1; *p && *p != ',';) { { /* * First handle the ones with a number argument. diff --git a/src/nvim/debugger.c b/src/nvim/debugger.c index 3ac128a20f..b6e35f3047 100644 --- a/src/nvim/debugger.c +++ b/src/nvim/debugger.c @@ -109,7 +109,7 @@ void do_debug(char_u *cmd) smsg(_("cmd: %s"), cmd); } // Repeat getting a command and executing it. - for (;; ) { + for (;;) { msg_scroll = true; need_wait_return = false; // Save the current typeahead buffer and replace it with an empty one. diff --git a/src/nvim/diff.c b/src/nvim/diff.c index 4e03f4761c..1f8acd8c79 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -739,7 +739,7 @@ static int diff_write_buffer(buf_T *buf, diffin_T *din) len = 0; for (lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) { - for (s = ml_get_buf(buf, lnum, false); *s != NUL; ) { + for (s = ml_get_buf(buf, lnum, false); *s != NUL;) { if (diff_flags & DIFF_ICASE) { char_u cbuf[MB_MAXBYTES + 1]; diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 7a24ee1b32..d505b40935 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -4166,7 +4166,7 @@ static int ins_compl_get_exp(pos_T *ini) pos = (compl_direction == FORWARD) ? &last_match_pos : &first_match_pos; // For ^N/^P loop over all the flags/windows/buffers in 'complete' - for (;; ) { + for (;;) { found_new_match = FAIL; set_match_pos = false; @@ -4384,7 +4384,7 @@ static int ins_compl_get_exp(pos_T *ini) p_ws = true; } bool looped_around = false; - for (;; ) { + for (;;) { bool cont_s_ipos = false; msg_silent++; // Don't want messages for wrapscan. @@ -5570,7 +5570,7 @@ int get_literal(void) no_mapping++; // don't map the next key hits cc = 0; i = 0; - for (;; ) { + for (;;) { nc = plain_vgetc(); if (!(State & CMDLINE) && MB_BYTE2LEN_CHECK(nc) == 1) { @@ -6677,7 +6677,7 @@ static void stop_insert(pos_T *end_insert_pos, int esc, int nomove) curwin->w_cursor = *end_insert_pos; check_cursor_col(); // make sure it is not past the line - for (;; ) { + for (;;) { if (gchar_cursor() == NUL && curwin->w_cursor.col > 0) { --curwin->w_cursor.col; } @@ -6868,7 +6868,7 @@ int oneleft(void) // We might get stuck on 'showbreak', skip over it. width = 1; - for (;; ) { + for (;;) { coladvance(v - width); // getviscol() is slow, skip it when 'showbreak' is empty, // 'breakindent' is not set and there are no multi-byte @@ -7202,7 +7202,7 @@ static void replace_join(int off) { int i; - for (i = replace_stack_nr; --i >= 0; ) { + for (i = replace_stack_nr; --i >= 0;) { if (replace_stack[i] == NUL && off-- <= 0) { --replace_stack_nr; memmove(replace_stack + i, replace_stack + i + 1, @@ -7251,7 +7251,7 @@ static void mb_replace_pop_ins(int cc) } // Handle composing chars. - for (;; ) { + for (;;) { c = replace_pop(); if (c == -1) { // stack empty break; @@ -9012,7 +9012,7 @@ static bool ins_tab(void) // correct replace stack. if ((State & REPLACE_FLAG) && !(State & VREPLACE_FLAG)) { - for (temp = i; --temp >= 0; ) { + for (temp = i; --temp >= 0;) { replace_join(repl_off); } } diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 0123c7265b..d3d0121632 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -1551,7 +1551,7 @@ static const char_u *skip_var_list(const char_u *arg, int *var_count, int *semic if (*arg == '[') { // "[var, var]": find the matching ']'. p = arg; - for (;; ) { + for (;;) { p = skipwhite(p + 1); // skip whites after '[', ';' or ',' s = skip_var_one(p); if (s == p) { @@ -2448,7 +2448,7 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, co // Check whether any of the list items is locked for (ri = tv_list_first(rettv->vval.v_list); - ri != NULL && ll_li != NULL; ) { + ri != NULL && ll_li != NULL;) { if (var_check_lock(TV_LIST_ITEM_TV(ll_li)->v_lock, lp->ll_name, TV_CSTRING)) { return; @@ -2464,7 +2464,7 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, co /* * Assign the List values to the list items. */ - for (ri = tv_list_first(rettv->vval.v_list); ri != NULL; ) { + for (ri = tv_list_first(rettv->vval.v_list); ri != NULL;) { if (op != NULL && *op != '=') { eexe_mod_op(TV_LIST_ITEM_TV(lp->ll_li), TV_LIST_ITEM_TV(ri), op); } else { @@ -2691,7 +2691,7 @@ void set_context_for_expression(expand_T *xp, char_u *arg, cmdidx_T cmdidx) xp->xp_context = EXPAND_USER_VARS; if (vim_strpbrk(arg, (char_u *)"\"'+-*/%.=!?~|&$([<>,#") == NULL) { // ":let var1 var2 ...": find last space. - for (p = arg + STRLEN(arg); p >= arg; ) { + for (p = arg + STRLEN(arg); p >= arg;) { xp->xp_pattern = p; MB_PTR_BACK(arg, p); if (ascii_iswhite(*p)) { @@ -3732,7 +3732,7 @@ static int eval5(char_u **arg, typval_T *rettv, int evaluate) /* * Repeat computing, until no '+', '-' or '.' is following. */ - for (;; ) { + for (;;) { op = **arg; if (op != '+' && op != '-' && op != '.') { break; @@ -3907,7 +3907,7 @@ static int eval6(char_u **arg, typval_T *rettv, int evaluate, int want_string) /* * Repeat computing, until no '*', '/' or '%' is following. */ - for (;; ) { + for (;;) { op = **arg; if (op != '*' && op != '/' && op != '%') { break; @@ -4890,7 +4890,7 @@ static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate) rettv->v_type = VAR_STRING; rettv->vval.v_string = name; - for (p = *arg + 1; *p != NUL && *p != '"'; ) { + for (p = *arg + 1; *p != NUL && *p != '"';) { if (*p == '\\') { switch (*++p) { case 'b': @@ -5026,7 +5026,7 @@ static int get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate) rettv->v_type = VAR_STRING; rettv->vval.v_string = str; - for (p = *arg + 1; *p != NUL; ) { + for (p = *arg + 1; *p != NUL;) { if (*p == '\'') { if (p[1] != '\'') { break; @@ -6086,7 +6086,7 @@ int assert_equalfile(typval_T *argvars) snprintf((char *)IObuff, IOSIZE, (char *)e_notread, fname2); } else { int64_t linecount = 1; - for (int64_t count = 0; ; count++) { + for (int64_t count = 0;; count++) { const int c1 = fgetc(fd1); const int c2 = fgetc(fd2); if (c1 == EOF) { @@ -6851,7 +6851,7 @@ dict_T *get_win_info(win_T *wp, int16_t tpnr, int16_t winnr) tv_dict_add_nr(dict, S_LEN("width"), wp->w_width); tv_dict_add_nr(dict, S_LEN("bufnr"), wp->w_buffer->b_fnum); tv_dict_add_nr(dict, S_LEN("wincol"), wp->w_wincol + 1); - + tv_dict_add_nr(dict, S_LEN("textoff"), win_col_off(wp)); tv_dict_add_nr(dict, S_LEN("terminal"), bt_terminal(wp->w_buffer)); tv_dict_add_nr(dict, S_LEN("quickfix"), bt_quickfix(wp->w_buffer)); tv_dict_add_nr(dict, S_LEN("loclist"), @@ -7382,7 +7382,7 @@ void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, const typval_T } // Default result is zero == OK. - for (;; ) { + for (;;) { if (lines->v_type == VAR_LIST) { // List argument, get next string. if (li == NULL) { diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 7549ec7ac8..dfadd28ebe 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2663,12 +2663,12 @@ static void f_fnamemodify(typval_T *argvars, typval_T *rettv, FunPtr fptr) char buf[NUMBUFLEN]; const char *fname = tv_get_string_chk(&argvars[0]); const char *const mods = tv_get_string_buf_chk(&argvars[1], buf); - if (fname == NULL) { + if (mods == NULL || fname == NULL) { fname = NULL; - } else if (mods != NULL && *mods != NUL) { + } else { len = strlen(fname); - size_t usedlen = 0; if (*mods != NUL) { + size_t usedlen = 0; (void)modify_fname((char_u *)mods, false, &usedlen, (char_u **)&fname, &fbuf, &len); } @@ -3174,7 +3174,7 @@ static void getchar_common(typval_T *argvars, typval_T *rettv) bool error = false; no_mapping++; - for (;; ) { + for (;;) { // Position the cursor. Needed after a message that ends in a space, // or if event processing caused a redraw. ui_cursor_goto(msg_row, msg_col); @@ -3386,15 +3386,17 @@ static void f_getcompletion(typval_T *argvars, typval_T *rettv, FunPtr fptr) emsg(_(e_invarg)); return; } + const char *pattern = tv_get_string(&argvars[0]); if (strcmp(type, "cmdline") == 0) { - set_one_cmd_context(&xpc, tv_get_string(&argvars[0])); + set_one_cmd_context(&xpc, pattern); xpc.xp_pattern_len = STRLEN(xpc.xp_pattern); + xpc.xp_col = STRLEN(pattern); goto theend; } ExpandInit(&xpc); - xpc.xp_pattern = (char_u *)tv_get_string(&argvars[0]); + xpc.xp_pattern = (char_u *)pattern; xpc.xp_pattern_len = STRLEN(xpc.xp_pattern); xpc.xp_context = cmdcomplete_str_to_type(type); if (xpc.xp_context == EXPAND_NOTHING) { @@ -3447,7 +3449,7 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr) // Numbers of the scope objects (window, tab) we want the working directory // of. A `-1` means to skip this scope, a `0` means the current object. int scope_number[] = { - [kCdScopeWindow ] = 0, // Number of window to look at. + [kCdScopeWindow] = 0, // Number of window to look at. [kCdScopeTabpage] = 0, // Number of tab to look at. }; @@ -3485,11 +3487,6 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } - // If the user didn't specify anything, default to window scope - if (scope == kCdScopeInvalid) { - scope = MIN_CD_SCOPE; - } - // Find the tabpage by number if (scope_number[kCdScopeTabpage] > 0) { tp = find_tabpage(scope_number[kCdScopeTabpage]); @@ -3535,12 +3532,13 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr) case kCdScopeGlobal: if (globaldir) { // `globaldir` is not always set. from = globaldir; - } else if (os_dirname(cwd, MAXPATHL) == FAIL) { // Get the OS CWD. + break; + } + FALLTHROUGH; // In global directory, just need to get OS CWD. + case kCdScopeInvalid: // If called without any arguments, get OS CWD. + if (os_dirname(cwd, MAXPATHL) == FAIL) { from = (char_u *)""; // Return empty string on failure. } - break; - case kCdScopeInvalid: // We should never get here - abort(); } if (from) { @@ -4667,7 +4665,7 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr) // Numbers of the scope objects (window, tab) we want the working directory // of. A `-1` means to skip this scope, a `0` means the current object. int scope_number[] = { - [kCdScopeWindow ] = 0, // Number of window to look at. + [kCdScopeWindow] = 0, // Number of window to look at. [kCdScopeTabpage] = 0, // Number of tab to look at. }; @@ -6182,7 +6180,7 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, if (regmatch.regprog != NULL) { regmatch.rm_ic = p_ic; - for (;; ) { + for (;;) { if (l != NULL) { if (li == NULL) { match = false; @@ -7727,8 +7725,8 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr) char *const buf = xmallocz(MAXPATHL); char *cpy; - for (;; ) { - for (;; ) { + for (;;) { + for (;;) { len = readlink(p, buf, MAXPATHL); if (len <= 0) { break; @@ -8603,7 +8601,7 @@ long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir clearpos(&firstpos); clearpos(&foundpos); pat = pat3; - for (;; ) { + for (;;) { searchit_arg_T sia; memset(&sia, 0, sizeof(sia)); sia.sa_stop_lnum = lnum_stop; diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index 69732f1a7d..d1275d6512 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -141,7 +141,7 @@ typedef struct { dict_T *v_dict; ///< Dictionary for VAR_DICT, can be NULL. partial_T *v_partial; ///< Closure: function with args. blob_T *v_blob; ///< Blob for VAR_BLOB, can be NULL. - } vval; ///< Actual value. + } vval; ///< Actual value. } typval_T; /// Values for (struct dictvar_S).dv_scope diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 80a22f6f9d..9478a8441b 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -2141,7 +2141,7 @@ void ex_function(exarg_T *eap) } // find extra arguments "range", "dict", "abort" and "closure" - for (;; ) { + for (;;) { p = skipwhite(p); if (STRNCMP(p, "range", 5) == 0) { flags |= FC_RANGE; @@ -2204,7 +2204,7 @@ void ex_function(exarg_T *eap) indent = 2; nesting = 0; - for (;; ) { + for (;;) { if (KeyTyped) { msg_scroll = true; saved_wait_return = false; diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 66e30bdf2b..77944851d2 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -303,7 +303,7 @@ void ex_align(exarg_T *eap) * Now try to move the line as much as possible to * the right. Stop when it moves too far. */ - do{ + do { (void)set_indent(++new_indent, 0); } while (linelen(NULL) <= width); @@ -774,7 +774,7 @@ void ex_retab(exarg_T *eap) col = 0; vcol = 0; did_undo = false; - for (;; ) { + for (;;) { if (ascii_iswhite(ptr[col])) { if (!got_tab && num_spaces == 0) { // First consecutive white-space @@ -2150,7 +2150,7 @@ static int check_readonly(int *forceit, buf_T *buf) if (buf->b_p_ro) { dialog_msg(buff, - _( "'readonly' option is set for \"%s\".\nDo you wish to write anyway?"), + _("'readonly' option is set for \"%s\".\nDo you wish to write anyway?"), buf->b_fname); } else { dialog_msg(buff, @@ -2944,7 +2944,7 @@ void ex_append(exarg_T *eap) State |= LANGMAP; } - for (;; ) { + for (;;) { msg_scroll = TRUE; need_wait_return = false; if (curbuf->b_p_ai) { @@ -3719,7 +3719,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle * 4. if subflags.do_all is set, find next match * 5. break if there isn't another match in this line */ - for (;; ) { + for (;;) { SubResult current_match = { .start = { 0, 0 }, .end = { 0, 0 }, @@ -5030,9 +5030,9 @@ int find_help_tags(const char_u *arg, int *num_matches, char_u ***matches, bool // When the string starting with "expr-" and containing '?' and matches // the table, it is taken literally (but ~ is escaped). Otherwise '?' // is recognized as a wildcard. - for (i = (int)ARRAY_SIZE(expr_table); --i >= 0; ) { + for (i = (int)ARRAY_SIZE(expr_table); --i >= 0;) { if (STRCMP(arg + 5, expr_table[i]) == 0) { - for (int si = 0, di = 0; ; si++) { + for (int si = 0, di = 0;; si++) { if (arg[si] == '~') { d[di++] = '\\'; } @@ -5047,7 +5047,7 @@ int find_help_tags(const char_u *arg, int *num_matches, char_u ***matches, bool } else { // Recognize a few exceptions to the rule. Some strings that contain // '*' with "star". Otherwise '*' is recognized as a wildcard. - for (i = (int)ARRAY_SIZE(mtable); --i >= 0; ) { + for (i = (int)ARRAY_SIZE(mtable); --i >= 0;) { if (STRCMP(arg, mtable[i]) == 0) { STRCPY(d, rtable[i]); break; diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 787b3f07b2..449e6f7bf5 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -410,7 +410,7 @@ static void script_dump_profile(FILE *fd) } else { // Keep going till the end of file, so that trailing // continuation lines are listed. - for (int i = 0; ; i++) { + for (int i = 0;; i++) { if (vim_fgets(IObuff, IOSIZE, sfd)) { break; } @@ -2505,7 +2505,7 @@ static char_u *get_one_sourceline(struct source_cookie *sp) // Loop until there is a finished line (or end-of-file). sp->sourcing_lnum++; - for (;; ) { + for (;;) { // make room to read at least 120 (more) characters ga_grow(&ga, 120); buf = (char_u *)ga.ga_data; diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h index 6e5dd144ad..ea899b660b 100644 --- a/src/nvim/ex_cmds_defs.h +++ b/src/nvim/ex_cmds_defs.h @@ -135,10 +135,10 @@ typedef struct { // Flags for the cs_lflags item in cstack_T. enum { - CSL_HAD_LOOP = 1, // just found ":while" or ":for" + CSL_HAD_LOOP = 1, // just found ":while" or ":for" CSL_HAD_ENDLOOP = 2, // just found ":endwhile" or ":endfor" - CSL_HAD_CONT = 4, // just found ":continue" - CSL_HAD_FINA = 8, // just found ":finally" + CSL_HAD_CONT = 4, // just found ":continue" + CSL_HAD_FINA = 8, // just found ":finally" }; /// Arguments used for Ex commands. diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index e622a2a68f..62919c98f7 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -432,8 +432,8 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, void *cookie, int flags) if (next_cmdline == NULL && !force_abort && cstack.cs_idx < 0 - && !(getline_is_func && - func_has_abort(real_cookie))) { + && !(getline_is_func + && func_has_abort(real_cookie))) { did_emsg = FALSE; } @@ -2065,7 +2065,7 @@ int parse_command_modifiers(exarg_T *eap, char **errormsg, bool skip_only) eap->save_msg_silent = -1; // Repeat until no more command modifiers are found. - for (;; ) { + for (;;) { while (*eap->cmd == ' ' || *eap->cmd == '\t' || *eap->cmd == ':') { @@ -2715,7 +2715,7 @@ static char_u *find_ucmd(exarg_T *eap, char_u *p, int *full, expand_T *xp, int * * Look for buffer-local user commands first, then global ones. */ gap = &curbuf->b_ucmds; - for (;; ) { + for (;;) { for (j = 0; j < gap->ga_len; ++j) { uc = USER_CMD_GA(gap, j); cp = eap->cmd; @@ -4071,7 +4071,7 @@ static linenr_T get_address(exarg_T *eap, char_u **ptr, cmd_addr_T addr_type, in } } - for (;; ) { + for (;;) { cmd = skipwhite(cmd); if (*cmd != '-' && *cmd != '+' && !ascii_isdigit(*cmd)) { break; @@ -5326,7 +5326,7 @@ static void uc_list(char_u *name, size_t name_len) garray_T *gap = (cmdwin_type != 0 && get_cmdline_type() == NUL) ? &prevwin->w_buffer->b_ucmds : &curbuf->b_ucmds; - for (;; ) { + for (;;) { for (i = 0; i < gap->ga_len; ++i) { cmd = USER_CMD_GA(gap, i); a = cmd->uc_argt; @@ -5713,7 +5713,7 @@ static void ex_delcommand(exarg_T *eap) garray_T *gap; gap = &curbuf->b_ucmds; - for (;; ) { + for (;;) { for (i = 0; i < gap->ga_len; ++i) { cmd = USER_CMD_GA(gap, i); cmp = STRCMP(eap->arg, cmd->uc_name); @@ -6153,12 +6153,12 @@ static void do_ucmd(exarg_T *eap) * Second round: copy result into "buf". */ buf = NULL; - for (;; ) { + for (;;) { p = cmd->uc_rep; // source q = buf; // destination totlen = 0; - for (;; ) { + for (;;) { start = vim_strchr(p, '<'); if (start != NULL) { end = vim_strchr(start + 1, '>'); @@ -6184,7 +6184,7 @@ static void do_ucmd(exarg_T *eap) } } - // break if there no <item> is found + // break if no <item> is found if (start == NULL || end == NULL) { break; } @@ -7753,6 +7753,7 @@ void post_chdir(CdScope scope, bool trigger_dirchanged) abort(); } + last_chdir_reason = NULL; shorten_fnames(true); if (trigger_dirchanged) { @@ -7870,7 +7871,9 @@ static void ex_pwd(exarg_T *eap) #endif if (p_verbose > 0) { char *context = "global"; - if (curwin->w_localdir != NULL) { + if (last_chdir_reason != NULL) { + context = last_chdir_reason; + } else if (curwin->w_localdir != NULL) { context = "window"; } else if (curtab->tp_localdir != NULL) { context = "tabpage"; @@ -8983,8 +8986,8 @@ ssize_t find_cmdline_var(const char_u *src, size_t *usedlen) /// @return an allocated string if a valid match was found. /// Returns NULL if no match was found. "usedlen" then still contains the /// number of characters to skip. -char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnump, - char **errormsg, int *escaped) +char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnump, char **errormsg, + int *escaped) { int i; char_u *s; @@ -9252,7 +9255,7 @@ static char_u *arg_all(void) * first time: compute the total length * second time: concatenate the names */ - for (;; ) { + for (;;) { len = 0; for (idx = 0; idx < ARGCOUNT; ++idx) { p = alist_name(&ARGLIST[idx]); @@ -9315,7 +9318,7 @@ char_u *expand_sfile(char_u *arg) result = vim_strsave(arg); - for (p = result; *p; ) { + for (p = result; *p;) { if (STRNCMP(p, "<sfile>", 7) != 0) { ++p; } else { @@ -9461,7 +9464,7 @@ static void ex_filetype(exarg_T *eap) } // Accept "plugin" and "indent" in any order. - for (;; ) { + for (;;) { if (STRNCMP(arg, "plugin", 6) == 0) { plugin = true; arg = skipwhite(arg + 6); diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c index 348a26d723..f60f0ebe98 100644 --- a/src/nvim/ex_eval.c +++ b/src/nvim/ex_eval.c @@ -1628,7 +1628,7 @@ void ex_endtry(exarg_T *eap) eap->errmsg = get_end_emsg(cstack); // Find the matching ":try" and report what's missing. idx = cstack->cs_idx; - do{ + do { --idx; } while (idx > 0 && !(cstack->cs_flags[idx] & CSF_TRY)); @@ -2091,7 +2091,7 @@ int has_loop_cmd(char_u *p) int len; // skip modifiers, white space and ':' - for (;; ) { + for (;;) { while (*p == ' ' || *p == '\t' || *p == ':') { ++p; } diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 0716b5445d..3b5953ae69 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1665,7 +1665,7 @@ static int may_do_command_line_next_incsearch(int firstc, long count, incsearch_ static void command_line_next_histidx(CommandLineState *s, bool next_match) { int j = (int)STRLEN(s->lookfor); - for (;; ) { + for (;;) { // one step backwards if (!next_match) { if (s->hiscnt == hislen) { @@ -2686,7 +2686,7 @@ static void color_expr_cmdline(const CmdlineInfo *const colored_ccline, viml_parser_destroy(&pstate); kv_resize(ret_ccline_colors->colors, kv_size(colors)); size_t prev_end = 0; - for (size_t i = 0 ; i < kv_size(colors) ; i++) { + for (size_t i = 0; i < kv_size(colors); i++) { const ParserHighlightChunk chunk = kv_A(colors, i); assert(chunk.start.col < INT_MAX); assert(chunk.end_col < INT_MAX); @@ -3466,7 +3466,7 @@ static bool cmdline_paste(int regname, bool literally, bool remcr) int len; // Locate start of last word in the cmd buffer. - for (w = ccline.cmdbuff + ccline.cmdpos; w > ccline.cmdbuff; ) { + for (w = ccline.cmdbuff + ccline.cmdpos; w > ccline.cmdbuff;) { len = utf_head_off(ccline.cmdbuff, w - 1) + 1; if (!vim_iswordc(utf_ptr2char(w - len))) { break; @@ -4386,7 +4386,7 @@ static int showmatches(expand_T *xp, int wildmenu) msg_outtrans_long_attr(p + 2, HL_ATTR(HLF_D)); break; } - for (j = maxlen - lastlen; --j >= 0; ) { + for (j = maxlen - lastlen; --j >= 0;) { msg_putchar(' '); } if (xp->xp_context == EXPAND_FILES @@ -4457,7 +4457,7 @@ char_u *sm_gettail(char_u *s, bool eager) char_u *t = s; int had_sep = FALSE; - for (p = s; *p != NUL; ) { + for (p = s; *p != NUL;) { if (vim_ispathsep(*p) #ifdef BACKSLASH_IN_FILENAME && !rem_backslash(p) @@ -5219,7 +5219,7 @@ static void expand_shellcmd(char_u *filepat, int *num_file, char_u ***file, int ga_init(&ga, (int)sizeof(char *), 10); hashtab_T found_ht; hash_init(&found_ht); - for (s = path; ; s = e) { + for (s = path;; s = e) { e = vim_strchr(s, ENV_SEPCHAR); if (e == NULL) { e = s + STRLEN(s); diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c index 9aa8cc0107..f80a63560c 100644 --- a/src/nvim/ex_session.c +++ b/src/nvim/ex_session.c @@ -345,8 +345,8 @@ static int put_view(FILE *fd, win_T *wp, int add_edit, unsigned *flagp, int curr // Load the file. // if (wp->w_buffer->b_ffname != NULL - && (!bt_nofile(wp->w_buffer) || - wp->w_buffer->terminal)) { + && (!bt_nofile(wp->w_buffer) + || wp->w_buffer->terminal)) { // Editing a file in this buffer: use ":edit file". // This may have side effects! (e.g., compressed or network file). // @@ -431,8 +431,8 @@ static int put_view(FILE *fd, win_T *wp, int add_edit, unsigned *flagp, int curr // if ((*flagp & SSOP_FOLDS) && wp->w_buffer->b_ffname != NULL - && (bt_normal(wp->w_buffer) || - bt_help(wp->w_buffer))) { + && (bt_normal(wp->w_buffer) + || bt_help(wp->w_buffer))) { if (put_folds(fd, wp) == FAIL) { return FAIL; } diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c index 36257fefb3..3a9acbd61c 100644 --- a/src/nvim/file_search.c +++ b/src/nvim/file_search.c @@ -605,9 +605,9 @@ char_u *vim_findfile(void *search_ctx_arg) } // upward search loop - for (;; ) { + for (;;) { // downward search loop - for (;; ) { + for (;;) { // check if user user wants to stop the search os_breakcheck(); if (got_int) { @@ -829,7 +829,7 @@ char_u *vim_findfile(void *search_ctx_arg) } else { suf = curbuf->b_p_sua; } - for (;; ) { + for (;;) { // if file exists and we didn't already find it if ((path_with_url((char *)file_path) || (os_path_exists(file_path) @@ -1500,7 +1500,7 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first /* When the file doesn't exist, try adding parts of * 'suffixesadd'. */ buf = suffixes; - for (;; ) { + for (;;) { if ( (os_path_exists(NameBuff) && (find_what == FINDFILE_BOTH @@ -1530,7 +1530,7 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first did_findfile_init = FALSE; } - for (;; ) { + for (;;) { if (did_findfile_init) { file_name = vim_findfile(fdip_search_ctx); if (file_name != NULL) { diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 321d884d9c..7573064fa9 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -995,7 +995,7 @@ retry: long tlen; tlen = 0; - for (;; ) { + for (;;) { p = ml_get(read_buf_lnum) + read_buf_col; n = (int)STRLEN(p); if ((int)tlen + n + 1 > size) { @@ -3125,7 +3125,7 @@ nobackup: // If conversion is taking place, we may first pretend to write and check // for conversion errors. Then loop again to write for real. // When not doing conversion this writes for real right away. - for (checking_conversion = true; ; checking_conversion = false) { + for (checking_conversion = true;; checking_conversion = false) { // There is no need to check conversion when: // - there is no conversion // - we make a backup file, that can be restored in case of conversion @@ -4265,8 +4265,8 @@ static char_u *check_for_bom(char_u *p, long size, int *lenp, int flags) len = 4; } else if (flags == (FIO_UCS2 | FIO_ENDIAN_L)) { name = "ucs-2le"; // FF FE - } else if (flags == FIO_ALL || - flags == (FIO_UTF16 | FIO_ENDIAN_L)) { + } else if (flags == FIO_ALL + || flags == (FIO_UTF16 | FIO_ENDIAN_L)) { // utf-16le is preferred, it also works for ucs-2le text name = "utf-16le"; // FF FE } @@ -4811,8 +4811,8 @@ int check_timestamps(int focus) } if (!stuff_empty() || global_busy || !typebuf_typed() - || autocmd_busy || curbuf->b_ro_locked > 0 || - allbuf_lock > 0) { + || autocmd_busy || curbuf->b_ro_locked > 0 + || allbuf_lock > 0) { need_check_timestamps = true; // check later } else { no_wait_return++; @@ -5727,7 +5727,7 @@ long read_eintr(int fd, void *buf, size_t bufsize) { long ret; - for (;; ) { + for (;;) { ret = read(fd, buf, bufsize); if (ret >= 0 || errno != EINTR) { break; diff --git a/src/nvim/fold.c b/src/nvim/fold.c index daf0df9326..4a8be7a31b 100644 --- a/src/nvim/fold.c +++ b/src/nvim/fold.c @@ -202,7 +202,7 @@ bool hasFoldingWin(win_T *const win, const linenr_T lnum, linenr_T *const firstp * Recursively search for a fold that contains "lnum". */ garray_T *gap = &win->w_folds; - for (;; ) { + for (;;) { if (!foldFind(gap, lnum_rel, &fp)) { break; } @@ -455,7 +455,7 @@ void foldOpenCursor(void) checkupdate(curwin); if (hasAnyFolding(curwin)) { - for (;; ) { + for (;;) { done = DONE_NOTHING; (void)setManualFold(curwin->w_cursor, true, false, &done); if (!(done & DONE_ACTION)) { @@ -716,7 +716,7 @@ void deleteFold(win_T *const wp, const linenr_T start, const linenr_T end, const garray_T *found_ga = NULL; linenr_T lnum_off = 0; bool use_level = false; - for (;; ) { + for (;;) { if (!foldFind(gap, lnum - lnum_off, &fp)) { break; } @@ -897,7 +897,7 @@ int foldMoveTo(const bool updown, const int dir, const long count) linenr_T lnum_found = curwin->w_cursor.lnum; int level = 0; bool last = false; - for (;; ) { + for (;;) { if (!foldFind(gap, curwin->w_cursor.lnum - lnum_off, &fp)) { if (!updown || gap->ga_len == 0) { break; @@ -1155,7 +1155,7 @@ static int foldLevelWin(win_T *wp, linenr_T lnum) // Recursively search for a fold that contains "lnum". gap = &wp->w_folds; - for (;; ) { + for (;;) { if (!foldFind(gap, lnum_rel, &fp)) { break; } @@ -1265,7 +1265,7 @@ static linenr_T setManualFoldWin(win_T *wp, linenr_T lnum, int opening, int recu * Find the fold, open or close it. */ gap = &wp->w_folds; - for (;; ) { + for (;;) { if (!foldFind(gap, lnum, &fp)) { // If there is a following fold, continue there next time. if (fp != NULL && fp < (fold_T *)gap->ga_data + gap->ga_len) { @@ -1928,7 +1928,7 @@ void foldtext_cleanup(char_u *str) } parseMarker(curwin); - for (s = str; *s != NUL; ) { + for (s = str; *s != NUL;) { size_t len = 0; if (STRNCMP(s, curwin->w_p_fmr, foldstartmarkerlen) == 0) { len = foldstartmarkerlen; @@ -2603,7 +2603,7 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *const gap, const int level, } // delete following folds that end before the current line - for (;; ) { + for (;;) { fp2 = fp + 1; if (fp2 >= (fold_T *)gap->ga_data + gap->ga_len || fp2->fd_top > flp->lnum) { diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 5267b313c7..2f4b59837a 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -1453,7 +1453,7 @@ int vgetc(void) } else { mod_mask = 0x0; last_recorded_len = 0; - for (;; ) { // this is done twice if there are modifiers + for (;;) { // this is done twice if there are modifiers bool did_inc = false; if (mod_mask) { // no mapping after modifier has been read no_mapping++; @@ -1793,7 +1793,7 @@ static int vgetorpeek(bool advance) * If a mapped key sequence is found we go back to the start to * try re-mapping. */ - for (;; ) { + for (;;) { /* * os_breakcheck() is slow, don't use it too often when * inside a mapping. But call it each time for typed @@ -1861,8 +1861,8 @@ static int vgetorpeek(bool advance) && State != CONFIRM && !((ctrl_x_mode_not_default() && vim_is_ctrl_x_key(c1)) || ((compl_cont_status & CONT_LOCAL) - && (c1 == Ctrl_N || - c1 == Ctrl_P)))) { + && (c1 == Ctrl_N + || c1 == Ctrl_P)))) { if (c1 == K_SPECIAL) { nolmaplen = 2; } else { @@ -1951,7 +1951,7 @@ static int vgetorpeek(bool advance) * If one of the typed keys cannot be * remapped, skip the entry. */ - for (n = mlen; --n >= 0; ) { + for (n = mlen; --n >= 0;) { if (*s++ & (RM_NONE|RM_ABBR)) { break; } @@ -2550,7 +2550,7 @@ int inchar(char_u *buf, int maxlen, long wait_time) #define DUM_LEN MAXMAPLEN * 3 + 3 char_u dum[DUM_LEN + 1]; - for (;; ) { + for (;;) { len = os_inchar(dum, DUM_LEN, 0L, 0, NULL); if (len == 0 || (len == 1 && dum[0] == 3)) { break; @@ -3599,7 +3599,7 @@ char_u *set_context_in_map_cmd(expand_T *xp, char_u *cmd, char_u *arg, bool forc expand_isabbrev = isabbrev; xp->xp_context = EXPAND_MAPPINGS; expand_buffer = false; - for (;; ) { + for (;;) { if (STRNCMP(arg, "<buffer>", 8) == 0) { expand_buffer = true; arg = skipwhite(arg + 8); @@ -3987,7 +3987,7 @@ char_u *vim_strsave_escape_csi(char_u *p) // 0xc0 -> 0xc3 - 0x80 -> 0xc3 K_SPECIAL KS_SPECIAL KE_FILLER char_u *res = xmalloc(STRLEN(p) * 4 + 1); char_u *d = res; - for (char_u *s = p; *s != NUL; ) { + for (char_u *s = p; *s != NUL;) { if (s[0] == K_SPECIAL && s[1] != NUL && s[2] != NUL) { // Copy special key unmodified. *d++ = *s++; diff --git a/src/nvim/globals.h b/src/nvim/globals.h index e2d3378402..b5e1fda9f1 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -789,6 +789,8 @@ extern char_u *compiled_sys; // directory is not a local directory, globaldir is NULL. EXTERN char_u *globaldir INIT(= NULL); +EXTERN char *last_chdir_reason INIT(= NULL); + // Whether 'keymodel' contains "stopsel" and "startsel". EXTERN bool km_stopsel INIT(= false); EXTERN bool km_startsel INIT(= false); @@ -842,6 +844,7 @@ EXTERN disptick_T display_tick INIT(= 0); // cursor position in Insert mode. EXTERN linenr_T spell_redraw_lnum INIT(= 0); +// uncrustify:off // The error messages that can be shared are included here. // Excluded are errors that are only used once and debugging messages. @@ -850,12 +853,8 @@ EXTERN char e_afterinit[] INIT(= N_("E905: Cannot set this option after startup" EXTERN char e_api_spawn_failed[] INIT(= N_("E903: Could not spawn API job")); EXTERN char e_argreq[] INIT(= N_("E471: Argument required")); EXTERN char e_backslash[] INIT(= N_("E10: \\ should be followed by /, ? or &")); -EXTERN char e_cmdwin[] INIT(= - N_( - "E11: Invalid in command-line window; <CR> executes, CTRL-C quits")); -EXTERN char e_curdir[] INIT(= - N_( - "E12: Command not allowed from exrc/vimrc in current dir or tag search")); +EXTERN char e_cmdwin[] INIT(= N_("E11: Invalid in command-line window; <CR> executes, CTRL-C quits")); +EXTERN char e_curdir[] INIT(= N_( "E12: Command not allowed from exrc/vimrc in current dir or tag search")); EXTERN char e_endif[] INIT(= N_("E171: Missing :endif")); EXTERN char e_endtry[] INIT(= N_("E600: Missing :endtry")); EXTERN char e_endwhile[] INIT(= N_("E170: Missing :endwhile")); @@ -885,10 +884,7 @@ EXTERN char e_channotpty[] INIT(= N_("E904: channel is not a pty")); EXTERN char e_stdiochan2[] INIT(= N_("E905: Couldn't open stdio channel: %s")); EXTERN char e_invstream[] INIT(= N_("E906: invalid stream for channel")); EXTERN char e_invstreamrpc[] INIT(= N_("E906: invalid stream for rpc channel, use 'rpc'")); -EXTERN char e_streamkey[] INIT(= - N_( - "E5210: dict key '%s' already set for buffered stream in channel %" - PRIu64)); +EXTERN char e_streamkey[] INIT(= N_("E5210: dict key '%s' already set for buffered stream in channel %" PRIu64)); EXTERN char e_libcall[] INIT(= N_("E364: Library call failed for \"%s()\"")); EXTERN char e_fsync[] INIT(= N_("E667: Fsync failed: %s")); EXTERN char e_mkdir[] INIT(= N_("E739: Cannot create directory %s: %s")); @@ -939,9 +935,7 @@ EXTERN char e_dictkey[] INIT(= N_("E716: Key not present in Dictionary: \"%s\"") EXTERN char e_listreq[] INIT(= N_("E714: List required")); EXTERN char e_listblobreq[] INIT(= N_("E897: List or Blob required")); EXTERN char e_listdictarg[] INIT(= N_("E712: Argument of %s must be a List or Dictionary")); -EXTERN char e_listdictblobarg[] INIT(= - N_( - "E896: Argument of %s must be a List, Dictionary or Blob")); +EXTERN char e_listdictblobarg[] INIT(= N_("E896: Argument of %s must be a List, Dictionary or Blob")); EXTERN char e_readerrf[] INIT(= N_("E47: Error while reading errorfile")); EXTERN char e_sandbox[] INIT(= N_("E48: Not allowed in sandbox")); EXTERN char e_secure[] INIT(= N_("E523: Not allowed here")); @@ -980,25 +974,21 @@ EXTERN char e_unsupportedoption[] INIT(= N_("E519: Option not supported")); EXTERN char e_fnametoolong[] INIT(= N_("E856: Filename too long")); EXTERN char e_float_as_string[] INIT(= N_("E806: using Float as a String")); -EXTERN char e_autocmd_err[] INIT(=N_("E5500: autocmd has thrown an exception: %s")); -EXTERN char e_cmdmap_err[] INIT(=N_("E5520: <Cmd> mapping must end with <CR>")); -EXTERN char -e_cmdmap_repeated[] INIT(=N_("E5521: <Cmd> mapping must end with <CR> before second <Cmd>")); -EXTERN char e_cmdmap_key[] INIT(=N_("E5522: <Cmd> mapping must not include %s key")); +EXTERN char e_autocmd_err[] INIT(= N_("E5500: autocmd has thrown an exception: %s")); +EXTERN char e_cmdmap_err[] INIT(= N_("E5520: <Cmd> mapping must end with <CR>")); +EXTERN char e_cmdmap_repeated[] INIT(= N_("E5521: <Cmd> mapping must end with <CR> before second <Cmd>")); +EXTERN char e_cmdmap_key[] INIT(= N_("E5522: <Cmd> mapping must not include %s key")); -EXTERN char e_api_error[] INIT(=N_("E5555: API call: %s")); +EXTERN char e_api_error[] INIT(= N_("E5555: API call: %s")); -EXTERN char e_luv_api_disabled[] INIT(=N_("E5560: %s must not be called in a lua loop callback")); +EXTERN char e_luv_api_disabled[] INIT(= N_("E5560: %s must not be called in a lua loop callback")); -EXTERN char e_floatonly[] INIT(=N_( - "E5601: Cannot close window, only floating window would remain")); -EXTERN char e_floatexchange[] INIT(=N_("E5602: Cannot exchange or rotate float")); +EXTERN char e_floatonly[] INIT(= N_("E5601: Cannot close window, only floating window would remain")); +EXTERN char e_floatexchange[] INIT(= N_("E5602: Cannot exchange or rotate float")); EXTERN char e_non_empty_string_required[] INIT(= N_("E1142: Non-empty string required")); -EXTERN char e_cannot_define_autocommands_for_all_events[] INIT(= - N_( - "E1155: Cannot define autocommands for ALL events")); +EXTERN char e_cannot_define_autocommands_for_all_events[] INIT(= N_("E1155: Cannot define autocommands for ALL events")); EXTERN char top_bot_msg[] INIT(= N_("search hit TOP, continuing at BOTTOM")); EXTERN char bot_top_msg[] INIT(= N_("search hit BOTTOM, continuing at TOP")); @@ -1020,6 +1010,8 @@ EXTERN bool embedded_mode INIT(= false); // Do not start a UI nor read/write to stdio (unless embedding). EXTERN bool headless_mode INIT(= false); +// uncrustify:on + /// Used to track the status of external functions. /// Currently only used for iconv(). typedef enum { diff --git a/src/nvim/hardcopy.c b/src/nvim/hardcopy.c index ab3f63c93e..93fcdc55a6 100644 --- a/src/nvim/hardcopy.c +++ b/src/nvim/hardcopy.c @@ -571,7 +571,7 @@ static void prt_header(prt_settings_T *const psettings, const int pagenum, const // Use a negative line number to indicate printing in the top margin. int page_line = 0 - prt_header_height(); mch_print_start_line(true, page_line); - for (char_u *p = tbuf; *p != NUL; ) { + for (char_u *p = tbuf; *p != NUL;) { const int l = utfc_ptr2len(p); assert(l >= 0); if (mch_print_text_out(p, (size_t)l)) { @@ -986,8 +986,7 @@ static colnr_T hardcopy_line(prt_settings_T *psettings, int page_line, prt_pos_T #define PRT_PS_DEFAULT_DPI (72) // Default user space resolution #define PRT_PS_DEFAULT_FONTSIZE (10) -#define PRT_MEDIASIZE_LEN (sizeof(prt_mediasize) / \ - sizeof(struct prt_mediasize_S)) +#define PRT_MEDIASIZE_LEN ARRAY_SIZE(prt_mediasize) static struct prt_mediasize_S prt_mediasize[] = { @@ -2455,7 +2454,7 @@ static int prt_add_resource(struct prt_ps_resource_S *resource) prt_dsc_textline("BeginDocument", (char *)resource->filename); - for (;; ) { + for (;;) { bytes_read = fread((char *)resource_buffer, sizeof(char_u), sizeof(resource_buffer), fd_resource); if (ferror(fd_resource)) { diff --git a/src/nvim/if_cscope.c b/src/nvim/if_cscope.c index 2c44ce380d..6f02ebfb48 100644 --- a/src/nvim/if_cscope.c +++ b/src/nvim/if_cscope.c @@ -557,7 +557,7 @@ static int cs_cnt_matches(size_t idx) int nlines = 0; char *buf = xmalloc(CSREAD_BUFSIZE); - for (;; ) { + for (;;) { errno = 0; if (!fgets(buf, CSREAD_BUFSIZE, csinfo[idx].fr_fp)) { if (errno == EINTR) { @@ -966,7 +966,7 @@ static int cs_find_common(char *opt, char *pat, int forceit, int verbose, int us qfpos++; // next symbol must be + or - if (strchr(CSQF_FLAGS, *qfpos) == NULL) { - (void)semsg(_("E469: invalid cscopequickfix flag %c for %c"), *qfpos, *(qfpos - 1));; + (void)semsg(_("E469: invalid cscopequickfix flag %c for %c"), *qfpos, *(qfpos - 1)); return FALSE; } diff --git a/src/nvim/lib/kbtree.h b/src/nvim/lib/kbtree.h index 5d9c1095bc..617773a79a 100644 --- a/src/nvim/lib/kbtree.h +++ b/src/nvim/lib/kbtree.h @@ -53,7 +53,7 @@ bool is_internal; \ key_t key[2*T-1]; \ kbnode_##name##_t *ptr[]; \ - } ; \ + }; \ typedef struct { \ kbnode_##name##_t *root; \ int n_keys, n_nodes; \ diff --git a/src/nvim/lib/khash.h b/src/nvim/lib/khash.h index e0faf94db9..8cfeb03cc4 100644 --- a/src/nvim/lib/khash.h +++ b/src/nvim/lib/khash.h @@ -459,7 +459,7 @@ 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; } + for (++s; *s; ++s) { h = (h << 5) - h + (uint8_t)*s; } } return h; } diff --git a/src/nvim/lua/xdiff.c b/src/nvim/lua/xdiff.c index 7eda9b6270..b2e971f9f3 100644 --- a/src/nvim/lua/xdiff.c +++ b/src/nvim/lua/xdiff.c @@ -17,7 +17,7 @@ #include "xdiff/xdiff.h" typedef enum { - kNluaXdiffModeUnified = 0, + kNluaXdiffModeUnified = 0, kNluaXdiffModeOnHunkCB, kNluaXdiffModeLocations, } NluaXdiffMode; diff --git a/src/nvim/mark.c b/src/nvim/mark.c index 51f4ba635f..39f18b333d 100644 --- a/src/nvim/mark.c +++ b/src/nvim/mark.c @@ -235,7 +235,7 @@ pos_T *movemark(int count) return (pos_T *)NULL; } - for (;; ) { + for (;;) { if (curwin->w_jumplistidx + count < 0 || curwin->w_jumplistidx + count >= curwin->w_jumplistlen) { return (pos_T *)NULL; diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index 12460646ed..42117bc762 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -764,7 +764,7 @@ int utfc_ptr2char(const char_u *p, int *pcc) && p[len] >= 0x80 && utf_composinglike(p, p + len)) { cc = utf_ptr2char(p + len); - for (;; ) { + for (;;) { pcc[i++] = cc; if (i == MAX_MCO) { break; @@ -1322,7 +1322,7 @@ static int utf_strnicmp(const char_u *s1, const char_u *s2, size_t n1, size_t n2 int c1, c2, cdiff; char_u buffer[6]; - for (;; ) { + for (;;) { c1 = utf_safe_read_char_adv(&s1, &n1); c2 = utf_safe_read_char_adv(&s2, &n2); @@ -1933,7 +1933,7 @@ void utf_find_illegal(void) } curwin->w_cursor.coladd = 0; - for (;; ) { + for (;;) { p = get_cursor_pos_ptr(); if (vimconv.vc_type != CONV_NONE) { xfree(tofree); @@ -2363,7 +2363,7 @@ static char_u *iconv_string(const vimconv_T *const vcp, char_u *str, size_t slen from = (char *)str; fromlen = slen; - for (;; ) { + for (;;) { if (len == 0 || ICONV_ERRNO == ICONV_E2BIG) { // Allocate enough room for most conversions. When re-allocating // increase the buffer size. diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c index 2a0ea9a269..3397296b3a 100644 --- a/src/nvim/memfile.c +++ b/src/nvim/memfile.c @@ -505,7 +505,7 @@ bool mf_release_all(void) // Flush as many blocks as possible, only if there is a swapfile. if (mfp->mf_fd >= 0) { - for (bhdr_T *hp = mfp->mf_used_last; hp != NULL; ) { + for (bhdr_T *hp = mfp->mf_used_last; hp != NULL;) { if (!(hp->bh_flags & BH_LOCKED) && (!(hp->bh_flags & BH_DIRTY) || mf_write(mfp, hp) != FAIL)) { diff --git a/src/nvim/memline.c b/src/nvim/memline.c index edab367f02..08202a6d5c 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -407,7 +407,7 @@ void ml_setname(buf_T *buf) */ dirp = p_dir; bool found_existing_dir = false; - for (;; ) { + for (;;) { if (*dirp == NUL) { // tried all directories, fail break; } @@ -504,7 +504,7 @@ void ml_open_file(buf_T *buf) */ dirp = p_dir; bool found_existing_dir = false; - for (;; ) { + for (;;) { if (*dirp == NUL) { break; } @@ -1236,7 +1236,7 @@ void ml_recover(bool checkext) } else if (error) { ++no_wait_return; msg(">>>>>>>>>>>>>"); - emsg(_( "E312: Errors detected while recovering; look for lines starting with ???")); + emsg(_("E312: Errors detected while recovering; look for lines starting with ???")); --no_wait_return; msg(_("See \":help E312\" for more information.")); msg(">>>>>>>>>>>>>"); @@ -2349,7 +2349,7 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b * move some of the pointer into the new block * prepare for updating the parent block */ - for (;; ) { // do this twice when splitting block 1 + for (;;) { // do this twice when splitting block 1 hp_new = ml_new_ptr(mfp); if (hp_new == NULL) { // TODO: try to fix tree return FAIL; @@ -2733,7 +2733,7 @@ linenr_T ml_firstmarked(void) * The search starts with lowest_marked line. This is the last line where * a mark was found, adjusted by inserting/deleting lines. */ - for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count; ) { + for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count;) { /* * Find the data block containing the line. * This also fills the stack with the blocks from the root to the data @@ -2775,7 +2775,7 @@ void ml_clearmarked(void) /* * The search starts with line lowest_marked. */ - for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count; ) { + for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count;) { /* * Find the data block containing the line. * This also fills the stack with the blocks from the root to the data @@ -3034,7 +3034,7 @@ static bhdr_T *ml_find_line(buf_T *buf, linenr_T lnum, int action) /* * search downwards in the tree until a data block is found */ - for (;; ) { + for (;;) { if ((hp = mf_get(mfp, bnum, page_count)) == NULL) { goto error_noblock; } @@ -3211,7 +3211,7 @@ int resolve_symlink(const char_u *fname, char_u *buf) // Put the result so far in tmp[], starting with the original name. STRLCPY(tmp, fname, MAXPATHL); - for (;; ) { + for (;;) { // Limit symlink depth to 100, catch recursive loops. if (++depth == 100) { semsg(_("E773: Symlink loop for \"%s\""), fname); @@ -3481,7 +3481,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_ fname = (char *)makeswapname((char_u *)buf_fname, buf->b_ffname, buf, (char_u *)dir_name); - for (;; ) { + for (;;) { if (fname == NULL) { // must be out of memory break; } diff --git a/src/nvim/memory.c b/src/nvim/memory.c index 547a9015b7..559a3cc435 100644 --- a/src/nvim/memory.c +++ b/src/nvim/memory.c @@ -573,7 +573,6 @@ void free_all_mem(void) return; } entered_free_all_mem = true; - // Don't want to trigger autocommands from here on. block_autocmds(); @@ -672,7 +671,7 @@ void free_all_mem(void) first_tabpage = NULL; // message history - for (;; ) { + for (;;) { if (delete_first_msg() == FAIL) { break; } @@ -687,7 +686,7 @@ void free_all_mem(void) // Must be after eval_clear to avoid it trying to access b:changedtick after // freeing it. p_acd = false; - for (buf = firstbuf; buf != NULL; ) { + for (buf = firstbuf; buf != NULL;) { bufref_T bufref; set_bufref(&bufref, buf); nextbuf = buf->b_next; diff --git a/src/nvim/menu.c b/src/nvim/menu.c index c2b6a5e402..d596b31062 100644 --- a/src/nvim/menu.c +++ b/src/nvim/menu.c @@ -80,7 +80,7 @@ void ex_menu(exarg_T *eap) modes = get_menu_cmd_modes((char *)eap->cmd, eap->forceit, &noremap, &unmenu); arg = eap->arg; - for (;; ) { + for (;;) { if (STRNCMP(arg, "<script>", 8) == 0) { noremap = REMAP_SCRIPT; arg = skipwhite(arg + 8); @@ -449,7 +449,7 @@ static int add_menu_path(const char_u *const menu_path, vimmenu_T *menuarg, } if (c != 0) { - menu->strings[i] = xmalloc(STRLEN(call_data) + 5 ); + menu->strings[i] = xmalloc(STRLEN(call_data) + 5); menu->strings[i][0] = c; if (d == 0) { STRCPY(menu->strings[i] + 1, call_data); @@ -1315,7 +1315,7 @@ static char_u *menu_text(const char_u *str, int *mnemonic, char_u **actext) } // Find mnemonic characters "&a" and reduce "&&" to "&". - for (p = text; p != NULL; ) { + for (p = text; p != NULL;) { p = vim_strchr(p, '&'); if (p != NULL) { if (p[1] == NUL) { // trailing "&" diff --git a/src/nvim/message.c b/src/nvim/message.c index 8223e6c188..6fcd4cef8a 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -401,7 +401,7 @@ void trunc_string(char_u *s, char_u *buf, int room_in, int buflen) } len += n; buf[e] = s[e]; - for (n = utfc_ptr2len(s + e); --n > 0; ) { + for (n = utfc_ptr2len(s + e); --n > 0;) { if (++e == buflen) { break; } @@ -883,7 +883,7 @@ char_u *msg_may_trunc(int force, char_u *s) return s; } int n; - for (n = 0; size >= room; ) { + for (n = 0; size >= room;) { size -= utf_ptr2cells(s + n); n += utfc_ptr2len(s + n); } @@ -2549,7 +2549,7 @@ static msgchunk_T *disp_sb_line(int row, msgchunk_T *smp) msgchunk_T *mp = smp; char_u *p; - for (;; ) { + for (;;) { msg_row = row; msg_col = mp->sb_msg_col; p = mp->sb_text; @@ -2688,7 +2688,7 @@ static int do_more_prompt(int typed_char) if (typed_char == NUL) { msg_moremsg(FALSE); } - for (;; ) { + for (;;) { /* * Get a typed character directly from the user. */ @@ -3436,7 +3436,7 @@ int do_dialog(int type, char_u *title, char_u *message, char_u *buttons, int dfl ++no_wait_return; hotkeys = msg_show_console_dialog(message, buttons, dfltbutton); - for (;; ) { + for (;;) { // Get a typed character directly from the user. c = get_keystroke(NULL); switch (c) { diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c index 5ecd4ca431..fd5d154cea 100644 --- a/src/nvim/misc1.c +++ b/src/nvim/misc1.c @@ -99,7 +99,7 @@ int get_leader_len(char_u *line, char_u **flags, bool backward, bool include_spa * scan through the 'comments' option for a match */ found_one = FALSE; - for (list = curbuf->b_p_com; *list; ) { + for (list = curbuf->b_p_com; *list;) { // Get one option part into part_buf[]. Advance "list" to next // one. Put "string" at start of string. if (!got_com && flags != NULL) { @@ -244,7 +244,7 @@ int get_last_leader_offset(char_u *line, char_u **flags) * scan through the 'comments' option for a match */ found_one = FALSE; - for (list = curbuf->b_p_com; *list; ) { + for (list = curbuf->b_p_com; *list;) { char_u *flags_save = list; /* @@ -340,7 +340,7 @@ int get_last_leader_offset(char_u *line, char_u **flags) } len1 = (int)STRLEN(com_leader); - for (list = curbuf->b_p_com; *list; ) { + for (list = curbuf->b_p_com; *list;) { char_u *flags_save = list; (void)copy_option_part(&list, part_buf2, COM_MAX_LEN, ","); @@ -359,7 +359,7 @@ int get_last_leader_offset(char_u *line, char_u **flags) // Now we have to verify whether string ends with a substring // beginning the com_leader. - for (off = (len2 > i ? i : len2); off > 0 && off + len1 > len2; ) { + for (off = (len2 > i ? i : len2); off > 0 && off + len1 > len2;) { --off; if (!STRNCMP(string + off, com_leader, len2 - off)) { if (i - off < lower_check_bound) { @@ -492,7 +492,7 @@ int get_keystroke(MultiQueue *events) int waited = 0; mapped_ctrl_c = 0; // mappings are not used here - for (;; ) { + for (;;) { // flush output before waiting ui_flush(); // Leave some room for check_termcode() to insert a key code into (max @@ -580,7 +580,7 @@ int get_number(int colon, int *mouse_used) } no_mapping++; - for (;; ) { + for (;;) { ui_cursor_goto(msg_row, msg_col); c = safe_vgetc(); if (ascii_isdigit(c)) { diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index f02c000e82..386094e509 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -245,7 +245,7 @@ retnomove: // Scroll by however many rows outside the window we are. if (row < 0) { count = 0; - for (first = true; curwin->w_topline > 1; ) { + for (first = true; curwin->w_topline > 1;) { if (curwin->w_topfill < win_get_fill(curwin, curwin->w_topline)) { count++; } else { @@ -270,7 +270,7 @@ retnomove: row = 0; } else if (row >= curwin->w_height_inner) { count = 0; - for (first = true; curwin->w_topline < curbuf->b_ml.ml_line_count; ) { + for (first = true; curwin->w_topline < curbuf->b_ml.ml_line_count;) { if (curwin->w_topfill > 0) { ++count; } else { @@ -448,7 +448,7 @@ win_T *mouse_find_win(int *gridp, int *rowp, int *colp) fp = topframe; *rowp -= firstwin->w_winrow; - for (;; ) { + for (;;) { if (fp->fr_layout == FR_LEAF) { break; } diff --git a/src/nvim/move.c b/src/nvim/move.c index 5114cd6d8a..d80e63e79d 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -382,8 +382,8 @@ static bool check_top_offset(void) topline_back(curwin, &loff); // Stop when included a line above the window. if (loff.lnum < curwin->w_topline - || (loff.lnum == curwin->w_topline && - loff.fill > 0)) { + || (loff.lnum == curwin->w_topline + && loff.fill > 0)) { break; } n += loff.height; @@ -1661,7 +1661,7 @@ void scroll_cursor_bot(int min_scroll, int set_topbot) boff.fill = curwin->w_topfill; boff.lnum = curwin->w_topline - 1; int i; - for (i = 0; i < scrolled && boff.lnum < curwin->w_botline; ) { + for (i = 0; i < scrolled && boff.lnum < curwin->w_botline;) { botline_forw(curwin, &boff); i += boff.height; ++line_count; diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 1effeefd32..03312e5df4 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -570,8 +570,8 @@ static bool normal_need_additional_char(NormalState *s) // // TODO(tarruda): Visual state needs to be refactored into a // separate state that "inherits" from normal state. - || ((cmdchar == 'a' || cmdchar == 'i') && - (pending_op || VIsual_active))); + || ((cmdchar == 'a' || cmdchar == 'i') + && (pending_op || VIsual_active))); } static bool normal_need_redraw_mode_message(NormalState *s) @@ -2283,7 +2283,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent) save_cursor = curwin->w_cursor; - for (;; ) { + for (;;) { which_button = get_mouse_button(KEY2TERMCAP1(c), &is_click, &is_drag); if (is_drag) { /* If the next character is the same mouse event then use that @@ -3928,7 +3928,7 @@ bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_ // Search forward for the identifier, ignore comment lines. clearpos(&found_pos); - for (;; ) { + for (;;) { t = searchit(curwin, curbuf, &curwin->w_cursor, NULL, FORWARD, pat, 1L, searchflags, RE_LAST, NULL); if (curwin->w_cursor.lnum >= old_pos.lnum) { @@ -4307,7 +4307,7 @@ static void nv_zet(cmdarg_T *cap) return; } n = nchar - '0'; - for (;; ) { + for (;;) { no_mapping++; nchar = plain_vgetc(); LANGMAP_ADJUST(nchar, true); @@ -5341,8 +5341,8 @@ static void nv_right(cmdarg_T *cap) for (n = cap->count1; n > 0; --n) { if ((!PAST_LINE && oneright() == false) - || (PAST_LINE && - *get_cursor_pos_ptr() == NUL)) { + || (PAST_LINE + && *get_cursor_pos_ptr() == NUL)) { // <Space> wraps to next line if 'whichwrap' has 's'. // 'l' wraps to next line if 'whichwrap' has 'l'. // CURS_RIGHT wraps to next line if 'whichwrap' has '>'. @@ -5838,7 +5838,7 @@ static void nv_brackets(cmdarg_T *cap) pos = NULL; } while (n > 0) { - for (;; ) { + for (;;) { if ((findc == '{' ? dec_cursor() : inc_cursor()) < 0) { // if not found anything, that's an error if (pos == NULL) { @@ -7688,8 +7688,8 @@ static void adjust_cursor(oparg_T *oap) // - 'virtualedit' is not "all" and not "onemore". if (curwin->w_cursor.col > 0 && gchar_cursor() == NUL && (!VIsual_active || *p_sel == 'o') - && !virtual_active() && - (ve_flags & VE_ONEMORE) == 0) { + && !virtual_active() + && (ve_flags & VE_ONEMORE) == 0) { curwin->w_cursor.col--; // prevent cursor from moving on the trail byte mb_adjust_cursor(); diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 7d7db2a8a6..b4b9545daf 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -378,7 +378,7 @@ static void shift_block(oparg_T *oap, int amount) bd.startspaces = 0; } } - for (; ascii_iswhite(*bd.textstart); ) { + for (; ascii_iswhite(*bd.textstart);) { // TODO: is passing bd.textstart for start of the line OK? incr = lbr_chartabsize_adv(bd.textstart, &bd.textstart, (bd.start_vcol)); total += incr; @@ -2037,7 +2037,7 @@ void op_tilde(oparg_T *oap) did_change = swapchars(oap->op_type, &pos, oap->end.col - pos.col + 1); } else { - for (;; ) { + for (;;) { did_change |= swapchars(oap->op_type, &pos, pos.lnum == oap->end.lnum ? oap->end.col + 1 : (int)STRLEN(ml_get_pos(&pos))); @@ -2987,7 +2987,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) /* For the = register we need to split the string at NL * characters. * Loop twice: count the number of lines and save them. */ - for (;; ) { + for (;;) { y_size = 0; ptr = insert_string; while (ptr != NULL) { @@ -3204,7 +3204,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) // get the old line and advance to the position to insert at oldp = get_cursor_line_ptr(); oldlen = STRLEN(oldp); - for (ptr = oldp; vcol < col && *ptr; ) { + for (ptr = oldp; vcol < col && *ptr;) { // Count a tab for what it's worth (if list mode not on) incr = lbr_chartabsize_adv(oldp, &ptr, vcol); vcol += incr; @@ -3936,8 +3936,8 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions || (utf_ptr2char(curr) < 0x100 && endcurr1 < 0x100)) && (!has_format_option(FO_MBYTE_JOIN2) || (utf_ptr2char(curr) < 0x100 && !utf_eat_space(endcurr1)) - || (endcurr1 < 0x100 && - !utf_eat_space(utf_ptr2char(curr))))) { + || (endcurr1 < 0x100 + && !utf_eat_space(utf_ptr2char(curr))))) { // don't add a space if the line is ending in a space if (endcurr1 == ' ') { endcurr1 = endcurr2; @@ -5631,7 +5631,7 @@ static varnumber_T line_count_info(char_u *line, varnumber_T *wc, varnumber_T *c varnumber_T chars = 0; int is_word = 0; - for (i = 0; i < limit && line[i] != NUL; ) { + for (i = 0; i < limit && line[i] != NUL;) { if (is_word) { if (ascii_isspace(line[i])) { words++; diff --git a/src/nvim/option.c b/src/nvim/option.c index 278cf7c608..45e2032b35 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1233,7 +1233,7 @@ int do_set(char_u *arg, int opt_flags) } errmsg = set_bool_option(opt_idx, varp, (int)value, - opt_flags); + opt_flags); } else { // Numeric or string. if (vim_strchr((const char_u *)"=:&<", nextchar) == NULL || prefix != 1) { @@ -2315,8 +2315,8 @@ static bool valid_spellfile(const char_u *val) /// @param opt_flags OPT_LOCAL and/or OPT_GLOBAL /// @param value_checked value was checked to be safe, no need to set P_INSECURE static char *did_set_string_option(int opt_idx, char_u **varp, bool new_value_alloced, - char_u *oldval, char *errbuf, size_t errbuflen, - int opt_flags, int *value_checked) + char_u *oldval, char *errbuf, size_t errbuflen, int opt_flags, + int *value_checked) { char *errmsg = NULL; char_u *s, *p; @@ -2625,7 +2625,7 @@ ambw_end: } } } else if (gvarp == &p_com) { // 'comments' - for (s = *varp; *s; ) { + for (s = *varp; *s;) { while (*s && *s != ':') { if (vim_strchr((char_u *)COM_ALL, *s) == NULL && !ascii_isdigit(*s) && *s != '-') { @@ -2704,7 +2704,7 @@ ambw_end: // 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 = (options[opt_idx].flags & P_ALLOCED); - for (s = p_shada; *s; ) { + for (s = p_shada; *s;) { // Check it's a valid character if (vim_strchr((char_u *)"!\"%'/:<@cfhnrs", *s) == NULL) { errmsg = illegal_char(errbuf, errbuflen, *s); @@ -2749,7 +2749,7 @@ ambw_end: errmsg = N_("E528: Must specify a ' value"); } } else if (gvarp == &p_sbr) { // 'showbreak' - for (s = *varp; *s; ) { + for (s = *varp; *s;) { if (ptr2cells(s) != 1) { errmsg = N_("E595: 'showbreak' contains unprintable or wide character"); } @@ -2893,7 +2893,7 @@ ambw_end: } } else if (gvarp == &p_cpt) { // check if it is a valid value for 'complete' -- Acevedo - for (s = *varp; *s; ) { + for (s = *varp; *s;) { while (*s == ',' || *s == ' ') { s++; } @@ -3369,7 +3369,7 @@ char *check_colorcolumn(win_T *wp) return NULL; // buffer was closed } - for (s = wp->w_p_cc; *s != NUL && count < 255; ) { + for (s = wp->w_p_cc; *s != NUL && count < 255;) { if (*s == '-' || *s == '+') { // -N and +N: add to 'textwidth' col = (*s == '-') ? -1 : 1; @@ -3436,6 +3436,37 @@ void check_blending(win_T *wp) wp->w_p_winbl > 0 || (wp->w_floating && wp->w_float_config.shadow); } +/// Calls mb_cptr2char_adv(p) and returns the character. +/// If "p" starts with "\x", "\u" or "\U" the hex or unicode value is used. +/// Returns 0 for invalid hex or invalid UTF-8 byte. +static int get_encoded_char_adv(char_u **p) +{ + char_u *s = *p; + + if (s[0] == '\\' && (s[1] == 'x' || s[1] == 'u' || s[1] == 'U')) { + int64_t num = 0; + int bytes; + int n; + for (bytes = s[1] == 'x' ? 1 : s[1] == 'u' ? 2 : 4; bytes > 0; bytes--) { + *p += 2; + n = hexhex2nr(*p); + if (n < 0) { + return 0; + } + num = num * 256 + n; + } + *p += 2; + return (int)num; + } + + // TODO(bfredl): use schar_T representation and utfc_ptr2len + int clen = utf_ptr2len(s); + int c = mb_cptr2char_adv((const char_u **)p); + if (clen == 1 && c > 127) { // Invalid UTF-8 byte + return 0; + } + return c; +} /// Handle setting 'listchars' or 'fillchars'. /// Assume monocell characters @@ -3540,26 +3571,21 @@ static char *set_chars_option(win_T *wp, char_u **varp, bool set) && p[len + 1] != NUL) { c2 = c3 = 0; s = p + len + 1; - - // TODO(bfredl): use schar_T representation and utfc_ptr2len - int c1len = utf_ptr2len(s); - c1 = mb_cptr2char_adv((const char_u **)&s); - if (utf_char2cells(c1) > 1 || (c1len == 1 && c1 > 127)) { + c1 = get_encoded_char_adv(&s); + if (c1 == 0 || utf_char2cells(c1) > 1) { return e_invarg; } if (tab[i].cp == &wp->w_p_lcs_chars.tab2) { if (*s == NUL) { return e_invarg; } - int c2len = utf_ptr2len(s); - c2 = mb_cptr2char_adv((const char_u **)&s); - if (utf_char2cells(c2) > 1 || (c2len == 1 && c2 > 127)) { + c2 = get_encoded_char_adv(&s); + if (c2 == 0 || utf_char2cells(c2) > 1) { return e_invarg; } if (!(*s == ',' || *s == NUL)) { - int c3len = utf_ptr2len(s); - c3 = mb_cptr2char_adv((const char_u **)&s); - if (utf_char2cells(c3) > 1 || (c3len == 1 && c3 > 127)) { + c3 = get_encoded_char_adv(&s); + if (c3 == 0 || utf_char2cells(c3) > 1) { return e_invarg; } } @@ -3592,9 +3618,8 @@ static char *set_chars_option(win_T *wp, char_u **varp, bool set) last_multispace = p; multispace_len = 0; while (*s != NUL && *s != ',') { - int c1len = utf_ptr2len(s); - c1 = mb_cptr2char_adv((const char_u **)&s); - if (utf_char2cells(c1) > 1 || (c1len == 1 && c1 > 127)) { + c1 = get_encoded_char_adv(&s); + if (c1 == 0 || utf_char2cells(c1) > 1) { return e_invarg; } multispace_len++; @@ -3607,7 +3632,7 @@ static char *set_chars_option(win_T *wp, char_u **varp, bool set) } else { int multispace_pos = 0; while (*s != NUL && *s != ',') { - c1 = mb_cptr2char_adv((const char_u **)&s); + c1 = get_encoded_char_adv(&s); if (p == last_multispace) { wp->w_p_lcs_chars.multispace[multispace_pos++] = c1; } @@ -6793,7 +6818,7 @@ static void langmap_set(void) ga_clear(&langmap_mapga); // clear the previous map first langmap_init(); // back to one-to-one map - for (p = p_langmap; p[0] != NUL; ) { + for (p = p_langmap; p[0] != NUL;) { for (p2 = p; p2[0] != NUL && p2[0] != ',' && p2[0] != ';'; MB_PTR_ADV(p2)) { if (p2[0] == '\\' && p2[1] != NUL) { diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 3ff13c2b3f..e9963516fc 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -369,7 +369,7 @@ static bool is_executable_in_path(const char *name, char **abspath) // is an executable file. char *p = path; bool rv = false; - for (;; ) { + for (;;) { char *e = xstrchrnul(p, ENV_SEPCHAR); // Combine the $PATH segment with `name`. diff --git a/src/nvim/os/stdpaths.c b/src/nvim/os/stdpaths.c index 10b0d391bf..5b824d23f4 100644 --- a/src/nvim/os/stdpaths.c +++ b/src/nvim/os/stdpaths.c @@ -146,7 +146,7 @@ char *stdpaths_user_data_subpath(const char *fname, const size_t trailing_pathse const size_t numcommas = (escape_commas ? memcnt(ret, ',', len) : 0); if (numcommas || trailing_pathseps) { ret = xrealloc(ret, len + trailing_pathseps + numcommas + 1); - for (size_t i = 0 ; i < len + numcommas ; i++) { + for (size_t i = 0; i < len + numcommas; i++) { if (ret[i] == ',') { memmove(ret + i + 1, ret + i, len - i + numcommas); ret[i] = '\\'; diff --git a/src/nvim/path.c b/src/nvim/path.c index c28d848683..7b9081eafa 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -1079,7 +1079,7 @@ const char *gettail_dir(const char *const fname) const char *next_dir_end = fname; bool look_for_sep = true; - for (const char *p = fname; *p != NUL; ) { + for (const char *p = fname; *p != NUL;) { if (vim_ispathsep(*p)) { if (look_for_sep) { next_dir_end = p; @@ -1289,8 +1289,8 @@ int gen_expand_wildcards(int num_pat, char_u **pat, int *num_file, char_u ***fil && !path_is_absolute(p) && !(p[0] == '.' && (vim_ispathsep(p[1]) - || (p[1] == '.' && - vim_ispathsep(p[2]))))) { + || (p[1] == '.' + && vim_ispathsep(p[2]))))) { /* :find completion where 'path' is used. * Recursiveness is OK here. */ recursive = false; @@ -1505,7 +1505,7 @@ void simplify_filename(char_u *filename) if (vim_ispathsep(*p)) { relative = false; - do{ + do { ++p; } while (vim_ispathsep(*p)); @@ -1517,8 +1517,8 @@ void simplify_filename(char_u *filename) * or "p" is at the "start" of the (absolute or relative) path name. */ if (vim_ispathsep(*p)) { STRMOVE(p, p + 1); // remove duplicate "/" - } else if (p[0] == '.' && - (vim_ispathsep(p[1]) || p[1] == NUL)) { + } else if (p[0] == '.' + && (vim_ispathsep(p[1]) || p[1] == NUL)) { if (p == start && relative) { p += 1 + (p[1] != NUL); // keep single "." or leading "./" } else { @@ -2198,7 +2198,7 @@ int match_suffix(char_u *fname) size_t fnamelen = STRLEN(fname); size_t setsuflen = 0; - for (char_u *setsuf = p_su; *setsuf; ) { + for (char_u *setsuf = p_su; *setsuf;) { setsuflen = copy_option_part(&setsuf, suf_buf, MAXSUFLEN, ".,"); if (setsuflen == 0) { char_u *tail = path_tail(fname); @@ -2245,11 +2245,17 @@ int path_full_dir_name(char *directory, char *buffer, size_t len) } if (os_chdir(directory) != SUCCESS) { - // Do not return immediately since we may be in the wrong directory. - retval = FAIL; - } - - if (retval == FAIL || os_dirname((char_u *)buffer, len) == FAIL) { + // Path does not exist (yet). For a full path fail, + // will use the path as-is. For a relative path use + // the current directory and append the file name. + if (path_is_absolute((const char_u *)directory)) { + // Do not return immediately since we may be in the wrong directory. + retval = FAIL; + } else { + xstrlcpy(buffer, old_dir, len); + append_path(buffer, directory, len); + } + } else if (os_dirname((char_u *)buffer, len) == FAIL) { // Do not return immediately since we are in the wrong directory. retval = FAIL; } diff --git a/src/nvim/po/check.vim b/src/nvim/po/check.vim index d55d4cfa4d..aca878f9d5 100644 --- a/src/nvim/po/check.vim +++ b/src/nvim/po/check.vim @@ -162,7 +162,10 @@ endwhile " Check that the file is well formed according to msgfmts understanding if executable("msgfmt") let filename = expand("%") - let a = system("msgfmt --statistics OLD_PO_FILE_INPUT=yes " . filename) + " Newer msgfmt does not take OLD_PO_FILE_INPUT argument, must be in + " environment. + let $OLD_PO_FILE_INPUT = 'yes' + let a = system("msgfmt --statistics " . filename) if v:shell_error != 0 let error = matchstr(a, filename.':\zs\d\+\ze:')+0 for line in split(a, '\n') | echomsg line | endfor diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index bf9052de6f..6a192d148f 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -539,7 +539,7 @@ static size_t efm_regpat_bufsz(char_u *efm) size_t sz; sz = (FMT_PATTERNS * 3) + (STRLEN(efm) << 2); - for (int i = FMT_PATTERNS - 1; i >= 0; ) { + for (int i = FMT_PATTERNS - 1; i >= 0;) { sz += STRLEN(fmt_pat[i--].pattern); } #ifdef BACKSLASH_IN_FILENAME @@ -2028,7 +2028,7 @@ void copy_loclist_stack(win_T *from, win_T *to) /// Get buffer number for file "directory/fname". /// Also sets the b_has_qf_entry flag. -static int qf_get_fnum(qf_list_T *qfl, char_u *directory, char_u *fname ) +static int qf_get_fnum(qf_list_T *qfl, char_u *directory, char_u *fname) { char_u *ptr = NULL; char_u *bufname; @@ -4380,7 +4380,7 @@ static char_u *get_mef_name(void) } // Keep trying until the name doesn't exist yet. - for (;; ) { + for (;;) { if (start == -1) { start = (int)os_get_pid(); } else { diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index 14f49d05d5..be365d4ab8 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -479,7 +479,7 @@ RuntimeSearchPath runtime_search_path_build(void) CharVec after_path = KV_INITIAL_VALUE; static char_u buf[MAXPATHL]; - for (char *entry = (char *)p_pp; *entry != NUL; ) { + for (char *entry = (char *)p_pp; *entry != NUL;) { char *cur_entry = entry; copy_option_part((char_u **)&entry, buf, MAXPATHL, ","); @@ -491,7 +491,7 @@ RuntimeSearchPath runtime_search_path_build(void) char *rtp_entry; - for (rtp_entry = (char *)p_rtp; *rtp_entry != NUL; ) { + for (rtp_entry = (char *)p_rtp; *rtp_entry != NUL;) { char *cur_entry = rtp_entry; copy_option_part((char_u **)&rtp_entry, buf, MAXPATHL, ","); size_t buflen = STRLEN(buf); @@ -663,7 +663,7 @@ static int add_pack_dir_to_rtp(char_u *fname, bool is_pack) } const char *insp = NULL; const char *after_insp = NULL; - for (const char *entry = (const char *)p_rtp; *entry != NUL; ) { + for (const char *entry = (const char *)p_rtp; *entry != NUL;) { const char *cur_entry = entry; copy_option_part((char_u **)&entry, buf, MAXPATHL, ","); diff --git a/src/nvim/screen.c b/src/nvim/screen.c index cc3fab3503..2ce2be0bfd 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -1084,7 +1084,7 @@ static void win_update(win_T *wp, Providers *providers) */ bot_start = 0; idx = 0; - for (;; ) { + for (;;) { wp->w_lines[idx] = wp->w_lines[j]; /* stop at line that didn't fit, unless it is still * valid (no lines deleted) */ @@ -1359,7 +1359,7 @@ static void win_update(win_T *wp, Providers *providers) win_check_ns_hl(wp); - for (;; ) { + for (;;) { /* stop updating when reached the end of the window (check for _past_ * the end of the window is at the end of the loop) */ if (row == wp->w_grid.Rows) { @@ -1508,7 +1508,7 @@ static void win_update(win_T *wp, Providers *providers) int x = row + new_rows; // move entries in w_lines[] upwards - for (;; ) { + for (;;) { // stop at last valid entry in w_lines[] if (i >= wp->w_lines_valid) { wp->w_lines_valid = j; @@ -2707,7 +2707,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc int sign_idx = 0; // Repeat for the whole displayed line. - for (;; ) { + for (;;) { int has_match_conc = 0; ///< match wants to conceal bool did_decrement_ptr = false; @@ -4413,8 +4413,8 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc || filler_todo > 0 || (wp->w_p_list && wp->w_p_lcs_chars.eol != NUL && p_extra != at_end_str) - || (n_extra != 0 && - (c_extra != NUL || *p_extra != NUL)))) { + || (n_extra != 0 + && (c_extra != NUL || *p_extra != NUL)))) { bool wrap = wp->w_p_wrap // Wrapping enabled. && filler_todo <= 0 // Not drawing diff filler lines. && lcs_eol_one != -1 // Haven't printed the lcs_eol character. @@ -5011,8 +5011,8 @@ static int skip_status_match_char(expand_T *xp, char_u *s) if ((rem_backslash(s) && xp->xp_context != EXPAND_HELP) || ((xp->xp_context == EXPAND_MENUS || xp->xp_context == EXPAND_MENUNAMES) - && (s[0] == '\t' || - (s[0] == '\\' && s[1] != NUL)))) { + && (s[0] == '\t' + || (s[0] == '\\' && s[1] != NUL)))) { #ifndef BACKSLASH_IN_FILENAME if (xp->xp_shell && csh_like_shell() && s[1] == '\\' && s[2] == '!') { return 2; @@ -6144,7 +6144,7 @@ static void next_search_hl(win_T *win, match_T *shl, linenr_T lnum, colnr_T minc * or none is found in this line. */ called_emsg = FALSE; - for (;; ) { + for (;;) { // Stop searching after passing the time limit. if (profile_passed_limit(shl->tm)) { shl->lnum = 0; // no match found in time diff --git a/src/nvim/search.c b/src/nvim/search.c index 0756fbf37d..2e45a8f509 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -370,8 +370,8 @@ int ignorecase_opt(char_u *pat, int ic_in, int scs) { int ic = ic_in; if (ic && !no_smartcase && scs - && !(ctrl_x_mode_not_default() && - curbuf->b_p_inf)) { + && !(ctrl_x_mode_not_default() + && curbuf->b_p_inf)) { ic = !pat_has_uppercase(pat); } no_smartcase = false; @@ -757,7 +757,7 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir, * relative to the end of the match. */ match_ok = false; - for (;; ) { + for (;;) { // Remember a position that is before the start // position, we use it if it's the last match in // the line. Always accept a position after @@ -1105,7 +1105,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, long count, /* * Repeat the search when pattern followed by ';', e.g. "/foo/;?bar". */ - for (;; ) { + for (;;) { bool show_top_bot_msg = false; searchstr = pat; @@ -1465,7 +1465,7 @@ int search_for_exact_line(buf_T *buf, pos_T *pos, Direction dir, char_u *pat) if (buf->b_ml.ml_line_count == 0) { return FAIL; } - for (;; ) { + for (;;) { pos->lnum += dir; if (pos->lnum < 1) { if (p_ws) { @@ -1585,7 +1585,7 @@ int searchc(cmdarg_T *cap, int t_cmd) len = (int)STRLEN(p); while (count--) { - for (;; ) { + for (;;) { if (dir > 0) { col += utfc_ptr2len(p + col); if (col >= len) { @@ -1808,6 +1808,9 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel) initc = NUL; } else if (initc != '#' && initc != NUL) { find_mps_values(&initc, &findc, &backwards, true); + if (dir) { + backwards = (dir == FORWARD) ? false : true; + } if (findc == NUL) { return NULL; } @@ -1870,7 +1873,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel) if (linep[pos.col] == NUL && pos.col) { --pos.col; } - for (;; ) { + for (;;) { initc = utf_ptr2char(linep + pos.col); if (initc == NUL) { break; @@ -1894,7 +1897,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel) // Set "match_escaped" if there are an odd number of // backslashes. - for (col = pos.col; check_prevcol(linep, col, '\\', &col); ) { + for (col = pos.col; check_prevcol(linep, col, '\\', &col);) { bslcnt++; } match_escaped = (bslcnt & 1); @@ -2278,7 +2281,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel) int col, bslcnt = 0; if (!cpo_bsl) { - for (col = pos.col; check_prevcol(linep, col, '\\', &col); ) { + for (col = pos.col; check_prevcol(linep, col, '\\', &col);) { bslcnt++; } } @@ -2520,7 +2523,7 @@ int findsent(Direction dir, long count) const int startlnum = pos.lnum; const bool cpo_J = vim_strchr(p_cpo, CPO_ENDOFSENT) != NULL; - for (;; ) { // find end of sentence + for (;;) { // find end of sentence c = gchar_pos(&pos); if (c == NUL || (pos.col == 0 && startPS(pos.lnum, NUL, FALSE))) { if (dir == BACKWARD && pos.lnum != startlnum) { @@ -2530,7 +2533,7 @@ int findsent(Direction dir, long count) } if (c == '.' || c == '!' || c == '?') { tpos = pos; - do{ + do { if ((c = inc(&tpos)) == -1) { break; } @@ -3004,7 +3007,7 @@ static void back_in_line(void) int sclass; // starting class sclass = cls(); - for (;; ) { + for (;;) { if (curwin->w_cursor.col == 0) { // stop at start of line break; } @@ -3427,12 +3430,22 @@ int current_block(oparg_T *oap, long count, int include, int what, int other) // user wants. save_cpo = p_cpo; p_cpo = (char_u *)(vim_strchr(p_cpo, CPO_MATCHBSL) != NULL ? "%M" : "%"); - while (count-- > 0) { - if ((pos = findmatch(NULL, what)) == NULL) { - break; + if ((pos = findmatch(NULL, what)) != NULL) { + while (count-- > 0) { + if ((pos = findmatch(NULL, what)) == NULL) { + break; + } + curwin->w_cursor = *pos; + start_pos = *pos; // the findmatch for end_pos will overwrite *pos + } + } else { + while (count-- > 0) { + if ((pos = findmatchlimit(NULL, what, FM_FORWARD, 0)) == NULL) { + break; + } + curwin->w_cursor = *pos; + start_pos = *pos; // the findmatch for end_pos will overwrite *pos } - curwin->w_cursor = *pos; - start_pos = *pos; // the findmatch for end_pos will overwrite *pos } p_cpo = save_cpo; @@ -3527,7 +3540,7 @@ static bool in_html_tag(bool end_tag) int lc = NUL; pos_T pos; - for (p = line + curwin->w_cursor.col; p > line; ) { + for (p = line + curwin->w_cursor.col; p > line;) { if (*p == '<') { // find '<' under/before cursor break; } @@ -3555,7 +3568,7 @@ static bool in_html_tag(bool end_tag) } // check that the matching '>' is not preceded by '/' - for (;; ) { + for (;;) { if (inc(&pos) < 0) { return false; } @@ -3791,7 +3804,7 @@ extend: } else { dir = FORWARD; } - for (i = count; --i >= 0; ) { + for (i = count; --i >= 0;) { if (start_lnum == (dir == BACKWARD ? 1 : curbuf->b_ml.ml_line_count)) { retval = FAIL; @@ -3806,7 +3819,7 @@ extend: start_lnum -= dir; break; } - for (;; ) { + for (;;) { if (start_lnum == (dir == BACKWARD ? 1 : curbuf->b_ml.ml_line_count)) { break; @@ -3946,7 +3959,7 @@ static int find_next_quote(char_u *line, int col, int quotechar, char_u *escape) { int c; - for (;; ) { + for (;;) { c = line[col]; if (c == NUL) { return -1; @@ -4118,7 +4131,7 @@ bool current_quote(oparg_T *oap, long count, bool include, int quotechar) // Also do this when there is a Visual area, a' may leave the cursor // in between two strings. col_start = 0; - for (;; ) { + for (;;) { // Find open quote character. col_start = find_next_quote(line, col_start, quotechar, NULL); if (col_start < 0 || col_start > first_col) { @@ -4842,7 +4855,7 @@ void find_pattern_in_path(char_u *ptr, Direction dir, size_t len, bool whole, bo } line = ml_get(lnum); - for (;; ) { + for (;;) { if (incl_regmatch.regprog != NULL && vim_regexec(&incl_regmatch, line, (colnr_T)0)) { char_u *p_fname = (curr_fname == curbuf->b_fname) @@ -5379,7 +5392,7 @@ static void show_pat_in_path(char_u *line, int type, bool did_show, int action, if (got_int) { // 'q' typed at "--more--" message return; } - for (;; ) { + for (;;) { p = line + STRLEN(line) - 1; if (fp != NULL) { // We used fgets(), so get rid of newline at end diff --git a/src/nvim/shada.c b/src/nvim/shada.c index 89f9d3a719..e75a244031 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -3977,7 +3977,7 @@ static bool shada_removable(const char *name) bool retval = false; char *new_name = (char *)home_replace_save(NULL, (char_u *)name); - for (p = (char *)p_shada; *p; ) { + for (p = (char *)p_shada; *p;) { (void)copy_option_part((char_u **)&p, (char_u *)part, ARRAY_SIZE(part), ", "); if (part[0] == 'r') { home_replace(NULL, (char_u *)(part + 1), (char_u *)NameBuff, MAXPATHL, true); diff --git a/src/nvim/sign.c b/src/nvim/sign.c index dfa863d0ff..d8eea7f942 100644 --- a/src/nvim/sign.c +++ b/src/nvim/sign.c @@ -774,7 +774,7 @@ static int sign_cmd_idx(char_u *begin_cmd, char_u *end_cmd) char_u save = *end_cmd; *end_cmd = (char_u)NUL; - for (idx = 0; ; idx++) { + for (idx = 0;; idx++) { if (cmds[idx] == NULL || STRCMP(begin_cmd, cmds[idx]) == 0) { break; } @@ -816,7 +816,7 @@ static sign_T *alloc_new_sign(char_u *name) // Check that next_sign_typenr is not already being used. // This only happens after wrapping around. Hopefully // another one got deleted and we can use its number. - for (lp = first_sign; lp != NULL; ) { + for (lp = first_sign; lp != NULL;) { if (lp->sn_typenr == next_sign_typenr) { next_sign_typenr++; if (next_sign_typenr == MAX_TYPENR) { diff --git a/src/nvim/spell.c b/src/nvim/spell.c index 20081bce4f..85d1e139bf 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -622,7 +622,7 @@ static void find_word(matchinf_T *mip, int mode) // - there is a byte that doesn't match, // - we reach the end of the tree, // - or we reach the end of the line. - for (;; ) { + for (;;) { if (flen <= 0 && *mip->mi_fend != NUL) { flen = fold_more(mip); } @@ -689,7 +689,7 @@ static void find_word(matchinf_T *mip, int mode) // One space in the good word may stand for several spaces in the // checked word. if (c == ' ') { - for (;; ) { + for (;;) { if (flen <= 0 && *mip->mi_fend != NUL) { flen = fold_more(mip); } @@ -1269,7 +1269,7 @@ static void find_prefix(matchinf_T *mip, int mode) // - there is a byte that doesn't match, // - we reach the end of the tree, // - or we reach the end of the line. - for (;; ) { + for (;;) { if (flen == 0 && *mip->mi_fend != NUL) { flen = fold_more(mip); } @@ -2083,7 +2083,7 @@ char *did_set_spelllang(win_T *wp) wp->w_s->b_cjk = 0; // Loop over comma separated language names. - for (splp = spl_copy; *splp != NUL; ) { + for (splp = spl_copy; *splp != NUL;) { // Get one language name. copy_option_part(&splp, lang, MAXWLEN, ","); region = NULL; @@ -2354,7 +2354,7 @@ static void use_midword(slang_T *lp, win_T *wp) return; } - for (char_u *p = lp->sl_midword; *p != NUL; ) { + for (char_u *p = lp->sl_midword; *p != NUL;) { const int c = utf_ptr2char(p); const int l = utfc_ptr2len(p); if (c < 256 && l <= 2) { @@ -2759,7 +2759,7 @@ int spell_casefold(const win_T *wp, char_u *str, int len, char_u *buf, int bufle int outi = 0; // Fold one character at a time. - for (char_u *p = str; p < str + len; ) { + for (char_u *p = str; p < str + len;) { if (outi + MB_MAXBYTES > buflen) { buf[outi] = NUL; return FAIL; @@ -2806,7 +2806,7 @@ int spell_check_sps(void) sps_flags = 0; sps_limit = 9999; - for (p = p_sps; *p != NUL; ) { + for (p = p_sps; *p != NUL;) { copy_option_part(&p, buf, MAXPATHL, ","); f = 0; @@ -3118,7 +3118,7 @@ static bool check_need_cap(linenr_T lnum, colnr_T col) regmatch.regprog = curwin->w_s->b_cap_prog; regmatch.rm_ic = FALSE; p = line + endcol; - for (;; ) { + for (;;) { MB_PTR_BACK(line, p); if (p == line || spell_iswordp_nmw(p, curwin)) { break; @@ -3330,7 +3330,7 @@ static void spell_find_suggest(char_u *badptr, int badlen, suginfo_T *su, int ma sps_copy = vim_strsave(p_sps); // Loop over the items in 'spellsuggest'. - for (p = sps_copy; *p != NUL; ) { + for (p = sps_copy; *p != NUL;) { copy_option_part(&p, buf, MAXPATHL, ","); if (STRNCMP(buf, "expr:", 5) == 0) { @@ -3557,7 +3557,7 @@ void onecap_copy(char_u *word, char_u *wcopy, bool upper) static void allcap_copy(char_u *word, char_u *wcopy) { char_u *d = wcopy; - for (char_u *s = word; *s != NUL; ) { + for (char_u *s = word; *s != NUL;) { int c = mb_cptr2char_adv((const char_u **)&s); if (c == 0xdf) { @@ -4352,8 +4352,8 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so // just deleted this byte, accepting it is always cheaper than // delete + substitute. if (c == fword[sp->ts_fidx] - || (sp->ts_tcharlen > 0 && - sp->ts_isdiff != DIFF_NONE)) { + || (sp->ts_tcharlen > 0 + && sp->ts_isdiff != DIFF_NONE)) { newscore = 0; } else { newscore = SCORE_SUBST; @@ -4513,7 +4513,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so // skip over NUL bytes n = sp->ts_arridx; - for (;; ) { + for (;;) { if (sp->ts_curi > byts[n]) { // Only NUL bytes at this node, go to next state. PROF_STORE(sp->ts_state) @@ -5257,7 +5257,7 @@ static int stp_sal_score(suggest_T *stp, suginfo_T *su, slang_T *slang, char_u * // space. if (ascii_iswhite(su->su_badptr[su->su_badlen]) && *skiptowhite(stp->st_word) == NUL) { - for (p = fword; *(p = skiptowhite(p)) != NUL; ) { + for (p = fword; *(p = skiptowhite(p)) != NUL;) { STRMOVE(p, p + 1); } } @@ -5568,7 +5568,7 @@ static int soundfold_find(slang_T *slang, char_u *word) byts = slang->sl_sbyts; idxs = slang->sl_sidxs; - for (;; ) { + for (;;) { // First byte is the number of possible bytes. len = byts[arridx++]; @@ -5701,7 +5701,7 @@ static void add_suggestion(suginfo_T *su, garray_T *gap, const char_u *goodword, // "thee the" is added next to changing the first "the" the "thee". const char_u *pgood = goodword + STRLEN(goodword); char_u *pbad = su->su_badptr + badlenarg; - for (;; ) { + for (;;) { goodlen = (int)(pgood - goodword); badlen = (int)(pbad - su->su_badptr); if (goodlen <= 0 || badlen <= 0) { @@ -6004,7 +6004,7 @@ static void spell_soundfold_sofo(slang_T *slang, char_u *inword, char_u *res) // The sl_sal_first[] table contains the translation for chars up to // 255, sl_sal the rest. - for (char_u *s = inword; *s != NUL; ) { + for (char_u *s = inword; *s != NUL;) { int c = mb_cptr2char_adv((const char_u **)&s); if (utf_class(c) == 0) { c = ' '; @@ -6015,7 +6015,7 @@ static void spell_soundfold_sofo(slang_T *slang, char_u *inword, char_u *res) if (ip == NULL) { // empty list, can't match c = NUL; } else { - for (;; ) { // find "c" in the list + for (;;) { // find "c" in the list if (*ip == 0) { // not found c = NUL; break; @@ -6069,7 +6069,7 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res) // Remove accents, if wanted. We actually remove all non-word characters. // But keep white space. wordlen = 0; - for (const char_u *s = inword; *s != NUL; ) { + for (const char_u *s = inword; *s != NUL;) { const char_u *t = s; c = mb_cptr2char_adv(&s); if (slang->sl_rem_accents) { @@ -6591,12 +6591,12 @@ static int spell_edit_score(slang_T *slang, char_u *badword, char_u *goodword) // Get the characters from the multi-byte strings and put them in an // int array for easy access. badlen = 0; - for (const char_u *p = badword; *p != NUL; ) { + for (const char_u *p = badword; *p != NUL;) { wbadword[badlen++] = mb_cptr2char_adv(&p); } wbadword[badlen++] = 0; goodlen = 0; - for (const char_u *p = goodword; *p != NUL; ) { + for (const char_u *p = goodword; *p != NUL;) { wgoodword[goodlen++] = mb_cptr2char_adv(&p); } wgoodword[goodlen++] = 0; @@ -6690,12 +6690,12 @@ static int spell_edit_score_limit_w(slang_T *slang, char_u *badword, char_u *goo // Get the characters from the multi-byte strings and put them in an // int array for easy access. bi = 0; - for (const char_u *p = badword; *p != NUL; ) { + for (const char_u *p = badword; *p != NUL;) { wbadword[bi++] = mb_cptr2char_adv(&p); } wbadword[bi++] = 0; gi = 0; - for (const char_u *p = goodword; *p != NUL; ) { + for (const char_u *p = goodword; *p != NUL;) { wgoodword[gi++] = mb_cptr2char_adv(&p); } wgoodword[gi++] = 0; @@ -6713,9 +6713,9 @@ static int spell_edit_score_limit_w(slang_T *slang, char_u *badword, char_u *goo score = 0; minscore = limit + 1; - for (;; ) { + for (;;) { // Skip over an equal part, score remains the same. - for (;; ) { + for (;;) { bc = wbadword[bi]; gc = wgoodword[gi]; @@ -7289,7 +7289,7 @@ int spell_word_start(int startcol) // Find a word character before "startcol". line = get_cursor_line_ptr(); - for (p = line + startcol; p > line; ) { + for (p = line + startcol; p > line;) { MB_PTR_BACK(line, p); if (spell_iswordp_nmw(p, curwin)) { break; diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index 0fc9012f27..ae4514dd30 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -549,7 +549,7 @@ static inline int spell_check_magic_string(FILE *const fd) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE { char buf[VIMSPELLMAGICL]; - SPELL_READ_BYTES(buf, VIMSPELLMAGICL, fd, ; ); + SPELL_READ_BYTES(buf, VIMSPELLMAGICL, fd,; ); if (memcmp(buf, VIMSPELLMAGIC, VIMSPELLMAGICL) != 0) { return SP_FORMERROR; } @@ -640,7 +640,7 @@ slang_T *spell_load_file(char_u *fname, char_u *lang, slang_T *old_lp, bool sile // <SECTIONS>: <section> ... <sectionend> // <section>: <sectionID> <sectionflags> <sectionlen> (section contents) - for (;; ) { + for (;;) { n = getc(fd); // <sectionID> or <sectionend> if (n == SN_END) { break; @@ -960,7 +960,7 @@ someerror: ga_init(&ga, 1, 100); for (wordnr = 0; wordnr < wcount; ++wordnr) { ga.ga_len = 0; - for (;; ) { + for (;;) { c = getc(fd); // <sugline> if (c < 0) { goto someerror; @@ -1030,7 +1030,7 @@ static int read_region_section(FILE *fd, slang_T *lp, int len) if (len > MAXREGIONS * 2) { return SP_FORMERROR; } - SPELL_READ_NONNUL_BYTES((char *)lp->sl_regions, (size_t)len, fd, ; ); + SPELL_READ_NONNUL_BYTES((char *)lp->sl_regions, (size_t)len, fd,; ); lp->sl_regions[len] = NUL; return 0; } @@ -1097,7 +1097,7 @@ static int read_prefcond_section(FILE *fd, slang_T *lp) if (n > 0) { char buf[MAXWLEN + 1]; buf[0] = '^'; // always match at one position only - SPELL_READ_NONNUL_BYTES(buf + 1, (size_t)n, fd, ; ); + SPELL_READ_NONNUL_BYTES(buf + 1, (size_t)n, fd,; ); buf[n + 1] = NUL; lp->sl_prefprog[i] = vim_regcomp((char_u *)buf, RE_MAGIC | RE_STRING); } @@ -1548,7 +1548,7 @@ static int set_sofo(slang_T *lp, char_u *from, char_u *to) // First count the number of items for each list. Temporarily use // sl_sal_first[] for this. - for (p = from, s = to; *p != NUL && *s != NUL; ) { + for (p = from, s = to; *p != NUL && *s != NUL;) { const int c = mb_cptr2char_adv((const char_u **)&p); MB_CPTR_ADV(s); if (c >= 256) { @@ -1571,7 +1571,7 @@ static int set_sofo(slang_T *lp, char_u *from, char_u *to) // Put the characters up to 255 in sl_sal_first[] the rest in a sl_sal // list. memset(lp->sl_sal_first, 0, sizeof(salfirst_T) * 256); - for (p = from, s = to; *p != NUL && *s != NUL; ) { + for (p = from, s = to; *p != NUL && *s != NUL;) { const int c = mb_cptr2char_adv((const char_u **)&p); const int i = mb_cptr2char_adv((const char_u **)&s); if (c >= 256) { @@ -1647,7 +1647,7 @@ static int *mb_str2wide(char_u *s) int i = 0; int *res = xmalloc((mb_charlen(s) + 1) * sizeof(int)); - for (char_u *p = s; *p != NUL; ) { + for (char_u *p = s; *p != NUL;) { res[i++] = mb_ptr2char_adv((const char_u **)&p); } res[i] = NUL; @@ -2095,7 +2095,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) // Split the line up in white separated items. Put a NUL after each // item. itemcnt = 0; - for (p = line;; ) { + for (p = line;;) { while (*p != NUL && *p <= ' ') { // skip white space and CR/NL ++p; } @@ -2646,7 +2646,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) int c; // Check that every character appears only once. - for (p = items[1]; *p != NUL; ) { + for (p = items[1]; *p != NUL;) { c = mb_ptr2char_adv((const char_u **)&p); if ((!GA_EMPTY(&spin->si_map) && vim_strchr(spin->si_map.ga_data, c) @@ -2804,7 +2804,7 @@ static void aff_process_flags(afffile_T *affile, affentry_T *entry) if (entry->ae_flags != NULL && (affile->af_compforbid != 0 || affile->af_comppermit != 0)) { - for (p = entry->ae_flags; *p != NUL; ) { + for (p = entry->ae_flags; *p != NUL;) { prevp = p; flag = get_affitem(affile->af_flagtype, &p); if (flag == affile->af_comppermit || flag == affile->af_compforbid) { @@ -2922,7 +2922,7 @@ static void process_compflags(spellinfo_T *spin, afffile_T *aff, char_u *compfla spin->si_compflags = p; tp = p + STRLEN(p); - for (p = compflags; *p != NUL; ) { + for (p = compflags; *p != NUL;) { if (vim_strchr((char_u *)"/?*+[]", *p) != NULL) { // Copy non-flag characters directly. *tp++ = *p++; @@ -2985,7 +2985,7 @@ static bool flag_in_afflist(int flagtype, char_u *afflist, unsigned flag) case AFT_CAPLONG: case AFT_LONG: - for (p = afflist; *p != NUL; ) { + for (p = afflist; *p != NUL;) { n = mb_ptr2char_adv((const char_u **)&p); if ((flagtype == AFT_LONG || (n >= 'A' && n <= 'Z')) && *p != NUL) { @@ -2998,7 +2998,7 @@ static bool flag_in_afflist(int flagtype, char_u *afflist, unsigned flag) break; case AFT_NUM: - for (p = afflist; *p != NUL; ) { + for (p = afflist; *p != NUL;) { int digits = getdigits_int(&p, true, 0); assert(digits >= 0); n = (unsigned int)digits; @@ -3248,9 +3248,9 @@ static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile) // Extract flags from the affix list. flags |= get_affix_flags(affile, afflist); - if (affile->af_needaffix != 0 && - flag_in_afflist(affile->af_flagtype, afflist, - affile->af_needaffix)) { + if (affile->af_needaffix != 0 + && flag_in_afflist(affile->af_flagtype, afflist, + affile->af_needaffix)) { need_affix = true; } @@ -3311,32 +3311,32 @@ static int get_affix_flags(afffile_T *affile, char_u *afflist) { int flags = 0; - if (affile->af_keepcase != 0 && - flag_in_afflist(affile->af_flagtype, afflist, - affile->af_keepcase)) { + if (affile->af_keepcase != 0 + && flag_in_afflist(affile->af_flagtype, afflist, + affile->af_keepcase)) { flags |= WF_KEEPCAP | WF_FIXCAP; } - if (affile->af_rare != 0 && - flag_in_afflist(affile->af_flagtype, afflist, affile->af_rare)) { + if (affile->af_rare != 0 + && flag_in_afflist(affile->af_flagtype, afflist, affile->af_rare)) { flags |= WF_RARE; } - if (affile->af_bad != 0 && - flag_in_afflist(affile->af_flagtype, afflist, affile->af_bad)) { + if (affile->af_bad != 0 + && flag_in_afflist(affile->af_flagtype, afflist, affile->af_bad)) { flags |= WF_BANNED; } - if (affile->af_needcomp != 0 && - flag_in_afflist(affile->af_flagtype, afflist, - affile->af_needcomp)) { + if (affile->af_needcomp != 0 + && flag_in_afflist(affile->af_flagtype, afflist, + affile->af_needcomp)) { flags |= WF_NEEDCOMP; } - if (affile->af_comproot != 0 && - flag_in_afflist(affile->af_flagtype, afflist, - affile->af_comproot)) { + if (affile->af_comproot != 0 + && flag_in_afflist(affile->af_flagtype, afflist, + affile->af_comproot)) { flags |= WF_COMPROOT; } - if (affile->af_nosuggest != 0 && - flag_in_afflist(affile->af_flagtype, afflist, - affile->af_nosuggest)) { + if (affile->af_nosuggest != 0 + && flag_in_afflist(affile->af_flagtype, afflist, + affile->af_nosuggest)) { flags |= WF_NOSUGGEST; } return flags; @@ -3355,7 +3355,7 @@ static int get_pfxlist(afffile_T *affile, char_u *afflist, char_u *store_afflist char_u key[AH_KEY_LEN]; hashitem_T *hi; - for (p = afflist; *p != NUL; ) { + for (p = afflist; *p != NUL;) { prevp = p; if (get_affitem(affile->af_flagtype, &p) != 0) { // A flag is a postponed prefix flag if it appears in "af_pref" @@ -3389,7 +3389,7 @@ static void get_compflags(afffile_T *affile, char_u *afflist, char_u *store_affl char_u key[AH_KEY_LEN]; hashitem_T *hi; - for (p = afflist; *p != NUL; ) { + for (p = afflist; *p != NUL;) { prevp = p; if (get_affitem(affile->af_flagtype, &p) != 0) { // A flag is a compound flag if it appears in "af_comp". @@ -5845,7 +5845,7 @@ static void set_map_str(slang_T *lp, char_u *map) // The similar characters are stored separated with slashes: // "aaa/bbb/ccc/". Fill sl_map_array[c] with the character before c and // before the same slash. For characters above 255 sl_map_hash is used. - for (p = map; *p != NUL; ) { + for (p = map; *p != NUL;) { c = mb_cptr2char_adv((const char_u **)&p); if (c == '/') { headc = 0; diff --git a/src/nvim/strings.c b/src/nvim/strings.c index 47cbf01996..c58e052ae9 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -242,7 +242,7 @@ char_u *vim_strsave_shellescape(const char_u *string, bool do_special, bool do_n #endif *d++ = '\''; - for (const char_u *p = string; *p != NUL; ) { + for (const char_u *p = string; *p != NUL;) { #ifdef WIN32 if (!p_ssl) { if (*p == '"') { @@ -405,7 +405,7 @@ int vim_stricmp(const char *s1, const char *s2) { int i; - for (;; ) { + for (;;) { i = (int)TOLOWER_LOC(*s1) - (int)TOLOWER_LOC(*s2); if (i != 0) { return i; // this character different diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 8347f1bff1..dd3f1b4dc9 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -691,7 +691,7 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid) * Restrict the search for the end of a comment to b_syn_sync_maxlines. */ if (find_start_comment((int)syn_block->b_syn_sync_maxlines) != NULL) { - for (idx = syn_block->b_syn_patterns.ga_len; --idx >= 0; ) { + for (idx = syn_block->b_syn_patterns.ga_len; --idx >= 0;) { if (SYN_ITEMS(syn_block)[idx].sp_syn.id == syn_block->b_syn_sync_id && SYN_ITEMS(syn_block)[idx].sp_type == SPTYPE_START) { @@ -752,7 +752,7 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid) for (current_lnum = lnum; current_lnum < end_lnum; ++current_lnum) { syn_start_line(); - for (;; ) { + for (;;) { had_sync_point = syn_finish_line(true); // When a sync point has been found, remember where, and // continue to look for another one, further on in the line. @@ -1146,7 +1146,7 @@ static void syn_stack_apply_changes_block(synblock_T *block, buf_T *buf) linenr_T n; prev = NULL; - for (p = block->b_sst_first; p != NULL; ) { + for (p = block->b_sst_first; p != NULL;) { if (p->sst_lnum + block->b_syn_sync_linebreaks > buf->b_mod_top) { n = p->sst_lnum + buf->b_mod_xlines; if (n <= buf->b_mod_bot) { @@ -1449,7 +1449,7 @@ static bool syn_stack_equal(synstate_T *sp) } int i; - for (i = current_state.ga_len; --i >= 0; ) { + for (i = current_state.ga_len; --i >= 0;) { // If the item has another index the state is different. if (bp[i].bs_idx != CUR_STATE(i).si_idx) { break; @@ -1788,9 +1788,9 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con line = syn_getcurline(); const char_u *cur_pos = line + current_col; if (vim_iswordp_buf(cur_pos, syn_buf) - && (current_col == 0 || - !vim_iswordp_buf(cur_pos - 1 - utf_head_off(line, cur_pos - 1), - syn_buf))) { + && (current_col == 0 + || !vim_iswordp_buf(cur_pos - 1 - utf_head_off(line, cur_pos - 1), + syn_buf))) { syn_id = check_keyword_id(line, (int)current_col, &endcol, &flags, &next_list, cur_si, &cchar); if (syn_id != 0) { @@ -1852,7 +1852,7 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con */ next_match_idx = 0; // no match in this line yet next_match_col = MAXCOL; - for (int idx = syn_block->b_syn_patterns.ga_len; --idx >= 0; ) { + for (int idx = syn_block->b_syn_patterns.ga_len; --idx >= 0;) { synpat_T *const spp = &(SYN_ITEMS(syn_block)[idx]); if (spp->sp_syncing == syncing && (displaying || !(spp->sp_flags & HL_DISPLAY)) @@ -2207,7 +2207,7 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con /// @return true if we already matched pattern "idx" at the current column. static bool did_match_already(int idx, garray_T *gap) { - for (int i = current_state.ga_len; --i >= 0; ) { + for (int i = current_state.ga_len; --i >= 0;) { if (CUR_STATE(i).si_m_startcol == (int)current_col && CUR_STATE(i).si_m_lnum == (int)current_lnum && CUR_STATE(i).si_idx == idx) { @@ -2217,7 +2217,7 @@ static bool did_match_already(int idx, garray_T *gap) // Zero-width matches with a nextgroup argument are not put on the syntax // stack, and can only be matched once anyway. - for (int i = gap->ga_len; --i >= 0; ) { + for (int i = gap->ga_len; --i >= 0;) { if (((int *)(gap->ga_data))[i] == idx) { return true; } @@ -2318,7 +2318,7 @@ static void check_state_ends(void) int had_extend; cur_si = &CUR_STATE(current_state.ga_len - 1); - for (;; ) { + for (;;) { if (cur_si->si_ends && (cur_si->si_m_endpos.lnum < current_lnum || (cur_si->si_m_endpos.lnum == current_lnum @@ -2658,7 +2658,7 @@ static void find_endpos(int idx, lpos_T *startpos, lpos_T *m_endpos, lpos_T *hl_ /* * Find the SKIP or first END pattern after the last START pattern. */ - for (;; ) { + for (;;) { spp = &(SYN_ITEMS(syn_block)[idx]); if (spp->sp_type != SPTYPE_START) { break; @@ -2687,7 +2687,7 @@ static void find_endpos(int idx, lpos_T *startpos, lpos_T *m_endpos, lpos_T *hl_ // use syntax iskeyword option save_chartab(buf_chartab); - for (;; ) { + for (;;) { /* * Find end pattern that matches first after "matchcol". */ @@ -3286,13 +3286,13 @@ void syntax_clear(synblock_T *block) clear_keywtab(&block->b_keywtab_ic); // free the syntax patterns - for (int i = block->b_syn_patterns.ga_len; --i >= 0; ) { + for (int i = block->b_syn_patterns.ga_len; --i >= 0;) { syn_clear_pattern(block, i); } ga_clear(&block->b_syn_patterns); // free the syntax clusters - for (int i = block->b_syn_clusters.ga_len; --i >= 0; ) { + for (int i = block->b_syn_clusters.ga_len; --i >= 0;) { syn_clear_cluster(block, i); } ga_clear(&block->b_syn_clusters); @@ -3336,7 +3336,7 @@ void reset_synblock(win_T *wp) static void syntax_sync_clear(void) { // free the syntax patterns - for (int i = curwin->w_s->b_syn_patterns.ga_len; --i >= 0; ) { + for (int i = curwin->w_s->b_syn_patterns.ga_len; --i >= 0;) { if (SYN_ITEMS(curwin->w_s)[i].sp_syncing) { syn_remove_pattern(curwin->w_s, i); } @@ -3484,7 +3484,7 @@ static void syn_clear_one(const int id, const bool syncing) } // clear the patterns for "id" - for (int idx = curwin->w_s->b_syn_patterns.ga_len; --idx >= 0; ) { + for (int idx = curwin->w_s->b_syn_patterns.ga_len; --idx >= 0;) { spp = &(SYN_ITEMS(curwin->w_s)[idx]); if (spp->sp_syn.id != id || spp->sp_syncing != syncing) { continue; @@ -3874,7 +3874,7 @@ static void put_pattern(const char *const s, const int c, const synpat_T *const msg_putchar(c); // output the pattern, in between a char that is not in the pattern - for (i = 0; vim_strchr(spp->sp_pattern, sepchars[i]) != NULL; ) { + for (i = 0; vim_strchr(spp->sp_pattern, sepchars[i]) != NULL;) { if (sepchars[++i] == NUL) { i = 0; // no good char found, just use the first one break; @@ -4015,7 +4015,7 @@ static void syn_clear_keyword(int id, hashtab_T *ht) } --todo; kp_prev = NULL; - for (kp = HI2KE(hi); kp != NULL; ) { + for (kp = HI2KE(hi); kp != NULL;) { if (kp->k_syn.id == id) { kp_next = kp->ke_next; if (kp_prev == NULL) { @@ -4191,7 +4191,7 @@ static char_u *get_syn_options(char_u *arg, syn_opt_arg_T *opt, int *conceal_cha opt->flags |= HL_CONCEAL; } - for (;; ) { + for (;;) { /* * This is used very often when a large number of keywords is defined. * Need to skip quickly when no option name is found. @@ -4201,7 +4201,7 @@ static char_u *get_syn_options(char_u *arg, syn_opt_arg_T *opt, int *conceal_cha break; } - for (fidx = ARRAY_SIZE(flagtab); --fidx >= 0; ) { + for (fidx = ARRAY_SIZE(flagtab); --fidx >= 0;) { p = flagtab[fidx].name; int i; for (i = 0, len = 0; p[i] != NUL; i += 2, ++len) { @@ -4273,7 +4273,7 @@ static char_u *get_syn_options(char_u *arg, syn_opt_arg_T *opt, int *conceal_cha } else { syn_id = syn_name2id((char *)gname); int i; - for (i = curwin->w_s->b_syn_patterns.ga_len; --i >= 0; ) { + for (i = curwin->w_s->b_syn_patterns.ga_len; --i >= 0;) { if (SYN_ITEMS(curwin->w_s)[i].sp_syn.id == syn_id && SYN_ITEMS(curwin->w_s)[i].sp_type == SPTYPE_START) { *opt->sync_idx = i; @@ -4460,7 +4460,7 @@ static void syn_cmd_keyword(exarg_T *eap, int syncing) // 2: Add an entry for each keyword. for (kw = keyword_copy; --cnt >= 0; kw += STRLEN(kw) + 1) { - for (p = vim_strchr(kw, '[');; ) { + for (p = vim_strchr(kw, '[');;) { if (p != NULL) { *p = NUL; } @@ -4972,7 +4972,7 @@ static int syn_scl_name2id(char_u *name) // Avoid using stricmp() too much, it's slow on some systems char_u *name_u = vim_strsave_up(name); int i; - for (i = curwin->w_s->b_syn_clusters.ga_len; --i >= 0; ) { + for (i = curwin->w_s->b_syn_clusters.ga_len; --i >= 0;) { if (SYN_CLSTR(curwin->w_s)[i].scl_name_u != NULL && STRCMP(name_u, SYN_CLSTR(curwin->w_s)[i].scl_name_u) == 0) { break; @@ -5078,7 +5078,7 @@ static void syn_cmd_cluster(exarg_T *eap, int syncing) } scl_id -= SYNID_CLUSTER; - for (;; ) { + for (;;) { if (STRNICMP(rest, "add", 3) == 0 && (ascii_iswhite(rest[3]) || rest[3] == '=')) { opt_len = 3; @@ -5174,7 +5174,7 @@ static char_u *get_syn_pattern(char_u *arg, synpat_T *ci) */ ++end; do { - for (idx = SPO_COUNT; --idx >= 0; ) { + for (idx = SPO_COUNT; --idx >= 0;) { if (STRNCMP(end, spo_name_tab[idx], 3) == 0) { break; } @@ -5456,7 +5456,7 @@ static int get_id_list(char_u **const arg, const int keylen, int16_t **const lis regmatch.rm_ic = TRUE; id = 0; - for (int i = highlight_ga.ga_len; --i >= 0; ) { + for (int i = highlight_ga.ga_len; --i >= 0;) { if (vim_regexec(®match, HL_TABLE()[i].sg_name, (colnr_T)0)) { if (round == 2) { // Got more items than expected; can happen @@ -6520,7 +6520,7 @@ const char *const highlight_init_cmdline[] = { /// Create default links for Nvim* highlight groups used for cmdline coloring void syn_init_cmdline_highlight(bool reset, bool init) { - for (size_t i = 0 ; highlight_init_cmdline[i] != NULL ; i++) { + for (size_t i = 0; highlight_init_cmdline[i] != NULL; i++) { do_highlight(highlight_init_cmdline[i], reset, init); } } @@ -6968,7 +6968,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) attr = 0; off = 0; while (arg[off] != NUL) { - for (i = ARRAY_SIZE(hl_attr_table); --i >= 0; ) { + for (i = ARRAY_SIZE(hl_attr_table); --i >= 0;) { len = (int)STRLEN(hl_name_table[i]); if (STRNICMP(arg + off, hl_name_table[i], len) == 0) { attr |= hl_attr_table[i]; @@ -7040,7 +7040,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) } else { // Reduce calls to STRICMP a bit, it can be slow. off = TOUPPER_ASC(*arg); - for (i = ARRAY_SIZE(color_names); --i >= 0; ) { + for (i = ARRAY_SIZE(color_names); --i >= 0;) { if (off == color_names[i][0] && STRICMP(arg + 1, color_names[i] + 1) == 0) { break; @@ -7536,6 +7536,7 @@ static bool syn_list_header(const bool did_header, const int outlen, const int i { int endcol = 19; bool newline = true; + int name_col = 0; bool adjust = true; if (!did_header) { @@ -7544,6 +7545,7 @@ static bool syn_list_header(const bool did_header, const int outlen, const int i return true; } msg_outtrans(HL_TABLE()[id - 1].sg_name); + name_col = msg_col; endcol = 15; } else if ((ui_has(kUIMessages) || msg_silent) && !force_newline) { msg_putchar(' '); @@ -7570,6 +7572,9 @@ static bool syn_list_header(const bool did_header, const int outlen, const int i // Show "xxx" with the attributes. if (!did_header) { + if (endcol == Columns - 1 && endcol <= name_col) { + msg_putchar(' '); + } msg_puts_attr("xxx", syn_id2attr(id)); msg_putchar(' '); } @@ -7784,7 +7789,7 @@ int syn_get_final_id(int hl_id) * Follow links until there is no more. * Look out for loops! Break after 100 links. */ - for (count = 100; --count >= 0; ) { + for (count = 100; --count >= 0;) { struct hl_group *sgp = &HL_TABLE()[hl_id - 1]; // index is ID minus one // ACHTUNG: when using "tmp" attribute (no link) the function might be @@ -7983,10 +7988,10 @@ static void highlight_list(void) { int i; - for (i = 10; --i >= 0; ) { + for (i = 10; --i >= 0;) { highlight_list_two(i, HL_ATTR(HLF_D)); } - for (i = 40; --i >= 0; ) { + for (i = 40; --i >= 0;) { highlight_list_two(99, 0); } } diff --git a/src/nvim/tag.c b/src/nvim/tag.c index 673ebc2668..1f4d3adc92 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -431,7 +431,7 @@ int do_tag(char_u *tag, int type, int count, int forceit, int verbose) /* * Repeat searching for tags, when a file has not been found. */ - for (;; ) { + for (;;) { int other_name; char_u *name; @@ -1638,7 +1638,7 @@ int find_tags(char_u *pat, int *num_matches, char_u ***matchesp, int flags, int /* * Read and parse the lines in the file one by one */ - for (;; ) { + for (;;) { // check for CTRL-C typed, more often when jumping around if (state == TS_BINARY || state == TS_SKIP_BACK) { line_breakcheck(); @@ -2403,7 +2403,7 @@ int get_tagfname(tagname_T *tnp, int first, char_u *buf) * tnp->tn_did_filefind_init == FALSE: setup for next part in 'tags'. * tnp->tn_did_filefind_init == TRUE: find next file in this part. */ - for (;; ) { + for (;;) { if (tnp->tn_did_filefind_init) { fname = vim_findfile(tnp->tn_search_ctx); if (fname != NULL) { @@ -2687,7 +2687,7 @@ static int jumpto_tag(const char_u *lbuf_arg, int forceit, int keep_help) // copy the command to pbuf[], remove trailing CR/NL str = tagp.command; - for (pbuf_end = pbuf; *str && *str != '\n' && *str != '\r'; ) { + for (pbuf_end = pbuf; *str && *str != '\n' && *str != '\r';) { *pbuf_end++ = *str++; if (pbuf_end - pbuf + 1 >= LSIZE) { break; @@ -3056,7 +3056,7 @@ static int find_extra(char_u **pp) char_u first_char = **pp; // Repeat for addresses separated with ';' - for (;; ) { + for (;;) { if (ascii_isdigit(*str)) { str = skipdigits(str + 1); } else if (*str == '/' || *str == '?') { diff --git a/src/nvim/testdir/test_arglist.vim b/src/nvim/testdir/test_arglist.vim index 8fd60d6a5a..164149476f 100644 --- a/src/nvim/testdir/test_arglist.vim +++ b/src/nvim/testdir/test_arglist.vim @@ -1,5 +1,9 @@ " Test argument list commands +func Reset_arglist() + args a | %argd +endfunc + func Test_argidx() args a b c last @@ -26,6 +30,8 @@ func Test_argidx() endfunc func Test_argadd() + call Reset_arglist() + %argdelete argadd a b c call assert_equal(0, argidx()) @@ -115,8 +121,7 @@ endfunc " Test for [count]argument and [count]argdelete commands " Ported from the test_argument_count.in test script func Test_argument() - " Clean the argument list - arga a | %argd + call Reset_arglist() let save_hidden = &hidden set hidden @@ -244,8 +249,7 @@ endfunc " Test for 0argadd and 0argedit " Ported from the test_argument_0count.in test script func Test_zero_argadd() - " Clean the argument list - arga a | %argd + call Reset_arglist() arga a b c d 2argu @@ -272,10 +276,6 @@ func Test_zero_argadd() call assert_equal('file with spaces', expand('%')) endfunc -func Reset_arglist() - args a | %argd -endfunc - " Test for argc() func Test_argc() call Reset_arglist() diff --git a/src/nvim/testdir/test_autochdir.vim b/src/nvim/testdir/test_autochdir.vim index 0b76828dd7..9ad727241e 100644 --- a/src/nvim/testdir/test_autochdir.vim +++ b/src/nvim/testdir/test_autochdir.vim @@ -26,4 +26,42 @@ func Test_set_filename() call delete('samples/Xtest') endfunc +func Test_verbose_pwd() + CheckFunction test_autochdir + let cwd = getcwd() + call test_autochdir() + + edit global.txt + call assert_match('\[global\].*testdir$', execute('verbose pwd')) + + call mkdir('Xautodir') + split Xautodir/local.txt + lcd Xautodir + call assert_match('\[window\].*testdir[/\\]Xautodir', execute('verbose pwd')) + + set acd + wincmd w + call assert_match('\[autochdir\].*testdir$', execute('verbose pwd')) + execute 'lcd' cwd + call assert_match('\[window\].*testdir$', execute('verbose pwd')) + execute 'tcd' cwd + call assert_match('\[tabpage\].*testdir$', execute('verbose pwd')) + execute 'cd' cwd + call assert_match('\[global\].*testdir$', execute('verbose pwd')) + edit + call assert_match('\[autochdir\].*testdir$', execute('verbose pwd')) + wincmd w + call assert_match('\[autochdir\].*testdir[/\\]Xautodir', execute('verbose pwd')) + set noacd + call assert_match('\[autochdir\].*testdir[/\\]Xautodir', execute('verbose pwd')) + wincmd w + call assert_match('\[global\].*testdir', execute('verbose pwd')) + wincmd w + call assert_match('\[window\].*testdir[/\\]Xautodir', execute('verbose pwd')) + + bwipe! + call chdir(cwd) + call delete('Xautodir', 'rf') +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim index c350a17236..0c8b8a45d9 100644 --- a/src/nvim/testdir/test_autocmd.vim +++ b/src/nvim/testdir/test_autocmd.vim @@ -222,6 +222,7 @@ func Test_win_tab_autocmd() augroup testing au WinNew * call add(g:record, 'WinNew') + au WinClosed * call add(g:record, 'WinClosed') au WinEnter * call add(g:record, 'WinEnter') au WinLeave * call add(g:record, 'WinLeave') au TabNew * call add(g:record, 'TabNew') @@ -238,8 +239,8 @@ func Test_win_tab_autocmd() call assert_equal([ \ 'WinLeave', 'WinNew', 'WinEnter', \ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter', - \ 'WinLeave', 'TabLeave', 'TabClosed', 'WinEnter', 'TabEnter', - \ 'WinLeave', 'WinEnter' + \ 'WinLeave', 'TabLeave', 'WinClosed', 'TabClosed', 'WinEnter', 'TabEnter', + \ 'WinLeave', 'WinClosed', 'WinEnter' \ ], g:record) let g:record = [] @@ -250,7 +251,7 @@ func Test_win_tab_autocmd() call assert_equal([ \ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter', \ 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter', - \ 'TabClosed' + \ 'WinClosed', 'TabClosed' \ ], g:record) augroup testing @@ -259,6 +260,45 @@ func Test_win_tab_autocmd() unlet g:record endfunc +func Test_WinClosed() + " Test that the pattern is matched against the closed window's ID, and both + " <amatch> and <afile> are set to it. + new + let winid = win_getid() + let g:matched = v:false + augroup test-WinClosed + autocmd! + execute 'autocmd WinClosed' winid 'let g:matched = v:true' + autocmd WinClosed * let g:amatch = str2nr(expand('<amatch>')) + autocmd WinClosed * let g:afile = str2nr(expand('<afile>')) + augroup END + close + call assert_true(g:matched) + call assert_equal(winid, g:amatch) + call assert_equal(winid, g:afile) + + " Test that WinClosed is non-recursive. + new + new + call assert_equal(3, winnr('$')) + let g:triggered = 0 + augroup test-WinClosed + autocmd! + autocmd WinClosed * let g:triggered += 1 + autocmd WinClosed * 2 wincmd c + augroup END + close + call assert_equal(1, winnr('$')) + call assert_equal(1, g:triggered) + + autocmd! test-WinClosed + augroup! test-WinClosed + unlet g:matched + unlet g:amatch + unlet g:afile + unlet g:triggered +endfunc + func s:AddAnAutocmd() augroup vimBarTest au BufReadCmd * echo 'hello' diff --git a/src/nvim/testdir/test_bufwintabinfo.vim b/src/nvim/testdir/test_bufwintabinfo.vim index bb672cf0ec..c04c8fbf60 100644 --- a/src/nvim/testdir/test_bufwintabinfo.vim +++ b/src/nvim/testdir/test_bufwintabinfo.vim @@ -1,108 +1,110 @@ " Tests for the getbufinfo(), getwininfo() and gettabinfo() functions function Test_getbufwintabinfo() - edit Xtestfile1 - edit Xtestfile2 - let buflist = getbufinfo() - call assert_equal(2, len(buflist)) - call assert_match('Xtestfile1', buflist[0].name) - call assert_match('Xtestfile2', getbufinfo('Xtestfile2')[0].name) - call assert_equal([], getbufinfo(2016)) - edit Xtestfile1 - hide edit Xtestfile2 - hide enew - call assert_equal(3, len(getbufinfo({'bufloaded':1}))) - - set tabstop&vim - let b:editor = 'vim' + edit Xtestfile1 + edit Xtestfile2 + let buflist = getbufinfo() + call assert_equal(2, len(buflist)) + call assert_match('Xtestfile1', buflist[0].name) + call assert_match('Xtestfile2', getbufinfo('Xtestfile2')[0].name) + call assert_equal([], getbufinfo(2016)) + edit Xtestfile1 + hide edit Xtestfile2 + hide enew + call assert_equal(3, len(getbufinfo({'bufloaded':1}))) + + set tabstop&vim + let b:editor = 'vim' + let l = getbufinfo('%') + call assert_equal(bufnr('%'), l[0].bufnr) + call assert_equal('vim', l[0].variables.editor) + call assert_notequal(-1, index(l[0].windows, '%'->bufwinid())) + + " Test for getbufinfo() with 'bufmodified' + call assert_equal(0, len(getbufinfo({'bufmodified' : 1}))) + call setbufline('Xtestfile1', 1, ["Line1"]) + let l = getbufinfo({'bufmodified' : 1}) + call assert_equal(1, len(l)) + call assert_equal(bufnr('Xtestfile1'), l[0].bufnr) + + if has('signs') + call append(0, ['Linux', 'Windows', 'Mac']) + sign define Mark text=>> texthl=Search + exe "sign place 2 line=3 name=Mark buffer=" . bufnr('%') let l = getbufinfo('%') - call assert_equal(bufnr('%'), l[0].bufnr) - call assert_equal('vim', l[0].variables.editor) - call assert_notequal(-1, index(l[0].windows, '%'->bufwinid())) - - " Test for getbufinfo() with 'bufmodified' - call assert_equal(0, len(getbufinfo({'bufmodified' : 1}))) - call setbufline('Xtestfile1', 1, ["Line1"]) - let l = getbufinfo({'bufmodified' : 1}) - call assert_equal(1, len(l)) - call assert_equal(bufnr('Xtestfile1'), l[0].bufnr) - - if has('signs') - call append(0, ['Linux', 'Windows', 'Mac']) - sign define Mark text=>> texthl=Search - exe "sign place 2 line=3 name=Mark buffer=" . bufnr('%') - let l = getbufinfo('%') - call assert_equal(2, l[0].signs[0].id) - call assert_equal(3, l[0].signs[0].lnum) - call assert_equal('Mark', l[0].signs[0].name) - sign unplace * - sign undefine Mark - enew! - endif - - only - let w1_id = win_getid() - new - let w2_id = win_getid() - tabnew | let w3_id = win_getid() - new | let w4_id = win_getid() - vert new | let w5_id = win_getid() - call setwinvar(0, 'signal', 'green') - tabfirst - let winlist = getwininfo() - call assert_equal(5, len(winlist)) - call assert_equal(winwidth(1), winlist[0].width) - call assert_equal(1, winlist[0].wincol) - " tabline adds one row in terminal, not in GUI - let tablineheight = winlist[0].winrow == 2 ? 1 : 0 - call assert_equal(tablineheight + 1, winlist[0].winrow) - - call assert_equal(winbufnr(2), winlist[1].bufnr) - call assert_equal(winheight(2), winlist[1].height) - call assert_equal(1, winlist[1].wincol) - call assert_equal(tablineheight + winheight(1) + 2, winlist[1].winrow) - - call assert_equal(1, winlist[2].winnr) - call assert_equal(tablineheight + 1, winlist[2].winrow) - call assert_equal(1, winlist[2].wincol) - - call assert_equal(winlist[2].width + 2, winlist[3].wincol) - call assert_equal(1, winlist[4].wincol) - - call assert_equal(1, winlist[0].tabnr) - call assert_equal(1, winlist[1].tabnr) - call assert_equal(2, winlist[2].tabnr) - call assert_equal(2, winlist[3].tabnr) - call assert_equal(2, winlist[4].tabnr) - - call assert_equal('green', winlist[2].variables.signal) - call assert_equal(w4_id, winlist[3].winid) - let winfo = w5_id->getwininfo()[0] - call assert_equal(2, winfo.tabnr) - call assert_equal([], getwininfo(3)) - - call settabvar(1, 'space', 'build') - let tablist = gettabinfo() - call assert_equal(2, len(tablist)) - call assert_equal(3, len(tablist[1].windows)) - call assert_equal(2, tablist[1].tabnr) - call assert_equal('build', tablist[0].variables.space) - call assert_equal(w2_id, tablist[0].windows[0]) - call assert_equal([], 3->gettabinfo()) - - tabonly | only - - lexpr '' - lopen - copen - let winlist = getwininfo() - call assert_false(winlist[0].quickfix) - call assert_false(winlist[0].loclist) - call assert_true(winlist[1].quickfix) - call assert_true(winlist[1].loclist) - call assert_true(winlist[2].quickfix) - call assert_false(winlist[2].loclist) - wincmd t | only + call assert_equal(2, l[0].signs[0].id) + call assert_equal(3, l[0].signs[0].lnum) + call assert_equal('Mark', l[0].signs[0].name) + sign unplace * + sign undefine Mark + enew! + endif + + only + let w1_id = win_getid() + setl foldcolumn=3 + new + let w2_id = win_getid() + tabnew | let w3_id = win_getid() + new | let w4_id = win_getid() + vert new | let w5_id = win_getid() + call setwinvar(0, 'signal', 'green') + tabfirst + let winlist = getwininfo() + call assert_equal(5, len(winlist)) + call assert_equal(winwidth(1), winlist[0].width) + call assert_equal(1, winlist[0].wincol) + " tabline adds one row in terminal, not in GUI + let tablineheight = winlist[0].winrow == 2 ? 1 : 0 + call assert_equal(tablineheight + 1, winlist[0].winrow) + + call assert_equal(winbufnr(2), winlist[1].bufnr) + call assert_equal(winheight(2), winlist[1].height) + call assert_equal(1, winlist[1].wincol) + call assert_equal(3, winlist[1].textoff) " foldcolumn + call assert_equal(tablineheight + winheight(1) + 2, winlist[1].winrow) + + call assert_equal(1, winlist[2].winnr) + call assert_equal(tablineheight + 1, winlist[2].winrow) + call assert_equal(1, winlist[2].wincol) + + call assert_equal(winlist[2].width + 2, winlist[3].wincol) + call assert_equal(1, winlist[4].wincol) + + call assert_equal(1, winlist[0].tabnr) + call assert_equal(1, winlist[1].tabnr) + call assert_equal(2, winlist[2].tabnr) + call assert_equal(2, winlist[3].tabnr) + call assert_equal(2, winlist[4].tabnr) + + call assert_equal('green', winlist[2].variables.signal) + call assert_equal(w4_id, winlist[3].winid) + let winfo = w5_id->getwininfo()[0] + call assert_equal(2, winfo.tabnr) + call assert_equal([], getwininfo(3)) + + call settabvar(1, 'space', 'build') + let tablist = gettabinfo() + call assert_equal(2, len(tablist)) + call assert_equal(3, len(tablist[1].windows)) + call assert_equal(2, tablist[1].tabnr) + call assert_equal('build', tablist[0].variables.space) + call assert_equal(w2_id, tablist[0].windows[0]) + call assert_equal([], 3->gettabinfo()) + + tabonly | only + + lexpr '' + lopen + copen + let winlist = getwininfo() + call assert_false(winlist[0].quickfix) + call assert_false(winlist[0].loclist) + call assert_true(winlist[1].quickfix) + call assert_true(winlist[1].loclist) + call assert_true(winlist[2].quickfix) + call assert_false(winlist[2].loclist) + wincmd t | only endfunction function Test_get_buf_options() diff --git a/src/nvim/testdir/test_cd.vim b/src/nvim/testdir/test_cd.vim index 0bba321ee2..57db0a2544 100644 --- a/src/nvim/testdir/test_cd.vim +++ b/src/nvim/testdir/test_cd.vim @@ -215,3 +215,42 @@ func Test_cd_from_non_existing_dir() cd - call assert_equal(saveddir, getcwd()) endfunc + +func Test_cd_unknown_dir() + call mkdir('Xa') + cd Xa + call writefile(['text'], 'Xb.txt') + edit Xa/Xb.txt + let first_buf = bufnr() + cd .. + edit + call assert_equal(first_buf, bufnr()) + edit Xa/Xb.txt + call assert_notequal(first_buf, bufnr()) + + bwipe! + exe "bwipe! " .. first_buf + call delete('Xa', 'rf') +endfunc + +func Test_getcwd_actual_dir() + CheckFunction test_autochdir + let startdir = getcwd() + call mkdir('Xactual') + call test_autochdir() + set autochdir + edit Xactual/file.txt + call assert_match('testdir.Xactual$', getcwd()) + lcd .. + call assert_match('testdir$', getcwd()) + edit + call assert_match('testdir.Xactual$', getcwd()) + call assert_match('testdir$', getcwd(win_getid())) + + set noautochdir + bwipe! + call chdir(startdir) + call delete('Xactual', 'rf') +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim index 98340d0ac6..75e17b47b8 100644 --- a/src/nvim/testdir/test_cmdline.vim +++ b/src/nvim/testdir/test_cmdline.vim @@ -428,14 +428,17 @@ func Test_getcompletion() call assert_equal([], l) func T(a, c, p) + let g:cmdline_compl_params = [a:a, a:c, a:p] return "oneA\noneB\noneC" endfunc command -nargs=1 -complete=custom,T MyCmd let l = getcompletion('MyCmd ', 'cmdline') call assert_equal(['oneA', 'oneB', 'oneC'], l) + call assert_equal(['', 'MyCmd ', 6], g:cmdline_compl_params) delcommand MyCmd delfunc T + unlet g:cmdline_compl_params " For others test if the name is recognized. let names = ['buffer', 'environment', 'file_in_path', 'mapping', 'tag', 'tag_listfiles', 'user'] diff --git a/src/nvim/testdir/test_execute_func.vim b/src/nvim/testdir/test_execute_func.vim index 15ba894dbe..f2c7da0aa9 100644 --- a/src/nvim/testdir/test_execute_func.vim +++ b/src/nvim/testdir/test_execute_func.vim @@ -107,6 +107,18 @@ func Test_win_execute() call win_gotoid(otherwin) bwipe! + + " check :lcd in another window does not change directory + let curid = win_getid() + let curdir = getcwd() + split Xother + lcd .. + " Use :pwd to get the actual current directory + let otherdir = execute('pwd') + call win_execute(curid, 'lcd testdir') + call assert_equal(otherdir, execute('pwd')) + bwipe! + execute 'cd ' .. curdir endfunc func Test_win_execute_update_ruler() diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim index d10fad690c..4a2ade5afa 100644 --- a/src/nvim/testdir/test_functions.vim +++ b/src/nvim/testdir/test_functions.vim @@ -1592,6 +1592,10 @@ func Test_bufadd_bufload() endfunc func Test_readdir() + if isdirectory('Xdir') + call delete('Xdir', 'rf') + endif + call mkdir('Xdir') call writefile([], 'Xdir/foo.txt') call writefile([], 'Xdir/bar.txt') diff --git a/src/nvim/testdir/test_highlight.vim b/src/nvim/testdir/test_highlight.vim index 6fd9477ce9..c38bfa5677 100644 --- a/src/nvim/testdir/test_highlight.vim +++ b/src/nvim/testdir/test_highlight.vim @@ -651,6 +651,16 @@ func Test_1_highlight_Normalgroup_exists() endif endfunc +function Test_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 + set columns=17 + let l:hi_StatusLineTermNC = join(split(execute('hi StatusLineTermNC'))) + call assert_match('StatusLineTermNC xxx', l:hi_StatusLineTermNC) + let &columns = l:org_columns +endfunction + " Test for using RGB color values in a highlight group func Test_xxlast_highlight_RGB_color() CheckCanRunGui diff --git a/src/nvim/testdir/test_listchars.vim b/src/nvim/testdir/test_listchars.vim index 7596b34433..9906b00222 100644 --- a/src/nvim/testdir/test_listchars.vim +++ b/src/nvim/testdir/test_listchars.vim @@ -286,6 +286,10 @@ func Test_listchars_unicode() call cursor(1, 1) call assert_equal(expected, ScreenLines(1, virtcol('$'))) + set listchars=eol:\\u21d4,space:\\u2423,multispace:≡\\u2262\\U00002263,nbsp:\\U00002260,tab:←↔\\u2192 + redraw! + call assert_equal(expected, ScreenLines(1, virtcol('$'))) + set listchars+=lead:⇨,trail:⇦ let expected = ['⇨⇨⇨⇨⇨⇨⇨⇨a←↔↔↔↔↔→b␣c≠d⇦⇦⇔'] redraw! diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index 8c6ce63ade..b38a59e98f 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -3653,6 +3653,9 @@ func Xqftick_tests(cchar) \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'r') call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick) + if isdirectory("Xone") + call delete("Xone", 'rf') + endif call writefile(["F8:80:L80", "F8:81:L81"], "Xone") Xfile Xone call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick) diff --git a/src/nvim/testdir/test_registers.vim b/src/nvim/testdir/test_registers.vim index fd8653a2eb..84a5aca3d5 100644 --- a/src/nvim/testdir/test_registers.vim +++ b/src/nvim/testdir/test_registers.vim @@ -43,6 +43,10 @@ func Test_yank_shows_register() endfunc func Test_display_registers() + " Disable clipboard + let save_clipboard = get(g:, 'clipboard', {}) + let g:clipboard = {} + e file1 e file2 call setline(1, ['foo', 'bar']) @@ -78,6 +82,7 @@ func Test_display_registers() \ . ' c ": ls', a) bwipe! + let g:clipboard = save_clipboard endfunc func Test_recording_status_in_ex_line() diff --git a/src/nvim/testdir/test_textobjects.vim b/src/nvim/testdir/test_textobjects.vim index c259453b5e..2b6bb8b302 100644 --- a/src/nvim/testdir/test_textobjects.vim +++ b/src/nvim/testdir/test_textobjects.vim @@ -421,4 +421,36 @@ func Test_textobj_quote() close! endfunc +" Test for i(, i<, etc. when cursor is in front of a block +func Test_textobj_find_paren_forward() + new + + " i< and a> when cursor is in front of a block + call setline(1, '#include <foo.h>') + normal 0yi< + call assert_equal('foo.h', @") + normal 0ya> + call assert_equal('<foo.h>', @") + + " 2i(, 3i( in front of a block enters second/third nested '(' + call setline(1, 'foo (bar (baz (quux)))') + normal 0yi) + call assert_equal('bar (baz (quux))', @") + normal 02yi) + call assert_equal('baz (quux)', @") + normal 03yi) + call assert_equal('quux', @") + + " 3i( in front of a block doesn't enter third but un-nested '(' + call setline(1, 'foo (bar (baz) (quux))') + normal 03di) + call assert_equal('foo (bar (baz) (quux))', getline(1)) + normal 02di) + call assert_equal('foo (bar () (quux))', getline(1)) + normal 0di) + call assert_equal('foo ()', getline(1)) + + close! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/undo.c b/src/nvim/undo.c index 7eb76abd2c..8161fce9f4 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -922,7 +922,7 @@ static u_header_T *unserialize_uhp(bufinfo_T *bi, const char *file_name) uhp->uh_time = undo_read_time(bi); // Unserialize optional fields. - for (;; ) { + for (;;) { int len = undo_read_byte(bi); if (len == EOF) { @@ -1504,7 +1504,7 @@ void u_read_undo(char *name, const char_u *hash, const char_u *orig_name FUNC_AT // Optional header fields. long last_save_nr = 0; - for (;; ) { + for (;;) { int len = undo_read_byte(&bi); if (len == 0 || len == EOF) { diff --git a/src/nvim/version.c b/src/nvim/version.c index 1fcbae8be3..5e2a81795a 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -458,11 +458,11 @@ static const int included_patches[] = { 1466, 1465, 1464, - // 1463, + 1463, 1462, - // 1461, - // 1460, - // 1459, + 1461, + 1460, + 1459, 1458, 1457, 1456, diff --git a/src/nvim/viml/parser/expressions.c b/src/nvim/viml/parser/expressions.c index 4f028fa87f..800ecf10db 100644 --- a/src/nvim/viml/parser/expressions.c +++ b/src/nvim/viml/parser/expressions.c @@ -1036,7 +1036,7 @@ void viml_pexpr_free_ast(ExprAST ast) ExprASTNode **const cur_node = kv_last(ast_stack); #ifndef NDEBUG // Explicitly check for AST recursiveness. - for (size_t i = 0 ; i < kv_size(ast_stack) - 1 ; i++) { + for (size_t i = 0; i < kv_size(ast_stack) - 1; i++) { assert(*kv_A(ast_stack, i) != *cur_node); } #endif diff --git a/src/nvim/window.c b/src/nvim/window.c index 26f483c842..e328ff5467 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -224,7 +224,7 @@ newwindow: beep_flush(); } else { if (Prenum) { // go to specified window - for (wp = firstwin; --Prenum > 0; ) { + for (wp = firstwin; --Prenum > 0;) { if (wp->w_next == NULL) { break; } else { @@ -1958,8 +1958,8 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int // Set the width/height of this frame. // Redraw when size or position changes if (topfr->fr_height != height || topfr->fr_win->w_winrow != row - || topfr->fr_width != width || - topfr->fr_win->w_wincol != col) { + || topfr->fr_width != width + || topfr->fr_win->w_wincol != col) { topfr->fr_win->w_winrow = row; frame_new_height(topfr, height, false, false); topfr->fr_win->w_wincol = col; @@ -2239,7 +2239,7 @@ void close_windows(buf_T *buf, int keep_curwin) ++RedrawingDisabled; - for (win_T *wp = firstwin; wp != NULL && !ONE_WINDOW; ) { + for (win_T *wp = firstwin; wp != NULL && !ONE_WINDOW;) { if (wp->w_buffer == buf && (!keep_curwin || wp != curwin) && !(wp->w_closing || wp->w_buffer->b_locked > 0)) { if (win_close(wp, false) == FAIL) { @@ -2582,7 +2582,7 @@ int win_close(win_T *win, bool free_buf) * If the cursor goes to the preview or the quickfix window, try * finding another window to go to. */ - for (;; ) { + for (;;) { if (wp->w_next == NULL) { wp = firstwin; } else { @@ -3147,12 +3147,12 @@ static void frame_new_height(frame_T *topfrp, int height, bool topfirst, bool wf break; } if (topfirst) { - do{ + do { frp = frp->fr_next; } while (wfh && frp != NULL && frame_fixed_height(frp)); } else { - do{ + do { frp = frp->fr_prev; } while (wfh && frp != NULL && frame_fixed_height(frp)); @@ -3347,12 +3347,12 @@ static void frame_new_width(frame_T *topfrp, int width, bool leftfirst, bool wfw break; } if (leftfirst) { - do{ + do { frp = frp->fr_next; } while (wfw && frp != NULL && frame_fixed_width(frp)); } else { - do{ + do { frp = frp->fr_prev; } while (wfw && frp != NULL && frame_fixed_width(frp)); @@ -4316,7 +4316,7 @@ win_T *win_vert_neighbor(tabpage_T *tp, win_T *wp, bool up, long count) * downwards neighbor. */ fr = foundfr; - for (;; ) { + for (;;) { if (fr == tp->tp_topframe) { goto end; } @@ -4334,7 +4334,7 @@ win_T *win_vert_neighbor(tabpage_T *tp, win_T *wp, bool up, long count) /* * Now go downwards to find the bottom or top frame in it. */ - for (;; ) { + for (;;) { if (nfr->fr_layout == FR_LEAF) { foundfr = nfr; break; @@ -4399,7 +4399,7 @@ win_T *win_horz_neighbor(tabpage_T *tp, win_T *wp, bool left, long count) * right neighbor. */ fr = foundfr; - for (;; ) { + for (;;) { if (fr == tp->tp_topframe) { goto end; } @@ -4417,7 +4417,7 @@ win_T *win_horz_neighbor(tabpage_T *tp, win_T *wp, bool left, long count) /* * Now go downwards to find the leftmost or rightmost frame in it. */ - for (;; ) { + for (;;) { if (nfr->fr_layout == FR_LEAF) { foundfr = nfr; break; @@ -4523,41 +4523,7 @@ static void win_enter_ext(win_T *const wp, const int flags) } changed_line_abv_curs(); // assume cursor position needs updating - // New directory is either the local directory of the window, tab or NULL. - char *new_dir = (char *)(curwin->w_localdir - ? curwin->w_localdir : curtab->tp_localdir); - - char cwd[MAXPATHL]; - if (os_dirname((char_u *)cwd, MAXPATHL) != OK) { - cwd[0] = NUL; - } - - if (new_dir) { - // Window/tab has a local directory: Save current directory as global - // (unless that was done already) and change to the local directory. - if (globaldir == NULL) { - if (cwd[0] != NUL) { - globaldir = (char_u *)xstrdup(cwd); - } - } - if (os_chdir(new_dir) == 0) { - if (!p_acd && pathcmp(new_dir, cwd, -1) != 0) { - do_autocmd_dirchanged(new_dir, curwin->w_localdir - ? kCdScopeWindow : kCdScopeTabpage, kCdCauseWindow); - } - shorten_fnames(true); - } - } else if (globaldir != NULL) { - // Window doesn't have a local directory and we are not in the global - // directory: Change to the global directory. - if (os_chdir((char *)globaldir) == 0) { - if (!p_acd && pathcmp((char *)globaldir, cwd, -1) != 0) { - do_autocmd_dirchanged((char *)globaldir, kCdScopeGlobal, kCdCauseWindow); - } - } - XFREE_CLEAR(globaldir); - shorten_fnames(true); - } + fix_current_dir(); if (flags & WEE_TRIGGER_NEW_AUTOCMDS) { apply_autocmds(EVENT_WINNEW, NULL, NULL, false, curbuf); @@ -4602,6 +4568,46 @@ static void win_enter_ext(win_T *const wp, const int flags) do_autochdir(); } +/// Used after making another window the current one: change directory if needed. +void fix_current_dir(void) +{ + // New directory is either the local directory of the window, tab or NULL. + char *new_dir = (char *)(curwin->w_localdir + ? curwin->w_localdir : curtab->tp_localdir); + char cwd[MAXPATHL]; + if (os_dirname((char_u *)cwd, MAXPATHL) != OK) { + cwd[0] = NUL; + } + + if (new_dir) { + // Window/tab has a local directory: Save current directory as global + // (unless that was done already) and change to the local directory. + if (globaldir == NULL) { + if (cwd[0] != NUL) { + globaldir = (char_u *)xstrdup(cwd); + } + } + if (os_chdir(new_dir) == 0) { + if (!p_acd && pathcmp(new_dir, cwd, -1) != 0) { + do_autocmd_dirchanged(new_dir, curwin->w_localdir + ? kCdScopeWindow : kCdScopeTabpage, kCdCauseWindow); + } + last_chdir_reason = NULL; + shorten_fnames(true); + } + } else if (globaldir != NULL) { + // Window doesn't have a local directory and we are not in the global + // directory: Change to the global directory. + if (os_chdir((char *)globaldir) == 0) { + if (!p_acd && pathcmp((char *)globaldir, cwd, -1) != 0) { + do_autocmd_dirchanged((char *)globaldir, kCdScopeGlobal, kCdCauseWindow); + } + } + XFREE_CLEAR(globaldir); + last_chdir_reason = NULL; + shorten_fnames(true); + } +} /// Jump to the first open window that contains buffer "buf", if one exists. /// Returns a pointer to the window found, otherwise NULL. @@ -5825,8 +5831,8 @@ void scroll_to_fraction(win_T *wp, int prev_height) // is visible. if (height > 0 && (!wp->w_p_scb || wp == curwin) - && (height < wp->w_buffer->b_ml.ml_line_count || - wp->w_topline > 1)) { + && (height < wp->w_buffer->b_ml.ml_line_count + || wp->w_topline > 1)) { /* * Find a value for w_topline that shows the cursor at the same * relative position in the window as before (more or less). @@ -6082,7 +6088,7 @@ void command_height(void) static void frame_add_height(frame_T *frp, int n) { frame_new_height(frp, frp->fr_height + n, false, false); - for (;; ) { + for (;;) { frp = frp->fr_parent; if (frp == NULL) { break; @@ -6626,6 +6632,9 @@ void restore_win_noblock(win_T *save_curwin, tabpage_T *save_curtab, bool no_dis curwin = save_curwin; curbuf = curwin->w_buffer; } + // If called by win_execute() and executing the command changed the + // directory, it now has to be restored. + fix_current_dir(); } /// Make "buf" the current buffer. @@ -7005,7 +7014,7 @@ int win_getid(typval_T *argvars) wp = tp->tp_firstwin; } } - for ( ; wp != NULL; wp = wp->w_next) { + for (; wp != NULL; wp = wp->w_next) { if (--winnr == 0) { return wp->handle; } diff --git a/src/uncrustify.cfg b/src/uncrustify.cfg index c06bf41d47..558fa1759f 100644 --- a/src/uncrustify.cfg +++ b/src/uncrustify.cfg @@ -141,7 +141,7 @@ sp_enum_before_assign = ignore # ignore/add/remove/force/not_defined # Add or remove space after assignment '=' in enum. # # Overrides sp_enum_assign. -sp_enum_after_assign = ignore # ignore/add/remove/force/not_defined +sp_enum_after_assign = force # ignore/add/remove/force/not_defined # Add or remove space around assignment ':' in enum. sp_enum_colon = ignore # ignore/add/remove/force/not_defined @@ -149,11 +149,11 @@ sp_enum_colon = ignore # ignore/add/remove/force/not_defined # Add or remove space around preprocessor '##' concatenation operator. # # Default: add -sp_pp_concat = ignore # ignore/add/remove/force/not_defined +sp_pp_concat = remove # ignore/add/remove/force/not_defined # Add or remove space after preprocessor '#' stringify operator. # Also affects the '#@' charizing operator. -sp_pp_stringify = ignore # ignore/add/remove/force/not_defined +sp_pp_stringify = remove # ignore/add/remove/force/not_defined # Add or remove space before preprocessor '#' stringify operator # as in '#define x(y) L#y'. @@ -334,10 +334,10 @@ sp_after_sparen = ignore # ignore/add/remove/force/not_defined sp_sparen_brace = ignore # ignore/add/remove/force/not_defined # Add or remove space between 'do' and '{'. -sp_do_brace_open = ignore # ignore/add/remove/force/not_defined +sp_do_brace_open = force # ignore/add/remove/force/not_defined # Add or remove space between '}' and 'while'. -sp_brace_close_while = ignore # ignore/add/remove/force/not_defined +sp_brace_close_while = force # ignore/add/remove/force/not_defined # Add or remove space between 'while' and '('. Overrides sp_before_sparen. sp_while_paren_open = ignore # ignore/add/remove/force/not_defined @@ -354,18 +354,18 @@ sp_special_semi = ignore # ignore/add/remove/force/not_defined # Add or remove space before ';'. # # Default: remove -sp_before_semi = ignore # ignore/add/remove/force/not_defined +sp_before_semi = remove # ignore/add/remove/force/not_defined # Add or remove space before ';' in non-empty 'for' statements. -sp_before_semi_for = ignore # ignore/add/remove/force/not_defined +sp_before_semi_for = remove # ignore/add/remove/force/not_defined # Add or remove space before a semicolon of an empty left part of a for # statement, as in 'for ( <here> ; ; )'. -sp_before_semi_for_empty = ignore # ignore/add/remove/force/not_defined +sp_before_semi_for_empty = remove # ignore/add/remove/force/not_defined # Add or remove space between the semicolons of an empty middle part of a for # statement, as in 'for ( ; <here> ; )'. -sp_between_semi_for_empty = ignore # ignore/add/remove/force/not_defined +sp_between_semi_for_empty = remove # ignore/add/remove/force/not_defined # Add or remove space after ';', except when followed by a comment. # @@ -379,10 +379,10 @@ sp_after_semi_for = force # ignore/add/remove/force/not_defined # Add or remove space after the final semicolon of an empty part of a for # statement, as in 'for ( ; ; <here> )'. -sp_after_semi_for_empty = ignore # ignore/add/remove/force/not_defined +sp_after_semi_for_empty = remove # ignore/add/remove/force/not_defined # Add or remove space before '[' (except '[]'). -sp_before_square = ignore # ignore/add/remove/force/not_defined +sp_before_square = remove # ignore/add/remove/force/not_defined # Add or remove space before '[' for a variable definition. # @@ -393,13 +393,13 @@ sp_before_vardef_square = remove # ignore/add/remove/force/not_defined sp_before_square_asm_block = ignore # ignore/add/remove/force/not_defined # Add or remove space before '[]'. -sp_before_squares = ignore # ignore/add/remove/force/not_defined +sp_before_squares = remove # ignore/add/remove/force/not_defined # Add or remove space before C++17 structured bindings. sp_cpp_before_struct_binding = ignore # ignore/add/remove/force/not_defined # Add or remove space inside a non-empty '[' and ']'. -sp_inside_square = ignore # ignore/add/remove/force/not_defined +sp_inside_square = remove # ignore/add/remove/force/not_defined # Add or remove space inside '[]'. sp_inside_square_empty = ignore # ignore/add/remove/force/not_defined @@ -592,18 +592,18 @@ sp_func_def_paren_empty = ignore # ignore/add/remove/force/not_defined # Add or remove space inside empty function '()'. # Overrides sp_after_angle unless use_sp_after_angle_always is set to true. -sp_inside_fparens = ignore # ignore/add/remove/force/not_defined +sp_inside_fparens = remove # ignore/add/remove/force/not_defined # Add or remove space inside function '(' and ')'. -sp_inside_fparen = ignore # ignore/add/remove/force/not_defined +sp_inside_fparen = remove # ignore/add/remove/force/not_defined # Add or remove space inside the first parentheses in a function type, as in # 'void (*x)(...)'. -sp_inside_tparen = ignore # ignore/add/remove/force/not_defined +sp_inside_tparen = remove # ignore/add/remove/force/not_defined # Add or remove space between the ')' and '(' in a function type, as in # 'void (*x)(...)'. -sp_after_tparen_close = ignore # ignore/add/remove/force/not_defined +sp_after_tparen_close = remove # ignore/add/remove/force/not_defined # Add or remove space between ']' and '(' when part of a function call. sp_square_fparen = ignore # ignore/add/remove/force/not_defined @@ -649,7 +649,7 @@ sp_func_class_paren = ignore # ignore/add/remove/force/not_defined sp_func_class_paren_empty = ignore # ignore/add/remove/force/not_defined # Add or remove space between 'return' and '('. -sp_return_paren = ignore # ignore/add/remove/force/not_defined +sp_return_paren = force # ignore/add/remove/force/not_defined # Add or remove space between 'return' and '{'. sp_return_brace = ignore # ignore/add/remove/force/not_defined @@ -714,7 +714,7 @@ sp_else_brace = add # ignore/add/remove/force/not_defined sp_brace_else = add # ignore/add/remove/force/not_defined # Add or remove space between '}' and the name of a typedef on the same line. -sp_brace_typedef = ignore # ignore/add/remove/force/not_defined +sp_brace_typedef = force # ignore/add/remove/force/not_defined # Add or remove space before the '{' of a 'catch' statement, if the '{' and # 'catch' are on the same line, as in 'catch (decl) <here> {'. @@ -1632,7 +1632,7 @@ nl_using_brace = ignore # ignore/add/remove/force/not_defined nl_brace_brace = ignore # ignore/add/remove/force/not_defined # Add or remove newline between 'do' and '{'. -nl_do_brace = ignore # ignore/add/remove/force/not_defined +nl_do_brace = remove # ignore/add/remove/force/not_defined # Add or remove newline between '}' and 'while' of 'do' statement. nl_brace_while = ignore # ignore/add/remove/force/not_defined @@ -2333,7 +2333,7 @@ pos_arith = ignore # ignore/break/force/lead/trail/join/ pos_assign = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force # The position of Boolean operators in wrapped expressions. -pos_bool = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force +pos_bool = lead # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force # The position of comparison operators in wrapped expressions. pos_compare = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force @@ -3307,5 +3307,5 @@ set QUESTION REAL_FATTR_CONST set QUESTION REAL_FATTR_NONNULL_ALL set QUESTION REAL_FATTR_PURE set QUESTION REAL_FATTR_WARN_UNUSED_RESULT -# option(s) with 'not default' value: 69 +# option(s) with 'not default' value: 87 # diff --git a/test/functional/ex_cmds/cd_spec.lua b/test/functional/ex_cmds/cd_spec.lua index 283fcf9672..f9cce0deb6 100644 --- a/test/functional/ex_cmds/cd_spec.lua +++ b/test/functional/ex_cmds/cd_spec.lua @@ -294,7 +294,16 @@ describe("getcwd()", function () command('set autochdir') command('edit ' .. directories.global .. '/foo') eq(curdir .. pathsep .. directories.global, cwd()) + eq(curdir, wcwd()) + call('mkdir', 'bar') + command('edit ' .. 'bar/foo') + eq(curdir .. pathsep .. directories.global .. pathsep .. 'bar', cwd()) + eq(curdir, wcwd()) + command('lcd ..') + eq(curdir .. pathsep .. directories.global, cwd()) + eq(curdir .. pathsep .. directories.global, wcwd()) + command('edit') + eq(curdir .. pathsep .. directories.global .. pathsep .. 'bar', cwd()) + eq(curdir .. pathsep .. directories.global, wcwd()) end) end) - - diff --git a/test/functional/legacy/autochdir_spec.lua b/test/functional/legacy/autochdir_spec.lua index 466e3ed830..37a94476a0 100644 --- a/test/functional/legacy/autochdir_spec.lua +++ b/test/functional/legacy/autochdir_spec.lua @@ -1,10 +1,11 @@ local lfs = require('lfs') local helpers = require('test.functional.helpers')(after_each) -local clear, eq = helpers.clear, helpers.eq -local eval, command = helpers.eval, helpers.command +local clear, eq, matches = helpers.clear, helpers.eq, helpers.matches +local eval, command, call = helpers.eval, helpers.command, helpers.call +local exec_capture = helpers.exec_capture describe('autochdir behavior', function() - local dir = 'Xtest-functional-legacy-autochdir' + local dir = 'Xtest_functional_legacy_autochdir' before_each(function() lfs.mkdir(dir) @@ -23,4 +24,35 @@ describe('autochdir behavior', function() eq('Xtest', eval("expand('%')")) eq(dir, eval([[substitute(getcwd(), '.*[/\\]\(\k*\)', '\1', '')]])) end) + + it(':verbose pwd shows whether autochdir is used', function() + local subdir = 'Xautodir' + command('cd '..dir) + local cwd = eval('getcwd()') + command('edit global.txt') + matches('%[global%].*'..dir, exec_capture('verbose pwd')) + call('mkdir', subdir) + command('split '..subdir..'/local.txt') + command('lcd '..subdir) + matches('%[window%].*'..dir..'[/\\]'..subdir, exec_capture('verbose pwd')) + command('set autochdir') + command('wincmd w') + matches('%[autochdir%].*'..dir, exec_capture('verbose pwd')) + command('lcd '..cwd) + matches('%[window%].*'..dir, exec_capture('verbose pwd')) + command('tcd '..cwd) + matches('%[tabpage%].*'..dir, exec_capture('verbose pwd')) + command('cd '..cwd) + matches('%[global%].*'..dir, exec_capture('verbose pwd')) + command('edit') + matches('%[autochdir%].*'..dir, exec_capture('verbose pwd')) + command('wincmd w') + matches('%[autochdir%].*'..dir..'[/\\]'..subdir, exec_capture('verbose pwd')) + command('set noautochdir') + matches('%[autochdir%].*'..dir..'[/\\]'..subdir, exec_capture('verbose pwd')) + command('wincmd w') + matches('%[global%].*'..dir, exec_capture('verbose pwd')) + command('wincmd w') + matches('%[window%].*'..dir..'[/\\]'..subdir, exec_capture('verbose pwd')) + end) end) diff --git a/test/functional/legacy/fnamemodify_spec.lua b/test/functional/legacy/fnamemodify_spec.lua index 6a5538c26f..6262db3a2f 100644 --- a/test/functional/legacy/fnamemodify_spec.lua +++ b/test/functional/legacy/fnamemodify_spec.lua @@ -29,7 +29,7 @@ describe('filename modifiers', function() call assert_equal('test.out', fnamemodify('test.out', ':.')) call assert_equal('../testdir/a', fnamemodify('../testdir/a', ':.')) call assert_equal(fnamemodify(tmpdir, ':~').'/test.out', fnamemodify('test.out', ':~')) - call assert_equal('../testdir/a', fnamemodify('../testdir/a', ':~')) + call assert_equal(fnamemodify(tmpdir, ':~').'/../testdir/a', fnamemodify('../testdir/a', ':~')) call assert_equal('a', fnamemodify('../testdir/a', ':t')) call assert_equal('', fnamemodify('.', ':p:t')) call assert_equal('test.out', fnamemodify('test.out', ':p:t')) diff --git a/test/functional/legacy/packadd_spec.lua b/test/functional/legacy/packadd_spec.lua index 48cd3ef9f8..4f9f5a0237 100644 --- a/test/functional/legacy/packadd_spec.lua +++ b/test/functional/legacy/packadd_spec.lua @@ -20,6 +20,9 @@ describe('packadd', function() func SetUp() let s:topdir = expand(getcwd() . '/Xdir') + if isdirectory(s:topdir) + call delete(s:topdir, 'rf') + endif exe 'set packpath=' . s:topdir let s:plugdir = expand(s:topdir . '/pack/mine/opt/mytest') endfunc diff --git a/test/functional/lua/diagnostic_spec.lua b/test/functional/lua/diagnostic_spec.lua index 6414483c0d..348b9de816 100644 --- a/test/functional/lua/diagnostic_spec.lua +++ b/test/functional/lua/diagnostic_spec.lua @@ -110,17 +110,21 @@ describe('vim.diagnostic', function() it('retrieves diagnostics from all buffers and namespaces', function() local result = exec_lua [[ - vim.diagnostic.set(diagnostic_ns, 1, { + local other_bufnr = vim.api.nvim_create_buf(true, false) + local lines = {"1st line of text", "2nd line of text", "wow", "cool", "more", "lines"} + vim.api.nvim_buf_set_lines(other_bufnr, 0, 1, false, lines) + + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { make_error('Diagnostic #1', 1, 1, 1, 1), make_error('Diagnostic #2', 2, 1, 2, 1), }) - vim.diagnostic.set(other_ns, 2, { + vim.diagnostic.set(other_ns, other_bufnr, { make_error('Diagnostic #3', 3, 1, 3, 1), }) return vim.diagnostic.get() ]] eq(3, #result) - eq(2, exec_lua([[return #vim.tbl_filter(function(d) return d.bufnr == 1 end, ...)]], result)) + eq(2, exec_lua([[return #vim.tbl_filter(function(d) return d.bufnr == diagnostic_bufnr end, ...)]], result)) eq('Diagnostic #1', result[1].message) end) @@ -339,6 +343,16 @@ describe('vim.diagnostic', function() eq(0, result[5]) eq(3, result[6]) end) + + it("doesn't error after bwipeout on buffer", function() + exec_lua [[ + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { lnum = 0, end_lnum = 0, col = 0, end_col = 0 }) + vim.cmd("bwipeout! " .. diagnostic_bufnr) + + vim.diagnostic.show(diagnostic_ns) + vim.diagnostic.hide(diagnostic_ns) + ]] + end) end) describe('enable() and disable()', function() @@ -625,6 +639,15 @@ describe('vim.diagnostic', function() ]]) end) + + it("doesn't error after bwipeout called on buffer", function() + exec_lua [[ + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { lnum = 0, end_lnum = 0, col = 0, end_col = 0 }) + vim.cmd("bwipeout! " .. diagnostic_bufnr) + + vim.diagnostic.reset(diagnostic_ns) + ]] + end) end) describe('get_next_pos()', function() @@ -682,6 +705,19 @@ describe('vim.diagnostic', function() return vim.diagnostic.get_prev_pos { namespace = diagnostic_ns } ]]) end) + + it('works with diagnostics past the end of the line #16349', function() + eq({4, 0}, exec_lua [[ + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_error('Diagnostic #1', 3, 9001, 3, 9001), + make_error('Diagnostic #2', 4, 0, 4, 0), + }) + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.api.nvim_win_set_cursor(0, {1, 1}) + vim.diagnostic.goto_next { float = false } + return vim.diagnostic.get_next_pos { namespace = diagnostic_ns } + ]]) + end) end) describe('get_prev_pos()', function() diff --git a/test/functional/lua/uri_spec.lua b/test/functional/lua/uri_spec.lua index 81f1820986..dbfbe2dbfe 100644 --- a/test/functional/lua/uri_spec.lua +++ b/test/functional/lua/uri_spec.lua @@ -143,8 +143,8 @@ describe('URI methods', function() end) it('uri_to_fname returns non-file scheme URI without authority unchanged', function() - eq('zipfile:/path/to/archive.zip%3A%3Afilename.txt', exec_lua [[ - return vim.uri_to_fname('zipfile:/path/to/archive.zip%3A%3Afilename.txt') + eq('zipfile:///path/to/archive.zip%3A%3Afilename.txt', exec_lua [[ + return vim.uri_to_fname('zipfile:///path/to/archive.zip%3A%3Afilename.txt') ]]) end) end) @@ -186,7 +186,7 @@ describe('URI methods', function() end) it('uri_to_bufnr & uri_from_bufnr returns original uri for non-file uris without authority', function() - local uri = 'zipfile:/path/to/archive.zip%3A%3Afilename.txt' + local uri = 'zipfile:///path/to/archive.zip%3A%3Afilename.txt' local test_case = string.format([[ local uri = '%s' return vim.uri_from_bufnr(vim.uri_to_bufnr(uri)) diff --git a/test/functional/plugin/lsp/incremental_sync_spec.lua b/test/functional/plugin/lsp/incremental_sync_spec.lua index 890db4abf5..5dd34e7665 100644 --- a/test/functional/plugin/lsp/incremental_sync_spec.lua +++ b/test/functional/plugin/lsp/incremental_sync_spec.lua @@ -297,7 +297,31 @@ describe('incremental synchronization', function() } test_edit({"🔥"}, {"x"}, expected_text_changes, 'utf-16', '\n') end) - it('deleting a multiple lines containing multibyte characters', function() + it('deleting a multibyte character from a long line', function() + local expected_text_changes = { + { + range = { + ['start'] = { + character = 85, + line = 1 + }, + ['end'] = { + character = 86, + line = 1 + } + }, + rangeLength = 1, + text = '' + } + } + local original_lines = { + "\\begin{document}", + "→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→", + "\\end{document}", + } + test_edit(original_lines, {"jx"}, expected_text_changes, 'utf-16', '\n') + end) + it('deleting multiple lines containing multibyte characters', function() local expected_text_changes = { { range = { diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index 228fc06e9b..b12d4227d5 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -66,7 +66,10 @@ local function fake_lsp_server_setup(test_name, timeout_ms, options) end end; }); - root_dir = vim.loop.cwd(); + workspace_folders = {{ + uri = 'file://' .. vim.loop.cwd(), + name = 'test_folder', + }}; on_init = function(client, result) TEST_RPC_CLIENT = client vim.rpcrequest(1, "init", result) @@ -153,7 +156,10 @@ describe('LSP', function() "-c", string.format("lua TEST_NAME = %q", test_name), "-c", "luafile "..fixture_filename; }; - root_dir = vim.loop.cwd(); + workspace_folders = {{ + uri = 'file://' .. vim.loop.cwd(), + name = 'test_folder', + }}; } end TEST_CLIENT1 = test__start_client() diff --git a/test/unit/path_spec.lua b/test/unit/path_spec.lua index 41954de9be..15ce59747e 100644 --- a/test/unit/path_spec.lua +++ b/test/unit/path_spec.lua @@ -54,15 +54,21 @@ describe('path.c', function() eq(lfs.currentdir(), (ffi.string(buffer))) end) - itp('fails if the given directory does not exist', function() - eq(FAIL, path_full_dir_name('does_not_exist', buffer, length)) - end) - itp('works with a normal relative dir', function() local result = path_full_dir_name('unit-test-directory', buffer, length) eq(lfs.currentdir() .. '/unit-test-directory', (ffi.string(buffer))) eq(OK, result) end) + + itp('works with a non-existing relative dir', function() + local result = path_full_dir_name('does-not-exist', buffer, length) + eq(lfs.currentdir() .. '/does-not-exist', (ffi.string(buffer))) + eq(OK, result) + end) + + itp('fails with a non-existing absolute dir', function() + eq(FAIL, path_full_dir_name('/does_not_exist', buffer, length)) + end) end) describe('path_full_compare', function() diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt index 8ad71cfd3a..1bdfa7a6dd 100644 --- a/third-party/CMakeLists.txt +++ b/third-party/CMakeLists.txt @@ -157,8 +157,8 @@ set(LUAJIT_SHA256 6c9e46877db2df16ca0fa76db4043ed30a1ae60c89d9ba2c3e4d35eb2360cd set(LUA_URL https://www.lua.org/ftp/lua-5.1.5.tar.gz) set(LUA_SHA256 2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333) -set(LUAROCKS_URL https://github.com/luarocks/luarocks/archive/v3.7.0.tar.gz) -set(LUAROCKS_SHA256 968c98ae894cea2c850f077133e3feb9f8ce94df7a33a5611bd4d25e07c94925) +set(LUAROCKS_URL https://github.com/luarocks/luarocks/archive/v3.8.0.tar.gz) +set(LUAROCKS_SHA256 ab6612ca9ab87c6984871d2712d05525775e8b50172701a0a1cabddf76de2be7) set(UNIBILIUM_URL https://github.com/neovim/unibilium/archive/92d929f.tar.gz) set(UNIBILIUM_SHA256 29815283c654277ef77a3adcc8840db79ddbb20a0f0b0c8f648bd8cd49a02e4b) |