diff options
-rw-r--r-- | runtime/doc/lsp.txt | 3 | ||||
-rw-r--r-- | runtime/doc/lua.txt | 22 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/buf.lua | 30 | ||||
-rw-r--r-- | runtime/lua/vim/ui.lua | 33 | ||||
-rw-r--r-- | test/functional/lua/ui_spec.lua | 25 | ||||
-rw-r--r-- | test/functional/plugin/lsp_spec.lua | 6 |
6 files changed, 106 insertions, 13 deletions
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index 80ac762792..83d201c23a 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -1100,7 +1100,8 @@ rename({new_name}) *vim.lsp.buf.rename()* Parameters: ~ {new_name} (string) If not provided, the user will be - prompted for a new name using |input()|. + prompted for a new name using + |vim.ui.input()|. server_ready() *vim.lsp.buf.server_ready()* Checks whether the language servers attached to the current diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 1e058874bd..ef2d87949d 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -1697,6 +1697,28 @@ uri_to_fname({uri}) *vim.uri_to_fname()* ============================================================================== Lua module: ui *lua-ui* +input({opts}, {on_confirm}) *vim.ui.input()* + Prompts the user for input + + Parameters: ~ + {opts} table Additional options. See |input()| + • prompt (string|nil) Text of the prompt. + Defaults to `Input:` . + • default (string|nil) Default reply to the + input + • completion (string|nil) Specifies type of + completion supported for input. Supported + types are the same that can be supplied to + a user-defined command using the + "-complete=" argument. See + |:command-completion| + • highlight (function) Function that will be + used for highlighting user inputs. + {on_confirm} function ((input|nil) -> ()) Called once the + user confirms or abort the input. `input` is + what the user typed. `nil` if the user + aborted the dialog. + select({items}, {opts}, {on_choice}) *vim.ui.select()* Prompts the user to pick a single item from a collection of entries diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index 128f0b01ad..b0348e8307 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -247,22 +247,35 @@ end --- Renames all references to the symbol under the cursor. --- ---@param new_name (string) If not provided, the user will be prompted for a new ----name using |input()|. +---name using |vim.ui.input()|. function M.rename(new_name) - local params = util.make_position_params() + local opts = { + prompt = "New Name: " + } + + ---@private + local function on_confirm(input) + if not (input and #input > 0) then return end + local params = util.make_position_params() + params.newName = input + request('textDocument/rename', params) + end + local function prepare_rename(err, result) if err == nil and result == nil then vim.notify('nothing to rename', vim.log.levels.INFO) return end if result and result.placeholder then - new_name = new_name or npcall(vfn.input, "New Name: ", result.placeholder) + opts.default = result.placeholder + if not new_name then npcall(vim.ui.input, opts, on_confirm) end elseif result and result.start and result['end'] and result.start.line == result['end'].line then local line = vfn.getline(result.start.line+1) local start_char = result.start.character+1 local end_char = result['end'].character - new_name = new_name or npcall(vfn.input, "New Name: ", string.sub(line, start_char, end_char)) + opts.default = string.sub(line, start_char, end_char) + if not new_name then npcall(vim.ui.input, opts, on_confirm) end else -- fallback to guessing symbol using <cword> -- @@ -270,13 +283,12 @@ function M.rename(new_name) -- returns an unexpected response, or requests for "default behavior" -- -- see https://microsoft.github.io/language-server-protocol/specification#textDocument_prepareRename - new_name = new_name or npcall(vfn.input, "New Name: ", vfn.expand('<cword>')) + opts.default = vfn.expand('<cword>') + if not new_name then npcall(vim.ui.input, opts, on_confirm) end end - if not (new_name and #new_name > 0) then return end - params.newName = new_name - request('textDocument/rename', params) + if new_name then on_confirm(new_name) end end - request('textDocument/prepareRename', params, prepare_rename) + request('textDocument/prepareRename', util.make_position_params(), prepare_rename) end --- Lists all the references to the symbol under the cursor in the quickfix window. diff --git a/runtime/lua/vim/ui.lua b/runtime/lua/vim/ui.lua index adc1e16759..9568b60fd0 100644 --- a/runtime/lua/vim/ui.lua +++ b/runtime/lua/vim/ui.lua @@ -37,5 +37,38 @@ function M.select(items, opts, on_choice) end end +--- Prompts the user for input +--- +---@param opts table Additional options. See |input()| +--- - prompt (string|nil) +--- Text of the prompt. Defaults to `Input: `. +--- - default (string|nil) +--- Default reply to the input +--- - completion (string|nil) +--- Specifies type of completion supported +--- for input. Supported types are the same +--- that can be supplied to a user-defined +--- command using the "-complete=" argument. +--- See |:command-completion| +--- - highlight (function) +--- Function that will be used for highlighting +--- user inputs. +---@param on_confirm function ((input|nil) -> ()) +--- Called once the user confirms or abort the input. +--- `input` is what the user typed. +--- `nil` if the user aborted the dialog. +function M.input(opts, on_confirm) + vim.validate { + on_confirm = { on_confirm, 'function', false }, + } + + opts = opts or {} + local input = vim.fn.input(opts) + if #input > 0 then + on_confirm(input) + else + on_confirm(nil) + end +end return M diff --git a/test/functional/lua/ui_spec.lua b/test/functional/lua/ui_spec.lua index 94f1b5840b..2371939204 100644 --- a/test/functional/lua/ui_spec.lua +++ b/test/functional/lua/ui_spec.lua @@ -43,4 +43,29 @@ describe('vim.ui', function() }, result[2]) end) end) + + describe('input', function() + it('can input text', function() + local result = exec_lua[[ + local opts = { + prompt = 'Input: ', + } + local input + local cb = function(item) + input = item + end + -- input would require input and block the test; + local prompt + vim.fn.input = function(opts) + prompt = opts.prompt + return "Inputted text" + end + vim.ui.input(opts, cb) + vim.wait(100, function() return input ~= nil end) + return {input, prompt} + ]] + eq('Inputted text', result[1]) + eq('Input: ', result[2]) + end) + end) end) diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index c025e9f4ab..ae7612ab08 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -2435,9 +2435,9 @@ describe('LSP', function() local bufnr = vim.api.nvim_get_current_buf() lsp.buf_attach_client(bufnr, TEST_RPC_CLIENT_ID) vim.lsp._stubs = {} - vim.fn.input = function(prompt, text) - vim.lsp._stubs.input_prompt = prompt - vim.lsp._stubs.input_text = text + vim.fn.input = function(opts, on_confirm) + vim.lsp._stubs.input_prompt = opts.prompt + vim.lsp._stubs.input_text = opts.default return 'renameto' -- expect this value in fake lsp end vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {'', 'this is line two'}) |