diff options
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/autoload/health/nvim.vim | 2 | ||||
-rw-r--r-- | runtime/doc/api.txt | 25 | ||||
-rw-r--r-- | runtime/doc/deprecated.txt | 4 | ||||
-rw-r--r-- | runtime/doc/index.txt | 5 | ||||
-rw-r--r-- | runtime/doc/lsp.txt | 83 | ||||
-rw-r--r-- | runtime/doc/map.txt | 5 | ||||
-rw-r--r-- | runtime/doc/options.txt | 89 | ||||
-rw-r--r-- | runtime/doc/quickref.txt | 2 | ||||
-rw-r--r-- | runtime/doc/syntax.txt | 4 | ||||
-rw-r--r-- | runtime/doc/treesitter.txt | 2 | ||||
-rw-r--r-- | runtime/doc/various.txt | 8 | ||||
-rw-r--r-- | runtime/doc/vim_diff.txt | 2 | ||||
-rw-r--r-- | runtime/lua/vim/_editor.lua | 1 | ||||
-rw-r--r-- | runtime/lua/vim/filetype.lua | 100 | ||||
-rw-r--r-- | runtime/lua/vim/filetype/detect.lua | 573 | ||||
-rw-r--r-- | runtime/lua/vim/lsp.lua | 81 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/buf.lua | 37 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/handlers.lua | 8 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/health.lua | 3 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/util.lua | 33 | ||||
-rw-r--r-- | runtime/lua/vim/treesitter/languagetree.lua | 8 | ||||
-rw-r--r-- | runtime/optwin.vim | 1 |
22 files changed, 831 insertions, 245 deletions
diff --git a/runtime/autoload/health/nvim.vim b/runtime/autoload/health/nvim.vim index f3732e012f..9b387095ee 100644 --- a/runtime/autoload/health/nvim.vim +++ b/runtime/autoload/health/nvim.vim @@ -45,7 +45,7 @@ function! s:check_config() abort let shadafile = empty(&shada) ? &shada : substitute(matchstr( \ split(&shada, ',')[-1], '^n.\+'), '^n', '', '') let shadafile = empty(&shadafile) ? empty(shadafile) ? - \ stdpath('data').'/shada/main.shada' : expand(shadafile) + \ stdpath('state').'/shada/main.shada' : expand(shadafile) \ : &shadafile ==# 'NONE' ? '' : &shadafile if !empty(shadafile) && empty(glob(shadafile)) " Since this may be the first time neovim has been run, we will try to diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 9e5420c227..58ec9756a2 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -844,8 +844,11 @@ nvim_eval_statusline({str}, {*opts}) *nvim_eval_statusline()* Treated as single-width even if it isn't. • highlights: (boolean) Return highlight information. + • use_winbar: (boolean) Evaluate winbar instead of + statusline. • use_tabline: (boolean) Evaluate tabline instead of statusline. When |TRUE|, {winid} is ignored. + Mutually exclusive with {use_winbar}. Return: ~ Dictionary containing statusline information, with these @@ -1725,8 +1728,7 @@ Vimscript Functions *api-vimscript* 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. + On execution error: fails with VimL error, updates v:errmsg. Parameters: ~ {dict} Dictionary, or String evaluating to a VimL |self| @@ -1740,8 +1742,7 @@ nvim_call_dict_function({dict}, {fn}, {args}) 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. + On execution error: fails with VimL error, updates v:errmsg. Parameters: ~ {fn} Function to call @@ -1760,6 +1761,8 @@ nvim_cmd({*cmd}, {*opts}) *nvim_cmd()* argument, expanding filenames in a command that otherwise doesn't expand filenames, etc. + On execution error: fails with VimL error, updates v:errmsg. + Parameters: ~ {cmd} Command to execute. Must be a Dictionary that can contain the same values as the return value of @@ -1781,8 +1784,7 @@ nvim_cmd({*cmd}, {*opts}) *nvim_cmd()* nvim_command({command}) *nvim_command()* Executes an Ex command. - On execution error: fails with VimL error, does not update - v:errmsg. + On execution error: fails with VimL error, updates v:errmsg. Prefer using |nvim_cmd()| or |nvim_exec()| over this. To evaluate multiple lines of Vim script or an Ex command @@ -1798,8 +1800,7 @@ 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. + On execution error: fails with VimL error, updates v:errmsg. Parameters: ~ {expr} VimL expression string @@ -1814,8 +1815,7 @@ nvim_exec({src}, {output}) *nvim_exec()* Unlike |nvim_command()| this function supports heredocs, script-scope (s:), etc. - On execution error: fails with VimL error, does not update - v:errmsg. + On execution error: fails with VimL error, updates v:errmsg. Parameters: ~ {src} Vimscript code @@ -3468,6 +3468,8 @@ nvim_create_autocmd({event}, {*opts}) *nvim_create_autocmd()* • buf: (number) the expanded value of |<abuf>| • file: (string) the expanded value of |<afile>| + • data: (any) arbitrary data passed to + |nvim_exec_autocmds()| • command (string) optional: Vim command to execute on event. Cannot be used with @@ -3543,6 +3545,9 @@ nvim_exec_autocmds({event}, {*opts}) *nvim_exec_autocmds()* • modeline (bool) optional: defaults to true. Process the modeline after the autocommands |<nomodeline>|. + • data (any): arbitrary data to send to the + autocommand callback. See + |nvim_create_autocmd()| for details. See also: ~ |:doautocmd| diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt index 13644cf208..e328bd28b5 100644 --- a/runtime/doc/deprecated.txt +++ b/runtime/doc/deprecated.txt @@ -106,11 +106,13 @@ internally and are no longer exposed as part of the API. Instead, use *vim.lsp.diagnostic.set_underline()* *vim.lsp.diagnostic.set_virtual_text()* -LSP Utility Functions ~ +LSP Functions ~ *vim.lsp.util.diagnostics_to_items()* Use |vim.diagnostic.toqflist()| instead. *vim.lsp.util.set_qflist()* Use |setqflist()| instead. *vim.lsp.util.set_loclist()* Use |setloclist()| instead. +*vim.lsp.buf_get_clients()* Use |vim.lsp.get_active_clients()| with + {buffer = bufnr} instead. Lua ~ *vim.register_keystroke_callback()* Use |vim.on_key()| instead. diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt index 5c36eaf8e5..58d49b5843 100644 --- a/runtime/doc/index.txt +++ b/runtime/doc/index.txt @@ -1501,8 +1501,9 @@ tag command action ~ |:recover| :rec[over] recover a file from a swap file |:redo| :red[o] redo one undone change |:redir| :redi[r] redirect messages to a file or register -|:redraw| :redr[aw] force a redraw of the display -|:redrawstatus| :redraws[tatus] force a redraw of the status line(s) +|:redraw| :redr[aw] force a redraw of the display +|:redrawstatus| :redraws[tatus] force a redraw of the status line(s) and + window bar(s) |:redrawtabline| :redrawt[abline] force a redraw of the tabline |:registers| :reg[isters] display the contents of registers |:resize| :res[ize] change current window height diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index 569c570624..af3189a393 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -461,6 +461,39 @@ LspSignatureActiveParameter ============================================================================== EVENTS *lsp-events* + *LspAttach* +After an LSP client attaches to a buffer. The |autocmd-pattern| is the +name of the buffer. When used from Lua, the client ID is passed to the +callback in the "data" table. Example: > + + vim.api.nvim_create_autocmd("LspAttach", { + callback = function(args) + local bufnr = args.buf + local client = vim.lsp.get_client_by_id(args.data.client_id) + if client.server_capabilities.completionProvider then + vim.bo[bufnr].omnifunc = "v:lua.vim.lsp.omnifunc" + end + if client.server_capabilities.definitionProvider then + vim.bo[bufnr].tagfunc = "v:lua.vim.lsp.tagfunc" + end + end, + }) +< + *LspDetach* +Just before an LSP client detaches from a buffer. The |autocmd-pattern| is the +name of the buffer. When used from Lua, the client ID is passed to the +callback in the "data" table. Example: > + + vim.api.nvim_create_autocmd("LspDetach", { + callback = function(args) + local client = vim.lsp.get_client_by_id(args.data.client_id) + -- Do something with the client + vim.cmd("setlocal tagfunc< omnifunc<") + end, + }) +< +In addition, the following |User| |autocommands| are provided: + LspProgressUpdate *LspProgressUpdate* Upon receipt of a progress notification from the server. See |vim.lsp.util.get_progress_messages()|. @@ -498,14 +531,6 @@ buf_detach_client({bufnr}, {client_id}) *vim.lsp.buf_detach_client()* {bufnr} (number) Buffer handle, or 0 for current {client_id} (number) Client id -buf_get_clients({bufnr}) *vim.lsp.buf_get_clients()* - Gets a map of client_id:client pairs for the given buffer, - where each value is a |vim.lsp.client| object. - - Parameters: ~ - {bufnr} (optional, number): Buffer handle, or 0 for - current - buf_is_attached({bufnr}, {client_id}) *vim.lsp.buf_is_attached()* Checks if a buffer is attached for a particular client. @@ -696,11 +721,22 @@ formatexpr({opts}) *vim.lsp.formatexpr()* • timeout_ms (default 500ms). The timeout period for the formatting request. -get_active_clients() *vim.lsp.get_active_clients()* - Gets all active clients. +get_active_clients({filter}) *vim.lsp.get_active_clients()* + Get active clients. + + Parameters: ~ + {filter} (table|nil) A table with key-value pairs used to + filter the returned clients. The available keys + are: + • id (number): Only return clients with the + given id + • bufnr (number): Only return clients attached + to this buffer + • name (string): Only return clients with the + given name Return: ~ - Table of |vim.lsp.client| objects + (table) List of |vim.lsp.client| objects *vim.lsp.get_buffers_by_client_id()* get_buffers_by_client_id({client_id}) @@ -1015,15 +1051,25 @@ completion({context}) *vim.lsp.buf.completion()* See also: ~ |vim.lsp.protocol.constants.CompletionTriggerKind| -declaration() *vim.lsp.buf.declaration()* +declaration({options}) *vim.lsp.buf.declaration()* Jumps to the declaration of the symbol under the cursor. Note: Many servers do not implement this method. Generally, see |vim.lsp.buf.definition()| instead. -definition() *vim.lsp.buf.definition()* + Parameters: ~ + {options} (table|nil) additional options + • reuse_win: (boolean) Jump to existing window + if buffer is already open. + +definition({options}) *vim.lsp.buf.definition()* Jumps to the definition of the symbol under the cursor. + Parameters: ~ + {options} (table|nil) additional options + • reuse_win: (boolean) Jump to existing window + if buffer is already open. + document_highlight() *vim.lsp.buf.document_highlight()* Send request to the server to resolve document highlights for the current text document position. This request can be @@ -1250,10 +1296,15 @@ signature_help() *vim.lsp.buf.signature_help()* Displays signature information about the symbol under the cursor in a floating window. -type_definition() *vim.lsp.buf.type_definition()* +type_definition({options}) *vim.lsp.buf.type_definition()* Jumps to the definition of the type of the symbol under the cursor. + Parameters: ~ + {options} (table|nil) additional options + • reuse_win: (boolean) Jump to existing window + if buffer is already open. + workspace_symbol({query}) *vim.lsp.buf.workspace_symbol()* Lists all symbols in the current workspace in the quickfix window. @@ -1539,12 +1590,14 @@ get_effective_tabstop({bufnr}) *vim.lsp.util.get_effective_tabstop()* |shiftwidth| *vim.lsp.util.jump_to_location()* -jump_to_location({location}, {offset_encoding}) +jump_to_location({location}, {offset_encoding}, {reuse_win}) Jumps to a location. Parameters: ~ {location} (table) (`Location`|`LocationLink`) {offset_encoding} (string) utf-8|utf-16|utf-32 (required) + {reuse_win} (boolean) Jump to existing window if + buffer is already opened. Return: ~ `true` if the jump succeeded diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index 056e6c3b56..98da68b76a 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -796,9 +796,8 @@ command. For example: > :noremap j k This will exchange the cursor up and down commands. -With the normal :map command, when the 'remap' option is on, mapping takes -place until the text is found not to be a part of a {lhs}. For example, if -you use: > +With the normal :map command mapping takes place until the text is found not +to be a part of a {lhs}. For example, if you use: > :map x y :map y x Vim will replace x with y, and then y with x, etc. When this has happened diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 4d6f589714..0c2de7d6ee 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -776,7 +776,7 @@ A jump table for the options with a short description can be found at |Q_op|. oldest version of a file. *'backupcopy'* *'bkc'* -'backupcopy' 'bkc' string (Vi default for Unix: "yes", otherwise: "auto") +'backupcopy' 'bkc' string (default: "auto") global or local to buffer |global-local| When writing a file and a backup is made, this option tells how it's done. This is a comma-separated list of words. @@ -1192,7 +1192,7 @@ A jump table for the options with a short description can be found at |Q_op|. (parts of 'cdpath' can be passed to the shell to expand file names). *'cedit'* -'cedit' string (Vim default: CTRL-F, Vi default: "") +'cedit' string (default: CTRL-F) global The key used in Command-line Mode to open the command-line window. Only non-printable keys are allowed. @@ -1291,8 +1291,6 @@ A jump table for the options with a short description can be found at |Q_op|. *'cinscopedecls'* *'cinsd'* 'cinscopedecls' 'cinsd' string (default "public,protected,private") local to buffer - {not available when compiled without the |+cindent| - feature} Keywords that are interpreted as a C++ scope declaration by |cino-g|. Useful e.g. for working with the Qt framework that defines additional scope declarations "signals", "public slots" and "private slots": > @@ -1545,8 +1543,7 @@ A jump table for the options with a short description can be found at |Q_op|. See 'preserveindent'. *'cpoptions'* *'cpo'* *cpo* -'cpoptions' 'cpo' string (Vim default: "aABceFs_", - Vi default: all flags) +'cpoptions' 'cpo' string (default: "aABceFs_") global A sequence of single character flags. When a character is present this indicates Vi-compatible behavior. This is used for things where @@ -2115,7 +2112,7 @@ A jump table for the options with a short description can be found at |Q_op|. security reasons. *'display'* *'dy'* -'display' 'dy' string (default "lastline,msgsep", Vi default: "") +'display' 'dy' string (default "lastline,msgsep") global Change the way text is displayed. This is comma-separated list of flags: @@ -2361,9 +2358,8 @@ A jump table for the options with a short description can be found at |Q_op|. *'fileformats'* *'ffs'* 'fileformats' 'ffs' string (default: - Vim+Vi Win32: "dos,unix", - Vim Unix: "unix,dos", - Vi others: "") + Win32: "dos,unix", + Unix: "unix,dos") global This gives the end-of-line (<EOL>) formats that will be tried when starting to edit a new buffer and when reading a file into an existing @@ -2452,6 +2448,7 @@ A jump table for the options with a short description can be found at |Q_op|. item default Used for ~ stl:c ' ' or '^' statusline of the current window stlnc:c ' ' or '=' statusline of the non-current windows + wbr:c ' ' window bar horiz:c '─' or '-' horizontal separators |:split| horizup:c '┴' or '-' upwards facing horizontal separator horizdown:c '┬' or '-' downwards facing horizontal separator @@ -2492,6 +2489,7 @@ A jump table for the options with a short description can be found at |Q_op|. item highlight group ~ stl:c StatusLine |hl-StatusLine| stlnc:c StatusLineNC |hl-StatusLineNC| + wbr:c WinBar |hl-WinBar| or |hl-WinBarNC| horiz:c WinSeparator |hl-WinSeparator| horizup:c WinSeparator |hl-WinSeparator| horizdown:c WinSeparator |hl-WinSeparator| @@ -2719,7 +2717,7 @@ A jump table for the options with a short description can be found at |Q_op|. character and white space. *'formatoptions'* *'fo'* -'formatoptions' 'fo' string (default: "tcqj", Vi default: "vt") +'formatoptions' 'fo' string (default: "tcqj") local to buffer This is a sequence of letters which describes how automatic formatting is to be done. See |fo-table|. When the 'paste' option is @@ -3151,7 +3149,7 @@ A jump table for the options with a short description can be found at |Q_op|. 'hidden' is set for one command with ":hide {command}" |:hide|. *'history'* *'hi'* -'history' 'hi' number (Vim default: 10000, Vi default: 0) +'history' 'hi' number (default: 10000) global A history of ":" commands, and a history of previous search patterns is remembered. This option decides how many entries may be stored in @@ -3506,8 +3504,7 @@ A jump table for the options with a short description can be found at |Q_op|. change 'iskeyword' instead. *'iskeyword'* *'isk'* -'iskeyword' 'isk' string (default: @,48-57,_,192-255 - Vi default: @,48-57,_) +'iskeyword' 'isk' string (default: @,48-57,_,192-255) local to buffer Keywords are used in searching and recognizing with many commands: "w", "*", "[i", etc. It is also used for "\k" in a |pattern|. See @@ -3777,8 +3774,7 @@ A jump table for the options with a short description can be found at |Q_op|. changing the way tabs are displayed. *'listchars'* *'lcs'* -'listchars' 'lcs' string (default: "tab:> ,trail:-,nbsp:+" - Vi default: "eol:$") +'listchars' 'lcs' string (default: "tab:> ,trail:-,nbsp:+") global or local to window |global-local| Strings to use in 'list' mode and for the |:list| command. It is a comma-separated list of string settings. @@ -4046,8 +4042,7 @@ A jump table for the options with a short description can be found at |Q_op|. This option cannot be set from a |modeline| or in the |sandbox|. *'modeline'* *'ml'* *'nomodeline'* *'noml'* -'modeline' 'ml' boolean (Vim default: on (off for root), - Vi default: off) +'modeline' 'ml' boolean (default: on (off for root)) local to buffer If 'modeline' is on 'modelines' gives the number of lines that is checked for set commands. If 'modeline' is off or 'modelines' is zero @@ -4102,7 +4097,7 @@ A jump table for the options with a short description can be found at |Q_op|. when using "rA" on an "A". *'more'* *'nomore'* -'more' boolean (Vim default: on, Vi default: off) +'more' boolean (default: on) global When on, listings pause when the whole screen is filled. You will get the |more-prompt|. When this option is off there are no pauses, the @@ -4357,7 +4352,7 @@ A jump table for the options with a short description can be found at |Q_op|. |there | 4 there | 1 there | 1 there *'numberwidth'* *'nuw'* -'numberwidth' 'nuw' number (Vim default: 4 Vi default: 8) +'numberwidth' 'nuw' number (default: 4) local to window Minimal number of columns to use for the line number. Only relevant when the 'number' or 'relativenumber' option is set or printing lines @@ -4798,15 +4793,6 @@ A jump table for the options with a short description can be found at |Q_op|. 'number', see |number_relativenumber| for all combinations of the two options. - *'remap'* *'noremap'* -'remap' boolean (default on) - global - Allows for mappings to work recursively. If you do not want this for - a single entry, use the :noremap[!] command. - NOTE: To avoid portability problems with Vim scripts, always keep - this option at the default "on". Only switch it off when working with - old Vi scripts. - *'report'* 'report' number (default 2) global @@ -5122,9 +5108,7 @@ A jump table for the options with a short description can be found at |Q_op|. *'sessionoptions'* *'ssop'* 'sessionoptions' 'ssop' string (default: "blank,buffers,curdir,folds, - help,tabpages,winsize" - Vi default: "blank,buffers,curdir,folds, - help,options,tabpages,winsize") + help,tabpages,winsize") global Changes the effect of the |:mksession| command. It is a comma- separated list of words. Each word enables saving and restoring @@ -5164,10 +5148,9 @@ A jump table for the options with a short description can be found at |Q_op|. If you leave out "options" many things won't work well after restoring the session. *'shada'* *'sd'* *E526* *E527* *E528* -'shada' 'sd' string (Vim default for +'shada' 'sd' string (default for Win32: !,'100,<50,s10,h,rA:,rB: - others: !,'100,<50,s10,h - Vi default: "") + others: !,'100,<50,s10,h) global When non-empty, the shada file is read upon startup and written when exiting Vim (see |shada-file|). The string should be a comma- @@ -5445,7 +5428,7 @@ A jump table for the options with a short description can be found at |Q_op|. < Also see 'completeslash'. *'shelltemp'* *'stmp'* *'noshelltemp'* *'nostmp'* -'shelltemp' 'stmp' boolean (Vim default on, Vi default off) +'shelltemp' 'stmp' boolean (default on) global When on, use temp files for shell commands. When off use a pipe. When using a pipe is not possible temp files are used anyway. @@ -5494,7 +5477,7 @@ A jump table for the options with a short description can be found at |Q_op|. function to get the effective shiftwidth value. *'shortmess'* *'shm'* -'shortmess' 'shm' string (Vim default "filnxtToOF", Vi default: "S") +'shortmess' 'shm' string (default "filnxtToOF") global This option helps to avoid all the |hit-enter| prompts caused by file messages, for example with CTRL-G, and to avoid some other messages. @@ -5568,7 +5551,7 @@ A jump table for the options with a short description can be found at |Q_op|. :setlocal showbreak=NONE < *'showcmd'* *'sc'* *'noshowcmd'* *'nosc'* -'showcmd' 'sc' boolean (Vim default: on, Vi default: off) +'showcmd' 'sc' boolean (default: on) global Show (partial) command in the last line of the screen. Set this option off if your terminal is slow. @@ -5614,7 +5597,7 @@ A jump table for the options with a short description can be found at |Q_op|. Note: Use of the short form is rated PG. *'showmode'* *'smd'* *'noshowmode'* *'nosmd'* -'showmode' 'smd' boolean (Vim default: on, Vi default: off) +'showmode' 'smd' boolean (default: on) global If in Insert, Replace or Visual mode put a message on the last line. The |hl-ModeMsg| highlight group determines the highlighting. @@ -6398,7 +6381,7 @@ A jump table for the options with a short description can be found at |Q_op|. If non-zero, tags are significant up to this number of characters. *'tagrelative'* *'tr'* *'notagrelative'* *'notr'* -'tagrelative' 'tr' boolean (Vim default: on, Vi default: off) +'tagrelative' 'tr' boolean (default: on) global If on and using a tags file in another directory, file names in that tags file are relative to the directory where the tags file is. @@ -6478,13 +6461,6 @@ A jump table for the options with a short description can be found at |Q_op|. C1 Control characters 0x80...0x9F - *'terse'* *'noterse'* -'terse' boolean (default off) - global - When set: Add 's' flag to 'shortmess' option (this makes the message - for a search that hits the start or end of the file not being - displayed). When reset: Remove 's' flag from 'shortmess' option. - *'textwidth'* *'tw'* 'textwidth' 'tw' number (default 0) local to buffer @@ -6853,7 +6829,7 @@ A jump table for the options with a short description can be found at |Q_op|. has been changed. *'whichwrap'* *'ww'* -'whichwrap' 'ww' string (Vim default: "b,s", Vi default: "") +'whichwrap' 'ww' string (default: "b,s") global Allow specified keys that move the cursor left/right to move to the previous/next line when the cursor is on the first/last character in @@ -6883,7 +6859,7 @@ A jump table for the options with a short description can be found at |Q_op|. makes "dl", "cl", "yl" etc. work normally. *'wildchar'* *'wc'* -'wildchar' 'wc' number (Vim default: <Tab>, Vi default: CTRL-E) +'wildchar' 'wc' number (default: <Tab>) global Character you have to type to start wildcard expansion in the command-line, as specified with 'wildmode'. @@ -7045,6 +7021,19 @@ A jump table for the options with a short description can be found at |Q_op|. key is never used for the menu. This option is not used for <F10>; on Win32. + *'winbar'* *'wbr'* +'winbar' 'wbr' string (default empty) + global or local to window |global-local| + When non-empty, this option enables the window bar and determines its + contents. The window bar is a bar that's shown at the top of every + window with it enabled. The value of 'winbar' is evaluated like with + 'statusline'. + + When changing something that is used in 'winbar' that does not trigger + it to be updated, use |:redrawstatus|. + + This option cannot be set in a modeline when 'modelineexpr' is off. + *'winblend'* *'winbl'* 'winblend' 'winbl' number (default 0) local to window @@ -7186,7 +7175,7 @@ A jump table for the options with a short description can be found at |Q_op|. starts. When typing text beyond this limit, an <EOL> will be inserted and inserting continues on the next line. Options that add a margin, such as 'number' and 'foldcolumn', cause - the text width to be further reduced. This is Vi compatible. + the text width to be further reduced. When 'textwidth' is non-zero, this option is not used. See also 'formatoptions' and |ins-textwidth|. diff --git a/runtime/doc/quickref.txt b/runtime/doc/quickref.txt index 961d734bfe..ff7e2ab400 100644 --- a/runtime/doc/quickref.txt +++ b/runtime/doc/quickref.txt @@ -824,7 +824,6 @@ Short explanation of each option: *option-list* 'redrawtime' 'rdt' timeout for 'hlsearch' and |:match| highlighting 'regexpengine' 're' default regexp engine to use 'relativenumber' 'rnu' show relative line number in front of each line -'remap' allow mappings to work recursively 'report' threshold for reporting nr. of lines changed 'revins' 'ri' inserting characters will work backwards 'rightleft' 'rl' window is right-to-left oriented @@ -896,7 +895,6 @@ Short explanation of each option: *option-list* 'tagstack' 'tgst' push tags onto the tag stack 'term' name of the terminal 'termbidi' 'tbidi' terminal takes care of bi-directionality -'terse' shorten some messages 'textwidth' 'tw' maximum width of text that is being inserted 'thesaurus' 'tsr' list of thesaurus files for keyword completion 'thesaurusfunc' 'tsrfu' function to be used for thesaurus completion diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index 0aceb30ce0..c3ad704bb7 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -5244,6 +5244,10 @@ Whitespace "nbsp", "space", "tab", "multispace", "lead" and "trail" in 'listchars'. *hl-WildMenu* WildMenu Current match in 'wildmenu' completion. + *hl-WinBar* +WinBar Window bar of current window. + *hl-WinBarNC* +WinBarNC Window bar of not-current windows. *hl-User1* *hl-User1..9* *hl-User9* The 'statusline' syntax allows the use of 9 different highlights in the diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index bc264bd971..339ae0c2ed 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -616,8 +616,6 @@ LanguageTree:children({self}) *LanguageTree:children()* LanguageTree:contains({self}, {range}) *LanguageTree:contains()* Determines whether {range} is contained in this language tree - This goes down the tree to recursively check children. - Parameters: ~ {range} A range, that is a `{ start_line, start_col, end_line, end_col }` table. diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt index 75ee0fdfdf..0a25904104 100644 --- a/runtime/doc/various.txt +++ b/runtime/doc/various.txt @@ -30,10 +30,10 @@ CTRL-L Clears and redraws the screen. The redraw may happen function (or a mapping if 'lazyredraw' set). *:redraws* *:redrawstatus* -:redraws[tatus][!] Redraws the status line of the current window, or all - status lines if "!" is included. - Useful if 'statusline' includes an item that doesn't - cause automatic updating. +:redraws[tatus][!] Redraws the status line and window bar of the current + window, or all status lines and window bars if "!" is + included. Useful if 'statusline' or 'winbar' includes + an item that doesn't cause automatic updating. *:redrawt* *:redrawtabline* :redrawt[abline] Redraw the tabline. Useful to update the tabline when diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index fc98331697..c926337b47 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -548,11 +548,13 @@ Options: 'maxmemtot' Nvim delegates memory-management to the OS. 'maxcombine' (6 is always used) *'prompt'* *'noprompt'* + *'remap'* *'noremap'* *'restorescreen'* *'rs'* *'norestorescreen'* *'nors'* 'shelltype' *'shortname'* *'sn'* *'noshortname'* *'nosn'* *'swapsync'* *'sws'* *'termencoding'* *'tenc'* (Vim 7.4.852 also removed this for Windows) + *'terse'* *'noterse'* (Add "s" to 'shortmess' instead) 'textauto' 'textmode' *'toolbar'* *'tb'* diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index dc25d68f61..e6ab48f30d 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -406,7 +406,6 @@ function vim.defer_fn(fn, timeout) timeout, 0, vim.schedule_wrap(function() - timer:stop() timer:close() fn() diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index fed0231ae9..8321e0b11e 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -810,11 +810,11 @@ local extension = { R = function(path, bufnr) require('vim.filetype.detect').r(bufnr) end, - asm = function() - vim.fn['dist#ft#FTasm']() + asm = function(path, bufnr) + require('vim.filetype.detect').asm(bufnr) end, - bas = function() - vim.fn['dist#ft#FTbas']() + bas = function(path, bufnr) + require('vim.filetype.detect').bas(bufnr) end, bi = function() vim.fn['dist#ft#FTbas']() @@ -828,11 +828,11 @@ local extension = { btm = function(path, bufnr) return require('vim.filetype.detect').btm(bufnr) end, - c = function() - vim.fn['dist#ft#FTlpc']() + c = function(path, bufnr) + return require('vim.filetype.detect').lpc(bufnr) end, - ch = function() - vim.fn['dist#ft#FTchange']() + ch = function(path, bufnr) + return require('vim.filetype.detect').change(bufnr) end, com = function() vim.fn['dist#ft#BindzoneCheck']('dcl') @@ -843,8 +843,8 @@ local extension = { csh = function() vim.fn['dist#ft#CSH']() end, - d = function() - vim.fn['dist#ft#DtraceCheck']() + d = function(path, bufnr) + return require('vim.filetype.detect').dtrace(bufnr) end, db = function() vim.fn['dist#ft#BindzoneCheck']('') @@ -862,30 +862,30 @@ local extension = { vim.fn['dist#ft#SetFileTypeSH']('bash') end, ent = function(path, bufnr) - return require('vim.filetype.detect').ent(bufnr) + require('vim.filetype.detect').ent(bufnr) end, env = function() vim.fn['dist#ft#SetFileTypeSH'](vim.fn.getline(1)) end, eu = function(path, bufnr) - return require('vim.filetype.detect').euphoria(bufnr) + require('vim.filetype.detect').euphoria(bufnr) end, ew = function(path, bufnr) - return require('vim.filetype.detect').euphoria(bufnr) + require('vim.filetype.detect').euphoria(bufnr) end, ex = function(path, bufnr) - return require('vim.filetype.detect').ex(bufnr) + require('vim.filetype.detect').ex(bufnr) end, exu = function(path, bufnr) - return require('vim.filetype.detect').euphoria(bufnr) + require('vim.filetype.detect').euphoria(bufnr) end, exw = function(path, bufnr) - return require('vim.filetype.detect').euphoria(bufnr) + require('vim.filetype.detect').euphoria(bufnr) end, frm = function(path, bufnr) require('vim.filetype.detect').frm(bufnr) end, - fs = function() + fs = function(path, bufnr) vim.fn['dist#ft#FTfs']() end, h = function(path, bufnr) @@ -897,8 +897,8 @@ local extension = { html = function() vim.fn['dist#ft#FThtml']() end, - i = function() - vim.fn['dist#ft#FTprogress_asm']() + i = function(path, bufnr) + require('vim.filetype.detect').progress_asm(bufnr) end, idl = function(path, bufnr) require('vim.filetype.detect').idl(bufnr) @@ -912,26 +912,26 @@ local extension = { ksh = function() vim.fn['dist#ft#SetFileTypeSH']('ksh') end, - lst = function() - vim.fn['dist#ft#FTasm']() + lst = function(path, bufnr) + require('vim.filetype.detect').asm(bufnr) end, - m = function() - vim.fn['dist#ft#FTm']() + m = function(path, bufnr) + require('vim.filetype.detect').m(bufnr) end, - mac = function() - vim.fn['dist#ft#FTasm']() + mac = function(path, bufnr) + require('vim.filetype.detect').asm(bufnr) end, mc = function(path, bufnr) require('vim.filetype.detect').mc(bufnr) end, - mm = function() - vim.fn['dist#ft#FTmm']() + mm = function(path, bufnr) + require('vim.filetype.detect').mm(bufnr) end, mms = function(path, bufnr) require('vim.filetype.detect').mms(bufnr) end, - p = function() - vim.fn['dist#ft#FTprogress_pascal']() + p = function(path, bufnr) + require('vim.filetype.detect').progress_pascal(bufnr) end, patch = function(path, bufnr) local firstline = getline(bufnr, 1) @@ -959,8 +959,8 @@ local extension = { rdf = function(path, bufnr) require('vim.filetype.detect').redif(bufnr) end, - rules = function() - vim.fn['dist#ft#FTRules']() + rules = function(path, bufnr) + require('vim.filetype.detect').rules(path, bufnr) end, sc = function(path, bufnr) require('vim.filetype.detect').sc(bufnr) @@ -1559,13 +1559,13 @@ local pattern = { ['%.zlog.*'] = starsetf('zsh'), ['%.zsh.*'] = starsetf('zsh'), ['.*%.[1-9]'] = function(path, bufnr) - return require('vim.filetype.detect').nroff(bufnr) + require('vim.filetype.detect').nroff(bufnr) end, - ['.*%.[aA]'] = function() - vim.fn['dist#ft#FTasm']() + ['.*%.[aA]'] = function(path, bufnr) + require('vim.filetype.detect').asm(bufnr) end, - ['.*%.[sS]'] = function() - vim.fn['dist#ft#FTasm']() + ['.*%.[sS]'] = function(path, bufnr) + require('vim.filetype.detect').asm(bufnr) end, ['.*%.properties_.._.._.*'] = starsetf('jproperties'), ['.*%.vhdl_[0-9].*'] = starsetf('vhdl'), @@ -1575,8 +1575,8 @@ local pattern = { ['.*/Xresources/.*'] = starsetf('xdefaults'), ['.*/app%-defaults/.*'] = starsetf('xdefaults'), ['.*/bind/db%..*'] = starsetf('bindzone'), - ['.*/debian/patches/.*'] = function() - vim.fn['dist#ft#Dep3patch']() + ['.*/debian/patches/.*'] = function(path, bufnr) + require('vim.filetype.detect').dep3patch(path, bufnr) end, ['.*/etc/Muttrc%.d/.*'] = starsetf('muttrc'), ['.*/etc/apache2/.*%.conf.*'] = starsetf('apache'), @@ -1680,24 +1680,24 @@ local pattern = { return 'git' end end, - ['.*%.[Cc][Ff][Gg]'] = function() - vim.fn['dist#ft#FTcfg']() + ['.*%.[Cc][Ff][Gg]'] = function(path, bufnr) + require('vim.filetype.detect').cfg(bufnr) end, - ['.*%.[Dd][Aa][Tt]'] = function() - vim.fn['dist#ft#FTdat']() + ['.*%.[Dd][Aa][Tt]'] = function(path, bufnr) + require('vim.filetype.detect').dat(bufnr) end, - ['.*%.[Mm][Oo][Dd]'] = function() - vim.fn['dist#ft#FTmod']() + ['.*%.[Mm][Oo][Dd]'] = function(path, bufnr) + require('vim.filetype.detect').mod(path, bufnr) end, - ['.*%.[Ss][Rr][Cc]'] = function() - vim.fn['dist#ft#FTsrc']() + ['.*%.[Ss][Rr][Cc]'] = function(path, bufnr) + require('vim.filetype.detect').src(bufnr) end, ['.*%.[Ss][Uu][Bb]'] = 'krl', - ['.*%.[Pp][Rr][Gg]'] = function() - vim.fn['dist#ft#FTprg']() + ['.*%.[Pp][Rr][Gg]'] = function(path, bufnr) + require('vim.filetype.detect').prg(bufnr) end, - ['.*%.[Ss][Yy][Ss]'] = function() - vim.fn['dist#ft#FTsys']() + ['.*%.[Ss][Yy][Ss]'] = function(path, bufnr) + require('vim.filetype.detect').sys(bufnr) end, -- Neovim only ['.*/queries/.*%.scm'] = 'query', -- tree-sitter queries diff --git a/runtime/lua/vim/filetype/detect.lua b/runtime/lua/vim/filetype/detect.lua index 4c363e7403..da59625353 100644 --- a/runtime/lua/vim/filetype/detect.lua +++ b/runtime/lua/vim/filetype/detect.lua @@ -1,15 +1,28 @@ +-- Contains filetype detection functions converted to Lua from Vim's autoload/runtime/dist/ft.vim file. + +-- Here are a few guidelines to follow when porting a new function: +-- * Sort the function alphabetically and omit 'ft' or 'check' from the new function name. +-- * Use ':find' instead of ':match' / ':sub' if possible. +-- * When '=~' is used to match a pattern, there are two possibilities: +-- - If the pattern only contains lowercase characters, treat the comparison as case-insensitive. +-- - Otherwise, treat it as case-sensitive. +-- (Basically, we apply 'smartcase': if upper case characters are used in the original pattern, then +-- it's likely that case does matter). +-- * When '\k', '\<' or '\>' is used in a pattern, use the 'matchregex' function. +-- Note that vim.regex is case-sensitive by default, so add the '\c' flag if only lowercase letters +-- are present in the pattern: +-- Example: +-- `if line =~ '^\s*unwind_protect\>'` => `if matchregex(line, [[\c^\s*unwind_protect\>]])` + local M = {} ---@private -local function getlines(bufnr, start_lnum, end_lnum, opts) +local function getlines(bufnr, start_lnum, end_lnum) if not end_lnum then -- Return a single line as a string return vim.api.nvim_buf_get_lines(bufnr, start_lnum - 1, start_lnum, false)[1] end - - local lines = vim.api.nvim_buf_get_lines(bufnr, start_lnum - 1, end_lnum, false) - opts = opts or {} - return opts.concat and (table.concat(lines) or '') or lines + return vim.api.nvim_buf_get_lines(bufnr, start_lnum - 1, end_lnum, false) end ---@private @@ -22,16 +35,103 @@ local function findany(s, patterns) return false end +---@private +local function nextnonblank(bufnr, start_lnum) + for _, line in ipairs(getlines(bufnr, start_lnum, -1)) do + if not line:find('^%s*$') then + return line + end + end + return nil +end + +---@private +local matchregex = (function() + local cache = {} + return function(line, pattern) + if line == nil then + return nil + end + if not cache[pattern] then + cache[pattern] = vim.regex(pattern) + end + return cache[pattern]:match_str(line) + end +end)() + -- luacheck: push no unused args -- luacheck: push ignore 122 -function M.asm(path, bufnr) end +-- This function checks for the kind of assembly that is wanted by the user, or +-- can be detected from the first five lines of the file. +function M.asm(bufnr) + -- Make sure b:asmsyntax exists + if not vim.b[bufnr].asmsyntax then + vim.b[bufnr].asmsyntax = '' + end -function M.asm_syntax(path, bufnr) end + if vim.b[bufnr].asmsyntax == '' then + M.asm_syntax(bufnr) + end -function M.bas(path, bufnr) end + -- If b:asmsyntax still isn't set, default to asmsyntax or GNU + if vim.b[bufnr].asmsyntax == '' then + if vim.g.asmsyntax and vim.g.asmsyntax ~= 0 then + vim.b[bufnr].asmsyntax = vim.g.asmsyntax + else + vim.b[bufnr].asmsyntax = 'asm' + end + end + vim.bo[bufnr].filetype = vim.fn.fnameescape(vim.b[bufnr].asmsyntax) +end + +-- Checks the first 5 lines for a asmsyntax=foo override. +-- Only whitespace characters can be present immediately before or after this statement. +function M.asm_syntax(bufnr) + local lines = table.concat(getlines(bufnr, 1, 5), ' '):lower() + local match = lines:match('%sasmsyntax=([a-zA-Z0-9]+)%s') + if match then + vim.b['asmsyntax'] = match + elseif findany(lines, { '%.title', '%.ident', '%.macro', '%.subtitle', '%.library' }) then + vim.b['asmsyntax'] = 'vmasm' + end +end -function M.bindzone(path, bufnr) end +local visual_basic_content = { 'vb_name', 'begin vb%.form', 'begin vb%.mdiform', 'begin vb%.usercontrol' } + +-- See frm() for Visual Basic form file detection +function M.bas(bufnr) + if vim.g.filetype_bas then + vim.bo[bufnr].filetype = vim.g.filetype_bas + return + end + + -- Most frequent FreeBASIC-specific keywords in distro files + local fb_keywords = + [[\c^\s*\%(extern\|var\|enum\|private\|scope\|union\|byref\|operator\|constructor\|delete\|namespace\|public\|property\|with\|destructor\|using\)\>\%(\s*[:=(]\)\@!]] + local fb_preproc = + [[\c^\s*\%(#\a\+\|option\s\+\%(byval\|dynamic\|escape\|\%(no\)\=gosub\|nokeyword\|private\|static\)\>\)]] + + local fb_comment = "^%s*/'" + -- OPTION EXPLICIT, without the leading underscore, is common to many dialects + local qb64_preproc = [[\c^\s*\%($\a\+\|option\s\+\%(_explicit\|_\=explicitarray\)\>\)]] + + for _, line in ipairs(getlines(bufnr, 1, 100)) do + if line:find(fb_comment) or matchregex(line, fb_preproc) or matchregex(line, fb_keywords) then + vim.bo[bufnr].filetype = 'freebasic' + return + elseif matchregex(line, qb64_preproc) then + vim.bo[bufnr].filetype = 'qb64' + return + elseif findany(line:lower(), visual_basic_content) then + vim.bo[bufnr].filetype = 'vb' + return + end + end + vim.bo[bufnr].filetype = 'basic' +end + +function M.bindzone(bufnr, default_ft) end function M.btm(bufnr) if vim.g.dosbatch_syntax_for_btm and vim.g.dosbatch_syntax_for_btm ~= 0 then @@ -47,14 +147,11 @@ local function is_rapid(bufnr, extension) local line = getlines(bufnr, 1):lower() return findany(line, { 'eio:cfg', 'mmc:cfg', 'moc:cfg', 'proc:cfg', 'sio:cfg', 'sys:cfg' }) end - local first = '^%s*module%s+%S+%s*' - -- Called from mod, prg or sys functions - for _, line in ipairs(getlines(bufnr, 1, -1)) do - if not line:find('^%s*$') then - return findany(line:lower(), { '^%s*%%%%%%', first .. '(', first .. '$' }) - end + local line = nextnonblank(bufnr, 1) + if line then + -- Called from mod, prg or sys functions + return matchregex(line:lower(), [[\c\v^\s*%(\%{3}|module\s+\k+\s*%(\(|$))]]) end - -- Only found blank lines return false end @@ -68,17 +165,110 @@ function M.cfg(bufnr) end end -function M.change(path, bufnr) end +-- This function checks if one of the first ten lines start with a '@'. In +-- that case it is probably a change file. +-- If the first line starts with # or ! it's probably a ch file. +-- If a line has "main", "include", "//" or "/*" it's probably ch. +-- Otherwise CHILL is assumed. +function M.change(bufnr) + local first_line = getlines(bufnr, 1) + if findany(first_line, { '^#', '^!' }) then + vim.bo[bufnr].filetype = 'ch' + return + end + for _, line in ipairs(getlines(bufnr, 1, 10)) do + if line:find('^@') then + vim.bo[bufnr].filetype = 'change' + return + end + if line:find('MODULE') then + vim.bo[bufnr].filetype = 'chill' + return + elseif findany(line:lower(), { 'main%s*%(', '#%s*include', '//' }) then + vim.bo[bufnr].filetype = 'ch' + return + end + end + vim.bo[bufnr].filetype = 'chill' +end function M.csh(path, bufnr) end -function M.dat(path, bufnr) end +-- Determine if a *.dat file is Kuka Robot Language +-- TODO: this one fails for some reason, so I omitted it. #18219 should be merged first. +function M.dat(bufnr) + -- if vim.g.filetype_dat then + -- vim.bo[bufnr].filetype = vim.g.filetype_dat + -- return + -- end + -- local line = nextnonblank(bufnr, 1):lower() + -- if findany(line, { "^%s*&%w+", "^%s*defdat" }) then + -- vim.bo[bufnr].filetype = "krl" + -- end +end -function M.dep3patch(path, bufnr) end +-- This function is called for all files under */debian/patches/*, make sure not +-- to non-dep3patch files, such as README and other text files. +function M.dep3patch(path, bufnr) + local file_name = vim.fn.fnamemodify(path, ':t') + if file_name == 'series' then + return + end -function M.dtrace(path, bufnr) end + for _, line in ipairs(getlines(bufnr, 1, 100)) do + if + findany(line, { + '^Description:', + '^Subject:', + '^Origin:', + '^Bug:', + '^Forwarded:', + '^Author:', + '^From:', + '^Reviewed%-by:', + '^Acked%-by:', + '^Last%-Updated:', + '^Applied%-Upstream:', + }) + then + vim.bo[bufnr].filetype = 'dep3patch' + return + elseif line:find('^%-%-%-') then + -- End of headers found. stop processing + return + end + end +end -function M.e(path, bufnr) end +function M.dtrace(bufnr) + local did_filetype = vim.fn.did_filetype() + if did_filetype and did_filetype ~= 0 then + -- Filetype was already detected + return + end + for _, line in ipairs(getlines(bufnr, 1, 100)) do + if matchregex(line, [[\c^module\>\|^import\>]]) then + -- D files often start with a module and/or import statement. + vim.bo[bufnr].filetype = 'd' + return + elseif findany(line, { '^#!%S+dtrace', '#pragma%s+D%s+option', ':%S-:%S-:' }) then + vim.bo[bufnr].filetype = 'dtrace' + return + end + end + vim.bo[bufnr].filetype = 'd' +end + +function M.e(path, bufnr) + if vim.g.filetype_euphoria then + vim.bo[bufnr].filetype = vim.g.filetype_euphoria + return + end + -- TODO: WIP + -- for _, line in ipairs(getlines(bufnr, 1, 100)) do + -- if line:find("^$") + -- end +end -- This function checks for valid cl syntax in the first five lines. -- Look for either an opening comment, '#', or a block start, '{'. @@ -110,8 +300,7 @@ function M.ex(bufnr) vim.bo[bufnr].filetype = vim.g.filetype_euphoria else for _, line in ipairs(getlines(bufnr, 1, 100)) do - -- TODO: in the Vim regex, \> is used to match the end of the word, can this be omitted? - if findany(line, { '^%-%-', '^ifdef', '^include' }) then + if matchregex(line, [[\c^--\|^ifdef\>\|^include\>]]) then vim.bo[bufnr].filetype = 'euphoria3' return end @@ -138,22 +327,34 @@ end function M.frm(bufnr) if vim.g.filetype_frm then vim.bo[bufnr].filetype = vim.g.filetype_frm + return + end + local lines = table.concat(getlines(bufnr, 1, 5)):lower() + if findany(lines, visual_basic_content) then + vim.bo[bufnr].filetype = 'vb' else - -- Always ignore case - local lines = getlines(bufnr, 1, 5, { concat = true }):lower() - if findany(lines, { 'vb_name', 'begin vb%.form', 'begin vb%.mdiform' }) then - vim.bo[bufnr].filetype = 'vb' - else - vim.bo[bufnr].filetype = 'form' - end + vim.bo[bufnr].filetype = 'form' end end -function M.fs(path, bufnr) end +-- Distinguish between Forth and F#. +function M.fs(bufnr) + -- TODO: WIP + -- if vim.g.filetype_fs then + -- vim.bo[bufnr].filetype = vim.g.filetype_fs + -- return + -- end + -- local line = nextnonblank(bufnr, 1) + -- if findany(line, { '^%s*.?%( ', '^%s*\\G? ', '^\\$', '^%s*: %S' }) then + -- vim.bo[bufnr].filetype = 'forth' + -- else + -- vim.bo[bufnr].filetype = 'fsharp' + -- end +end function M.header(bufnr) for _, line in ipairs(getlines(bufnr, 1, 200)) do - if findany(line, { '^@interface', '^@end', '^@class' }) then + if findany(line:lower(), { '^@interface', '^@end', '^@class' }) then if vim.g.c_syntax_for_h then vim.bo[bufnr].filetype = 'objc' else @@ -171,11 +372,22 @@ function M.header(bufnr) end end +function M.html(bufnr) + for _, line in ipairs(getlines(bufnr, 1, 10)) do + if matchregex(line, [[\<DTD\s\+XHTML\s]]) then + vim.bo[bufnr].filetype = 'xhtml' + return + elseif matchregex(line, [[\c{%\s*\(extends\|block\|load\)\>\|{#\s\+]]) then + vim.bo[bufnr].filetype = 'htmldjango' + return + end + end + vim.bo[bufnr].filetype = 'html' +end + function M.idl(bufnr) for _, line in ipairs(getlines(bufnr, 1, 50)) do - -- Always ignore case - line = line:lower() - if findany(line, { '^%s*import%s+"unknwn"%.idl', '^%s*import%s+"objidl"%.idl' }) then + if findany(line:lower(), { '^%s*import%s+"unknwn"%.idl', '^%s*import%s+"objidl"%.idl' }) then vim.bo[bufnr].filetype = 'msidl' return end @@ -198,11 +410,83 @@ function M.inp(bufnr) end end -function M.lpc(path, bufnr) end +function M.lpc(bufnr) + if vim.g.lpc_syntax_for_c then + for _, line in ipairs(getlines(bufnr, 1, 12)) do + if + findany(line, { + '^//', + '^inherit', + '^private', + '^protected', + '^nosave', + '^string', + '^object', + '^mapping', + '^mixed', + }) + then + vim.bo[bufnr].filetype = 'lpc' + return + end + end + end + vim.bo[bufnr].filetype = 'c' +end -function M.lprolog(path, bufnr) end +function M.m(bufnr) + if vim.g.filetype_m then + vim.bo[bufnr].filetype = vim.g.filetype_m + return + end -function M.m(path, bufnr) end + -- Excluding end(for|function|if|switch|while) common to Murphi + local octave_block_terminators = + [[\<end\%(_try_catch\|classdef\|enumeration\|events\|methods\|parfor\|properties\)\>]] + local objc_preprocessor = [[\c^\s*#\s*\%(import\|include\|define\|if\|ifn\=def\|undef\|line\|error\|pragma\)\>]] + + -- Whether we've seen a multiline comment leader + local saw_comment = false + for _, line in ipairs(getlines(bufnr, 1, 100)) do + if line:find('^%s*/%*') then + -- /* ... */ is a comment in Objective C and Murphi, so we can't conclude + -- it's either of them yet, but track this as a hint in case we don't see + -- anything more definitive. + saw_comment = true + end + if line:find('^%s*//') or matchregex(line, [[\c^\s*@import\>]]) or matchregex(line, objc_preprocessor) then + vim.bo[bufnr].filetype = 'objc' + return + end + if + findany(line, { '^%s*#', '^%s*%%!' }) + or matchregex(line, [[\c^\s*unwind_protect\>]]) + or matchregex(line, [[\c\%(^\|;\)\s*]] .. octave_block_terminators) + then + vim.bo[bufnr].filetype = 'octave' + return + elseif line:find('^%s*%%') then + vim.bo[bufnr].filetype = 'matlab' + return + elseif line:find('^%s*%(%*') then + vim.bo[bufnr].filetype = 'mma' + return + elseif matchregex(line, [[\c^\s*\(\(type\|var\)\>\|--\)]]) then + vim.bo[bufnr].filetype = 'murphi' + return + end + end + + if saw_comment then + -- We didn't see anything definitive, but this looks like either Objective C + -- or Murphi based on the comment leader. Assume the former as it is more + -- common. + vim.bo[bufnr].filetype = 'objc' + else + -- Default is Matlab + vim.bo[bufnr].filetype = 'matlab' + end +end -- Rely on the file to start with a comment. -- MS message text files use ';', Sendmail files use '#' or 'dnl' @@ -221,7 +505,15 @@ function M.mc(bufnr) vim.bo[bufnr].filetype = 'm4' end -function M.mm(path, bufnr) end +function M.mm(bufnr) + for _, line in ipairs(getlines(bufnr, 1, 20)) do + if matchregex(line, [[\c^\s*\(#\s*\(include\|import\)\>\|@import\>\|/\*\)]]) then + vim.bo[bufnr].filetype = 'objcpp' + return + end + end + vim.bo[bufnr].filetype = 'nroff' +end function M.mms(bufnr) for _, line in ipairs(getlines(bufnr, 1, 20)) do @@ -236,35 +528,129 @@ function M.mms(bufnr) vim.bo[bufnr].filetype = 'mmix' end -function M.mod(path, bufnr) end +-- Returns true if file content looks like LambdaProlog +local function is_lprolog(bufnr) + -- Skip apparent comments and blank lines, what looks like + -- LambdaProlog comment may be RAPID header + for _, line in ipairs(getlines(bufnr, 1, -1)) do + -- The second pattern matches a LambdaProlog comment + if not findany(line, { '^%s*$', '^%s*%%' }) then + -- The pattern must not catch a go.mod file + return matchregex(line, [[\c\<module\s\+\w\+\s*\.\s*\(%\|$\)]]) ~= nil + end + end +end + +-- Determine if *.mod is ABB RAPID, LambdaProlog, Modula-2, Modsim III or go.mod +function M.mod(path, bufnr) + if vim.g.filetype_mod then + vim.bo[bufnr].filetype = vim.g.filetype_mod + elseif is_lprolog(bufnr) then + vim.bo[bufnr].filetype = 'lprolog' + elseif matchregex(nextnonblank(bufnr, 1), [[\%(\<MODULE\s\+\w\+\s*;\|^\s*(\*\)]]) then + vim.bo[bufnr].filetype = 'modula2' + elseif is_rapid(bufnr) then + vim.bo[bufnr].filetype = 'rapid' + elseif matchregex(path, [[\c\<go\.mod$]]) then + vim.bo[bufnr].filetype = 'gomod' + else + -- Nothing recognized, assume modsim3 + vim.bo[bufnr].filetype = 'modsim3' + end +end -- This function checks if one of the first five lines start with a dot. In --- that case it is probably an nroff file: 'filetype' is set and 1 is returned. +-- that case it is probably an nroff file: 'filetype' is set and true is returned. function M.nroff(bufnr) for _, line in ipairs(getlines(bufnr, 1, 5)) do if line:find('^%.') then vim.bo[bufnr].filetype = 'nroff' - return 1 + return true end end - return 0 + return false end -function M.perl(path, bufnr) end +-- If the file has an extension of 't' and is in a directory 't' or 'xt' then +-- it is almost certainly a Perl test file. +-- If the first line starts with '#' and contains 'perl' it's probably a Perl file. +-- (Slow test) If a file contains a 'use' statement then it is almost certainly a Perl file. +function M.perl(path, bufnr) + local dirname = vim.fn.expand(path, '%:p:h:t') + if vim.fn.expand(dirname, '%:e') == 't' and (dirname == 't' or dirname == 'xt') then + vim.bo[bufnr].filetype = 'perl' + return true + end + local first_line = getlines(bufnr, 1) + if first_line:find('^#') and first_line:lower():find('perl') then + vim.bo[bufnr].filetype = 'perl' + return true + end + for _, line in ipairs(getlines(bufnr, 1, 30)) do + if matchregex(line, [[\c^use\s\s*\k]]) then + vim.bo[bufnr].filetype = 'perl' + return true + end + end + return false +end function M.pl(path, bufnr) end -function M.pp(path, bufnr) end +local pascal_comments = { '^%s*{', '^%s*%(*', '^%s*//' } +local pascal_keywords = [[\c^\s*\%(program\|unit\|library\|uses\|begin\|procedure\|function\|const\|type\|var\)\>]] + +function M.pp(bufnr) + -- TODO: WIP + + -- if vim.g.filetype_pp then + -- vim.bo[bufnr].filetype = vim.g.filetype_pp + -- return + -- end + -- local first_line = nextnonblank(bufnr, 1):lower() + -- if findany(first_line, { pascal_comments, pascal_keywords }) then + -- vim.bo[bufnr].filetype = "pascal" + -- else + -- vim.bo[bufnr].filetype = "puppet" + -- end +end + +function M.prg(bufnr) + if vim.g.filetype_prg then + vim.bo[bufnr].filetype = vim.g.filetype_prg + elseif is_rapid(bufnr) then + vim.bo[bufnr].filetype = 'rapid' + else + -- Nothing recognized, assume Clipper + vim.bo[bufnr].filetype = 'clipper' + end +end -function M.prg(path, bufnr) end +-- This function checks for an assembly comment in the first ten lines. +-- If not found, assume Progress. +function M.progress_asm(bufnr) + if vim.g.filetype_i then + vim.bo[bufnr].filetype = vim.g.filetype_i + return + end -function M.progress_asm(path, bufnr) end + for _, line in ipairs(getlines(bufnr, 1, 10)) do + if line:find('^%s*;') or line:find('^/%*') then + return M.asm(bufnr) + elseif not line:find('^%s*$') or line:find('^/%*') then + -- Not an empty line: doesn't look like valid assembly code + -- or it looks like a Progress /* comment. + break + end + end + vim.bo[bufnr].filetype = 'progress' +end function M.progress_cweb(bufnr) if vim.g.filetype_w then vim.bo[bufnr].filetype = vim.g.filetype_w else - if getlines(bufnr, 1):find('^&ANALYZE') or getlines(bufnr, 3):find('^&GLOBAL%-DEFINE') then + if getlines(bufnr, 1):lower():find('^&analyze') or getlines(bufnr, 3):lower():find('^&global%-define') then vim.bo[bufnr].filetype = 'progress' else vim.bo[bufnr].filetype = 'cweb' @@ -272,15 +658,33 @@ function M.progress_cweb(bufnr) end end -function M.progress_pascal(path, bufnr) end +-- This function checks for valid Pascal syntax in the first 10 lines. +-- Look for either an opening comment or a program start. +-- If not found, assume Progress. +function M.progress_pascal(bufnr) + if vim.g.filetype_p then + vim.bo[bufnr].filetype = vim.g.filetype_p + return + end + for _, line in ipairs(getlines(bufnr, 1, 10)) do + if findany(line, pascal_comments) or matchregex(line, pascal_keywords) then + vim.bo[bufnr].filetype = 'pascal' + return + elseif not line:find('^%s*$') or line:find('^/%*') then + -- Not an empty line: Doesn't look like valid Pascal code. + -- Or it looks like a Progress /* comment + break + end + end + vim.bo[bufnr].filetype = 'progress' +end function M.proto(path, bufnr) end function M.r(bufnr) local lines = getlines(bufnr, 1, 50) - -- TODO: \< / \> which match the beginning / end of a word -- Rebol is easy to recognize, check for that first - if table.concat(lines):lower():find('rebol') then + if matchregex(table.concat(lines), [[\c\<rebol\>]]) then vim.bo[bufnr].filetype = 'rebol' return end @@ -315,7 +719,43 @@ function M.redif(bufnr) end end -function M.rules(path, bufnr) end +local udev_rules_pattern = '^%s*udev_rules%s*=%s*"([%^"]+)/*".*' +function M.rules(path, bufnr) + path = path:lower() + if + findany(path, { + '/etc/udev/.*%.rules$', + '/etc/udev/rules%.d/.*$.rules$', + '/usr/lib/udev/.*%.rules$', + '/usr/lib/udev/rules%.d/.*%.rules$', + '/lib/udev/.*%.rules$', + '/lib/udev/rules%.d/.*%.rules$', + }) + then + vim.bo[bufnr].filetype = 'udevrules' + elseif path:find('^/etc/ufw/') then + -- Better than hog + vim.bo[bufnr].filetype = 'conf' + elseif findany(path, { '^/etc/polkit%-1/rules%.d', '/usr/share/polkit%-1/rules%.d' }) then + vim.bo[bufnr].filetype = 'javascript' + else + local ok, config_lines = pcall(vim.fn.readfile, '/etc/udev/udev.conf') + if not ok then + vim.bo[bufnr].filetype = 'hog' + return + end + local dir = vim.fn.expand(path, ':h') + for _, line in ipairs(config_lines) do + local match = line:match(udev_rules_pattern) + local udev_rules = line:gsub(udev_rules_pattern, match, 1) + if dir == udev_rules then + vim.bo[bufnr].filetype = 'udevrules' + return + end + end + vim.bo[bufnr].filetype = 'hog' + end +end -- This function checks the first 25 lines of file extension "sc" to resolve -- detection between scala and SuperCollider @@ -359,9 +799,27 @@ function M.sql(bufnr) end end -function M.src(path, bufnr) end +-- Determine if a *.src file is Kuka Robot Language +function M.src(bufnr) + if vim.g.filetype_src then + vim.bo[bufnr].filetype = vim.g.filetype_src + return + end + local line = nextnonblank(bufnr, 1) + if matchregex(line, [[\c\v^\s*%(\&\w+|%(global\s+)?def%(fct)?>)]]) then + vim.bo[bufnr].filetype = 'krl' + end +end -function M.sys(path, bufnr) end +function M.sys(bufnr) + if vim.g.filetype_sys then + vim.bo[bufnr].filetype = vim.g.filetype_sys + elseif is_rapid(bufnr) then + vim.bo[bufnr].filetype = 'rapid' + else + vim.bo[bufnr].filetype = 'bat' + end +end function M.tex(path, bufnr) end @@ -380,8 +838,8 @@ end function M.xml(bufnr) for _, line in ipairs(getlines(bufnr, 1, 100)) do + local is_docbook4 = line:find('<!DOCTYPE.*DocBook') line = line:lower() - local is_docbook4 = line:find('<!doctype.*docbook') local is_docbook5 = line:find([[ xmlns="http://docbook.org/ns/docbook"]]) if is_docbook4 or is_docbook5 then vim.b[bufnr].docbk_type = 'xml' @@ -403,10 +861,9 @@ function M.y(bufnr) vim.bo[bufnr].filetype = 'yacc' return end - -- TODO: in the Vim regex, \> is used to match the end of the word after "class", - -- can this be omitted? - if findany(line, { '^%s*#', '^%class', '^%s*#%s*include' }) then + if matchregex(line, [[\c^\s*\(#\|class\>\)]]) and not line:lower():find('^%s*#%s*include') then vim.bo[bufnr].filetype = 'racc' + return end end vim.bo[bufnr].filetype = 'yacc' diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index e99a7c282c..07987ee003 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1,5 +1,3 @@ -local if_nil = vim.F.if_nil - local default_handlers = require('vim.lsp.handlers') local log = require('vim.lsp.log') local lsp_rpc = require('vim.lsp.rpc') @@ -8,11 +6,16 @@ local util = require('vim.lsp.util') local sync = require('vim.lsp.sync') local vim = vim -local nvim_err_writeln, nvim_buf_get_lines, nvim_command, nvim_buf_get_option = - vim.api.nvim_err_writeln, vim.api.nvim_buf_get_lines, vim.api.nvim_command, vim.api.nvim_buf_get_option +local nvim_err_writeln, nvim_buf_get_lines, nvim_command, nvim_buf_get_option, nvim_exec_autocmds = + vim.api.nvim_err_writeln, + vim.api.nvim_buf_get_lines, + vim.api.nvim_command, + vim.api.nvim_buf_get_option, + vim.api.nvim_exec_autocmds local uv = vim.loop local tbl_isempty, tbl_extend = vim.tbl_isempty, vim.tbl_extend local validate = vim.validate +local if_nil = vim.F.if_nil local lsp = { protocol = protocol, @@ -867,15 +870,27 @@ function lsp.start_client(config) pcall(config.on_exit, code, signal, client_id) end + for bufnr, client_ids in pairs(all_buffer_active_clients) do + if client_ids[client_id] then + vim.schedule(function() + nvim_exec_autocmds('LspDetach', { + buffer = bufnr, + modeline = false, + data = { client_id = client_id }, + }) + + local namespace = vim.lsp.diagnostic.get_namespace(client_id) + vim.diagnostic.reset(namespace, bufnr) + end) + + client_ids[client_id] = nil + end + end + active_clients[client_id] = nil uninitialized_clients[client_id] = nil - lsp.diagnostic.reset(client_id, all_buffer_active_clients) changetracking.reset(client_id) - for _, client_ids in pairs(all_buffer_active_clients) do - client_ids[client_id] = nil - end - if code ~= 0 or (signal ~= 0 and signal ~= 15) then local msg = string.format('Client %s quit with exit code %s and signal %s', client_id, code, signal) vim.schedule(function() @@ -1213,6 +1228,13 @@ function lsp.start_client(config) ---@param bufnr (number) Buffer number function client._on_attach(bufnr) text_document_did_open_handler(bufnr, client) + + nvim_exec_autocmds('LspAttach', { + buffer = bufnr, + modeline = false, + data = { client_id = client.id }, + }) + if config.on_attach then -- TODO(ashkan) handle errors. pcall(config.on_attach, client, bufnr) @@ -1359,6 +1381,12 @@ function lsp.buf_detach_client(bufnr, client_id) return end + nvim_exec_autocmds('LspDetach', { + buffer = bufnr, + modeline = false, + data = { client_id = client_id }, + }) + changetracking.reset_buf(client, bufnr) if vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'openClose') then @@ -1435,11 +1463,29 @@ function lsp.stop_client(client_id, force) end end ---- Gets all active clients. +--- Get active clients. --- ----@returns Table of |vim.lsp.client| objects -function lsp.get_active_clients() - return vim.tbl_values(active_clients) +---@param filter (table|nil) A table with key-value pairs used to filter the +--- returned clients. The available keys are: +--- - id (number): Only return clients with the given id +--- - bufnr (number): Only return clients attached to this buffer +--- - name (string): Only return clients with the given name +---@returns (table) List of |vim.lsp.client| objects +function lsp.get_active_clients(filter) + validate({ filter = { filter, 't', true } }) + + filter = filter or {} + + local clients = {} + + local t = filter.bufnr and (all_buffer_active_clients[resolve_bufnr(filter.bufnr)] or {}) or active_clients + for client_id in pairs(t) do + local client = active_clients[client_id] + if (filter.id == nil or client.id == filter.id) and (filter.name == nil or client.name == filter.name) then + clients[#clients + 1] = client + end + end + return clients end function lsp._vim_exit_handler() @@ -1814,12 +1860,13 @@ end --- is a |vim.lsp.client| object. --- ---@param bufnr (optional, number): Buffer handle, or 0 for current +---@returns (table) Table of (client_id, client) pairs +---@deprecated Use |vim.lsp.get_active_clients()| instead. function lsp.buf_get_clients(bufnr) - bufnr = resolve_bufnr(bufnr) local result = {} - for_each_buffer_client(bufnr, function(client, client_id) - result[client_id] = client - end) + for _, client in ipairs(lsp.get_active_clients({ bufnr = resolve_bufnr(bufnr) })) do + result[client.id] = client + end return result end diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index b0bf2c6e5b..1207da094a 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -63,26 +63,45 @@ function M.hover() request('textDocument/hover', params) end +---@private +local function request_with_options(name, params, options) + local req_handler + if options then + req_handler = function(err, result, ctx, config) + local client = vim.lsp.get_client_by_id(ctx.client_id) + local handler = client.handlers[name] or vim.lsp.handlers[name] + handler(err, result, ctx, vim.tbl_extend('force', config or {}, options)) + end + end + request(name, params, req_handler) +end + --- Jumps to the declaration of the symbol under the cursor. ---@note Many servers do not implement this method. Generally, see |vim.lsp.buf.definition()| instead. --- -function M.declaration() +---@param options table|nil additional options +--- - reuse_win: (boolean) Jump to existing window if buffer is already open. +function M.declaration(options) local params = util.make_position_params() - request('textDocument/declaration', params) + request_with_options('textDocument/declaration', params, options) end --- Jumps to the definition of the symbol under the cursor. --- -function M.definition() +---@param options table|nil additional options +--- - reuse_win: (boolean) Jump to existing window if buffer is already open. +function M.definition(options) local params = util.make_position_params() - request('textDocument/definition', params) + request_with_options('textDocument/definition', params, options) end --- Jumps to the definition of the type of the symbol under the cursor. --- -function M.type_definition() +---@param options table|nil additional options +--- - reuse_win: (boolean) Jump to existing window if buffer is already open. +function M.type_definition(options) local params = util.make_position_params() - request('textDocument/typeDefinition', params) + request_with_options('textDocument/typeDefinition', params, options) end --- Lists all the implementations for the symbol under the cursor in the @@ -844,7 +863,8 @@ function M.code_action(options) end local context = options.context or {} if not context.diagnostics then - context.diagnostics = vim.lsp.diagnostic.get_line_diagnostics() + local bufnr = vim.api.nvim_get_current_buf() + context.diagnostics = vim.lsp.diagnostic.get_line_diagnostics(bufnr) end local params = util.make_range_params() params.context = context @@ -870,7 +890,8 @@ function M.range_code_action(context, start_pos, end_pos) validate({ context = { context, 't', true } }) context = context or {} if not context.diagnostics then - context.diagnostics = vim.lsp.diagnostic.get_line_diagnostics() + local bufnr = vim.api.nvim_get_current_buf() + context.diagnostics = vim.lsp.diagnostic.get_line_diagnostics(bufnr) end local params = util.make_given_range_params(start_pos, end_pos) params.context = context diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index b3a253c118..61cc89dcac 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -327,18 +327,20 @@ M['textDocument/hover'] = M.hover ---@param result (table) result of LSP method; a location or a list of locations. ---@param ctx (table) table containing the context of the request, including the method ---(`textDocument/definition` can return `Location` or `Location[]` -local function location_handler(_, result, ctx, _) +local function location_handler(_, result, ctx, config) if result == nil or vim.tbl_isempty(result) then local _ = log.info() and log.info(ctx.method, 'No location found') return nil end local client = vim.lsp.get_client_by_id(ctx.client_id) + config = config or {} + -- textDocument/definition can return Location or Location[] -- https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition if vim.tbl_islist(result) then - util.jump_to_location(result[1], client.offset_encoding) + util.jump_to_location(result[1], client.offset_encoding, config.reuse_win) if #result > 1 then vim.fn.setqflist({}, ' ', { @@ -348,7 +350,7 @@ local function location_handler(_, result, ctx, _) api.nvim_command('botright copen') end else - util.jump_to_location(result, client.offset_encoding) + util.jump_to_location(result, client.offset_encoding, config.reuse_win) end end diff --git a/runtime/lua/vim/lsp/health.lua b/runtime/lua/vim/lsp/health.lua index 74714ebc6b..bf8fe0932e 100644 --- a/runtime/lua/vim/lsp/health.lua +++ b/runtime/lua/vim/lsp/health.lua @@ -17,7 +17,8 @@ function M.check() local log_path = vim.lsp.get_log_path() report_info(string.format('Log path: %s', log_path)) - local log_size = vim.loop.fs_stat(log_path).size + local log_file = vim.loop.fs_stat(log_path) + local log_size = log_file and log_file.size or 0 local report_fn = (log_size / 1000000 > 100 and report_warn or report_info) report_fn(string.format('Log size: %d KB', log_size / 1000)) diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index e8a8e06f46..4663cf9f09 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -684,6 +684,16 @@ function M.text_document_completion_list_to_complete_items(result, prefix) return matches end +---@private +--- Like vim.fn.bufwinid except it works across tabpages. +local function bufwinid(bufnr) + for _, win in ipairs(api.nvim_list_wins()) do + if api.nvim_win_get_buf(win) == bufnr then + return win + end + end +end + --- Rename old_fname to new_fname --- ---@param opts (table) @@ -708,10 +718,9 @@ function M.rename(old_fname, new_fname, opts) assert(ok, err) local newbuf = vim.fn.bufadd(new_fname) - for _, win in pairs(api.nvim_list_wins()) do - if api.nvim_win_get_buf(win) == oldbuf then - api.nvim_win_set_buf(win, newbuf) - end + local win = bufwinid(oldbuf) + if win then + api.nvim_win_set_buf(win, newbuf) end api.nvim_buf_delete(oldbuf, { force = true }) end @@ -1004,8 +1013,9 @@ end --- ---@param location table (`Location`|`LocationLink`) ---@param offset_encoding string utf-8|utf-16|utf-32 (required) +---@param reuse_win boolean Jump to existing window if buffer is already opened. ---@returns `true` if the jump succeeded -function M.jump_to_location(location, offset_encoding) +function M.jump_to_location(location, offset_encoding, reuse_win) -- location may be Location or LocationLink local uri = location.uri or location.targetUri if uri == nil then @@ -1024,8 +1034,13 @@ function M.jump_to_location(location, offset_encoding) vim.fn.settagstack(vim.fn.win_getid(), { items = items }, 't') --- Jump to new location (adjusting for UTF-16 encoding of characters) - api.nvim_set_current_buf(bufnr) - api.nvim_buf_set_option(bufnr, 'buflisted', true) + local win = reuse_win and bufwinid(bufnr) + if win then + api.nvim_set_current_win(win) + else + api.nvim_set_current_buf(bufnr) + api.nvim_buf_set_option(bufnr, 'buflisted', true) + end local range = location.range or location.targetSelectionRange local row = range.start.line local col = get_line_byte_from_position(bufnr, range.start, offset_encoding) @@ -1676,7 +1691,7 @@ end --- ---@param items (table) list of items function M.set_loclist(items, win_id) - vim.api.nvim_echo({ { 'vim.lsp.util.set_loclist is deprecated. See :h deprecated', 'WarningMsg' } }, true, {}) + vim.deprecate('vim.lsp.util.set_loclist', 'setloclist', '0.8') vim.fn.setloclist(win_id or 0, {}, ' ', { title = 'Language Server', items = items, @@ -1690,7 +1705,7 @@ end --- ---@param items (table) list of items function M.set_qflist(items) - vim.api.nvim_echo({ { 'vim.lsp.util.set_qflist is deprecated. See :h deprecated', 'WarningMsg' } }, true, {}) + vim.deprecate('vim.lsp.util.set_qflist', 'setqflist', '0.8') vim.fn.setqflist({}, ' ', { title = 'Language Server', items = items, diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index 2157112d2f..57d8c5fd21 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -519,17 +519,11 @@ local function tree_contains(tree, range) local start_fits = start_row < range[1] or (start_row == range[1] and start_col <= range[2]) local end_fits = end_row > range[3] or (end_row == range[3] and end_col >= range[4]) - if start_fits and end_fits then - return true - end - - return false + return start_fits and end_fits end --- Determines whether {range} is contained in this language tree --- ---- This goes down the tree to recursively check children. ---- ---@param range A range, that is a `{ start_line, start_col, end_line, end_col }` table. function LanguageTree:contains(range) for _, tree in pairs(self._trees) do diff --git a/runtime/optwin.vim b/runtime/optwin.vim index a13e945098..493f7b57d0 100644 --- a/runtime/optwin.vim +++ b/runtime/optwin.vim @@ -956,7 +956,6 @@ call <SID>Header("mapping") call append("$", "maxmapdepth\tmaximum depth of mapping") call append("$", " \tset mmd=" . &mmd) call append("$", "remap\trecognize mappings in mapped keys") -call <SID>BinOptionG("remap", &remap) call append("$", "timeout\tallow timing out halfway into a mapping") call <SID>BinOptionG("to", &to) call append("$", "ttimeout\tallow timing out halfway into a key code") |