bat previewer optimization for ctags with no line numbers (#355)

main
bhagwan 2 years ago
parent bcbd20b690
commit fc77943cdf

@ -139,9 +139,9 @@ local function stripBeforeLastOccurrenceOf(str, sep)
end
function M.entry_to_ctag(entry)
function M.entry_to_ctag(entry, noesc)
local scode = entry:match("%:.-/^?\t?(.*)/")
if scode then
if scode and not noesc then
-- scode = string.gsub(scode, "[$]$", "")
scode = string.gsub(scode, [[\\]], [[\]])
scode = string.gsub(scode, [[\/]], [[/]])

@ -131,9 +131,53 @@ function Previewer.cmd_async:new(o, opts)
return self
end
local grep_tag = function(file, tag)
local line = 1
local filepath = file
local pattern = utils.rg_escape(tag)
if not pattern or not filepath then return line end
local grep_cmd = vim.fn.executable("rg") == 1
and {"rg", "--line-number"}
or {"grep", "-n", "-P"}
-- ctags uses '$' at the end of short patterns
-- 'rg|grep' does not match these properly when
-- 'fileformat' isn't set to 'unix', when set to
-- 'dos' we need to prepend '$' with '\r$' with 'rg'
-- it is simpler to just ignore it compleley.
--[[ local ff = fileformat(filepath)
if ff == 'dos' then
pattern = pattern:gsub("\\%$$", "\\r%$")
else
pattern = pattern:gsub("\\%$$", "%$")
end --]]
-- equivalent pattern to `rg --crlf`
-- see discussion in #219
pattern = pattern:gsub("\\%$$", "\\r??%$")
local cmd = utils.tbl_deep_clone(grep_cmd)
table.insert(cmd, pattern)
table.insert(cmd, filepath)
local out = utils.io_system(cmd)
if not utils.shell_error() then
line = out:match("[^:]+")
end
-- if line == 1 then print(cmd) end
return line
end
function Previewer.cmd_async:parse_entry_and_verify(entrystr)
local entry = path.entry_to_file(entrystr, not self.relative and self.opts.cwd)
local filepath = entry.bufname or entry.path or ''
if self.opts._ctag and entry.line<=1 then
-- tags without line numbers
-- make sure we don't already have line #
-- (in the case the line no. is actually 1)
local line = entry.stripped:match("[^:]+(%d+):")
local ctag = path.entry_to_ctag(entry.stripped, true)
if not line and ctag then
entry.ctag = ctag
entry.line = grep_tag(filepath, entry.ctag)
end
end
local errcmd = nil
-- verify the file exists on disk and is accessible
if #filepath==0 or not vim.loop.fs_stat(filepath) then
@ -166,12 +210,22 @@ end
function Previewer.bat_async:cmdline(o)
o = o or {}
local act = shell.preview_action_cmd(function(items)
local act = shell.preview_action_cmd(function(items, fzf_lines)
local filepath, entry, errcmd = self:parse_entry_and_verify(items[1])
local cmd = errcmd or ('%s %s %s %s'):format(
local line_range = ''
if entry.ctag then
-- this is a ctag without line numbers, since we can't
-- provide the preview file offset to fzf via the field
-- index expression we use '--line-range' instead
local start_line = math.max(1, entry.line-fzf_lines/2)
local end_line = start_line + fzf_lines-1
line_range = ("--line-range=%d:%d"):format(start_line, end_line)
end
local cmd = errcmd or ('%s %s %s %s %s'):format(
self.cmd, self.args,
self.opts.line_field_index and
("--highlight-line=%d"):format(entry.line) or '',
line_range,
vim.fn.shellescape(filepath))
-- uncomment to see the command in the preview window
-- cmd = vim.fn.shellescape(cmd)

@ -176,17 +176,19 @@ local function get_tags_cmd(opts)
end
local function tags(opts)
opts.ctags_file = opts.ctags_file and vim.fn.expand(opts.ctags_file) or "tags"
if not vim.loop.fs_open(opts.ctags_file, "r", 438) then
utils.info("Tags file does not exists. Create one with ctags -R")
return
end
-- signal actions this is a ctag
opts._ctag = true
opts.ctags_file = opts.ctags_file and vim.fn.expand(opts.ctags_file) or "tags"
opts._ctags_file = opts.cwd and path.join({opts.cwd, opts.ctags_file}) or opts.ctags_file
opts._curr_file = opts._curr_file and path.relative(opts._curr_file, opts.cwd or vim.loop.cwd())
if not vim.loop.fs_stat(opts._ctags_file) then
utils.info(("Tags file ('%s') does not exists. Create one with ctags -R")
:format(opts._ctags_file))
return
end
opts.cmd = opts.cmd or get_tags_cmd(opts)
opts._fn_transform = make_entry.tag -- multiprocess=false
opts._fn_transform_str = [[return require("make_entry").tag]] -- multiprocess=true

Loading…
Cancel
Save