Skip to content
This repository was archived by the owner on Jul 7, 2022. It is now read-only.

Commit 85ce064

Browse files
authored
Dart outline fzf and telescope handlers (#11)
* Implement fzf handler * Add telescope support * Add tree option to fzf * Add some keybindings * Add more examples * Add screenshots for each handler
1 parent 389c119 commit 85ce064

File tree

3 files changed

+147
-17
lines changed

3 files changed

+147
-17
lines changed

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,16 @@ autocmd InsertLeave,BufEnter,BufWinEnter,TabEnter,BufWritePost *.rs :lua require
6464
Check out the [example file](examples/dart/closing_labels.lua) for setup
6565

6666
## Outline (dartls)
67-
![outline](https://raw.githubusercontent.com/tjdevries/media.repo/b27a8366b460cac2629d5fdb81862e5bd1d0a553/lsp_extensions/dart-outline.png)
67+
Rending in loclist:
68+
<img align="left" alt="dart-outline-loclist" src="https://raw.githubusercontent.com/tjdevries/media.repo/b27a8366b460cac2629d5fdb81862e5bd1d0a553/lsp_extensions/dart-outline.png">
69+
70+
71+
Rendering in fzf:
72+
<img align="left" alt="dart-outline-fzf" src="https://raw.githubusercontent.com/PatOConnor43/media.repo/0a8aa1c6fc89087c4771557c1e59864700821b26/lsp_extensions/dart-outline-fzf.png">
73+
74+
75+
Rendering in telescope:
76+
<img align="left" alt="dart-outline-telescope" src="https://raw.githubusercontent.com/PatOConnor43/media.repo/0a8aa1c6fc89087c4771557c1e59864700821b26/lsp_extensions/dart-outline-telescope.png">
6877

6978
[Outline Documentation](https://github.com/dart-lang/sdk/blob/master/pkg/analysis_server/tool/lsp_spec/README.md#darttextdocumentpublishoutline-notification)
7079

examples/dart/outline.lua

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ nvim_lsp.dartls.setup{
1212
}
1313

1414
-- Next, when you want to actually show the outline, you will need to call one
15-
-- of the display methods (either loclist() or custom().
15+
-- of the display methods.
1616
require('lsp_extensions.dart.outline').loclist({})
1717

1818
-- If you want to handle the display yourself you can use the `custom()` function.
@@ -23,8 +23,7 @@ require('lsp_extensions.dart.outline').custom({}, function(items) print(items) e
2323
-- prefixes you can do that by passing `kind_prefixes` into the opts. If you
2424
-- pair this with a patched [Nerdfont](https://www.nerdfonts.com/) you can
2525
-- define a very custom experience. You can define a function that looks like:
26-
DART_SHOW_OUTLINE = function()
27-
require('lsp_extensions.dart.outline').loclist({kind_prefixes={
26+
DART_KIND_PREFIXES = {
2827
CLASS = "",
2928
CLASS_TYPE_ALIAS = "",
3029
COMPILATION_UNIT = "",
@@ -52,8 +51,14 @@ DART_SHOW_OUTLINE = function()
5251
UNIT_TEST_GROUP = "",
5352
UNIT_TEST_TEST = "",
5453
UNKNOWN = "",
55-
}})
54+
}
55+
DART_SHOW_OUTLINE = function()
56+
require('lsp_extensions.dart.outline').loclist({kind_prefixes=DART_KIND_PREFIXES})
5657
end
5758

5859
-- And then call it from neovim with :lua DART_SHOW_OUTLINE()
5960

61+
-- The outline also has built in handlers for fzf and telescope.nvim
62+
require('lsp_extensions.dart.outline').fzf({kind_prefixes=DART_KIND_PREFIXES, fzf_opts={'--height', '40%', '--reverse', '--border', '--inline-info'}})
63+
-- OR
64+
require('lsp_extensions.dart.outline').telescope({kind_prefixes=DART_KIND_PREFIXES, telescope_opts={borderchars={'', '', '', '', '', '', '', ''}}})

lua/lsp_extensions/dart/outline.lua

Lines changed: 128 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ local default_kind_prefixes = {
8181
-- @tparam string fname is the filename of the buffer that the outline belongs to
8282
-- @tparam table items is the in progress table of items
8383
-- @tparam table node is the current `Element` that is being traversed
84-
_DART_OUTLINE_APPEND_CHILDREN = function(opts, fname, items, node)
84+
_DART_OUTLINE_APPEND_CHILDREN = function(opts, fname, items, node, tree_prefix)
8585
if node == nil then
8686
return
8787
end
@@ -107,9 +107,25 @@ _DART_OUTLINE_APPEND_CHILDREN = function(opts, fname, items, node)
107107
end
108108

109109
local text = table.concat(stringBuilder, ' ')
110-
table.insert(items, {filename = fname, lnum = range.start.line + 1, col = range.start.character + 1, text = text})
111-
for _, child in ipairs(node.children or {}) do
112-
_DART_OUTLINE_APPEND_CHILDREN(opts, fname, items, child)
110+
table.insert(
111+
items,
112+
{
113+
filename = fname,
114+
lnum = range.start.line + 1,
115+
col = range.start.character + 1,
116+
text = text,
117+
tree_prefix = tree_prefix,
118+
}
119+
)
120+
121+
-- We're done if there's no more children
122+
if node.children == nil or vim.tbl_isempty(node.children) then
123+
return
124+
end
125+
126+
local child_tree_prefix = tree_prefix .. ' '
127+
for _, child in ipairs(node.children) do
128+
_DART_OUTLINE_APPEND_CHILDREN(opts, fname, items, child, child_tree_prefix)
113129
end
114130
end
115131

@@ -130,22 +146,22 @@ end
130146
--
131147
-- @tparam table opts is table used to mutate items
132148
-- @tparam table outline the outline for the current request
133-
-- @treturn table {{filename = string, lnum = number, col = number, text = string}, ...}
149+
-- @treturn table {{filename = string, lnum = number, col = number, text = string, tree_prefix = string}, ...}
134150
local build_items = function(opts, outline)
135151
local fname = vim.api.nvim_buf_get_name(0)
136152
local items = {}
137153
for _, node in ipairs(outline.children or {}) do
138-
_DART_OUTLINE_APPEND_CHILDREN(opts, fname, items, node)
154+
_DART_OUTLINE_APPEND_CHILDREN(opts, fname, items, node, '')
139155
end
140156
return items
141157
end
142158

143159
-- This function allows you to specify your own outline handler to do whatever
144160
-- you want. Check out the loclist implementation as an example.
145161
--
146-
-- @tparam table opts is table used to mutate items. opts.kind_prefixes is a
147-
-- table that allows specifying a prefix per kind type. This can be especially
148-
-- useful if you want to display unicode or patched font icons.
162+
-- @tparam table opts is table used to mutate items.
163+
-- - opts.kind_prefixes is a table that allows specifying a prefix per kind type.
164+
-- This can be especially useful if you want to display unicode or patched font icons.
149165
-- @tparam function(items) handler is a function which takes a list of items
150166
M.custom = function(opts, handler)
151167
opts = opts or {}
@@ -161,9 +177,9 @@ end
161177

162178
-- This function displays the outline in the loclist.
163179
--
164-
-- @tparam table opts is table used to mutate items. opts.kind_prefixes is a
165-
-- table that allows specifying a prefix per kind type. This can be especially
166-
-- useful if you want to display unicode or patched font icons.
180+
-- @tparam table opts is table used to mutate items.
181+
-- - opts.kind_prefixes is a table that allows specifying a prefix per kind type.
182+
-- This can be especially useful if you want to display unicode or patched font icons.
167183
M.loclist = function(opts)
168184
M.custom(opts, function(items)
169185
vim.fn.setloclist(0, {}, ' ', {
@@ -174,6 +190,106 @@ M.loclist = function(opts)
174190
end)
175191
end
176192

193+
-- This function displays the outline in fzf.
194+
--
195+
-- @tparam table opts is table used to mutate items.
196+
-- - opts.tree is a bool specifying if you want the outline to appear as a tree.
197+
-- - opts.kind_prefixes is a table that allows specifying a prefix per kind type.
198+
-- This can be especially useful if you want to display unicode or patched font icons.
199+
-- - opts.fzf_opts is a table of strings passed to fzf. Default: {'--reverse'}
200+
M.fzf = function(opts)
201+
M.custom(opts, function(items)
202+
opts = opts or {}
203+
if opts.tree == nil then
204+
opts.tree = true
205+
end
206+
local fzf_opts = opts.fzf_opts or {'--reverse'}
207+
local stringifiedItems = {}
208+
for _, item in ipairs(items) do
209+
table.insert(stringifiedItems, string.format('%s%s:%d:%d', (opts.tree and item.tree_prefix) or '', item.text, item.lnum, item.col))
210+
end
211+
-- Calling fzf as explained here:
212+
-- https://github.com/junegunn/fzf/issues/1778#issuecomment-697208274
213+
local fzf_run = vim.fn['fzf#run']
214+
local fzf_wrap = vim.fn['fzf#wrap']
215+
local wrapped = fzf_wrap('Outline', {
216+
source = stringifiedItems,
217+
options = fzf_opts,
218+
})
219+
wrapped["sink*"] = nil
220+
wrapped.sink = function(line)
221+
local pattern = '%S+:(%d+):(%d+)'
222+
local lnum, col = string.match(line, pattern)
223+
vim.call('cursor', lnum, col)
224+
end
225+
fzf_run(wrapped)
226+
end)
227+
end
228+
229+
-- This function displays the outline with telescope.nvim.
230+
--
231+
-- @tparam table opts is table used to mutate items.
232+
-- - opts.tree is a bool specifying if you want the outline to appear as a tree.
233+
-- - opts.kind_prefixes is a table that allows specifying a prefix per kind type.
234+
-- This can be especially useful if you want to display unicode or patched font icons.
235+
-- - opts.telescope_opts is a table of options passed to telescope. Default:
236+
-- {hide_filename = true, ignore_filename = true, sorting_strategy = 'ascending'}
237+
M.telescope = function(opts)
238+
M.custom(opts, function(items)
239+
local has_telescope, pickers = pcall(require, 'telescope.pickers')
240+
if not has_telescope then
241+
error('Missing https://github.com/nvim-lua/telescope.nvim')
242+
end
243+
opts = opts or {}
244+
if opts.tree == nil then
245+
opts.tree = true
246+
end
247+
local telescope_opts = opts.telescope_opts or {hide_filename = true, ignore_filename = true, sorting_strategy = 'ascending'}
248+
local actions = require('telescope.actions')
249+
local finders = require('telescope.finders')
250+
local previewers = require('telescope.previewers')
251+
local sorters = require('telescope.sorters')
252+
253+
pickers.new(telescope_opts, {
254+
prompt_title = 'Outline',
255+
sorting_strategy = telescope_opts.sorting_strategy,
256+
finder = finders.new_table {
257+
results = items,
258+
entry_maker = function(entry)
259+
return {
260+
valid = true,
261+
value = entry,
262+
ordinal = entry.text,
263+
-- Optionally enable displaying tree structure
264+
display = string.format('%s%s:%d', (opts.tree and entry.tree_prefix) or '', entry.text, entry.lnum),
265+
filename = entry.filename,
266+
lnum = entry.lnum,
267+
col = entry.col,
268+
}
269+
end
270+
},
271+
previewer = previewers.qflist.new(telescope_opts),
272+
sorter = sorters.get_generic_fuzzy_sorter(telescope_opts),
273+
attach_mappings = function(prompt_bufnr, map)
274+
local run_command = function(bufnr)
275+
local selection = actions.get_selected_entry(bufnr)
276+
actions.close(prompt_bufnr)
277+
vim.call('cursor', selection.lnum, selection.col+1)
278+
end
279+
280+
map('i', '<C-k>', actions.move_selection_previous)
281+
map('i', '<C-j>', actions.move_selection_next)
282+
map('n', '<C-k>', actions.move_selection_previous)
283+
map('n', '<C-j>', actions.move_selection_next)
284+
map('i', '<CR>', run_command)
285+
map('n', '<CR>', run_command)
286+
287+
return true
288+
end,
289+
}):find()
290+
end)
291+
end
292+
177293
-- Gets a callback to register to the dartls outline notification.
178294
M.get_callback = function()
179295
return function(_, _, result, _, _)

0 commit comments

Comments
 (0)