fix(#1831): remove windows executable functionality due to occasional vim freeze and performance concerns (#1868)

* #1831 exploratory testing: disable file executable checks

* fix(#1831): remove windows executable functionality
This commit is contained in:
Alexander Courtis 2022-12-31 12:34:55 +11:00 committed by GitHub
parent 9e4c39572f
commit 3c4958ab3d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 44 additions and 97 deletions

View File

@ -15,6 +15,7 @@ CONTENTS *nvim-tree*
7. Highlight Groups |nvim-tree-highlight| 7. Highlight Groups |nvim-tree-highlight|
8. Events |nvim-tree-events| 8. Events |nvim-tree-events|
9. Bookmarks |nvim-tree-bookmarks| 9. Bookmarks |nvim-tree-bookmarks|
10. OS Specific Restrictions |nvim-tree-os-specific|
============================================================================== ==============================================================================
1. INTRODUCTION *nvim-tree-introduction* 1. INTRODUCTION *nvim-tree-introduction*
@ -1580,7 +1581,7 @@ e.g. handler for node renamed: >
{folder_name} `{string}` Absolute path to the removed folder. {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 You can toggle marks on files/folders with
`require("nvim-tree.api").marks.toggle(node)` which is bound to `m` by `require("nvim-tree.api").marks.toggle(node)` which is bound to `m` by
@ -1601,4 +1602,15 @@ vim.keymap.set("n", "<leader>mn", require("nvim-tree.api").marks.navigate.next)
vim.keymap.set("n", "<leader>mp", require("nvim-tree.api").marks.navigate.prev) vim.keymap.set("n", "<leader>mp", require("nvim-tree.api").marks.navigate.prev)
vim.keymap.set("n", "<leader>ms", require("nvim-tree.api").marks.navigate.select) vim.keymap.set("n", "<leader>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: vim:tw=78:ts=4:sw=4:et:ft=help:norl:

View File

@ -1,13 +1,7 @@
local lib = require "nvim-tree.lib" local lib = require "nvim-tree.lib"
local notify = require "nvim-tree.notify" local notify = require "nvim-tree.notify"
local M = { 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 utils = require "nvim-tree.utils" local utils = require "nvim-tree.utils"
local events = require "nvim-tree.events" local events = require "nvim-tree.events"
@ -34,7 +28,7 @@ function M.fn(node)
end end
-- configs -- configs
if M.config.is_unix then if utils.is_unix then
if M.config.trash.cmd == nil then if M.config.trash.cmd == nil then
M.config.trash.cmd = "trash" M.config.trash.cmd = "trash"
end end
@ -108,6 +102,7 @@ function M.fn(node)
end end
function M.setup(opts) function M.setup(opts)
M.config = {}
M.config.trash = opts.trash or {} M.config.trash = opts.trash or {}
M.enable_reload = not opts.filesystem_watchers.enable M.enable_reload = not opts.filesystem_watchers.enable
end end

View File

@ -1,12 +1,7 @@
local notify = require "nvim-tree.notify" local notify = require "nvim-tree.notify"
local utils = require "nvim-tree.utils"
local M = { 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,
},
}
function M.fn(node) function M.fn(node)
if #M.config.system_open.cmd == 0 then if #M.config.system_open.cmd == 0 then
@ -50,17 +45,18 @@ function M.fn(node)
end end
function M.setup(opts) function M.setup(opts)
M.config = {}
M.config.system_open = opts.system_open or {} M.config.system_open = opts.system_open or {}
if #M.config.system_open.cmd == 0 then if #M.config.system_open.cmd == 0 then
if M.config.is_windows then if utils.is_windows then
M.config.system_open = { M.config.system_open = {
cmd = "cmd", cmd = "cmd",
args = { "/c", "start", '""' }, args = { "/c", "start", '""' },
} }
elseif M.config.is_macos then elseif utils.is_macos then
M.config.system_open.cmd = "open" M.config.system_open.cmd = "open"
elseif M.config.is_unix then elseif utils.is_unix then
M.config.system_open.cmd = "xdg-open" M.config.system_open.cmd = "xdg-open"
end end
end end

View File

@ -23,6 +23,10 @@ local function populate_children(handle, cwd, node, git_status)
end end
local abs = utils.path_join { cwd, name } 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) t = get_type_from(t, abs)
if not filters.should_filter(abs, filter_status) and not nodes_by_path[abs] then if not filters.should_filter(abs, filter_status) and not nodes_by_path[abs] then
local child = nil 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) explorer_node.update_git_status(child, node_ignored, git_status)
end end
end end
log.profile_end(ps, pn)
end end
end end

View File

@ -1,10 +1,7 @@
local utils = require "nvim-tree.utils" local utils = require "nvim-tree.utils"
local watch = require "nvim-tree.explorer.watch" local watch = require "nvim-tree.explorer.watch"
local M = { local M = {}
is_windows = vim.fn.has "win32" == 1,
is_wsl = vim.fn.has "wsl" == 1,
}
function M.folder(parent, absolute_path, name) function M.folder(parent, absolute_path, name)
local handle = utils.fs_scandir_profiled(absolute_path) local handle = utils.fs_scandir_profiled(absolute_path)
@ -27,21 +24,16 @@ function M.folder(parent, absolute_path, name)
return node return node
end end
function M.is_executable(parent, absolute_path, ext) --- path is an executable file or directory
if M.is_windows then --- @param absolute_path string
return utils.is_windows_exe(ext) --- @return boolean
elseif M.is_wsl then function M.is_executable(absolute_path)
if parent.is_wsl_windows_fs_path == nil then if utils.is_windows or utils.is_wsl then
-- Evaluate lazily when needed and do so only once for each parent --- executable detection on windows is buggy and not performant hence it is disabled
-- as 'wslpath' calls can get expensive in highly populated directories. return false
parent.is_wsl_windows_fs_path = utils.is_wsl_windows_fs_path(absolute_path) else
end return vim.loop.fs_access(absolute_path, "X")
if parent.is_wsl_windows_fs_path then
return utils.is_wsl_windows_fs_exe(ext)
end
end end
return vim.loop.fs_access(absolute_path, "X")
end end
function M.file(parent, absolute_path, name) function M.file(parent, absolute_path, name)
@ -50,7 +42,7 @@ function M.file(parent, absolute_path, name)
return { return {
type = "file", type = "file",
absolute_path = absolute_path, absolute_path = absolute_path,
executable = M.is_executable(parent, absolute_path, ext), executable = M.is_executable(absolute_path),
extension = ext, extension = ext,
fs_stat = vim.loop.fs_stat(absolute_path), fs_stat = vim.loop.fs_stat(absolute_path),
name = name, name = name,

View File

@ -104,7 +104,7 @@ function M.reload(node, git_status, unloaded_bufnr)
else else
local n = nodes_by_path[abs] local n = nodes_by_path[abs]
if n then 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) n.fs_stat = fs_stat_cached(abs)
end end
end end

View File

@ -6,8 +6,11 @@ local M = {
debouncers = {}, 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 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) function M.path_to_matching_str(path)
return path:gsub("(%-)", "(%%-)"):gsub("(%.)", "(%%.)"):gsub("(%_)", "(%%_)") return path:gsub("(%-)", "(%%-)"):gsub("(%.)", "(%%.)"):gsub("(%_)", "(%%_)")
@ -152,63 +155,6 @@ function M.get_nodes_by_line(nodes_all, line_start)
return nodes_by_line return nodes_by_line
end 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) function M.rename_loaded_buffers(old_path, new_path)
for _, buf in pairs(vim.api.nvim_list_bufs()) do for _, buf in pairs(vim.api.nvim_list_bufs()) do
if vim.api.nvim_buf_is_loaded(buf) then if vim.api.nvim_buf_is_loaded(buf) then