mirror of
https://github.com/neovim/neovim.git
synced 2025-12-14 10:25:42 +00:00
feat(lsp): incremental-selection operator-pending mode #36575
Problem: LSP incremental selection provides default visual-mode keymaps for `an` and `in`. Operator-pending mode is not supported, so `dan` and `can` do not apply the operation. Solution: Modify selection_range() to be synchronous. Add operator-pending mappings.
This commit is contained in:
@@ -83,7 +83,7 @@ These GLOBAL keymaps are created unconditionally when Nvim starts:
|
|||||||
- "grt" is mapped to |vim.lsp.buf.type_definition()|
|
- "grt" is mapped to |vim.lsp.buf.type_definition()|
|
||||||
- "gO" is mapped to |vim.lsp.buf.document_symbol()|
|
- "gO" is mapped to |vim.lsp.buf.document_symbol()|
|
||||||
- CTRL-S (Insert mode) is mapped to |vim.lsp.buf.signature_help()|
|
- CTRL-S (Insert mode) is mapped to |vim.lsp.buf.signature_help()|
|
||||||
- "an" and "in" (Visual mode) are mapped to outer and inner incremental
|
- "an" and "in" (Visual and Operator-pending mode) are mapped to outer and inner incremental
|
||||||
selections, respectively, using |vim.lsp.buf.selection_range()|
|
selections, respectively, using |vim.lsp.buf.selection_range()|
|
||||||
|
|
||||||
BUFFER-LOCAL DEFAULTS
|
BUFFER-LOCAL DEFAULTS
|
||||||
@@ -1512,13 +1512,16 @@ rename({new_name}, {opts}) *vim.lsp.buf.rename()*
|
|||||||
ones where client.name matches this field.
|
ones where client.name matches this field.
|
||||||
• {bufnr}? (`integer`) (default: current buffer)
|
• {bufnr}? (`integer`) (default: current buffer)
|
||||||
|
|
||||||
selection_range({direction}) *vim.lsp.buf.selection_range()*
|
*vim.lsp.buf.selection_range()*
|
||||||
|
selection_range({direction}, {timeout_ms})
|
||||||
Perform an incremental selection at the cursor position based on ranges
|
Perform an incremental selection at the cursor position based on ranges
|
||||||
given by the LSP. The `direction` parameter specifies the number of times
|
given by the LSP. The `direction` parameter specifies the number of times
|
||||||
to expand the selection. Negative values will shrink the selection.
|
to expand the selection. Negative values will shrink the selection.
|
||||||
|
|
||||||
Parameters: ~
|
Parameters: ~
|
||||||
• {direction} (`integer`)
|
• {direction} (`integer`)
|
||||||
|
• {timeout_ms} (`integer?`) (default: `1000`) Maximum time
|
||||||
|
(milliseconds) to wait for a result.
|
||||||
|
|
||||||
signature_help({config}) *vim.lsp.buf.signature_help()*
|
signature_help({config}) *vim.lsp.buf.signature_help()*
|
||||||
Displays signature information about the symbol under the cursor in a
|
Displays signature information about the symbol under the cursor in a
|
||||||
|
|||||||
@@ -227,6 +227,14 @@ do
|
|||||||
vim.lsp.buf.selection_range(-vim.v.count1)
|
vim.lsp.buf.selection_range(-vim.v.count1)
|
||||||
end, { desc = 'vim.lsp.buf.selection_range(-vim.v.count1)' })
|
end, { desc = 'vim.lsp.buf.selection_range(-vim.v.count1)' })
|
||||||
|
|
||||||
|
vim.keymap.set('o', 'an', function()
|
||||||
|
vim.lsp.buf.selection_range(vim.v.count1, 1000)
|
||||||
|
end, { desc = 'vim.lsp.buf.selection_range(vim.v.count1, timeout_ms)' })
|
||||||
|
|
||||||
|
vim.keymap.set('o', 'in', function()
|
||||||
|
vim.lsp.buf.selection_range(-vim.v.count1, 1000)
|
||||||
|
end, { desc = 'vim.lsp.buf.selection_range(-vim.v.count1, timeout_ms)' })
|
||||||
|
|
||||||
vim.keymap.set('n', 'gO', function()
|
vim.keymap.set('n', 'gO', function()
|
||||||
vim.lsp.buf.document_symbol()
|
vim.lsp.buf.document_symbol()
|
||||||
end, { desc = 'vim.lsp.buf.document_symbol()' })
|
end, { desc = 'vim.lsp.buf.document_symbol()' })
|
||||||
|
|||||||
@@ -1408,8 +1408,10 @@ end
|
|||||||
--- will shrink the selection.
|
--- will shrink the selection.
|
||||||
---
|
---
|
||||||
--- @param direction integer
|
--- @param direction integer
|
||||||
function M.selection_range(direction)
|
--- @param timeout_ms integer? (default: `1000`) Maximum time (milliseconds) to wait for a result.
|
||||||
|
function M.selection_range(direction, timeout_ms)
|
||||||
validate('direction', direction, 'number')
|
validate('direction', direction, 'number')
|
||||||
|
validate('timeout_ms', timeout_ms, 'number', true)
|
||||||
|
|
||||||
if selection_ranges then
|
if selection_ranges then
|
||||||
local new_index = selection_ranges.index + direction
|
local new_index = selection_ranges.index + direction
|
||||||
@@ -1434,21 +1436,21 @@ function M.selection_range(direction)
|
|||||||
positions = { position_params.position },
|
positions = { position_params.position },
|
||||||
}
|
}
|
||||||
|
|
||||||
lsp.buf_request(
|
timeout_ms = timeout_ms or 1000
|
||||||
0,
|
local result, err = lsp.buf_request_sync(0, method, params, timeout_ms)
|
||||||
method,
|
|
||||||
params,
|
|
||||||
---@param response lsp.SelectionRange[]?
|
|
||||||
function(err, response)
|
|
||||||
if err then
|
if err then
|
||||||
lsp.log.error(err.code, err.message)
|
lsp.log.error('selectionRange request failed: ' .. err)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if not response then
|
if not result or not result[client.id] or not result[client.id].result then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
-- We only requested one range, thus we get the first and only response here.
|
if result[client.id].error then
|
||||||
response = response[1]
|
lsp.log.error(result[client.id].error.code, result[client.id].error.message)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- We only requested one range, thus we get the first and only reponse here.
|
||||||
|
local response = assert(result[client.id].result[1]) ---@type lsp.SelectionRange
|
||||||
local ranges = {} ---@type lsp.Range[]
|
local ranges = {} ---@type lsp.Range[]
|
||||||
local lines = api.nvim_buf_get_lines(0, 0, -1, false)
|
local lines = api.nvim_buf_get_lines(0, 0, -1, false)
|
||||||
|
|
||||||
@@ -1490,7 +1492,5 @@ function M.selection_range(direction)
|
|||||||
select_range(ranges[index])
|
select_range(ranges[index])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|||||||
Reference in New Issue
Block a user