diff options
Diffstat (limited to 'runtime/lua/vim')
-rw-r--r-- | runtime/lua/vim/_defaults.lua | 13 | ||||
-rw-r--r-- | runtime/lua/vim/_meta/options.lua | 58 | ||||
-rw-r--r-- | runtime/lua/vim/_meta/vvars.lua | 8 | ||||
-rw-r--r-- | runtime/lua/vim/filetype.lua | 5 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/buf.lua | 116 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/util.lua | 131 | ||||
-rw-r--r-- | runtime/lua/vim/treesitter/dev.lua | 6 | ||||
-rw-r--r-- | runtime/lua/vim/treesitter/health.lua | 18 |
8 files changed, 223 insertions, 132 deletions
diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua index d3b7bda871..f399360f1e 100644 --- a/runtime/lua/vim/_defaults.lua +++ b/runtime/lua/vim/_defaults.lua @@ -363,6 +363,19 @@ do cmd({ cmd = 'blast' }) end end, { desc = ':blast' }) + + -- Add empty lines + vim.keymap.set('n', '[<Space>', function() + local repeated = vim.fn['repeat']({ '' }, vim.v.count1) + local linenr = vim.api.nvim_win_get_cursor(0)[1] + vim.api.nvim_buf_set_lines(0, linenr - 1, linenr - 1, true, repeated) + end, { desc = 'Add empty line above cursor' }) + + vim.keymap.set('n', ']<Space>', function() + local repeated = vim.fn['repeat']({ '' }, vim.v.count1) + local linenr = vim.api.nvim_win_get_cursor(0)[1] + vim.api.nvim_buf_set_lines(0, linenr, linenr, true, repeated) + end, { desc = 'Add empty line below cursor' }) end end diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index 5e5b6b5ed1..45ab14a774 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -1106,7 +1106,7 @@ vim.bo.cot = vim.bo.completeopt vim.go.completeopt = vim.o.completeopt vim.go.cot = vim.go.completeopt ---- only for MS-Windows +--- only modifiable in MS-Windows --- When this option is set it overrules 'shellslash' for completion: --- - When this option is set to "slash", a forward slash is used for path --- completion in insert mode. This is useful when editing HTML tag, or @@ -2294,31 +2294,31 @@ vim.wo.fcs = vim.wo.fillchars vim.go.fillchars = vim.o.fillchars vim.go.fcs = vim.go.fillchars ---- Expression that is evaluated to obtain the filename(s) for the `:find` +--- Function that is called to obtain the filename(s) for the `:find` --- command. When this option is empty, the internal `file-searching` --- mechanism is used. --- ---- While evaluating the expression, the `v:fname` variable is set to the ---- argument of the `:find` command. +--- The value can be the name of a function, a `lambda` or a `Funcref`. +--- See `option-value-function` for more information. --- ---- The expression is evaluated only once per `:find` command invocation. ---- The expression can process all the directories specified in 'path'. +--- The function is called with two arguments. The first argument is a +--- `String` and is the `:find` command argument. The second argument is +--- a `Boolean` and is set to `v:true` when the function is called to get +--- a List of command-line completion matches for the `:find` command. +--- The function should return a List of strings. --- ---- The expression may be evaluated for command-line completion as well, ---- in which case the `v:cmdcomplete` variable will be set to `v:true`, ---- otherwise it will be set to `v:false`. +--- The function is called only once per `:find` command invocation. +--- The function can process all the directories specified in 'path'. --- ---- If a match is found, the expression should return a `List` containing ---- one or more file names. If a match is not found, the expression +--- If a match is found, the function should return a `List` containing +--- one or more file names. If a match is not found, the function --- should return an empty List. --- ---- If any errors are encountered during the expression evaluation, an +--- If any errors are encountered during the function invocation, an --- empty List is used as the return value. --- ---- Using a function call without arguments is faster `expr-option-function` ---- --- It is not allowed to change text or jump to another window while ---- evaluating 'findexpr' `textlock`. +--- executing the 'findfunc' `textlock`. --- --- This option cannot be set from a `modeline` or in the `sandbox`, for --- security reasons. @@ -2327,28 +2327,28 @@ vim.go.fcs = vim.go.fillchars --- --- ```vim --- " Use glob() ---- func FindExprGlob() ---- let pat = v:cmdcomplete ? $'{v:fname}*' : v:fname +--- func FindFuncGlob(cmdarg, cmdcomplete) +--- let pat = a:cmdcomplete ? $'{a:cmdarg}*' : a:cmdarg --- return glob(pat, v:false, v:true) --- endfunc ---- set findexpr=FindExprGlob() +--- set findfunc=FindFuncGlob --- --- " Use the 'git ls-files' output ---- func FindGitFiles() +--- func FindGitFiles(cmdarg, cmdcomplete) --- let fnames = systemlist('git ls-files') ---- return fnames->filter('v:val =~? v:fname') +--- return fnames->filter('v:val =~? a:cmdarg') --- endfunc ---- set findexpr=FindGitFiles() +--- set findfunc=FindGitFiles --- ``` --- --- --- @type string -vim.o.findexpr = "" -vim.o.fexpr = vim.o.findexpr -vim.bo.findexpr = vim.o.findexpr -vim.bo.fexpr = vim.bo.findexpr -vim.go.findexpr = vim.o.findexpr -vim.go.fexpr = vim.go.findexpr +vim.o.findfunc = "" +vim.o.ffu = vim.o.findfunc +vim.bo.findfunc = vim.o.findfunc +vim.bo.ffu = vim.bo.findfunc +vim.go.findfunc = vim.o.findfunc +vim.go.ffu = vim.go.findfunc --- When writing a file and this option is on, <EOL> at the end of file --- will be restored if missing. Turn this option off if you want to @@ -5547,7 +5547,7 @@ vim.o.srr = vim.o.shellredir vim.go.shellredir = vim.o.shellredir vim.go.srr = vim.go.shellredir ---- only for MS-Windows +--- only modifiable in MS-Windows --- When set, a forward slash is used when expanding file names. This is --- useful when a Unix-like shell is used instead of cmd.exe. Backward --- slashes can still be typed, but they are changed to forward slashes by @@ -5564,7 +5564,7 @@ vim.go.srr = vim.go.shellredir --- Also see 'completeslash'. --- --- @type boolean -vim.o.shellslash = false +vim.o.shellslash = true vim.o.ssl = vim.o.shellslash vim.go.shellslash = vim.o.shellslash vim.go.ssl = vim.go.shellslash diff --git a/runtime/lua/vim/_meta/vvars.lua b/runtime/lua/vim/_meta/vvars.lua index b104356334..e00402ab3f 100644 --- a/runtime/lua/vim/_meta/vvars.lua +++ b/runtime/lua/vim/_meta/vvars.lua @@ -44,11 +44,6 @@ vim.v.cmdarg = ... --- @type integer vim.v.cmdbang = ... ---- When evaluating 'findexpr': if 'findexpr' is used for cmdline ---- completion the value is `v:true`, otherwise it is `v:false`. ---- @type boolean -vim.v.cmdcomplete = ... - --- The current locale setting for collation order of the runtime --- environment. This allows Vim scripts to be aware of the --- current locale encoding. Technical: it's the value of @@ -272,8 +267,7 @@ vim.v.fcs_choice = ... vim.v.fcs_reason = ... --- When evaluating 'includeexpr': the file name that was ---- detected. When evaluating 'findexpr': the argument passed to ---- the `:find` command. Empty otherwise. +--- detected. Empty otherwise. --- @type string vim.v.fname = ... diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index f6928c6428..6caf25c588 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -588,6 +588,7 @@ local extension = { ibi = 'ibasic', icn = 'icon', idl = detect.idl, + idr = 'idris2', inc = detect.inc, inf = 'inform', INF = 'inform', @@ -595,6 +596,7 @@ local extension = { inko = 'inko', inp = detect.inp, ms = detect_seq(detect.nroff, 'xmath'), + ipkg = 'ipkg', iss = 'iss', mst = 'ist', ist = 'ist', @@ -668,12 +670,14 @@ local extension = { journal = 'ledger', ldg = 'ledger', ledger = 'ledger', + leo = 'leo', less = 'less', lex = 'lex', lxx = 'lex', ['l++'] = 'lex', l = 'lex', lhs = 'lhaskell', + lidr = 'lidris2', ll = 'lifelines', ly = 'lilypond', ily = 'lilypond', @@ -1151,6 +1155,7 @@ local extension = { sface = 'surface', svelte = 'svelte', svg = 'svg', + sw = 'sway', swift = 'swift', swiftinterface = 'swift', swig = 'swig', diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index 152226a757..6d7597c5ff 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -258,6 +258,33 @@ function M.implementation(opts) get_locations(ms.textDocument_implementation, opts) end +--- @param results table<integer,{err: lsp.ResponseError?, result: lsp.SignatureHelp?}> +local function process_signature_help_results(results) + local signatures = {} --- @type [vim.lsp.Client,lsp.SignatureInformation][] + + -- Pre-process results + for client_id, r in pairs(results) do + local err = r.err + local client = assert(lsp.get_client_by_id(client_id)) + if err then + vim.notify( + client.name .. ': ' .. tostring(err.code) .. ': ' .. err.message, + vim.log.levels.ERROR + ) + api.nvim_command('redraw') + else + local result = r.result --- @type lsp.SignatureHelp + if result and result.signatures and result.signatures[1] then + for _, sig in ipairs(result.signatures) do + signatures[#signatures + 1] = { client, sig } + end + end + end + end + + return signatures +end + local sig_help_ns = api.nvim_create_namespace('vim_lsp_signature_help') --- @class vim.lsp.buf.signature_help.Opts : vim.lsp.util.open_floating_preview.Opts @@ -270,58 +297,79 @@ local sig_help_ns = api.nvim_create_namespace('vim_lsp_signature_help') function M.signature_help(config) local method = ms.textDocument_signatureHelp - config = config or {} + config = config and vim.deepcopy(config) or {} config.focus_id = method - lsp.buf_request(0, method, client_positional_params(), function(err, result, ctx) - local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) - - if err then - vim.notify( - client.name .. ': ' .. tostring(err.code) .. ': ' .. err.message, - vim.log.levels.ERROR - ) - api.nvim_command('redraw') - return - end - + lsp.buf_request_all(0, method, client_positional_params(), function(results, ctx) if api.nvim_get_current_buf() ~= ctx.bufnr then -- Ignore result since buffer changed. This happens for slow language servers. return end - -- When use `autocmd CompleteDone <silent><buffer> lua vim.lsp.buf.signature_help()` to call signatureHelp handler - -- If the completion item doesn't have signatures It will make noise. Change to use `print` that can use `<silent>` to ignore - if not result or not result.signatures or not result.signatures[1] then + local signatures = process_signature_help_results(results) + + if not next(signatures) then if config.silent ~= true then print('No signature help available') end return end - local triggers = - vim.tbl_get(client.server_capabilities, 'signatureHelpProvider', 'triggerCharacters') - local ft = vim.bo[ctx.bufnr].filetype - local lines, hl = util.convert_signature_help_to_markdown_lines(result, ft, triggers) - if not lines or vim.tbl_isempty(lines) then - if config.silent ~= true then - print('No signature help available') + local total = #signatures + local idx = 0 + + --- @param update_win? integer + local function show_signature(update_win) + idx = (idx % total) + 1 + local client, result = signatures[idx][1], signatures[idx][2] + --- @type string[]? + local triggers = + vim.tbl_get(client.server_capabilities, 'signatureHelpProvider', 'triggerCharacters') + local lines, hl = + util.convert_signature_help_to_markdown_lines({ signatures = { result } }, ft, triggers) + if not lines then + return end - return + + local sfx = total > 1 and string.format(' (%d/%d) (<C-s> to cycle)', idx, total) or '' + local title = string.format('Signature Help: %s%s', client.name, sfx) + if config.border then + config.title = title + else + table.insert(lines, 1, '# ' .. title) + if hl then + hl[1] = hl[1] + 1 + hl[3] = hl[3] + 1 + end + end + + config._update_win = update_win + + local buf, win = util.open_floating_preview(lines, 'markdown', config) + + if hl then + vim.api.nvim_buf_clear_namespace(buf, sig_help_ns, 0, -1) + vim.hl.range( + buf, + sig_help_ns, + 'LspSignatureActiveParameter', + { hl[1], hl[2] }, + { hl[3], hl[4] } + ) + end + return buf, win end - local fbuf = util.open_floating_preview(lines, 'markdown', config) + local fbuf, fwin = show_signature() - -- Highlight the active parameter. - if hl then - vim.hl.range( - fbuf, - sig_help_ns, - 'LspSignatureActiveParameter', - { hl[1], hl[2] }, - { hl[3], hl[4] } - ) + if total > 1 then + vim.keymap.set('n', '<C-s>', function() + show_signature(fwin) + end, { + buffer = fbuf, + desc = 'Cycle next signature', + }) end end) end diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 763cd940c3..4ca4239127 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -737,7 +737,7 @@ function M.convert_signature_help_to_markdown_lines(signature_help, ft, triggers if active_signature >= #signature_help.signatures or active_signature < 0 then active_signature = 0 end - local signature = signature_help.signatures[active_signature + 1] + local signature = vim.deepcopy(signature_help.signatures[active_signature + 1]) local label = signature.label if ft then -- wrap inside a code block for proper rendering @@ -804,9 +804,11 @@ function M.convert_signature_help_to_markdown_lines(signature_help, ft, triggers active_offset[2] = active_offset[2] + #contents[1] end - active_hl = {} - list_extend(active_hl, get_pos_from_offset(active_offset[1], contents) or {}) - list_extend(active_hl, get_pos_from_offset(active_offset[2], contents) or {}) + local a_start = get_pos_from_offset(active_offset[1], contents) + local a_end = get_pos_from_offset(active_offset[2], contents) + if a_start and a_end then + active_hl = { a_start[1], a_start[2], a_end[1], a_end[2] } + end end return contents, active_hl @@ -818,7 +820,7 @@ end ---@param width integer window width (in character cells) ---@param height integer window height (in character cells) ---@param opts? vim.lsp.util.open_floating_preview.Opts ----@return table Options +---@return vim.api.keyset.win_config function M.make_floating_popup_options(width, height, opts) validate('opts', opts, 'table', true) opts = opts or {} @@ -1500,6 +1502,8 @@ end --- to display the full window height. --- (default: `'auto'`) --- @field anchor_bias? 'auto'|'above'|'below' +--- +--- @field _update_win? integer --- Shows contents in a floating window. --- @@ -1521,43 +1525,49 @@ function M.open_floating_preview(contents, syntax, opts) local bufnr = api.nvim_get_current_buf() - -- check if this popup is focusable and we need to focus - if opts.focus_id and opts.focusable ~= false and opts.focus then - -- Go back to previous window if we are in a focusable one - local current_winnr = api.nvim_get_current_win() - if vim.w[current_winnr][opts.focus_id] then - api.nvim_command('wincmd p') - return bufnr, current_winnr - end - do - local win = find_window_by_var(opts.focus_id, bufnr) - if win and api.nvim_win_is_valid(win) and vim.fn.pumvisible() == 0 then - -- focus and return the existing buf, win - api.nvim_set_current_win(win) - api.nvim_command('stopinsert') - return api.nvim_win_get_buf(win), win + local floating_winnr = opts._update_win + + -- Create/get the buffer + local floating_bufnr --- @type integer + if floating_winnr then + floating_bufnr = api.nvim_win_get_buf(floating_winnr) + else + -- check if this popup is focusable and we need to focus + if opts.focus_id and opts.focusable ~= false and opts.focus then + -- Go back to previous window if we are in a focusable one + local current_winnr = api.nvim_get_current_win() + if vim.w[current_winnr][opts.focus_id] then + api.nvim_command('wincmd p') + return bufnr, current_winnr + end + do + local win = find_window_by_var(opts.focus_id, bufnr) + if win and api.nvim_win_is_valid(win) and vim.fn.pumvisible() == 0 then + -- focus and return the existing buf, win + api.nvim_set_current_win(win) + api.nvim_command('stopinsert') + return api.nvim_win_get_buf(win), win + end end end - end - -- check if another floating preview already exists for this buffer - -- and close it if needed - local existing_float = vim.b[bufnr].lsp_floating_preview - if existing_float and api.nvim_win_is_valid(existing_float) then - api.nvim_win_close(existing_float, true) + -- check if another floating preview already exists for this buffer + -- and close it if needed + local existing_float = vim.b[bufnr].lsp_floating_preview + if existing_float and api.nvim_win_is_valid(existing_float) then + api.nvim_win_close(existing_float, true) + end + floating_bufnr = api.nvim_create_buf(false, true) end - -- Create the buffer - local floating_bufnr = api.nvim_create_buf(false, true) - -- Set up the contents, using treesitter for markdown local do_stylize = syntax == 'markdown' and vim.g.syntax_on ~= nil + if do_stylize then local width = M._make_floating_popup_size(contents, opts) contents = M._normalize_markdown(contents, { width = width }) vim.bo[floating_bufnr].filetype = 'markdown' vim.treesitter.start(floating_bufnr) - api.nvim_buf_set_lines(floating_bufnr, 0, -1, false, contents) else -- Clean up input: trim empty lines contents = vim.split(table.concat(contents, '\n'), '\n', { trimempty = true }) @@ -1565,19 +1575,47 @@ function M.open_floating_preview(contents, syntax, opts) if syntax then vim.bo[floating_bufnr].syntax = syntax end - api.nvim_buf_set_lines(floating_bufnr, 0, -1, true, contents) end - -- Compute size of float needed to show (wrapped) lines - if opts.wrap then - opts.wrap_at = opts.wrap_at or api.nvim_win_get_width(0) + vim.bo[floating_bufnr].modifiable = true + api.nvim_buf_set_lines(floating_bufnr, 0, -1, false, contents) + + if floating_winnr then + api.nvim_win_set_config(floating_winnr, { + border = opts.border, + title = opts.title, + }) else - opts.wrap_at = nil - end - local width, height = M._make_floating_popup_size(contents, opts) + -- Compute size of float needed to show (wrapped) lines + if opts.wrap then + opts.wrap_at = opts.wrap_at or api.nvim_win_get_width(0) + else + opts.wrap_at = nil + end + + -- TODO(lewis6991): These function assume the current window to determine options, + -- therefore it won't work for opts._update_win and the current window if the floating + -- window + local width, height = M._make_floating_popup_size(contents, opts) + local float_option = M.make_floating_popup_options(width, height, opts) - local float_option = M.make_floating_popup_options(width, height, opts) - local floating_winnr = api.nvim_open_win(floating_bufnr, false, float_option) + floating_winnr = api.nvim_open_win(floating_bufnr, false, float_option) + + api.nvim_buf_set_keymap( + floating_bufnr, + 'n', + 'q', + '<cmd>bdelete<cr>', + { silent = true, noremap = true, nowait = true } + ) + close_preview_autocmd(opts.close_events, floating_winnr, { floating_bufnr, bufnr }) + + -- save focus_id + if opts.focus_id then + api.nvim_win_set_var(floating_winnr, opts.focus_id, bufnr) + end + api.nvim_buf_set_var(bufnr, 'lsp_floating_preview', floating_winnr) + end if do_stylize then vim.wo[floating_winnr].conceallevel = 2 @@ -1590,21 +1628,6 @@ function M.open_floating_preview(contents, syntax, opts) vim.bo[floating_bufnr].modifiable = false vim.bo[floating_bufnr].bufhidden = 'wipe' - api.nvim_buf_set_keymap( - floating_bufnr, - 'n', - 'q', - '<cmd>bdelete<cr>', - { silent = true, noremap = true, nowait = true } - ) - close_preview_autocmd(opts.close_events, floating_winnr, { floating_bufnr, bufnr }) - - -- save focus_id - if opts.focus_id then - api.nvim_win_set_var(floating_winnr, opts.focus_id, bufnr) - end - api.nvim_buf_set_var(bufnr, 'lsp_floating_preview', floating_winnr) - return floating_bufnr, floating_winnr end diff --git a/runtime/lua/vim/treesitter/dev.lua b/runtime/lua/vim/treesitter/dev.lua index 7b522ca92b..d68a30cc11 100644 --- a/runtime/lua/vim/treesitter/dev.lua +++ b/runtime/lua/vim/treesitter/dev.lua @@ -527,7 +527,7 @@ function M.inspect_tree(opts) end, }) - api.nvim_create_autocmd('BufHidden', { + api.nvim_create_autocmd({ 'BufHidden', 'BufUnload' }, { group = group, buffer = buf, once = true, @@ -665,10 +665,10 @@ function M.edit_query(lang) api.nvim_buf_clear_namespace(query_buf, edit_ns, 0, -1) end, }) - api.nvim_create_autocmd('BufHidden', { + api.nvim_create_autocmd({ 'BufHidden', 'BufUnload' }, { group = group, buffer = buf, - desc = 'Close the editor window when the source buffer is hidden', + desc = 'Close the editor window when the source buffer is hidden or unloaded', once = true, callback = function() close_win(query_win) diff --git a/runtime/lua/vim/treesitter/health.lua b/runtime/lua/vim/treesitter/health.lua index 637f9ea543..53b64d1dec 100644 --- a/runtime/lua/vim/treesitter/health.lua +++ b/runtime/lua/vim/treesitter/health.lua @@ -4,10 +4,21 @@ local health = vim.health --- Performs a healthcheck for treesitter integration function M.check() - local parsers = vim.api.nvim_get_runtime_file('parser/*', true) + health.start('Treesitter features') + + health.info( + string.format( + 'Treesitter ABI support: min %d, max %d', + vim.treesitter.minimum_language_version, + ts.language_version + ) + ) - health.info(string.format('Nvim runtime ABI version: %d', ts.language_version)) + local can_wasm = vim._ts_add_language_from_wasm ~= nil + health.info(string.format('WASM parser support: %s', tostring(can_wasm))) + health.start('Treesitter parsers') + local parsers = vim.api.nvim_get_runtime_file('parser/*', true) for _, parser in pairs(parsers) do local parsername = vim.fn.fnamemodify(parser, ':t:r') local is_loadable, err_or_nil = pcall(ts.language.add, parsername) @@ -28,9 +39,6 @@ function M.check() ) end end - - local can_wasm = vim._ts_add_language_from_wasm ~= nil - health.info(string.format('Can load WASM parsers: %s', tostring(can_wasm))) end return M |