feat: Add tags (#219)
This commit is contained in:
@@ -923,4 +923,54 @@ builtin.keymaps = function(opts)
|
||||
}):find()
|
||||
end
|
||||
|
||||
builtin.tags = function(opts)
|
||||
opts = opts or {}
|
||||
|
||||
local ctags_file = opts.ctags_file or 'tags'
|
||||
|
||||
if not vim.loop.fs_open(vim.fn.expand(ctags_file), "r", 438) then
|
||||
print('Tags file does not exists. Create one with ctags -R')
|
||||
return
|
||||
end
|
||||
|
||||
local fd = assert(vim.loop.fs_open(vim.fn.expand(ctags_file), "r", 438))
|
||||
local stat = assert(vim.loop.fs_fstat(fd))
|
||||
local data = assert(vim.loop.fs_read(fd, stat.size, 0))
|
||||
assert(vim.loop.fs_close(fd))
|
||||
|
||||
local results = vim.split(data, '\n')
|
||||
|
||||
pickers.new(opts,{
|
||||
prompt = 'Tags',
|
||||
finder = finders.new_table {
|
||||
results = results,
|
||||
entry_maker = make_entry.gen_from_ctags(opts),
|
||||
},
|
||||
previewer = previewers.ctags.new(opts),
|
||||
sorter = conf.generic_sorter(opts),
|
||||
attach_mappings = function(prompt_bufnr)
|
||||
actions._goto_file_selection:enhance {
|
||||
post = function()
|
||||
local selection = actions.get_selected_entry(prompt_bufnr)
|
||||
|
||||
local scode = string.gsub(selection.scode, '[$]$', '')
|
||||
scode = string.gsub(scode, [[\\]], [[\]])
|
||||
scode = string.gsub(scode, [[\/]], [[/]])
|
||||
scode = string.gsub(scode, '[*]', [[\*]])
|
||||
|
||||
vim.cmd('norm! gg')
|
||||
vim.fn.search(scode)
|
||||
vim.cmd('norm! zz')
|
||||
end,
|
||||
}
|
||||
return true
|
||||
end
|
||||
}):find()
|
||||
end
|
||||
|
||||
builtin.current_buffer_tags = function(opts)
|
||||
opts = opts or {}
|
||||
return builtin.tags(vim.tbl_extend("force", {only_current_file = true, hide_filename = true}, opts))
|
||||
end
|
||||
|
||||
return builtin
|
||||
|
||||
@@ -559,4 +559,73 @@ function make_entry.gen_from_vimoptions(opts)
|
||||
end
|
||||
end
|
||||
|
||||
function make_entry.gen_from_ctags(opts)
|
||||
opts = opts or {}
|
||||
|
||||
local cwd = vim.fn.expand(opts.cwd or vim.fn.getcwd())
|
||||
local current_file = path.normalize(vim.fn.expand('%'), cwd)
|
||||
|
||||
local display_items = {
|
||||
{ width = 30 },
|
||||
{ remaining = true },
|
||||
}
|
||||
|
||||
if opts.show_line then
|
||||
table.insert(display_items, 2, { width = 30 })
|
||||
end
|
||||
|
||||
local displayer = entry_display.create {
|
||||
separator = " │ ",
|
||||
items = display_items,
|
||||
}
|
||||
|
||||
local make_display = function(entry)
|
||||
local filename
|
||||
if not opts.hide_filename then
|
||||
if opts.shorten_path then
|
||||
filename = path.shorten(entry.filename)
|
||||
else
|
||||
filename = entry.filename
|
||||
end
|
||||
end
|
||||
|
||||
local scode
|
||||
if opts.show_line then
|
||||
scode = entry.scode
|
||||
end
|
||||
|
||||
return displayer {
|
||||
filename,
|
||||
entry.tag,
|
||||
scode,
|
||||
}
|
||||
end
|
||||
|
||||
return function(line)
|
||||
if line == '' or line:sub(1, 1) == '!' then
|
||||
return nil
|
||||
end
|
||||
|
||||
local tag, file, scode = string.match(line, '([^\t]+)\t([^\t]+)\t/^\t?(.*)/;"\t+.*')
|
||||
|
||||
if opts.only_current_file and file ~= current_file then
|
||||
return nil
|
||||
end
|
||||
|
||||
return {
|
||||
valid = true,
|
||||
|
||||
ordinal = file .. ': ' .. tag,
|
||||
display = make_display,
|
||||
scode = scode,
|
||||
tag = tag,
|
||||
|
||||
filename = file,
|
||||
|
||||
col = 1,
|
||||
lnum = 1,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
return make_entry
|
||||
|
||||
@@ -43,8 +43,8 @@ end
|
||||
|
||||
local function truncate(str, len)
|
||||
-- TODO: This doesn't handle multi byte chars...
|
||||
if vim.fn.strdisplaywidth(str) > len - 1 then
|
||||
str = str:sub(1, len)
|
||||
if vim.fn.strdisplaywidth(str) > len then
|
||||
str = str:sub(1, len - 1)
|
||||
str = str .. "…"
|
||||
end
|
||||
return str
|
||||
@@ -68,8 +68,10 @@ entry_display.create = function(configuration)
|
||||
|
||||
return function(self, picker)
|
||||
local results = {}
|
||||
for k, v in ipairs(self) do
|
||||
table.insert(results, generator[k](v, picker))
|
||||
for i = 1, table.getn(generator) do
|
||||
if self[i] ~= nil then
|
||||
table.insert(results, generator[i](self[i], picker))
|
||||
end
|
||||
end
|
||||
|
||||
return table.concat(results, configuration.separator or "│")
|
||||
|
||||
@@ -400,6 +400,46 @@ previewers.vimgrep = defaulter(function(opts)
|
||||
}
|
||||
end, {})
|
||||
|
||||
previewers.ctags = defaulter(function(opts)
|
||||
return previewers.new {
|
||||
setup = function()
|
||||
return {}
|
||||
end,
|
||||
|
||||
teardown = function(self)
|
||||
if self.state and self.state.hl_id then
|
||||
pcall(vim.fn.matchdelete, self.state.hl_id, self.state.hl_win)
|
||||
self.state.hl_id = nil
|
||||
end
|
||||
end,
|
||||
|
||||
preview_fn = function(self, entry, status)
|
||||
with_preview_window(status, nil, function()
|
||||
local scode = string.gsub(entry.scode, '[$]$', '')
|
||||
scode = string.gsub(scode, [[\\]], [[\]])
|
||||
scode = string.gsub(scode, [[\/]], [[/]])
|
||||
scode = string.gsub(scode, '[*]', [[\*]])
|
||||
|
||||
local new_bufnr = vim.fn.bufnr(entry.filename, true)
|
||||
vim.fn.bufload(new_bufnr)
|
||||
|
||||
vim.api.nvim_win_set_buf(status.preview_win, new_bufnr)
|
||||
vim.api.nvim_win_set_option(status.preview_win, 'wrap', false)
|
||||
vim.api.nvim_win_set_option(status.preview_win, 'winhl', 'Normal:Normal')
|
||||
vim.api.nvim_win_set_option(status.preview_win, 'signcolumn', 'no')
|
||||
vim.api.nvim_win_set_option(status.preview_win, 'foldlevel', 100)
|
||||
|
||||
pcall(vim.fn.matchdelete, self.state.hl_id, self.state.hl_win)
|
||||
vim.fn.search(scode)
|
||||
vim.cmd "norm zz"
|
||||
|
||||
self.state.hl_win = status.preview_win
|
||||
self.state.hl_id = vim.fn.matchadd('Search', scode)
|
||||
end)
|
||||
end
|
||||
}
|
||||
end, {})
|
||||
|
||||
previewers.qflist = defaulter(function(opts)
|
||||
opts = opts or {}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user