Skip to content

Commit 8b9dc8e

Browse files
committed
feat(extra): add workspace_symbol_live scope to pickers.lsp()
Resolve #2113
1 parent 5ba71ec commit 8b9dc8e

File tree

6 files changed

+69
-9
lines changed

6 files changed

+69
-9
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ There are following change types:
105105

106106
- Add `pickers.colorschemes` picker. By @pkazmier, PR #1789.
107107

108+
- Add `workspace_symbol_live` live scope to `pickers.lsp` picker. This allows searching for LSP symbols in the workspace with live feedback. Relates to `workspace_symbol` scope similar to how `MiniPick.builtin.grep_live()` relates to `MiniPick.builtin.grep()`.
109+
108110
- Add `<C-e>` mapping for `pickers.history` picker to edit commands or searches in cmdline. By @TheLeoP, PR #1960.
109111

110112
## mini.files

doc/mini-extra.txt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -621,12 +621,16 @@ Notes:
621621
- "references".
622622
- "type_definition".
623623
- "workspace_symbol".
624+
- "workspace_symbol_live" - same as "workspace_symbol", but with live
625+
feedback treating picker's prompt as LSP server query. Similar to
626+
how |MiniPick.builtin.grep_live()| and |MiniPick.builtin.grep()| are
627+
related. To use regular matching, use |MiniPick-actions-refine|.
624628
- Relies on `vim.lsp.buf` methods supporting |vim.lsp.LocationOpts.OnList|.
625629
In particular, it means that picker is started only if LSP server returns
626630
list of locations and not a single location.
627631
- Doesn't return anything due to async nature of `vim.lsp.buf` methods.
628632
- Requires set up |mini.icons| to show extra icons and highlighting in
629-
"document_symbol" and "workspace_symbol" scopes.
633+
"document_symbol", "workspace_symbol", "workspace_symbol_live" scopes.
630634

631635
Examples:
632636

@@ -639,7 +643,7 @@ Parameters ~
639643
Possible fields:
640644
- <scope> `(string)` - LSP method to use. One of the supported ones (see
641645
list above). Default: `nil` which means explicit scope is needed.
642-
- <symbol_query> `(string)` - query for |vim.lsp.buf.workspace_symbol()|.
646+
- <symbol_query> `(string)` - query for `"workspace_symbol"` scope.
643647
Default: empty string for all symbols (according to LSP specification).
644648
{opts} `(table|nil)` Options forwarded to |MiniPick.start()|.
645649

doc/mini-pick.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,8 @@ This action is useful in at least two cases:
563563
both "hello" and "world" exact matches (in no particular order) with default
564564
matching, type "'hello" (notice "'" at the start) followed by `<C-Space>` and
565565
another "'world".
566-
- Reset `match` to default. Particularly useful in |MiniPick.builtin.grep_live()|.
566+
- Reset `match` to default. Particularly useful in |MiniPick.builtin.grep_live()|
567+
and |MiniExtra.pickers.lsp()| with `scope='workspace_symbol_live'`.
567568

568569
## Scroll ~
569570
*MiniPick-actions-scroll*

lua/mini/extra.lua

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,12 +1172,16 @@ end
11721172
--- - "references".
11731173
--- - "type_definition".
11741174
--- - "workspace_symbol".
1175+
--- - "workspace_symbol_live" - same as "workspace_symbol", but with live
1176+
--- feedback treating picker's prompt as LSP server query. Similar to
1177+
--- how |MiniPick.builtin.grep_live()| and |MiniPick.builtin.grep()| are
1178+
--- related. To use regular matching, use |MiniPick-actions-refine|.
11751179
--- - Relies on `vim.lsp.buf` methods supporting |vim.lsp.LocationOpts.OnList|.
11761180
--- In particular, it means that picker is started only if LSP server returns
11771181
--- list of locations and not a single location.
11781182
--- - Doesn't return anything due to async nature of `vim.lsp.buf` methods.
11791183
--- - Requires set up |mini.icons| to show extra icons and highlighting in
1180-
--- "document_symbol" and "workspace_symbol" scopes.
1184+
--- "document_symbol", "workspace_symbol", "workspace_symbol_live" scopes.
11811185
---
11821186
--- Examples:
11831187
---
@@ -1189,7 +1193,7 @@ end
11891193
--- Possible fields:
11901194
--- - <scope> `(string)` - LSP method to use. One of the supported ones (see
11911195
--- list above). Default: `nil` which means explicit scope is needed.
1192-
--- - <symbol_query> `(string)` - query for |vim.lsp.buf.workspace_symbol()|.
1196+
--- - <symbol_query> `(string)` - query for `"workspace_symbol"` scope.
11931197
--- Default: empty string for all symbols (according to LSP specification).
11941198
---@param opts __extra_pickers_opts
11951199
---
@@ -1201,16 +1205,27 @@ MiniExtra.pickers.lsp = function(local_opts, opts)
12011205
if local_opts.scope == nil then H.error('`pickers.lsp` needs an explicit scope.') end
12021206
--stylua: ignore
12031207
local allowed_scopes = {
1204-
'declaration', 'definition', 'document_symbol', 'implementation', 'references', 'type_definition', 'workspace_symbol',
1208+
'declaration', 'definition', 'document_symbol', 'implementation',
1209+
'references', 'type_definition', 'workspace_symbol', 'workspace_symbol_live'
12051210
}
12061211
local scope = H.pick_validate_scope(local_opts, allowed_scopes, 'lsp')
12071212

1208-
local buf_lsp_opts = H.lsp_make_opts(scope, opts)
1213+
local buf_lsp_opts, picker_opts = H.lsp_make_opts(scope, opts)
12091214
if scope == 'references' then return vim.lsp.buf[scope](nil, buf_lsp_opts) end
12101215
if scope == 'workspace_symbol' then
12111216
local query = tostring(local_opts.symbol_query)
12121217
return vim.lsp.buf[scope](query, buf_lsp_opts)
12131218
end
1219+
if scope == 'workspace_symbol_live' then
1220+
picker_opts.source.match = function(_, _, query)
1221+
if #query == 0 then return MiniPick.set_picker_items({}, { do_match = false }) end
1222+
local win_id = MiniPick.get_picker_state().windows.target
1223+
local buf_id = vim.api.nvim_win_get_buf(win_id)
1224+
vim.api.nvim_buf_call(buf_id, function() vim.lsp.buf.workspace_symbol(table.concat(query), buf_lsp_opts) end)
1225+
end
1226+
1227+
return H.pick_start({}, picker_opts, opts)
1228+
end
12141229
vim.lsp.buf[scope](buf_lsp_opts)
12151230
end
12161231

@@ -1991,10 +2006,14 @@ H.lsp_make_opts = function(source, opts)
19912006
end
19922007
items = process(items)
19932008

2009+
if MiniPick.is_picker_active() and source == 'workspace_symbol_live' then
2010+
return MiniPick.set_picker_items(items, { do_match = false })
2011+
end
2012+
19942013
return H.pick_start(items, picker_opts, opts)
19952014
end
19962015

1997-
return { on_list = on_list }
2016+
return { on_list = on_list }, picker_opts
19982017
end
19992018

20002019
H.get_symbol_kind_map = function()

lua/mini/pick.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,8 @@
557557
--- both "hello" and "world" exact matches (in no particular order) with default
558558
--- matching, type "'hello" (notice "'" at the start) followed by `<C-Space>` and
559559
--- another "'world".
560-
--- - Reset `match` to default. Particularly useful in |MiniPick.builtin.grep_live()|.
560+
--- - Reset `match` to default. Particularly useful in |MiniPick.builtin.grep_live()|
561+
--- and |MiniExtra.pickers.lsp()| with `scope='workspace_symbol_live'`.
561562
---
562563
--- ## Scroll ~
563564
--- *MiniPick-actions-scroll*

tests/test_extra.lua

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2910,6 +2910,7 @@ local scope_to_request = {
29102910
references = 'textDocument/references',
29112911
type_definition = 'textDocument/typeDefinition',
29122912
workspace_symbol = 'workspace/symbol',
2913+
workspace_symbol_live = 'workspace/symbol',
29132914
}
29142915

29152916
local validate_location_scope = function(scope)
@@ -3105,6 +3106,38 @@ T['pickers']['lsp()']['works for `workspace_symbol` after `MiniIcons.tweak_lsp_k
31053106
validate_symbol_scope_with_tweaked_kind('workspace_symbol', 'replace')
31063107
end
31073108

3109+
T['pickers']['lsp()']['works for `workspace_symbol_live`'] = function()
3110+
-- Test only "live" part in the hope that "workspace_symbol" part is the same
3111+
3112+
setup_lsp()
3113+
mock_slash_path_sep()
3114+
pick_lsp({ scope = 'workspace_symbol_live' })
3115+
validate_picker_name('LSP (workspace_symbol_live)')
3116+
3117+
local validate = function(did_request, query)
3118+
eq(child.lua_get('#_G.lsp_requests > 0'), did_request)
3119+
eq(child.lua_get('_G.params'), query ~= nil and { query = query } or vim.NIL)
3120+
3121+
child.lua('_G.lsp_requests, _G.params = {}, nil')
3122+
end
3123+
3124+
-- Should not do any request on start
3125+
validate(false, nil)
3126+
eq(get_picker_items(), {})
3127+
3128+
-- Should make new request on every picker query change
3129+
type_keys('a')
3130+
validate(true, 'a')
3131+
3132+
type_keys('x')
3133+
validate(true, 'ax')
3134+
3135+
-- Should not make request for empty query and show no items instead
3136+
type_keys('<C-u>')
3137+
validate(false, nil)
3138+
eq(get_picker_items(), {})
3139+
end
3140+
31083141
T['pickers']['lsp()']['respects `local_opts.symbol_query`'] = function()
31093142
setup_lsp()
31103143

0 commit comments

Comments
 (0)