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:
11858
data/help/tags
Normal file
11858
data/help/tags
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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?
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user