You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

178 lines
4.6 KiB
Lua

-- modified version of:
-- https://github.com/vijaymarupudi/nvim-fzf/blob/master/lua/fzf/actions.lua
local uv = vim.loop
local path = require "fzf-lua.path"
local libuv = require "fzf-lua.libuv"
local M = {}
local _counter = 0
local _registry = {}
function M.register_func(fn)
_counter = _counter + 1
_registry[_counter] = fn
return _counter
end
function M.get_func(counter)
return _registry[counter]
end
-- creates a new address to listen to messages from actions. This is important,
-- if the user is using a custom fixed $NVIM_LISTEN_ADDRESS. Different neovim
-- instances will then use the same path as the address and it causes a mess,
-- i.e. actions stop working on the old instance. So we create our own (random
-- path) RPC server for this instance if it hasn't been started already.
-- NOT USED ANYMORE, we use `vim.g.fzf_lua_server` instead
-- local action_server_address = nil
function M.raw_async_action(fn, fzf_field_expression, debug)
if not fzf_field_expression then
fzf_field_expression = "{+}"
end
local receiving_function = function(pipe_path, ...)
local pipe = uv.new_pipe(false)
local args = {...}
uv.pipe_connect(pipe, pipe_path, function(err)
vim.schedule(function ()
fn(pipe, unpack(args))
end)
end)
end
local id = M.register_func(receiving_function)
-- this is for windows WSL and AppImage users, their nvim path isn't just
-- 'nvim', it can be something else
local nvim_bin = vim.v.argv[1]
local call_args = ("fzf_lua_server=[[%s]], fnc_id=%d %s"):format(
vim.g.fzf_lua_server, id, debug and ", debug=true" or "")
local action_cmd = ("%s -n --headless --clean --cmd %s %s"):format(
libuv.shellescape(nvim_bin),
libuv.shellescape(("lua loadfile([[%s]])().rpc_nvim_exec_lua({%s})")
:format(path.join{vim.g.fzf_lua_directory, "shell_helper.lua"}, call_args)),
fzf_field_expression)
return action_cmd, id
end
function M.async_action(fn, fzf_field_expression, debug)
local action_string, id = M.raw_async_action(fn, fzf_field_expression, debug)
return vim.fn.shellescape(action_string), id
end
function M.raw_action(fn, fzf_field_expression, debug)
local receiving_function = function(pipe, ...)
local ret = fn(...)
local on_complete = function(_)
-- We are NOT asserting, in case fzf closes
-- the pipe before we can send the preview
-- assert(not err)
uv.close(pipe)
end
if type(ret) == "string" then
uv.write(pipe, ret, on_complete)
elseif type(ret) == nil then
on_complete()
elseif type(ret) == "table" then
if not vim.tbl_isempty(ret) then
uv.write(pipe, vim.tbl_map(function(x) return x.."\n" end, ret), on_complete)
else
on_complete()
end
else
uv.write(pipe, tostring(ret) .. "\n", on_complete)
end
end
return M.raw_async_action(receiving_function, fzf_field_expression, debug)
end
function M.action(fn, fzf_field_expression ,debug)
local action_string, id = M.raw_action(fn, fzf_field_expression, debug)
return vim.fn.shellescape(action_string), id
end
M.preview_action_cmd = function(fn, fzf_field_expression, debug)
return M.async_action(function(pipe, ...)
local function on_finish(_, _)
if pipe and not uv.is_closing(pipe) then
uv.close(pipe)
pipe = nil
end
end
local function on_write(data, cb)
if not pipe then
cb(true)
else
uv.write(pipe, data, cb)
end
end
return libuv.spawn({
cmd = fn(...),
cb_finish = on_finish,
cb_write = on_write,
}, false)
end, fzf_field_expression, debug)
end
M.reload_action_cmd = function(opts, fzf_field_expression)
local _pid = nil
return M.raw_async_action(function(pipe, args)
local function on_pid(pid)
_pid = pid
if opts.pid_cb then
opts.pid_cb(pid)
end
end
local function on_finish(_, _)
if pipe and not uv.is_closing(pipe) then
uv.close(pipe)
pipe = nil
end
end
local function on_write(data, cb)
if not pipe then
cb(true)
else
uv.write(pipe, data, cb)
end
end
-- terminate previously running commands
libuv.process_kill(_pid)
-- return libuv.spawn({
return libuv.async_spawn({
cwd = opts.cwd,
cmd = opts._reload_command(args[1]),
cb_finish = on_finish,
cb_write = on_write,
cb_pid = on_pid,
-- must send false, 'coroutinify' adds callback as last argument
-- which will conflict with the 'fn_transform' argument
}, opts._fn_transform or false)
end, fzf_field_expression, opts.debug)
end
return M