feature: Vim help-tags picker (#117)

* feature: Vim help-tags picker

* fix: filtered results were wrong because of missing `entry.value`

* fix: filtered (Vim only help) items are listed in results as empty
entries.

* fix: avoid search history pollution by replacing / in cmd returned by taglist() with search()

* fix: improve search() formatting

* fix: escape tilde in search() command

* fix: improve help-preview

* fix: improve search()

* fix: search() string fixes.

* fix: use no magic to do magic

Co-authored-by: TJ DeVries <devries.timothyj@gmail.com>
This commit is contained in:
Senghan Bright
2020-09-25 06:16:48 +02:00
committed by GitHub
parent a38bb06e7d
commit c3f9b25606
4 changed files with 11965 additions and 11 deletions

11858
data/help/tags Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -402,6 +402,45 @@ builtin.command_history = function(opts)
}):find() }):find()
end end
builtin.help_tags = function(opts)
opts = opts or {}
local sourced_file = require('plenary.debug_utils').sourced_filepath()
local base_directory = vim.fn.fnamemodify(sourced_file, ":h:h:h")
local file = base_directory .. "/data/help/tags"
local tags = {}
local f = assert(io.open(file, "rb"))
for line in f:lines() do
table.insert(tags, line)
end
f:close()
pickers.new(opts, {
prompt = 'Help',
finder = finders.new_table {
results = tags,
entry_maker = make_entry.gen_from_tagfile(opts),
},
-- TODO: previewer for Vim help
previewer = previewers.help.new(opts),
sorter = sorters.get_generic_fuzzy_sorter(),
attach_mappings = function(prompt_bufnr, map)
local view_help = function()
local selection = actions.get_selected_entry(prompt_bufnr)
actions.close(prompt_bufnr)
vim.cmd("help " .. selection.value)
end
map('i', '<CR>', view_help)
map('n', '<CR>', view_help)
return true
end
}):find()
end
-- TODO: What the heck should we do for accepting this. -- TODO: What the heck should we do for accepting this.
-- vim.fn.setreg("+", "nnoremap $TODO :lua require('telescope.builtin').<whatever>()<CR>") -- vim.fn.setreg("+", "nnoremap $TODO :lua require('telescope.builtin').<whatever>()<CR>")
-- TODO: Can we just do the names instead? -- TODO: Can we just do the names instead?

View File

@@ -284,4 +284,53 @@ function make_entry.gen_from_treesitter(opts)
end end
end end
function make_entry.gen_from_tagfile(opts)
local help_entry, version
local delim = string.char(7)
local make_display = function(line)
help_entry = ""
display = ""
version = ""
line = line .. delim
for section in line:gmatch("(.-)" .. delim) do
if section:find("^vim:") == nil then
local ver = section:match("^neovim:(.*)")
if ver == nil then
help_entry = section
else
version = ver:sub(1, -2)
end
end
end
result = {}
if version ~= "" then -- some Vim only entries are unversioned
if opts.show_version then
result.display = string.format("%s [%s]", help_entry, version)
else
result.display = help_entry
end
result.value = help_entry
end
return result
end
return function(line)
local entry = {
entry_type = make_entry.types.GENERIC,
}
local d = make_display(line)
entry.valid = next(d) ~= nil
entry.display = d.display
entry.value = d.value
entry.ordinal = d.value
return entry
end
end
return make_entry return make_entry

View File

@@ -58,7 +58,7 @@ end
local previewer_ns = vim.api.nvim_create_namespace('telescope.previewers') local previewer_ns = vim.api.nvim_create_namespace('telescope.previewers')
local with_preview_window = function(status, bufnr, callable) local with_preview_window = function(status, bufnr, callable)
if bufnr and vim.api.nvim_buf_call then if bufnr and vim.api.nvim_buf_call and false then
vim.api.nvim_buf_call(bufnr, callable) vim.api.nvim_buf_call(bufnr, callable)
else else
return context_manager.with(function() return context_manager.with(function()
@@ -365,17 +365,17 @@ previewers.qflist = defaulter(function(opts)
} }
end, {}) end, {})
-- WIP
previewers.help = defaulter(function(_) previewers.help = defaulter(function(_)
return previewers.new { return previewers.new {
preview_fn = function(_, entry, status) preview_fn = function(_, entry, status)
with_preview_window(status, nil, function() with_preview_window(status, nil, function()
local old_tags = vim.o.tags local special_chars = ":~^.?/%[%]%*"
vim.o.tags = vim.fn.expand("$VIMRUNTIME") .. '/doc/tags'
local taglist = vim.fn.taglist('^' .. entry.value .. '$') local escaped = vim.fn.escape(entry.value, special_chars)
local tagfile = vim.fn.expand("$VIMRUNTIME") .. '/doc/tags'
local taglist = vim.fn.taglist('^' .. escaped .. '$', tagfile)
if vim.tbl_isempty(taglist) then if vim.tbl_isempty(taglist) then
taglist = vim.fn.taglist(entry.value) taglist = vim.fn.taglist(escaped, tagfile)
end end
if vim.tbl_isempty(taglist) then if vim.tbl_isempty(taglist) then
@@ -384,15 +384,23 @@ previewers.help = defaulter(function(_)
local best_entry = taglist[1] local best_entry = taglist[1]
local new_bufnr = vim.fn.bufnr(best_entry.filename, true) local new_bufnr = vim.fn.bufnr(best_entry.filename, true)
vim.api.nvim_buf_set_option(new_bufnr, 'filetype', 'help') vim.api.nvim_buf_set_option(new_bufnr, 'filetype', 'help')
vim.api.nvim_win_set_buf(status.preview_win, new_bufnr) vim.api.nvim_win_set_buf(status.preview_win, new_bufnr)
vim.cmd [["gg"]] local search_query = best_entry.cmd
print(best_entry.cmd)
vim.cmd(string.format([[execute "%s"]], best_entry.cmd))
vim.o.tags = old_tags -- remove leading '/'
search_query = search_query:sub(2)
-- Set the query to "very nomagic".
-- This should make it work quite nicely given tags.
search_query = [[\V]] .. search_query
log.trace([[lua vim.fn.search("]], search_query, [[")]])
vim.cmd "norm! gg"
vim.fn.search(search_query, "W")
vim.cmd "norm zt"
end) end)
end end
} }