aboutsummaryrefslogtreecommitdiff
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/autoload/man.vim107
-rw-r--r--runtime/doc/lua.txt120
-rw-r--r--runtime/filetype.vim9
-rw-r--r--runtime/lua/vim/filetype.lua62
-rw-r--r--runtime/lua/vim/keymap.lua135
-rw-r--r--runtime/lua/vim/lsp.lua44
-rw-r--r--runtime/lua/vim/lsp/buf.lua15
-rw-r--r--runtime/lua/vim/lsp/diagnostic.lua42
-rw-r--r--runtime/lua/vim/lsp/util.lua16
-rw-r--r--runtime/scripts.vim2
-rw-r--r--runtime/syntax/checkhealth.vim4
11 files changed, 456 insertions, 100 deletions
diff --git a/runtime/autoload/man.vim b/runtime/autoload/man.vim
index 90d353f9de..a954e1b1a3 100644
--- a/runtime/autoload/man.vim
+++ b/runtime/autoload/man.vim
@@ -7,7 +7,6 @@ let s:loaded_man = 1
let s:find_arg = '-w'
let s:localfile_arg = v:true " Always use -l if possible. #6683
-let s:section_arg = '-S'
function! man#init() abort
try
@@ -216,16 +215,38 @@ endfunction
function! s:get_path(sect, name) abort
" Some man implementations (OpenBSD) return all available paths from the
- " search command, so we get() the first one. #8341
- if empty(a:sect)
- return substitute(get(split(s:system(['man', s:find_arg, a:name])), 0, ''), '\n\+$', '', '')
+ " search command. Previously, this function would simply select the first one.
+ "
+ " However, some searches will report matches that are incorrect:
+ " man -w strlen may return string.3 followed by strlen.3, and therefore
+ " selecting the first would get us the wrong page. Thus, we must find the
+ " first matching one.
+ "
+ " There's yet another special case here. Consider the following:
+ " If you run man -w strlen and string.3 comes up first, this is a problem. We
+ " should search for a matching named one in the results list.
+ " However, if you search for man -w clock_gettime, you will *only* get
+ " clock_getres.2, which is the right page. Searching the resuls for
+ " clock_gettime will no longer work. In this case, we should just use the
+ " first one that was found in the correct section.
+ "
+ " Finally, we can avoid relying on -S or -s here since they are very
+ " inconsistently supported. Instead, call -w with a section and a name.
+ let results = split(s:system(['man', s:find_arg, a:sect, a:name]))
+
+ if empty(results)
+ return ''
endif
- " '-s' flag handles:
- " - tokens like 'printf(echo)'
- " - sections starting with '-'
- " - 3pcap section (found on macOS)
- " - commas between sections (for section priority)
- return substitute(get(split(s:system(['man', s:find_arg, s:section_arg, a:sect, a:name])), 0, ''), '\n\+$', '', '')
+
+ " find any that match the specified name
+ let namematches = filter(copy(results), 'fnamemodify(v:val, ":t") =~ a:name')
+ let sectmatches = []
+
+ if !empty(namematches) && !empty(a:sect)
+ let sectmatches = filter(copy(namematches), 'fnamemodify(v:val, ":e") == a:sect')
+ endif
+
+ return substitute(get(sectmatches, 0, get(namematches, 0, results[0])), '\n\+$', '', '')
endfunction
" s:verify_exists attempts to find the path to a manpage
@@ -243,40 +264,72 @@ endfunction
" then we don't do it again in step 2.
function! s:verify_exists(sect, name) abort
let sect = a:sect
- if empty(sect)
- let sect = get(b:, 'man_default_sects', '')
- endif
- try
- return s:get_path(sect, a:name)
- catch /^command error (/
- endtry
-
- if !empty(get(b:, 'man_default_sects', '')) && sect !=# b:man_default_sects
+ if empty(sect)
+ " no section specified, so search with b:man_default_sects
+ if exists('b:man_default_sects')
+ let sects = split(b:man_default_sects, ',')
+ for sec in sects
+ try
+ let res = s:get_path(sec, a:name)
+ if !empty(res)
+ return res
+ endif
+ catch /^command error (/
+ endtry
+ endfor
+ endif
+ else
+ " try with specified section
try
- return s:get_path(b:man_default_sects, a:name)
+ let res = s:get_path(sect, a:name)
+ if !empty(res)
+ return res
+ endif
catch /^command error (/
endtry
- endif
- if !empty(sect)
- try
- return s:get_path('', a:name)
- catch /^command error (/
- endtry
+ " try again with b:man_default_sects
+ if exists('b:man_default_sects')
+ let sects = split(b:man_default_sects, ',')
+ for sec in sects
+ try
+ let res = s:get_path(sec, a:name)
+ if !empty(res)
+ return res
+ endif
+ catch /^command error (/
+ endtry
+ endfor
+ endif
endif
+ " if none of the above worked, we will try with no section
+ try
+ let res = s:get_path('', a:name)
+ if !empty(res)
+ return res
+ endif
+ catch /^command error (/
+ endtry
+
+ " if that still didn't work, we will check for $MANSECT and try again with it
+ " unset
if !empty($MANSECT)
try
let MANSECT = $MANSECT
call setenv('MANSECT', v:null)
- return s:get_path('', a:name)
+ let res = s:get_path('', a:name)
+ if !empty(res)
+ return res
+ endif
catch /^command error (/
finally
call setenv('MANSECT', MANSECT)
endtry
endif
+ " finally, if that didn't work, there is no hope
throw 'no manual entry for ' . a:name
endfunction
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index 4f76c7c7a6..80c1f58323 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -1240,19 +1240,32 @@ inspect({object}, {options}) *vim.inspect()*
https://github.com/kikito/inspect.lua
https://github.com/mpeterv/vinspect
-notify({msg}, {log_level}, {opts}) *vim.notify()*
- Notification provider
+notify({msg}, {level}, {opts}) *vim.notify()*
+ Display a notification to the user.
- Without a runtime, writes to :Messages
+ This function can be overridden by plugins to display
+ notifications using a custom provider (such as the system
+ notification provider). By default, writes to |:messages|.
Parameters: ~
- {msg} string Content of the notification to show to
- the user
- {log_level} number|nil enum from vim.log.levels
- {opts} table|nil additional options (timeout, etc)
+ {msg} string Content of the notification to show to the
+ user.
+ {level} number|nil One of the values from
+ |vim.log.levels|.
+ {opts} table|nil Optional parameters. Unused by default.
- See also: ~
- :help nvim_notify
+notify_once({msg}, {level}, {opts}) *vim.notify_once()*
+ Display a notification only one time.
+
+ Like |vim.notify()|, but subsequent calls with the same
+ message will not display a notification.
+
+ Parameters: ~
+ {msg} string Content of the notification to show to the
+ user.
+ {level} number|nil One of the values from
+ |vim.log.levels|.
+ {opts} table|nil Optional parameters. Unused by default.
on_key({fn}, {ns_id}) *vim.on_key()*
Adds Lua function {fn} with namespace id {ns_id} as a listener
@@ -1316,6 +1329,18 @@ paste({lines}, {phase}) *vim.paste()*
See also: ~
|paste|
+pretty_print({...}) *vim.pretty_print()*
+ Prints given arguments in human-readable format. Example: >
+ -- Print highlight group Normal and store it's contents in a variable.
+ local hl_normal = vim.pretty_print(vim.api.nvim_get_hl_by_name("Normal", true))
+<
+
+ Return: ~
+ given arguments.
+
+ See also: ~
+ |vim.inspect()|
+
region({bufnr}, {pos1}, {pos2}, {regtype}, {inclusive}) *vim.region()*
Get a table of lines with start, end columns for a region
marked by two points
@@ -1847,4 +1872,81 @@ add({filetypes}) *vim.filetype.add()*
{filetypes} table A table containing new filetype maps
(see example).
+
+==============================================================================
+Lua module: keymap *lua-keymap*
+
+del({modes}, {lhs}, {opts}) *vim.keymap.del()*
+ Remove an existing mapping. Examples: >
+
+ vim.keymap.del('n', 'lhs')
+
+ vim.keymap.del({'n', 'i', 'v'}, '<leader>w', { buffer = 5 })
+<
+
+ Parameters: ~
+ {opts} table A table of optional arguments:
+ • buffer: (number or boolean) Remove a mapping
+ from the given buffer. When "true" or 0, use the
+ current buffer.
+
+ See also: ~
+ |vim.keymap.set()|
+
+set({mode}, {lhs}, {rhs}, {opts}) *vim.keymap.set()*
+ Add a new |mapping|. Examples: >
+
+ -- Can add mapping to Lua functions
+ vim.keymap.set('n', 'lhs', function() print("real lua function") end)
+
+ -- Can use it to map multiple modes
+ vim.keymap.set({'n', 'v'}, '<leader>lr', vim.lsp.buf.references, { buffer=true })
+
+ -- Can add mapping for specific buffer
+ vim.keymap.set('n', '<leader>w', "<cmd>w<cr>", { silent = true, buffer = 5 })
+
+ -- Expr mappings
+ vim.keymap.set('i', '<Tab>', function()
+ return vim.fn.pumvisible() == 1 and "<C-n>" or "<Tab>"
+ end, { expr = true })
+ -- <Plug> mappings
+ vim.keymap.set('n', '[%', '<Plug>(MatchitNormalMultiBackward)')
+<
+
+ Note that in a mapping like: >
+
+ vim.keymap.set('n', 'asdf', require('jkl').my_fun)
+<
+
+ the require('jkl') gets evaluated during this call in order to
+ access the function. If you want to avoid this cost at startup
+ you can wrap it in a function, for example: >
+
+ vim.keymap.set('n', 'asdf', function() return require('jkl').my_fun() end)
+<
+
+ Parameters: ~
+ {mode} string|table Same mode short names as
+ |nvim_set_keymap()|. Can also be list of modes to
+ create mapping on multiple modes.
+ {lhs} string Left-hand side |{lhs}| of the mapping.
+ {rhs} string|function Right-hand side |{rhs}| of the
+ mapping. Can also be a Lua function.
+ {opts} table A table of |:map-arguments| such as
+ "silent". In addition to the options listed in
+ |nvim_set_keymap()|, this table also accepts the
+ following keys:
+ • replace_keycodes: (boolean, default true) When
+ both this and expr is "true",
+ |nvim_replace_termcodes()| is applied to the
+ result of Lua expr maps.
+ • remap: (boolean) Make the mapping recursive.
+ This is the inverse of the "noremap" option from
+ |nvim_set_keymap()|. Default `true` if `lhs` is
+ a string starting with `<plug>`
+ (case-insensitive), `false` otherwise.
+
+ See also: ~
+ |nvim_set_keymap()|
+
vim:tw=78:ts=8:ft=help:norl:
diff --git a/runtime/filetype.vim b/runtime/filetype.vim
index 7fdbfe32d8..907f806f31 100644
--- a/runtime/filetype.vim
+++ b/runtime/filetype.vim
@@ -493,7 +493,7 @@ au BufNewFile,BufRead */debian/patches/* call dist#ft#Dep3patch()
" Diff files
au BufNewFile,BufRead *.diff,*.rej setf diff
au BufNewFile,BufRead *.patch
- \ if getline(1) =~ '^From [0-9a-f]\{40\} Mon Sep 17 00:00:00 2001$' |
+ \ if getline(1) =~# '^From [0-9a-f]\{40,\} Mon Sep 17 00:00:00 2001$' |
\ setf gitsendemail |
\ else |
\ setf diff |
@@ -672,6 +672,7 @@ autocmd BufRead,BufNewFile *.gift setf gift
" Git
au BufNewFile,BufRead COMMIT_EDITMSG,MERGE_MSG,TAG_EDITMSG setf gitcommit
+au BufNewFile,BufRead NOTES_EDITMSG,EDIT_DESCRIPTION setf gitcommit
au BufNewFile,BufRead *.git/config,.gitconfig,/etc/gitconfig setf gitconfig
au BufNewFile,BufRead */.config/git/config setf gitconfig
au BufNewFile,BufRead .gitmodules,*.git/modules/*/config setf gitconfig
@@ -680,12 +681,8 @@ if !empty($XDG_CONFIG_HOME)
endif
au BufNewFile,BufRead git-rebase-todo setf gitrebase
au BufRead,BufNewFile .gitsendemail.msg.?????? setf gitsendemail
-au BufNewFile,BufRead .msg.[0-9]*
- \ if getline(1) =~ '^From.*# This line is ignored.$' |
- \ setf gitsendemail |
- \ endif
au BufNewFile,BufRead *.git/*
- \ if getline(1) =~ '^\x\{40\}\>\|^ref: ' |
+ \ if getline(1) =~# '^\x\{40,\}\>\|^ref: ' |
\ setf git |
\ endif
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index 54b20f7391..28cffdf072 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -15,7 +15,7 @@ local function starsetf(ft)
end
end, {
-- Starset matches should always have lowest priority
- priority = -1,
+ priority = -math.huge,
}}
end
@@ -868,6 +868,8 @@ local filename = {
["TAG_EDITMSG"] = "gitcommit",
["MERGE_MSG"] = "gitcommit",
["COMMIT_EDITMSG"] = "gitcommit",
+ ["NOTES_EDITMSG"] = "gitcommit",
+ ["EDIT_DESCRIPTION"] = "gitcommit",
[".gitconfig"] = "gitconfig",
[".gitmodules"] = "gitconfig",
["/.config/git/config"] = "gitconfig",
@@ -1454,6 +1456,25 @@ local function dispatch(ft, path, bufnr, ...)
end
---@private
+local function match_pattern(name, path, tail, pat)
+ -- If the pattern contains a / match against the full path, otherwise just the tail
+ local fullpat = "^" .. pat .. "$"
+ local matches
+ if pat:find("/") then
+ -- Similar to |autocmd-pattern|, if the pattern contains a '/' then check for a match against
+ -- both the short file name (as typed) and the full file name (after expanding to full path
+ -- and resolving symlinks)
+ matches = name:match(fullpat) or path:match(fullpat)
+ else
+ matches = tail:match(fullpat)
+ end
+ return matches
+end
+
+--- Set the filetype for the given buffer from a file name.
+---
+---@param name string File name (can be an absolute or relative path)
+---@param bufnr number|nil The buffer to set the filetype for. Defaults to the current buffer.
function M.match(name, bufnr)
-- When fired from the main filetypedetect autocommand the {bufnr} argument is omitted, so we use
-- the current buffer. The {bufnr} argument is provided to allow extensibility in case callers
@@ -1474,21 +1495,18 @@ function M.match(name, bufnr)
return
end
- -- Next, check the file path against available patterns
- for _, v in ipairs(pattern_sorted) do
+ -- Next, check the file path against available patterns with non-negative priority
+ local j = 1
+ for i, v in ipairs(pattern_sorted) do
local k = next(v)
- local ft = v[k][1]
- -- If the pattern contains a / match against the full path, otherwise just the tail
- local pat = "^" .. k .. "$"
- local matches
- if k:find("/") then
- -- Similar to |autocmd-pattern|, if the pattern contains a '/' then check for a match against
- -- both the short file name (as typed) and the full file name (after expanding to full path
- -- and resolving symlinks)
- matches = name:match(pat) or path:match(pat)
- else
- matches = tail:match(pat)
+ local opts = v[k][2]
+ if opts.priority < 0 then
+ j = i
+ break
end
+
+ local ft = v[k][1]
+ local matches = match_pattern(name, path, tail, k)
if matches then
if dispatch(ft, path, bufnr, matches) then
return
@@ -1496,11 +1514,25 @@ function M.match(name, bufnr)
end
end
- -- Finally, check file extension
+ -- Next, check file extension
local ext = vim.fn.fnamemodify(name, ":e")
if dispatch(extension[ext], path, bufnr) then
return
end
+
+ -- Finally, check patterns with negative priority
+ for i = j, #pattern_sorted do
+ local v = pattern_sorted[i]
+ local k = next(v)
+
+ local ft = v[k][1]
+ local matches = match_pattern(name, path, tail, k)
+ if matches then
+ if dispatch(ft, path, bufnr, matches) then
+ return
+ end
+ end
+ end
end
return M
diff --git a/runtime/lua/vim/keymap.lua b/runtime/lua/vim/keymap.lua
new file mode 100644
index 0000000000..d53b790746
--- /dev/null
+++ b/runtime/lua/vim/keymap.lua
@@ -0,0 +1,135 @@
+local keymap = {}
+
+--- Add a new |mapping|.
+--- Examples:
+--- <pre>
+--- -- Can add mapping to Lua functions
+--- vim.keymap.set('n', 'lhs', function() print("real lua function") end)
+---
+--- -- Can use it to map multiple modes
+--- vim.keymap.set({'n', 'v'}, '<leader>lr', vim.lsp.buf.references, { buffer=true })
+---
+--- -- Can add mapping for specific buffer
+--- vim.keymap.set('n', '<leader>w', "<cmd>w<cr>", { silent = true, buffer = 5 })
+---
+--- -- Expr mappings
+--- vim.keymap.set('i', '<Tab>', function()
+--- return vim.fn.pumvisible() == 1 and "<C-n>" or "<Tab>"
+--- end, { expr = true })
+--- -- <Plug> mappings
+--- vim.keymap.set('n', '[%%', '<Plug>(MatchitNormalMultiBackward)')
+--- </pre>
+---
+--- Note that in a mapping like:
+--- <pre>
+--- vim.keymap.set('n', 'asdf', require('jkl').my_fun)
+--- </pre>
+---
+--- the require('jkl') gets evaluated during this call in order to access the function. If you want to
+--- avoid this cost at startup you can wrap it in a function, for example:
+--- <pre>
+--- vim.keymap.set('n', 'asdf', function() return require('jkl').my_fun() end)
+--- </pre>
+---
+---@param mode string|table Same mode short names as |nvim_set_keymap()|.
+--- Can also be list of modes to create mapping on multiple modes.
+---@param lhs string Left-hand side |{lhs}| of the mapping.
+---@param rhs string|function Right-hand side |{rhs}| of the mapping. Can also be a Lua function.
+--
+---@param opts table A table of |:map-arguments| such as "silent". In addition to the options
+--- listed in |nvim_set_keymap()|, this table also accepts the following keys:
+--- - replace_keycodes: (boolean, default true) When both this and expr is "true",
+--- |nvim_replace_termcodes()| is applied to the result of Lua expr maps.
+--- - remap: (boolean) Make the mapping recursive. This is the
+--- inverse of the "noremap" option from |nvim_set_keymap()|.
+--- Default `true` if `lhs` is a string starting with `<plug>` (case-insensitive), `false` otherwise.
+---@see |nvim_set_keymap()|
+function keymap.set(mode, lhs, rhs, opts)
+ vim.validate {
+ mode = {mode, {'s', 't'}},
+ lhs = {lhs, 's'},
+ rhs = {rhs, {'s', 'f'}},
+ opts = {opts, 't', true}
+ }
+
+ opts = vim.deepcopy(opts) or {}
+ local is_rhs_luaref = type(rhs) == "function"
+ mode = type(mode) == 'string' and {mode} or mode
+
+ if is_rhs_luaref and opts.expr and opts.replace_keycodes ~= false then
+ local user_rhs = rhs
+ rhs = function ()
+ return vim.api.nvim_replace_termcodes(user_rhs(), true, true, true)
+ end
+ end
+ -- clear replace_keycodes from opts table
+ opts.replace_keycodes = nil
+
+ if opts.remap == nil then
+ -- remap by default on <plug> mappings and don't otherwise.
+ opts.noremap = is_rhs_luaref or rhs:lower():match("^<plug>") == nil
+ else
+ -- remaps behavior is opposite of noremap option.
+ opts.noremap = not opts.remap
+ opts.remap = nil
+ end
+
+ if is_rhs_luaref then
+ opts.callback = rhs
+ rhs = ''
+ end
+
+ if opts.buffer then
+ local bufnr = opts.buffer == true and 0 or opts.buffer
+ opts.buffer = nil
+ for _, m in ipairs(mode) do
+ vim.api.nvim_buf_set_keymap(bufnr, m, lhs, rhs, opts)
+ end
+ else
+ opts.buffer = nil
+ for _, m in ipairs(mode) do
+ vim.api.nvim_set_keymap(m, lhs, rhs, opts)
+ end
+ end
+end
+
+--- Remove an existing mapping.
+--- Examples:
+--- <pre>
+--- vim.keymap.del('n', 'lhs')
+---
+--- vim.keymap.del({'n', 'i', 'v'}, '<leader>w', { buffer = 5 })
+--- </pre>
+---@param opts table A table of optional arguments:
+--- - buffer: (number or boolean) Remove a mapping from the given buffer.
+--- When "true" or 0, use the current buffer.
+---@see |vim.keymap.set()|
+---
+function keymap.del(modes, lhs, opts)
+ vim.validate {
+ mode = {modes, {'s', 't'}},
+ lhs = {lhs, 's'},
+ opts = {opts, 't', true}
+ }
+
+ opts = opts or {}
+ modes = type(modes) == 'string' and {modes} or modes
+
+ local buffer = false
+ if opts.buffer ~= nil then
+ buffer = opts.buffer == true and 0 or opts.buffer
+ opts.buffer = nil
+ end
+
+ if buffer == false then
+ for _, mode in ipairs(modes) do
+ vim.api.nvim_del_keymap(mode, lhs)
+ end
+ else
+ for _, mode in ipairs(modes) do
+ vim.api.nvim_buf_del_keymap(buffer, mode, lhs)
+ end
+ end
+end
+
+return keymap
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index 7df0064b6b..fc9c991c05 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -306,7 +306,6 @@ local function once(fn)
end
end
-
local changetracking = {}
do
--@private
@@ -327,6 +326,7 @@ do
if not state then
state = {
pending_changes = {};
+ last_flush = {};
use_incremental_sync = (
if_nil(client.config.flags.allow_incremental_sync, true)
and client.resolved_capabilities.text_document_did_change == protocol.TextDocumentSyncKind.Incremental
@@ -347,8 +347,11 @@ do
function changetracking.reset_buf(client, bufnr)
changetracking.flush(client)
local state = state_by_client[client.id]
- if state and state.buffers then
- state.buffers[bufnr] = nil
+ if state then
+ if state.buffers then
+ state.buffers[bufnr] = nil
+ end
+ state.last_flush = {}
end
end
@@ -362,6 +365,33 @@ do
end
---@private
+ --
+ -- Adjust debounce time by taking time of last didChange notification into
+ -- consideration. If the last didChange happened more than `debounce` time ago,
+ -- debounce can be skipped and otherwise maybe reduced.
+ --
+ -- This turns the debounce into a kind of client rate limiting
+ local function next_debounce(debounce, state, bufnr)
+ if debounce == 0 then
+ return 0
+ end
+ local ns_to_ms = 0.000001
+ local last_flush = state.last_flush[bufnr]
+ if not last_flush then
+ return debounce
+ end
+ local now = uv.hrtime()
+ local ms_since_last_flush = (now - last_flush) * ns_to_ms
+ local remaining_debounce = debounce - ms_since_last_flush
+ if remaining_debounce > 0 then
+ return remaining_debounce
+ else
+ state.last_flush[bufnr] = now
+ return 0
+ end
+ end
+
+ ---@private
function changetracking.prepare(bufnr, firstline, lastline, new_lastline)
local incremental_changes = function(client)
local cached_buffers = state_by_client[client.id].buffers
@@ -383,8 +413,12 @@ do
return
end
local state = state_by_client[client.id]
- local debounce = client.config.flags.debounce_text_changes or 150
+ changetracking._reset_timer(state)
+ local debounce = next_debounce(client.config.flags.debounce_text_changes or 150, state, bufnr)
if debounce == 0 then
+ if state.pending_change then
+ state.pending_change()
+ end
local changes = state.use_incremental_sync and incremental_changes(client) or full_changes()
client.notify("textDocument/didChange", {
textDocument = {
@@ -395,7 +429,6 @@ do
})
return
end
- changetracking._reset_timer(state)
if state.use_incremental_sync then
-- This must be done immediately and cannot be delayed
-- The contents would further change and startline/endline may no longer fit
@@ -406,6 +439,7 @@ do
end
state.pending_change = function()
state.pending_change = nil
+ state.last_flush[bufnr] = uv.hrtime()
if client.is_stopped() or not vim.api.nvim_buf_is_valid(bufnr) then
return
end
diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua
index 543fdb0237..c1d777ae6c 100644
--- a/runtime/lua/vim/lsp/buf.lua
+++ b/runtime/lua/vim/lsp/buf.lua
@@ -627,14 +627,19 @@ end
--- Executes an LSP server command.
---
----@param command A valid `ExecuteCommandParams` object
+---@param command_params table A valid `ExecuteCommandParams` object
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand
-function M.execute_command(command)
+function M.execute_command(command_params)
validate {
- command = { command.command, 's' },
- arguments = { command.arguments, 't', true }
+ command = { command_params.command, 's' },
+ arguments = { command_params.arguments, 't', true }
}
- request('workspace/executeCommand', command)
+ command_params = {
+ command=command_params.command,
+ arguments=command_params.arguments,
+ workDoneToken=command_params.workDoneToken,
+ }
+ request('workspace/executeCommand', command_params )
end
return M
diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua
index 8850d25233..f38b469f3c 100644
--- a/runtime/lua/vim/lsp/diagnostic.lua
+++ b/runtime/lua/vim/lsp/diagnostic.lua
@@ -243,7 +243,7 @@ end
---@param client_id number
---@private
function M.save(diagnostics, bufnr, client_id)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.save is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.save is deprecated. See :h deprecated', vim.log.levels.WARN)
local namespace = M.get_namespace(client_id)
vim.diagnostic.set(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id))
end
@@ -257,7 +257,7 @@ end
--- If nil, diagnostics of all clients are included.
---@return table with diagnostics grouped by bufnr (bufnr: Diagnostic[])
function M.get_all(client_id)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.get_all is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.get_all is deprecated. See :h deprecated', vim.log.levels.WARN)
local result = {}
local namespace
if client_id then
@@ -279,7 +279,7 @@ end
--- Else, return just the diagnostics associated with the client_id.
---@param predicate function|nil Optional function for filtering diagnostics
function M.get(bufnr, client_id, predicate)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.get is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.get is deprecated. See :h deprecated', vim.log.levels.WARN)
predicate = predicate or function() return true end
if client_id == nil then
local all_diagnostics = {}
@@ -341,7 +341,7 @@ end
---@param severity DiagnosticSeverity
---@param client_id number the client id
function M.get_count(bufnr, severity, client_id)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.get_count is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.get_count is deprecated. See :h deprecated', vim.log.levels.WARN)
severity = severity_lsp_to_vim(severity)
local opts = { severity = severity }
if client_id ~= nil then
@@ -358,7 +358,7 @@ end
---@param opts table See |vim.lsp.diagnostic.goto_next()|
---@return table Previous diagnostic
function M.get_prev(opts)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.get_prev is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.get_prev is deprecated. See :h deprecated', vim.log.levels.WARN)
if opts then
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
@@ -376,7 +376,7 @@ end
---@param opts table See |vim.lsp.diagnostic.goto_next()|
---@return table Previous diagnostic position
function M.get_prev_pos(opts)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.get_prev_pos is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.get_prev_pos is deprecated. See :h deprecated', vim.log.levels.WARN)
if opts then
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
@@ -393,7 +393,7 @@ end
---
---@param opts table See |vim.lsp.diagnostic.goto_next()|
function M.goto_prev(opts)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.goto_prev is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.goto_prev is deprecated. See :h deprecated', vim.log.levels.WARN)
if opts then
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
@@ -411,7 +411,7 @@ end
---@param opts table See |vim.lsp.diagnostic.goto_next()|
---@return table Next diagnostic
function M.get_next(opts)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.get_next is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.get_next is deprecated. See :h deprecated', vim.log.levels.WARN)
if opts then
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
@@ -429,7 +429,7 @@ end
---@param opts table See |vim.lsp.diagnostic.goto_next()|
---@return table Next diagnostic position
function M.get_next_pos(opts)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.get_next_pos is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.get_next_pos is deprecated. See :h deprecated', vim.log.levels.WARN)
if opts then
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
@@ -444,7 +444,7 @@ end
---
---@deprecated Prefer |vim.diagnostic.goto_next()|
function M.goto_next(opts)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.goto_next is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.goto_next is deprecated. See :h deprecated', vim.log.levels.WARN)
if opts then
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
@@ -468,7 +468,7 @@ end
--- - severity_limit (DiagnosticSeverity):
--- - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid.
function M.set_signs(diagnostics, bufnr, client_id, _, opts)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.set_signs is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.set_signs is deprecated. See :h deprecated', vim.log.levels.WARN)
local namespace = M.get_namespace(client_id)
if opts and not opts.severity and opts.severity_limit then
opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
@@ -489,7 +489,7 @@ end
--- - severity_limit (DiagnosticSeverity):
--- - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid.
function M.set_underline(diagnostics, bufnr, client_id, _, opts)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.set_underline is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.set_underline is deprecated. See :h deprecated', vim.log.levels.WARN)
local namespace = M.get_namespace(client_id)
if opts and not opts.severity and opts.severity_limit then
opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
@@ -511,7 +511,7 @@ end
--- - severity_limit (DiagnosticSeverity):
--- - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid.
function M.set_virtual_text(diagnostics, bufnr, client_id, _, opts)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.set_virtual_text is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.set_virtual_text is deprecated. See :h deprecated', vim.log.levels.WARN)
local namespace = M.get_namespace(client_id)
if opts and not opts.severity and opts.severity_limit then
opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
@@ -530,7 +530,7 @@ end
---@return an array of [text, hl_group] arrays. This can be passed directly to
--- the {virt_text} option of |nvim_buf_set_extmark()|.
function M.get_virtual_text_chunks_for_line(bufnr, _, line_diags, opts)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.get_virtual_text_chunks_for_line is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.get_virtual_text_chunks_for_line is deprecated. See :h deprecated', vim.log.levels.WARN)
return vim.diagnostic._get_virt_text_chunks(diagnostic_lsp_to_vim(line_diags, bufnr), opts)
end
@@ -548,7 +548,7 @@ end
---@param position table|nil The (0,0)-indexed position
---@return table {popup_bufnr, win_id}
function M.show_position_diagnostics(opts, buf_nr, position)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.show_position_diagnostics is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.show_position_diagnostics is deprecated. See :h deprecated', vim.log.levels.WARN)
opts = opts or {}
opts.scope = "cursor"
opts.pos = position
@@ -572,7 +572,7 @@ end
---@param client_id number|nil the client id
---@return table {popup_bufnr, win_id}
function M.show_line_diagnostics(opts, buf_nr, line_nr, client_id)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.show_line_diagnostics is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.show_line_diagnostics is deprecated. See :h deprecated', vim.log.levels.WARN)
opts = opts or {}
opts.scope = "line"
opts.pos = line_nr
@@ -596,7 +596,7 @@ end
--- client. The default is to redraw diagnostics for all attached
--- clients.
function M.redraw(bufnr, client_id)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.redraw is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.redraw is deprecated. See :h deprecated', vim.log.levels.WARN)
bufnr = get_bufnr(bufnr)
if not client_id then
return vim.lsp.for_each_buffer_client(bufnr, function(client)
@@ -624,7 +624,7 @@ end
--- - {workspace}: (boolean, default true)
--- - Set the list with workspace diagnostics
function M.set_qflist(opts)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.set_qflist is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.set_qflist is deprecated. See :h deprecated', vim.log.levels.WARN)
opts = opts or {}
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
@@ -656,7 +656,7 @@ end
--- - {workspace}: (boolean, default false)
--- - Set the list with workspace diagnostics
function M.set_loclist(opts)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.set_loclist is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.set_loclist is deprecated. See :h deprecated', vim.log.levels.WARN)
opts = opts or {}
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
@@ -684,7 +684,7 @@ end
-- send diagnostic information and the client will still process it. The
-- diagnostics are simply not displayed to the user.
function M.disable(bufnr, client_id)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.disable is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.disable is deprecated. See :h deprecated', vim.log.levels.WARN)
if not client_id then
return vim.lsp.for_each_buffer_client(bufnr, function(client)
M.disable(bufnr, client.id)
@@ -705,7 +705,7 @@ end
--- client. The default is to enable diagnostics for all attached
--- clients.
function M.enable(bufnr, client_id)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.enable is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.enable is deprecated. See :h deprecated', vim.log.levels.WARN)
if not client_id then
return vim.lsp.for_each_buffer_client(bufnr, function(client)
M.enable(bufnr, client.id)
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index dcd68a3433..89c5ebe8f7 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -10,14 +10,6 @@ local uv = vim.loop
local npcall = vim.F.npcall
local split = vim.split
-local _warned = {}
-local warn_once = function(message)
- if not _warned[message] then
- vim.api.nvim_err_writeln(message)
- _warned[message] = true
- end
-end
-
local M = {}
local default_border = {
@@ -201,6 +193,11 @@ end
local function get_lines(bufnr, rows)
rows = type(rows) == "table" and rows or { rows }
+ -- This is needed for bufload and bufloaded
+ if bufnr == 0 then
+ bufnr = vim.api.nvim_get_current_buf()
+ end
+
---@private
local function buf_lines()
local lines = {}
@@ -1822,7 +1819,7 @@ function M.make_given_range_params(start_pos, end_pos, bufnr, offset_encoding)
end_pos = {end_pos, 't', true};
offset_encoding = {offset_encoding, 's', true};
}
- bufnr = bufnr or 0
+ bufnr = bufnr or vim.api.nvim_get_current_buf()
offset_encoding = offset_encoding or M._get_offset_encoding(bufnr)
local A = list_extend({}, start_pos or api.nvim_buf_get_mark(bufnr, '<'))
local B = list_extend({}, end_pos or api.nvim_buf_get_mark(bufnr, '>'))
@@ -1928,7 +1925,6 @@ function M.lookup_section(settings, section)
end
M._get_line_byte_from_position = get_line_byte_from_position
-M._warn_once = warn_once
M.buf_versions = {}
diff --git a/runtime/scripts.vim b/runtime/scripts.vim
index 3790b1c10f..e41405a6c5 100644
--- a/runtime/scripts.vim
+++ b/runtime/scripts.vim
@@ -384,7 +384,7 @@ else
set ft=scheme
" Git output
- elseif s:line1 =~# '^\(commit\|tree\|object\) \x\{40\}\>\|^tag \S\+$'
+ elseif s:line1 =~# '^\(commit\|tree\|object\) \x\{40,\}\>\|^tag \S\+$'
set ft=git
" Gprof (gnu profiler)
diff --git a/runtime/syntax/checkhealth.vim b/runtime/syntax/checkhealth.vim
index dff880a0bc..37f1822740 100644
--- a/runtime/syntax/checkhealth.vim
+++ b/runtime/syntax/checkhealth.vim
@@ -12,7 +12,9 @@ unlet! b:current_syntax
syn case match
" We do not care about markdown syntax errors
-syn clear markdownError
+if hlexists('markdownError')
+ syn clear markdownError
+endif
syn keyword healthError ERROR[:] containedin=markdownCodeBlock,mkdListItemLine
syn keyword healthWarning WARNING[:] containedin=markdownCodeBlock,mkdListItemLine