From 9a0f625804304100ac1a58222b4abd1868da437a Mon Sep 17 00:00:00 2001 From: bhagwan Date: Fri, 11 Feb 2022 23:02:53 -0800 Subject: [PATCH] normaize fzf FIELD INDEX EXPRESSION, see below: - refactor fzf field index experssion and line field number options - enable native fzf previewers (bat/cat/head) for all file/buffer providers - buffers|lines|blines|tabs now respect default previewer --- README.md | 2 +- doc/fzf-lua.txt | 2 +- lua/fzf-lua/config.lua | 16 ++++--- lua/fzf-lua/core.lua | 18 +++++++- lua/fzf-lua/path.lua | 2 + lua/fzf-lua/previewer/fzf.lua | 68 +++++++++++++++++------------- lua/fzf-lua/providers/buffers.lua | 10 +++-- lua/fzf-lua/providers/dap.lua | 2 +- lua/fzf-lua/providers/grep.lua | 6 +-- lua/fzf-lua/providers/lsp.lua | 8 ++-- lua/fzf-lua/providers/quickfix.lua | 2 +- lua/fzf-lua/providers/tags.lua | 2 +- 12 files changed, 85 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index 5ebd1c8..9c852a4 100644 --- a/README.md +++ b/README.md @@ -586,7 +586,7 @@ require'fzf-lua'.setup { fzf_opts = { -- do not include bufnr in fuzzy matching -- tiebreak by line no. - ['--delimiter'] = vim.fn.shellescape('[]]'), + ['--delimiter'] = vim.fn.shellescape('[\\]:]'), ["--nth"] = '2..', ["--tiebreak"] = 'index', }, diff --git a/doc/fzf-lua.txt b/doc/fzf-lua.txt index 8fbe0e0..a33c655 100644 --- a/doc/fzf-lua.txt +++ b/doc/fzf-lua.txt @@ -628,7 +628,7 @@ Consult the list below for available settings: fzf_opts = { -- do not include bufnr in fuzzy matching -- tiebreak by line no. - ['--delimiter'] = vim.fn.shellescape('[]]'), + ['--delimiter'] = vim.fn.shellescape('[\\]:]'), ["--nth"] = '2..', ["--tiebreak"] = 'index', }, diff --git a/lua/fzf-lua/config.lua b/lua/fzf-lua/config.lua index 9714791..97aa38e 100644 --- a/lua/fzf-lua/config.lua +++ b/lua/fzf-lua/config.lua @@ -169,6 +169,10 @@ M.globals = { cmd = "man -c %s | col -bx", _ctor = previewers.builtin.man_pages, }, + man_native = { + cmd = "man", + _ctor = previewers.fzf.man_pages, + }, builtin = { syntax = true, syntax_delay = 0, @@ -309,7 +313,7 @@ M.globals.loclist = { _actions = function() return M.globals.actions.files end, } M.globals.buffers = { - previewer = "builtin", + previewer = M._default_previewer_fn, prompt = 'Buffers> ', file_icons = true and M._has_devicons, color_icons = true, @@ -323,7 +327,7 @@ M.globals.buffers = { }, } M.globals.tabs = { - previewer = "builtin", + previewer = M._default_previewer_fn, prompt = 'Tabs> ', tab_title = "Tab", tab_marker = "<<", @@ -336,21 +340,21 @@ M.globals.tabs = { }, } M.globals.lines = { - previewer = "builtin", + previewer = M._default_previewer_fn, prompt = 'Lines> ', file_icons = true and M._has_devicons, color_icons = true, show_unlisted = false, no_term_buffers = true, fzf_opts = { - ['--delimiter'] = vim.fn.shellescape('[]]'), + ['--delimiter'] = vim.fn.shellescape('[\\]:]'), ["--nth"] = '2..', ["--tiebreak"] = 'index', }, _actions = function() return M.globals.actions.buffers end, } M.globals.blines = { - previewer = "builtin", + previewer = M._default_previewer_fn, prompt = 'BLines> ', file_icons = true and M._has_devicons, color_icons = true, @@ -540,7 +544,7 @@ M.globals.dap = { previewer = M._default_previewer_fn, _actions = function() return M.globals.actions.files end, fzf_opts = { - ['--delimiter'] = vim.fn.shellescape('[]]'), + ['--delimiter'] = vim.fn.shellescape('[\\]:]'), ["--with-nth"] = '2..', }, }, diff --git a/lua/fzf-lua/core.lua b/lua/fzf-lua/core.lua index f82603c..4101607 100644 --- a/lua/fzf-lua/core.lua +++ b/lua/fzf-lua/core.lua @@ -416,8 +416,22 @@ M.make_entry_lcol = function(opts, entry) (opts.trim_entry and vim.trim(entry.text)) or entry.text) end -M.set_fzf_line_args = function(opts) - opts._line_placeholder = 2 +-- given the default delimiter ':' this is the +-- fzf experssion field index for the line number +-- when entry format is 'file:line:col: text' +-- this is later used with native fzf previewers +-- for setting the preview offset (and on some +-- cases the highlighted line) +M.set_fzf_field_index = function(opts, default_idx, default_expr) + opts.line_field_index = opts.line_field_index or default_idx or 2 + -- when entry contains lines we set the fzf FIELD INDEX EXPRESSION + -- to the below so that only the filename is sent to the preview + -- action, otherwise we will have issues with entries with text + -- containing '--' as fzf won't know how to interpret the cmd + -- this works when the delimiter is only ':', when using multiple + -- or different delimiters (e.g. in 'lines') we need to use a different + -- field index experssion such as "{..-2}" (all fields but the last 2) + opts.field_index_expr = opts.field_index_expr or default_expr or "{1}" return opts end diff --git a/lua/fzf-lua/path.lua b/lua/fzf-lua/path.lua index 76f30cd..d0bf691 100644 --- a/lua/fzf-lua/path.lua +++ b/lua/fzf-lua/path.lua @@ -210,6 +210,8 @@ function M.entry_to_file(entry, cwd, force_uri) return { stripped = stripped, bufnr = tonumber(bufnr), + bufname = bufnr and vim.api.nvim_buf_is_valid(tonumber(bufnr)) + and vim.api.nvim_buf_get_name(tonumber(bufnr)), terminal = terminal, path = file, line = tonumber(line) or 1, diff --git a/lua/fzf-lua/previewer/fzf.lua b/lua/fzf-lua/previewer/fzf.lua index bf1f883..9e5179d 100644 --- a/lua/fzf-lua/previewer/fzf.lua +++ b/lua/fzf-lua/previewer/fzf.lua @@ -34,13 +34,13 @@ function Previewer.base:preview_offset() # '--preview-window '~3:+{2}+3/2'' ]] - if self.opts._line_placeholder then - return ("+{%d}-/2"):format(self.opts._line_placeholder) + if self.opts.line_field_index then + return ("+{%d}-/2"):format(self.opts.line_field_index) end end function Previewer.base:fzf_delimiter() - if not self.opts._line_placeholder then return end + if not self.opts.line_field_index then return end -- set delimiter to ':' -- entry format is 'file:line:col: text' local delim = self.opts.fzf_opts and self.opts.fzf_opts["--delimiter"] @@ -50,7 +50,9 @@ function Previewer.base:fzf_delimiter() if delim:match("%[.*%]")then delim = delim:match("(%[.*)%]") .. ':]' else - delim = '[' .. delim:match("[^[^']+") .. ':]' + delim = '[' .. + utils.rg_escape(delim:match("^'?(.*)'$?")):gsub("%]", "\\]") + .. ':]' end end return delim @@ -73,15 +75,11 @@ end function Previewer.cmd:action(o) o = o or {} - local filespec = "{}" - if self.opts._line_placeholder then - filespec = "{1}" - end local act = shell.raw_action(function (items, _, _) -- only preview first item - local file = path.entry_to_file(items[1], not self.relative and self.opts.cwd) - return file.path - end, filespec) + local entry = path.entry_to_file(items[1], not self.relative and self.opts.cwd) + return entry.bufname or entry.path + end, self.opts.field_index_expr or "{}") return act end @@ -98,8 +96,8 @@ function Previewer.bat:cmdline(o) o = o or {} o.action = o.action or self:action(o) local highlight_line = "" - if self.opts._line_placeholder then - highlight_line = string.format("--highlight-line={%d}", self.opts._line_placeholder) + if self.opts.line_field_index then + highlight_line = string.format("--highlight-line={%d}", self.opts.line_field_index) end return vim.fn.shellescape(string.format('sh -c "%s %s %s `%s`"', self.cmd, self.args, highlight_line, self:action(o))) @@ -116,10 +114,11 @@ end function Previewer.head:cmdline(o) o = o or {} o.action = o.action or self:action(o) - local lines = "" - if self.opts._line_placeholder then - lines = string.format("--lines={%d}", self.opts._line_placeholder) - end + local lines = "--lines=-0" + -- print all lines instead + -- if self.opts.line_field_index then + -- lines = string.format("--lines={%d}", self.opts.line_field_index) + -- end return vim.fn.shellescape(string.format('sh -c "%s %s %s `%s`"', self.cmd, self.args, lines, self:action(o))) end @@ -132,11 +131,24 @@ function Previewer.cmd_async:new(o, opts) return self 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 '' + local errcmd = nil + -- verify the file exists on disk and is accessible + if #filepath==0 or not vim.loop.fs_stat(filepath) then + errcmd = ('echo "%s: NO SUCH FILE OR ACCESS DENIED"'):format( + filepath and #filepath>0 and vim.fn.shellescape(filepath) or "") + end + return filepath, entry, errcmd +end + function Previewer.cmd_async:cmdline(o) o = o or {} local act = shell.preview_action_cmd(function(items) - local file = path.entry_to_file(items[1], not self.relative and self.opts.cwd) - local cmd = string.format('%s %s %s', self.cmd, self.args, vim.fn.shellescape(file.path)) + local filepath, _, errcmd = self:parse_entry_and_verify(items[1]) + local cmd = errcmd or ('%s %s %s'):format( + self.cmd, self.args, vim.fn.shellescape(filepath)) -- uncomment to see the command in the preview window -- cmd = vim.fn.shellescape(cmd) return cmd @@ -154,17 +166,13 @@ end function Previewer.bat_async:cmdline(o) o = o or {} - local highlight_line = "" - if self.opts._line_placeholder then - highlight_line = string.format("--highlight-line=", self.opts._line_placeholder) - end local act = shell.preview_action_cmd(function(items) - local file = path.entry_to_file(items[1], not self.relative and self.opts.cwd) - local cmd = string.format('%s %s %s%s "%s"', + local filepath, entry, errcmd = self:parse_entry_and_verify(items[1]) + local cmd = errcmd or ('%s %s %s %s'):format( self.cmd, self.args, - highlight_line, - utils._if(#highlight_line>0, tostring(file.line), ""), - file.path) + self.opts.line_field_index and + ("--highlight-line=%d"):format(entry.line) or '', + vim.fn.shellescape(filepath)) -- uncomment to see the command in the preview window -- cmd = vim.fn.shellescape(cmd) return cmd @@ -172,7 +180,7 @@ function Previewer.bat_async:cmdline(o) return act end -Previewer.git_diff = Previewer.cmd_async:extend() +Previewer.git_diff = Previewer.base:extend() function Previewer.git_diff:new(o, opts) Previewer.git_diff.super.new(self, o, opts) @@ -236,7 +244,7 @@ function Previewer.git_diff:cmdline(o) return act end -Previewer.man_pages = Previewer.cmd_async:extend() +Previewer.man_pages = Previewer.base:extend() function Previewer.man_pages:new(o, opts) Previewer.man_pages.super.new(self, o, opts) diff --git a/lua/fzf-lua/providers/buffers.lua b/lua/fzf-lua/providers/buffers.lua index 2f92374..5391b7c 100644 --- a/lua/fzf-lua/providers/buffers.lua +++ b/lua/fzf-lua/providers/buffers.lua @@ -186,6 +186,8 @@ M.buffers = function(opts) opts.fzf_opts['--header-lines'] = (not opts.ignore_current_buffer and opts.sort_lastused) and '1' + opts = core.set_fzf_field_index(opts) + core.fzf_wrap(opts, contents, function(selected) if not selected then return end @@ -260,7 +262,7 @@ M.buffer_lines = function(opts) opts.fzf_opts['--query'] = vim.fn.shellescape(opts.search) end - opts = core.set_fzf_line_args(opts) + opts = core.set_fzf_field_index(opts, 3, "{..-2}") core.fzf_wrap(opts, items, function(selected) if not selected then return end @@ -343,8 +345,10 @@ M.tabs = function(opts) -- opts.fzf_opts["--no-multi"] = '' opts.fzf_opts["--preview-window"] = 'hidden:right:0' - opts.fzf_opts["--delimiter"] = vim.fn.shellescape('[\\)]') - opts.fzf_opts["--with-nth"] = '2' + opts.fzf_opts["--delimiter"] = vim.fn.shellescape('[\\):]') + opts.fzf_opts["--with-nth"] = '2..' + + opts = core.set_fzf_field_index(opts, 3) core.fzf_wrap(opts, contents, function(selected) diff --git a/lua/fzf-lua/providers/dap.lua b/lua/fzf-lua/providers/dap.lua index 1943ee4..a6e7557 100644 --- a/lua/fzf-lua/providers/dap.lua +++ b/lua/fzf-lua/providers/dap.lua @@ -162,7 +162,7 @@ M.breakpoints = function(opts) :format(utils.ansi_codes.yellow(""))) end - opts = core.set_fzf_line_args(opts) + opts = core.set_fzf_field_index(opts, 3, "{..-2}") core.fzf_wrap(opts, contents, function(selected) diff --git a/lua/fzf-lua/providers/grep.lua b/lua/fzf-lua/providers/grep.lua index ed8ed42..5a59cb1 100644 --- a/lua/fzf-lua/providers/grep.lua +++ b/lua/fzf-lua/providers/grep.lua @@ -104,7 +104,7 @@ M.grep = function(opts) contents = contents .. " 2>&1" end - opts = core.set_fzf_line_args(opts) + opts = core.set_fzf_field_index(opts) core.fzf_files(opts, contents) opts.search = nil end @@ -157,7 +157,7 @@ M.live_grep_st = function(opts) -- conflicts with 'change:reload' event opts.global_resume_query = false opts.__FNCREF__ = opts.__FNCREF__ or utils.__FNCREF__() - opts = core.set_fzf_line_args(opts) + opts = core.set_fzf_field_index(opts) opts = core.set_fzf_interactive_cmd(opts) core.fzf_files(opts) end @@ -280,7 +280,7 @@ M.live_grep_mt = function(opts) -- conflicts with 'change:reload' event opts.global_resume_query = false opts.__FNCREF__ = opts.__FNCREF__ or utils.__FNCREF__() - opts = core.set_fzf_line_args(opts) + opts = core.set_fzf_field_index(opts) core.fzf_files(opts) opts.search = nil end diff --git a/lua/fzf-lua/providers/lsp.lua b/lua/fzf-lua/providers/lsp.lua index 8c94e11..d925e93 100644 --- a/lua/fzf-lua/providers/lsp.lua +++ b/lua/fzf-lua/providers/lsp.lua @@ -294,7 +294,7 @@ end local function fzf_lsp_locations(opts) opts = normalize_lsp_opts(opts, config.globals.lsp) if not opts then return end - opts = core.set_fzf_line_args(opts) + opts = core.set_fzf_field_index(opts) if opts.force_uri == nil then opts.force_uri = true end opts = set_lsp_fzf_fn(opts) if not opts.fzf_fn then return end @@ -335,7 +335,7 @@ M.workspace_symbols = function(opts) opts = normalize_lsp_opts(opts, config.globals.lsp) if not opts then return end opts.lsp_params = {query = opts.query or ''} - opts = core.set_fzf_line_args(opts) + opts = core.set_fzf_field_index(opts) if opts.force_uri == nil then opts.force_uri = true end opts = set_lsp_fzf_fn(opts) if not opts.fzf_fn then return end @@ -633,7 +633,7 @@ M.diagnostics = function(opts) end)() end - opts = core.set_fzf_line_args(opts) + opts = core.set_fzf_field_index(opts) if opts.force_uri == nil then opts.force_uri = true end return core.fzf_files(opts) end @@ -694,7 +694,7 @@ M.live_workspace_symbols = function(opts) opts.global_resume_query = false opts.__FNCREF__ = M.live_workspace_symbols opts = core.set_fzf_interactive_cb(opts) - opts = core.set_fzf_line_args(opts) + opts = core.set_fzf_field_index(opts) if opts.force_uri == nil then opts.force_uri = true end core.fzf_files(opts) opts.search = nil diff --git a/lua/fzf-lua/providers/quickfix.lua b/lua/fzf-lua/providers/quickfix.lua index f7c86db..e0f64ee 100644 --- a/lua/fzf-lua/providers/quickfix.lua +++ b/lua/fzf-lua/providers/quickfix.lua @@ -31,7 +31,7 @@ local quickfix_run = function(opts, cfg, locations) utils.delayed_cb(cb) end - opts = core.set_fzf_line_args(opts) + opts = core.set_fzf_field_index(opts) return core.fzf_files(opts, contents) end diff --git a/lua/fzf-lua/providers/tags.lua b/lua/fzf-lua/providers/tags.lua index 6b9796f..60e8be9 100644 --- a/lua/fzf-lua/providers/tags.lua +++ b/lua/fzf-lua/providers/tags.lua @@ -144,7 +144,7 @@ local fzf_tags = function(opts) -- signal actions this is a ctag opts._ctag = true opts = core.set_header(opts, 2) - opts = core.set_fzf_line_args(opts) + opts = core.set_fzf_field_index(opts) return core.fzf_files(opts, contents) end