system_open: use asynchronous vim.loop to spawn process + let user customize the command to be used to open a file/folder with default system application (#551)

This commit is contained in:
xeluxee 2021-08-14 15:13:56 +02:00 committed by GitHub
parent 7014b6aff4
commit d74af818c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 25 deletions

View File

@ -145,7 +145,7 @@ highlight NvimTreeFolderIcon guibg=blue
- type `]c` to go to next git item
- type `[c` to go to prev git item
- type `-` to navigate up to the parent directory of the current file/directory
- type `s` to open a file with default system application or a folder with default file manager
- type `s` to open a file with default system application or a folder with default file manager (if you want to change the command used to do it see `:h g:nvim_tree_system_open_command` and `:h g:nvim_tree_system_open_command_args`)
- if the file is a directory, `<CR>` will open the directory otherwise it will open the file in the buffer near the tree
- if the file is a symlink, `<CR>` will follow the symlink (if the target is a file)
- `<C-v>` will open the file in a vertical split

View File

@ -198,6 +198,20 @@ Can be `0` or `1`. When `1`, will close the tree when a file is opened.
Applies to: `edit`, `vsplit`, `split`, `tabnew`.
Default is 0
|g:nvim_tree_system_open_command| *g:nvim_tree_system_open_command*
A string containing the command used to open a file/folder with default system
application. If left unset it will be automatically filled with the right
command, depending on the operating system. If your operating system isn't
recognized or if you want to use another command you can edit it.
Default: depends on the operating system
|g:nvim_tree_system_open_command_args| *g:nvim_tree_system_open_command_args*
An array of strings containing the arguments to be passed to the command
specified in |g:nvim_tree_system_open_command|.
Default: unset if not using Windows
|g:nvim_tree_disable_keybindings| *g:nvim_tree_disable_keybindings*
Can be `0` or `1`. When `1`, will disable all keybindings by the plugin.

View File

@ -97,34 +97,47 @@ local keypress_funcs = {
return lib.open_file('preview', node.absolute_path)
end,
system_open = function(node)
local system_command
if vim.fn.has('win16') == 1 or vim.fn.has('win32') == 1 or vim.fn.has('win64') == 1 then
system_command = 'start "" '
elseif vim.fn.has('win32unix') == 1 then
if vim.fn.stridx(vim.fn.system('uname'), 'CYGWIN') ~= -1 then
system_command = 'cygstart '
if vim.g.nvim_tree_system_open_command == nil then
if vim.fn.has('win32') == 1 or vim.fn.has('win32unix') == 1 then
vim.g.nvim_tree_system_open_command = 'cmd'
vim.g.nvim_tree_system_open_command_args = {'/c', 'start', '""'}
elseif vim.fn.has('mac') == 1 or vim.fn.has('macunix') == 1 then
vim.g.nvim_tree_system_open_command = 'open'
elseif vim.fn.has('unix') == 1 then
vim.g.nvim_tree_system_open_command = 'xdg-open'
else
system_command = 'start "" '
error('\nNvimTree system_open: cannot open file with system application. Unrecognized platform.\nPlease fill g:nvim_tree_system_open_command with the name of the system file launcher.')
return
end
elseif vim.fn.has('mac') == 1 or vim.fn.has('macunix') == 1 then
system_command = 'open '
elseif vim.fn.has('unix') == 1 then
system_command = 'xdg-open '
else
vim.cmd('echohl ErrorMsg')
vim.cmd('echomsg "NvimTree system_open: cannot open file with system application. Unsupported platform."')
vim.cmd('echohl None')
end
local process = {}
process.args = vim.g.nvim_tree_system_open_command_args or {}
table.insert(process.args, node.link_to or node.absolute_path)
process.errors = '\n'
process.stderr = luv.new_pipe(false)
process.handle, process.pid = luv.spawn(vim.g.nvim_tree_system_open_command,
{args = process.args, stdio = {nil, nil, process.stderr}},
function(code)
process.stderr:read_stop()
process.stderr:close()
process.handle:close()
if code ~= 0 then
process.errors = process.errors .. string.format('NvimTree system_open: return code %d.', code)
error(process.errors)
end
end
)
if not process.handle then
error("\n" .. process.pid .. "\nNvimTree system_open: failed to spawn process using '" .. vim.g.nvim_tree_system_open_command .. "'.")
return
end
local command_output = vim.fn.system(system_command .. '"' .. vim.fn.substitute(node.absolute_path, '"', '\\\\"', 'g') .. '"')
if vim.v.shell_error ~= 0 then
vim.cmd('echohl ErrorMsg')
vim.cmd(string.format('echomsg "NvimTree system_open: return code %d."', vim.v.shell_error))
vim.cmd('echomsg "' .. vim.fn.substitute(command_output, '\n', '" | echomsg "', 'g') .. '"')
vim.cmd('echohl None')
end
luv.read_start(process.stderr,
function(err, data)
if err then return end
if data then process.errors = process.errors .. data end
end
)
end,
}