added experimental icon support for 'live_grep' (+resume) (issue #168)

Warning: this may cause a performance degradation so you have to
manually enable this by setting `grep.experimental = true` or directly
via `:lua require'fzf-lua'.live_grep({ experimental = true })`
main
bhagwan 3 years ago
parent 3f4d57bec6
commit a499bd78a4

@ -411,6 +411,9 @@ require'fzf-lua'.setup {
git_icons = true, -- show git icons?
file_icons = true, -- show file icons?
color_icons = true, -- colorize file|git icons
-- 'true' enables file and git icons in 'live_grep'
-- degrades performance in large datasets, YMMV
experimental = false,
},
args = {
prompt = 'Args ',

@ -445,6 +445,9 @@ Consult the list below for available settings:
git_icons = true, -- show git icons?
file_icons = true, -- show file icons?
color_icons = true, -- colorize file|git icons
-- 'true' enables file and git icons in 'live_grep'
-- degrades performance in large datasets, YMMV
experimental = false,
},
args = {
prompt = 'Args ',

@ -343,6 +343,18 @@ M.fzf_files = function(opts)
end
-- save to upvalue for performance reasons
local string_byte = string.byte
local string_sub = string.sub
local function find_last_newline(str)
for i=#str,1,-1 do
if string_byte(str, i) == 10 then
return i
end
end
end
-- https://github.com/luvit/luv/blob/master/docs.md
-- uv.spawn returns tuple: handle, pid
local _, _pid
@ -360,18 +372,22 @@ M.set_fzf_interactive_cmd = function(opts)
local shell_cmd = opts._reload_command(args[1])
local output_pipe = uv.new_pipe(false)
local error_pipe = uv.new_pipe(false)
local read_cb_count = 0
local write_cb_count = 0
local prev_line_content = nil
local shell = vim.env.SHELL or "sh"
local close_pipe = function()
if not uv.is_closing(pipe) then
local finish = function()
if pipe and not uv.is_closing(pipe) then
uv.close(pipe)
pipe = nil
end
output_pipe:shutdown()
error_pipe:shutdown()
end
-- terminate previously running commands
if _pid then
if _pid and type(uv.os_getpriority(_pid)) == 'number' then
uv.kill(_pid, 9)
end
@ -384,40 +400,82 @@ M.set_fzf_interactive_cmd = function(opts)
error_pipe:read_stop()
output_pipe:close()
error_pipe :close()
if read_cb_count==0 then
if write_cb_count==0 then
-- only close if all our uv.write
-- calls are completed
close_pipe()
finish()
end
_pid = nil
end)
local read_cb = function(err, data)
read_cb_count = read_cb_count + 1
-- save current process pid
local pid = _pid
if err then
close_pipe()
assert(not err)
end
if not data then
read_cb_count = read_cb_count - 1
local function write_cb(data)
if not pipe then return end
if pid ~= _pid then
-- safety, I never saw this get called
-- will set `pipe = nill`
finish()
return
end
write_cb_count = write_cb_count + 1
uv.write(pipe, data, function(err)
if err then
close_pipe()
-- sometime fails?
-- assert(not err)
finish()
end
read_cb_count = read_cb_count - 1
if read_cb_count == 0 and uv.is_closing(output_pipe) then
write_cb_count = write_cb_count - 1
if write_cb_count == 0 and uv.is_closing(output_pipe) then
-- spawn callback already called and did not close the pipe
-- due to read_cb_count>0, since this is the last call
-- due to write_cb_count>0, since this is the last call
-- we can close the fzf pipe
close_pipe()
finish()
end
end)
end
local function process_lines(str)
if not opts._transform_command then
write_cb(str)
else
write_cb(str:gsub("[^\n]+",
function(x)
return opts._transform_command(x)
end))
end
end
local read_cb = function(err, data)
if err then
finish()
assert(not err)
end
if not data then
return
end
if prev_line_content then
data = prev_line_content .. data
prev_line_content = nil
end
if string_byte(data, #data) == 10 then
process_lines(data)
else
local nl_index = find_last_newline(data)
if not nl_index then
prev_line_content = data
else
prev_line_content = string_sub(data, nl_index + 1)
local stripped_with_newline = string_sub(data, 1, nl_index)
process_lines(stripped_with_newline)
end
end
end
output_pipe:read_start(read_cb)
error_pipe:read_start(read_cb)
end, placeholder)
@ -492,9 +550,7 @@ M.set_fzf_interactive = function(opts, act_cmd, placeholder)
if opts.exec_empty_query or (query and #query>0) then
opts.fzf_fn = require("fzf.helpers").cmd_line_transformer(
act_cmd:gsub(placeholder, vim.fn.shellescape(query)),
function(x)
return M.make_entry_file(opts, x)
end)
function(x) return x end)
end
opts.fzf_opts['--phony'] = ''
opts.fzf_opts['--query'] = vim.fn.shellescape(query)
@ -502,12 +558,6 @@ M.set_fzf_interactive = function(opts, act_cmd, placeholder)
vim.fn.shellescape(string.format("change:reload:%s || true", act_cmd)))
end
-- we cannot parse any entries as they're not getting called
-- past the initial command, until I can find a solution for
-- that icons must be disabled
opts.git_icons = false
opts.file_icons = false
return opts
end

@ -60,7 +60,7 @@ M.files = require'fzf-lua.providers.files'.files
M.files_resume = require'fzf-lua.providers.files'.files_resume
M.args = require'fzf-lua.providers.files'.args
M.grep = require'fzf-lua.providers.grep'.grep
M.live_grep = require'fzf-lua.providers.grep'.live_grep_native
M.live_grep = require'fzf-lua.providers.grep'.live_grep
M.live_grep_native = require'fzf-lua.providers.grep'.live_grep_native
M.live_grep_resume = require'fzf-lua.providers.grep'.live_grep_resume
M.grep_last = require'fzf-lua.providers.grep'.grep_last

@ -250,6 +250,7 @@ function Previewer.buffer_or_file:parse_entry(entry_str)
end
function Previewer.buffer_or_file:populate_preview_buf(entry_str)
if not self.win or not self.win:validate_preview() then return end
local entry = self:parse_entry(entry_str)
if entry.bufnr and api.nvim_buf_is_loaded(entry.bufnr) then
-- must convert to number or our backup will have conflicting keys

@ -164,6 +164,12 @@ M.live_grep = function(opts)
return get_grep_cmd(opts, query, true)
end
if opts.experimental then
opts._transform_command = function(x)
return core.make_entry_file(opts, x)
end
end
opts = core.set_fzf_line_args(opts)
opts = core.set_fzf_interactive_cmd(opts)
core.fzf_files(opts)

@ -645,6 +645,7 @@ function FzfWin.win_leave()
end
function FzfWin:update_scrollbar()
if not self:validate_preview() then return end
local border_winid = self.border_winid
local preview_winid = self.preview_winid
local border_chars = strip_border_highlights(self.winopts.border)

Loading…
Cancel
Save