aboutsummaryrefslogtreecommitdiff
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/autoload/health/nvim.vim2
-rw-r--r--runtime/doc/api.txt25
-rw-r--r--runtime/doc/deprecated.txt4
-rw-r--r--runtime/doc/index.txt5
-rw-r--r--runtime/doc/lsp.txt83
-rw-r--r--runtime/doc/map.txt5
-rw-r--r--runtime/doc/options.txt89
-rw-r--r--runtime/doc/quickref.txt2
-rw-r--r--runtime/doc/syntax.txt4
-rw-r--r--runtime/doc/treesitter.txt2
-rw-r--r--runtime/doc/various.txt8
-rw-r--r--runtime/doc/vim_diff.txt2
-rw-r--r--runtime/lua/vim/_editor.lua1
-rw-r--r--runtime/lua/vim/filetype.lua100
-rw-r--r--runtime/lua/vim/filetype/detect.lua573
-rw-r--r--runtime/lua/vim/lsp.lua81
-rw-r--r--runtime/lua/vim/lsp/buf.lua37
-rw-r--r--runtime/lua/vim/lsp/handlers.lua8
-rw-r--r--runtime/lua/vim/lsp/health.lua3
-rw-r--r--runtime/lua/vim/lsp/util.lua33
-rw-r--r--runtime/lua/vim/treesitter/languagetree.lua8
-rw-r--r--runtime/optwin.vim1
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")