summaryrefslogtreecommitdiff
path: root/lua
diff options
context:
space:
mode:
authorSimon Hauser <Simon-Hauser@outlook.de>2020-11-16 21:17:13 +0100
committerGitHub <noreply@github.com>2020-11-16 15:17:13 -0500
commiteaa7011f8499f2c8c473a5beb50100f1cae006cf (patch)
tree6b004689f95f0cf93b476428f3543a29a3483559 /lua
parent81172630270325947d2c6b3afda5599e34b48499 (diff)
feat: Add tags (#219)
Diffstat (limited to 'lua')
-rw-r--r--lua/telescope/builtin/init.lua50
-rw-r--r--lua/telescope/make_entry.lua69
-rw-r--r--lua/telescope/pickers/entry_display.lua10
-rw-r--r--lua/telescope/previewers.lua40
4 files changed, 165 insertions, 4 deletions
diff --git a/lua/telescope/builtin/init.lua b/lua/telescope/builtin/init.lua
index 2336a42..80c1f3f 100644
--- a/lua/telescope/builtin/init.lua
+++ b/lua/telescope/builtin/init.lua
@@ -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
diff --git a/lua/telescope/make_entry.lua b/lua/telescope/make_entry.lua
index 906eb95..57344ab 100644
--- a/lua/telescope/make_entry.lua
+++ b/lua/telescope/make_entry.lua
@@ -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
diff --git a/lua/telescope/pickers/entry_display.lua b/lua/telescope/pickers/entry_display.lua
index c661b89..aef3047 100644
--- a/lua/telescope/pickers/entry_display.lua
+++ b/lua/telescope/pickers/entry_display.lua
@@ -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 "│")
diff --git a/lua/telescope/previewers.lua b/lua/telescope/previewers.lua
index d85d149..29442fa 100644
--- a/lua/telescope/previewers.lua
+++ b/lua/telescope/previewers.lua
@@ -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 {}