diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index 9c4b33f3ca7..8efcb0f5ee2 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -15,6 +15,7 @@ CONTENTS *nvim-tree* 7. Highlight Groups |nvim-tree-highlight| 8. Events |nvim-tree-events| 9. Bookmarks |nvim-tree-bookmarks| + 10. OS Specific Restrictions |nvim-tree-os-specific| ============================================================================== 1. INTRODUCTION *nvim-tree-introduction* @@ -1580,7 +1581,7 @@ e.g. handler for node renamed: > {folder_name} `{string}` Absolute path to the removed folder. ============================================================================== - 9. BOOKMARKS *nvim-tree-bookmarks* + 9. BOOKMARKS *nvim-tree-bookmarks* You can toggle marks on files/folders with `require("nvim-tree.api").marks.toggle(node)` which is bound to `m` by @@ -1601,4 +1602,15 @@ vim.keymap.set("n", "mn", require("nvim-tree.api").marks.navigate.next) vim.keymap.set("n", "mp", require("nvim-tree.api").marks.navigate.prev) vim.keymap.set("n", "ms", require("nvim-tree.api").marks.navigate.select) +============================================================================== + 10. OS SPECIFIC RESTRICTIONS *nvim-tree-os-specific* + +macOS +- Trash is unavailable + +Windows WSL and PowerShell +- Trash is unavailable +- Executable file detection is disabled as this is non-performant and can + freeze nvim + vim:tw=78:ts=4:sw=4:et:ft=help:norl: diff --git a/lua/nvim-tree/actions/fs/trash.lua b/lua/nvim-tree/actions/fs/trash.lua index dc8c624d767..76ea2aa4aa7 100644 --- a/lua/nvim-tree/actions/fs/trash.lua +++ b/lua/nvim-tree/actions/fs/trash.lua @@ -1,13 +1,7 @@ local lib = require "nvim-tree.lib" local notify = require "nvim-tree.notify" -local M = { - config = { - is_windows = vim.fn.has "win32" == 1 or vim.fn.has "win32unix" == 1, - is_macos = vim.fn.has "mac" == 1 or vim.fn.has "macunix" == 1, - is_unix = vim.fn.has "unix" == 1, - }, -} +local M = {} local utils = require "nvim-tree.utils" local events = require "nvim-tree.events" @@ -34,7 +28,7 @@ function M.fn(node) end -- configs - if M.config.is_unix then + if utils.is_unix then if M.config.trash.cmd == nil then M.config.trash.cmd = "trash" end @@ -108,6 +102,7 @@ function M.fn(node) end function M.setup(opts) + M.config = {} M.config.trash = opts.trash or {} M.enable_reload = not opts.filesystem_watchers.enable end diff --git a/lua/nvim-tree/actions/node/system-open.lua b/lua/nvim-tree/actions/node/system-open.lua index aecb7f9d22c..a5ff2bd17f1 100644 --- a/lua/nvim-tree/actions/node/system-open.lua +++ b/lua/nvim-tree/actions/node/system-open.lua @@ -1,12 +1,7 @@ local notify = require "nvim-tree.notify" +local utils = require "nvim-tree.utils" -local M = { - config = { - is_windows = vim.fn.has "win32" == 1 or vim.fn.has "win32unix" == 1, - is_macos = vim.fn.has "mac" == 1 or vim.fn.has "macunix" == 1, - is_unix = vim.fn.has "unix" == 1, - }, -} +local M = {} function M.fn(node) if #M.config.system_open.cmd == 0 then @@ -50,17 +45,18 @@ function M.fn(node) end function M.setup(opts) + M.config = {} M.config.system_open = opts.system_open or {} if #M.config.system_open.cmd == 0 then - if M.config.is_windows then + if utils.is_windows then M.config.system_open = { cmd = "cmd", args = { "/c", "start", '""' }, } - elseif M.config.is_macos then + elseif utils.is_macos then M.config.system_open.cmd = "open" - elseif M.config.is_unix then + elseif utils.is_unix then M.config.system_open.cmd = "xdg-open" end end diff --git a/lua/nvim-tree/explorer/explore.lua b/lua/nvim-tree/explorer/explore.lua index 0ea6addf674..a8aed702a54 100644 --- a/lua/nvim-tree/explorer/explore.lua +++ b/lua/nvim-tree/explorer/explore.lua @@ -23,6 +23,10 @@ local function populate_children(handle, cwd, node, git_status) end local abs = utils.path_join { cwd, name } + + local pn = string.format("explore populate_children %s", abs) + local ps = log.profile_start(pn) + t = get_type_from(t, abs) if not filters.should_filter(abs, filter_status) and not nodes_by_path[abs] then local child = nil @@ -42,6 +46,8 @@ local function populate_children(handle, cwd, node, git_status) explorer_node.update_git_status(child, node_ignored, git_status) end end + + log.profile_end(ps, pn) end end diff --git a/lua/nvim-tree/explorer/node-builders.lua b/lua/nvim-tree/explorer/node-builders.lua index bf02e1f9007..02780a4eb68 100644 --- a/lua/nvim-tree/explorer/node-builders.lua +++ b/lua/nvim-tree/explorer/node-builders.lua @@ -1,10 +1,7 @@ local utils = require "nvim-tree.utils" local watch = require "nvim-tree.explorer.watch" -local M = { - is_windows = vim.fn.has "win32" == 1, - is_wsl = vim.fn.has "wsl" == 1, -} +local M = {} function M.folder(parent, absolute_path, name) local handle = utils.fs_scandir_profiled(absolute_path) @@ -27,21 +24,16 @@ function M.folder(parent, absolute_path, name) return node end -function M.is_executable(parent, absolute_path, ext) - if M.is_windows then - return utils.is_windows_exe(ext) - elseif M.is_wsl then - if parent.is_wsl_windows_fs_path == nil then - -- Evaluate lazily when needed and do so only once for each parent - -- as 'wslpath' calls can get expensive in highly populated directories. - parent.is_wsl_windows_fs_path = utils.is_wsl_windows_fs_path(absolute_path) - end - - if parent.is_wsl_windows_fs_path then - return utils.is_wsl_windows_fs_exe(ext) - end +--- path is an executable file or directory +--- @param absolute_path string +--- @return boolean +function M.is_executable(absolute_path) + if utils.is_windows or utils.is_wsl then + --- executable detection on windows is buggy and not performant hence it is disabled + return false + else + return vim.loop.fs_access(absolute_path, "X") end - return vim.loop.fs_access(absolute_path, "X") end function M.file(parent, absolute_path, name) @@ -50,7 +42,7 @@ function M.file(parent, absolute_path, name) return { type = "file", absolute_path = absolute_path, - executable = M.is_executable(parent, absolute_path, ext), + executable = M.is_executable(absolute_path), extension = ext, fs_stat = vim.loop.fs_stat(absolute_path), name = name, diff --git a/lua/nvim-tree/explorer/reload.lua b/lua/nvim-tree/explorer/reload.lua index 2247a3a468a..5f6a6ce419b 100644 --- a/lua/nvim-tree/explorer/reload.lua +++ b/lua/nvim-tree/explorer/reload.lua @@ -104,7 +104,7 @@ function M.reload(node, git_status, unloaded_bufnr) else local n = nodes_by_path[abs] if n then - n.executable = builders.is_executable(n.parent, abs, n.extension or "") + n.executable = builders.is_executable(abs) n.fs_stat = fs_stat_cached(abs) end end diff --git a/lua/nvim-tree/utils.lua b/lua/nvim-tree/utils.lua index 812f7407a7a..b1c62889be4 100644 --- a/lua/nvim-tree/utils.lua +++ b/lua/nvim-tree/utils.lua @@ -6,8 +6,11 @@ local M = { debouncers = {}, } -M.is_windows = vim.fn.has "win32" == 1 or vim.fn.has "win32unix" == 1 +M.is_unix = vim.fn.has "unix" == 1 +M.is_macos = vim.fn.has "mac" == 1 or vim.fn.has "macunix" == 1 M.is_wsl = vim.fn.has "wsl" == 1 +-- false for WSL +M.is_windows = vim.fn.has "win32" == 1 or vim.fn.has "win32unix" == 1 function M.path_to_matching_str(path) return path:gsub("(%-)", "(%%-)"):gsub("(%.)", "(%%.)"):gsub("(%_)", "(%%_)") @@ -152,63 +155,6 @@ function M.get_nodes_by_line(nodes_all, line_start) return nodes_by_line end ----Matching executable files in Windows. ----@param ext string ----@return boolean -function M.is_windows_exe(ext) - if not M.pathexts then - if not vim.env.PATHEXT then - return false - end - - local wexe = vim.split(vim.env.PATHEXT:gsub("%.", ""), ";") - M.pathexts = {} - for _, v in pairs(wexe) do - M.pathexts[v] = true - end - end - - return M.pathexts[ext:upper()] -end - ---- Check whether path maps to Windows filesystem mounted by WSL --- @param path string --- @return boolean -function M.is_wsl_windows_fs_path(path) - -- Run 'wslpath' command to try translating WSL path to Windows path. - -- Consume stderr output as well because 'wslpath' can produce permission - -- errors on some files (e.g. temporary files in root of system drive). - local handle = io.popen('wslpath -w "' .. path .. '" 2>/dev/null') - if handle then - local output = handle:read "*a" - handle:close() - - return string.find(output, "^\\\\wsl$\\") == nil - end - - return false -end - ---- Check whether extension is Windows executable under WSL --- @param ext string --- @return boolean -function M.is_wsl_windows_fs_exe(ext) - if not vim.env.PATHEXT then - -- Extract executable extensions from within WSL. - -- Redirect stderr to null to silence warnings when - -- Windows command is executed from Linux filesystem: - -- > CMD.EXE was started with the above path as the current directory. - -- > UNC paths are not supported. Defaulting to Windows directory. - local handle = io.popen 'cmd.exe /c "echo %PATHEXT%" 2>/dev/null' - if handle then - vim.env.PATHEXT = handle:read "*a" - handle:close() - end - end - - return M.is_windows_exe(ext) -end - function M.rename_loaded_buffers(old_path, new_path) for _, buf in pairs(vim.api.nvim_list_bufs()) do if vim.api.nvim_buf_is_loaded(buf) then