diff options
| author | Yi Ming <ofseed@foxmail.com> | 2026-03-30 22:54:55 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-03-30 10:54:55 -0400 |
| commit | 57797ed7d465afabf522df2f53e78e570b9e2833 (patch) | |
| tree | 737b8105ba9cc3352b2e4ffc12b819f9a34ca14a /runtime/lua/vim | |
| parent | f062c6fd437e2e54b65a005c2d1b2858d4cab507 (diff) | |
| download | rneovim-57797ed7d465afabf522df2f53e78e570b9e2833.tar.gz rneovim-57797ed7d465afabf522df2f53e78e570b9e2833.tar.bz2 rneovim-57797ed7d465afabf522df2f53e78e570b9e2833.zip | |
feat(lsp): respect 'switchbuf' for jump commands, drop `reuse_win` #38510
Problem:
LSP jump operations such as `buf.definition`/`buf.type_definition` do
not follow the 'switchbuf' option. Instead their behavior is controlled
by `vim.lsp.LocationOpts.reuse_win`. When `reuse_win=true`, the effect
is very similar to `set switchbuf=useopen`.
Note that functions like `buf.definition` open the quickfix
window when there are multiple results, and jumping between quickfix
entries already follows 'switchbuf', so unifying the behavior is more
intuitive.
Solution:
Follow the 'switchbuf' option and drop `reuse_win`.
We can achieve this behavior by using :cfirst when the quickfix list has
only one item, rather than customizing the jump logic as before.
Diffstat (limited to 'runtime/lua/vim')
| -rw-r--r-- | runtime/lua/vim/lsp/buf.lua | 71 |
1 files changed, 30 insertions, 41 deletions
diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index a00077f4cb..24cdc5af47 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -184,9 +184,18 @@ local function request_with_opts(name, params, opts) end ---@param method vim.lsp.protocol.Method.ClientToServer.Request ----@param opts? vim.lsp.LocationOpts +---@param opts? vim.lsp.ListOpts local function get_locations(method, opts) opts = opts or {} + ---@diagnostic disable-next-line: undefined-field + if opts.reuse_win then + vim.deprecate( + 'vim.lsp.buf.<method>({ reuse_win = true })', + "vim.lsp.buf.<method>() and the value of 'switchbuf' of preference", + '0.13' + ) + end + local bufnr = api.nvim_get_current_buf() local win = api.nvim_get_current_win() @@ -232,39 +241,24 @@ local function get_locations(method, opts) return end - if #all_items == 1 then - local item = all_items[1] - local b = item.bufnr or vim.fn.bufadd(item.filename) - - -- Save position in jumplist - vim.cmd("normal! m'") - -- Push a new item into tagstack - local tagstack = { { tagname = tagname, from = from } } - vim.fn.settagstack(vim.fn.win_getid(win), { items = tagstack }, 't') - - vim.bo[b].buflisted = true - local w = win - if opts.reuse_win and api.nvim_win_get_buf(w) ~= b then - w = vim.fn.bufwinid(b) - w = w >= 0 and w or vim.fn.win_findbuf(b)[1] or win - if w ~= win then - api.nvim_set_current_win(w) - end - end - api.nvim_win_set_buf(w, b) - api.nvim_win_set_cursor(w, { item.lnum, item.col - 1 }) - vim._with({ win = w }, function() - -- Open folds under the cursor - vim.cmd('normal! zv') - end) - return - end if opts.loclist then vim.fn.setloclist(0, {}, ' ', { title = title, items = all_items }) - vim.cmd.lopen() + if #all_items == 1 then + local tagstack = { { tagname = tagname, from = from } } + vim.fn.settagstack(vim.fn.win_getid(win), { items = tagstack }, 't') + vim.cmd('lfirst') + else + vim.cmd.lopen() + end else vim.fn.setqflist({}, ' ', { title = title, items = all_items }) - vim.cmd('botright copen') + if #all_items == 1 then + local tagstack = { { tagname = tagname, from = from } } + vim.fn.settagstack(vim.fn.win_getid(win), { items = tagstack }, 't') + vim.cmd('cfirst') + else + vim.cmd('botright copen') + end end end) end @@ -283,7 +277,7 @@ end --- vim.lsp.buf.definition({ on_list = on_list }) --- vim.lsp.buf.references(nil, { on_list = on_list }) --- ``` ---- @field on_list? fun(t: vim.lsp.LocationOpts.OnList) +--- @field on_list? fun(t: vim.lsp.ListOpts.OnList) --- --- Whether to use the |location-list| or the |quickfix| list in the default handler. --- ```lua @@ -292,33 +286,28 @@ end --- ``` --- @field loclist? boolean ---- @class vim.lsp.LocationOpts.OnList +--- @class vim.lsp.ListOpts.OnList --- @field items vim.quickfix.entry[] See |setqflist-what| --- @field title? string Title for the list. --- @field context? { bufnr: integer, method: string } Subset of `ctx` from |lsp-handler|. ---- @class vim.lsp.LocationOpts: vim.lsp.ListOpts ---- ---- Jump to existing window if buffer is already open. ---- @field reuse_win? boolean - --- 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. ---- @param opts? vim.lsp.LocationOpts +--- @param opts? vim.lsp.ListOpts function M.declaration(opts) validate('opts', opts, 'table', true) get_locations('textDocument/declaration', opts) end --- Jumps to the definition of the symbol under the cursor. ---- @param opts? vim.lsp.LocationOpts +--- @param opts? vim.lsp.ListOpts function M.definition(opts) validate('opts', opts, 'table', true) get_locations('textDocument/definition', opts) end --- Jumps to the definition of the type of the symbol under the cursor. ---- @param opts? vim.lsp.LocationOpts +--- @param opts? vim.lsp.ListOpts function M.type_definition(opts) validate('opts', opts, 'table', true) get_locations('textDocument/typeDefinition', opts) @@ -326,7 +315,7 @@ end --- Lists all the implementations for the symbol under the cursor in the --- quickfix window. ---- @param opts? vim.lsp.LocationOpts +--- @param opts? vim.lsp.ListOpts function M.implementation(opts) validate('opts', opts, 'table', true) get_locations('textDocument/implementation', opts) |