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 next git item
- type `[c` to go to prev git item - type `[c` to go to prev git item
- type `-` to navigate up to the parent directory of the current file/directory - 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 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) - 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 - `<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`. Applies to: `edit`, `vsplit`, `split`, `tabnew`.
Default is 0 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* |g:nvim_tree_disable_keybindings| *g:nvim_tree_disable_keybindings*
Can be `0` or `1`. When `1`, will disable all keybindings by the plugin. 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) return lib.open_file('preview', node.absolute_path)
end, end,
system_open = function(node) system_open = function(node)
local system_command if vim.g.nvim_tree_system_open_command == nil then
if vim.fn.has('win16') == 1 or vim.fn.has('win32') == 1 or vim.fn.has('win64') == 1 then if vim.fn.has('win32') == 1 or vim.fn.has('win32unix') == 1 then
system_command = 'start "" ' vim.g.nvim_tree_system_open_command = 'cmd'
elseif vim.fn.has('win32unix') == 1 then vim.g.nvim_tree_system_open_command_args = {'/c', 'start', '""'}
if vim.fn.stridx(vim.fn.system('uname'), 'CYGWIN') ~= -1 then elseif vim.fn.has('mac') == 1 or vim.fn.has('macunix') == 1 then
system_command = 'cygstart ' 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 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 end
elseif vim.fn.has('mac') == 1 or vim.fn.has('macunix') == 1 then end
system_command = 'open '
elseif vim.fn.has('unix') == 1 then local process = {}
system_command = 'xdg-open ' process.args = vim.g.nvim_tree_system_open_command_args or {}
else table.insert(process.args, node.link_to or node.absolute_path)
vim.cmd('echohl ErrorMsg') process.errors = '\n'
vim.cmd('echomsg "NvimTree system_open: cannot open file with system application. Unsupported platform."') process.stderr = luv.new_pipe(false)
vim.cmd('echohl None') 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 return
end end
luv.read_start(process.stderr,
local command_output = vim.fn.system(system_command .. '"' .. vim.fn.substitute(node.absolute_path, '"', '\\\\"', 'g') .. '"') function(err, data)
if err then return end
if vim.v.shell_error ~= 0 then if data then process.errors = process.errors .. data end
vim.cmd('echohl ErrorMsg') end
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
end, end,
} }