diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index c7041cdcc5a..bf8a44952ce 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -29,9 +29,10 @@ CONTENTS *nvim-tree* 5.14 Opts: Trash |nvim-tree-opts-trash| 5.15 Opts: Tab |nvim-tree-opts-tab| 5.16 Opts: Notify |nvim-tree-opts-notify| - 5.17 Opts: UI |nvim-tree-opts-ui| - 5.18 Opts: Experimental |nvim-tree-opts-experimental| - 5.19 Opts: Log |nvim-tree-opts-log| + 5.17 Opts: Help |nvim-tree-opts-help| + 5.18 Opts: UI |nvim-tree-opts-ui| + 5.19 Opts: Experimental |nvim-tree-opts-experimental| + 5.20 Opts: Log |nvim-tree-opts-log| 6. API |nvim-tree-api| 6.1 API Tree |nvim-tree-api.tree| 6.2 API File System |nvim-tree-api.fs| @@ -565,6 +566,9 @@ Following is the default configuration. See |nvim-tree-opts| for details. threshold = vim.log.levels.INFO, absolute_path = true, }, + help = { + sort_by = "key", + }, ui = { confirm = { remove = true, @@ -1433,7 +1437,16 @@ Whether to use absolute paths or item names in fs action notifications. Type: `boolean`, Default: `true` ============================================================================== - 5.17 OPTS: UI *nvim-tree-opts-ui* + 5.17 OPTS: HELP *nvim-tree-opts-help* + +*nvim-tree.help.sort_by* +Defines how mappings are sorted in the help window. +Can be `"key"` (sort alphabetically by keymap) +or `"desc"` (sort alphabetically by description). + Type: `string`, Default: `"key"` + +============================================================================== + 5.18 OPTS: UI *nvim-tree-opts-ui* *nvim-tree.ui.confirm* Confirmation prompts. @@ -1447,14 +1460,14 @@ Confirmation prompts. Type: `boolean`, Default: `true` ============================================================================== - 5.18 OPTS: EXPERIMENTAL *nvim-tree-opts-experimental* + 5.19 OPTS: EXPERIMENTAL *nvim-tree-opts-experimental* *nvim-tree.experimental* Experimental features that may become default or optional functionality. In the event of a problem please disable the experiment and raise an issue. ============================================================================== - 5.19 OPTS: LOG *nvim-tree-opts-log* + 5.20 OPTS: LOG *nvim-tree-opts-log* Configuration for diagnostic logging. diff --git a/lua/nvim-tree.lua b/lua/nvim-tree.lua index c6384c86e69..db4209861b0 100644 --- a/lua/nvim-tree.lua +++ b/lua/nvim-tree.lua @@ -588,6 +588,9 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS threshold = vim.log.levels.INFO, absolute_path = true, }, + help = { + sort_by = "key", + }, ui = { confirm = { remove = true, @@ -667,6 +670,9 @@ local ACCEPTED_STRINGS = { bookmarks_placement = { "before", "after", "signcolumn" }, }, }, + help = { + sort_by = { "key", "desc" }, + }, } local function validate_options(conf) diff --git a/lua/nvim-tree/actions/fs/copy-paste.lua b/lua/nvim-tree/actions/fs/copy-paste.lua index 3ac651da90c..8953cd320a9 100644 --- a/lua/nvim-tree/actions/fs/copy-paste.lua +++ b/lua/nvim-tree/actions/fs/copy-paste.lua @@ -252,15 +252,19 @@ function M.print_clipboard() end local function copy_to_clipboard(content) + local clipboard_name if M.config.actions.use_system_clipboard == true then vim.fn.setreg("+", content) vim.fn.setreg('"', content) - return notify.info(string.format("Copied %s to system clipboard!", content)) + clipboard_name = "system" else vim.fn.setreg('"', content) vim.fn.setreg("1", content) - return notify.info(string.format("Copied %s to neovim clipboard!", content)) + clipboard_name = "neovim" end + + vim.api.nvim_exec_autocmds("TextYankPost", {}) + return notify.info(string.format("Copied %s to %s clipboard!", content, clipboard_name)) end function M.copy_filename(node) diff --git a/lua/nvim-tree/git/utils.lua b/lua/nvim-tree/git/utils.lua index b9ba371c515..e088be6beae 100644 --- a/lua/nvim-tree/git/utils.lua +++ b/lua/nvim-tree/git/utils.lua @@ -36,15 +36,20 @@ function M.get_toplevel(cwd) -- git always returns path with forward slashes if vim.fn.has "win32" == 1 then -- msys2 git support + -- cygpath calls must in array format to avoid shell compatibility issues if M.use_cygpath then - toplevel = vim.fn.system("cygpath -w " .. vim.fn.shellescape(toplevel)) + toplevel = vim.fn.system { "cygpath", "-w", toplevel } if vim.v.shell_error ~= 0 then return nil, nil end - git_dir = vim.fn.system("cygpath -w " .. vim.fn.shellescape(git_dir)) + -- remove trailing newline(\n) character added by vim.fn.system + toplevel = toplevel:gsub("\n", "") + git_dir = vim.fn.system { "cygpath", "-w", git_dir } if vim.v.shell_error ~= 0 then return nil, nil end + -- remove trailing newline(\n) character added by vim.fn.system + git_dir = git_dir:gsub("\n", "") end toplevel = toplevel:gsub("/", "\\") git_dir = git_dir:gsub("/", "\\") diff --git a/lua/nvim-tree/help.lua b/lua/nvim-tree/help.lua index 78617cb025e..c7342be54d1 100644 --- a/lua/nvim-tree/help.lua +++ b/lua/nvim-tree/help.lua @@ -84,17 +84,29 @@ end --- @return number maximum length of text local function compute() local head_lhs = "nvim-tree mappings" - local head_rhs = "exit: q" + local head_rhs1 = "exit: q" + local head_rhs2 = string.format("sort by %s: s", M.config.sort_by == "key" and "description" or "keymap") -- formatted lhs and desc from active keymap local mappings = vim.tbl_map(function(map) return { lhs = tidy_lhs(map.lhs), desc = tidy_desc(map.desc) } end, keymap.get_keymap()) - -- sort roughly by lhs - table.sort(mappings, function(a, b) - return sort_lhs(a.lhs, b.lhs) - end) + -- sorter function for mappings + local sort_fn + + if M.config.sort_by == "desc" then + sort_fn = function(a, b) + return a.desc:lower() < b.desc:lower() + end + else + -- by default sort roughly by lhs + sort_fn = function(a, b) + return sort_lhs(a.lhs, b.lhs) + end + end + + table.sort(mappings, sort_fn) -- longest lhs and description local max_lhs = 0 @@ -105,11 +117,14 @@ local function compute() end -- increase desc if lines are shorter than the header - max_desc = math.max(max_desc, #head_lhs + #head_rhs - max_lhs) + max_desc = math.max(max_desc, #head_lhs + #head_rhs1 - max_lhs) -- header, not padded local hl = { { "NvimTreeRootFolder", 0, 0, #head_lhs } } - local lines = { ("%s%s%s"):format(head_lhs, string.rep(" ", max_desc + max_lhs - #head_lhs - #head_rhs + 2), head_rhs) } + local lines = { + head_lhs .. string.rep(" ", max_desc + max_lhs - #head_lhs - #head_rhs1 + 2) .. head_rhs1, + string.rep(" ", max_desc + max_lhs - #head_rhs2 + 2) .. head_rhs2, + } local width = #lines[1] -- mappings, left padded 1 @@ -121,7 +136,7 @@ local function compute() width = math.max(#line, width) -- highlight lhs - table.insert(hl, { "NvimTreeFolderName", i, 1, #l.lhs + 1 }) + table.insert(hl, { "NvimTreeFolderName", i + 1, 1, #l.lhs + 1 }) end return lines, hl, width @@ -175,14 +190,25 @@ local function open() vim.wo[M.winnr].winhl = WIN_HL vim.wo[M.winnr].cursorline = M.config.cursorline - -- quit binding - vim.keymap.set("n", "q", close, { - desc = "nvim-tree: exit help", - buffer = M.bufnr, - noremap = true, - silent = true, - nowait = true, - }) + local function toggle_sort() + M.config.sort_by = (M.config.sort_by == "desc") and "key" or "desc" + open() + end + + local keymaps = { + q = { fn = close, desc = "nvim-tree: exit help" }, + s = { fn = toggle_sort, desc = "nvim-tree: toggle sorting method" }, + } + + for k, v in pairs(keymaps) do + vim.keymap.set("n", k, v.fn, { + desc = v.desc, + buffer = M.bufnr, + noremap = true, + silent = true, + nowait = true, + }) + end -- close window and delete buffer on leave vim.api.nvim_create_autocmd({ "BufLeave", "WinLeave" }, { @@ -202,6 +228,7 @@ end function M.setup(opts) M.config.cursorline = opts.view.cursorline + M.config.sort_by = opts.help.sort_by end return M diff --git a/lua/nvim-tree/utils.lua b/lua/nvim-tree/utils.lua index a0cf9c23741..637117fca62 100644 --- a/lua/nvim-tree/utils.lua +++ b/lua/nvim-tree/utils.lua @@ -280,19 +280,38 @@ function M.move_missing_val(src, src_path, src_pos, dst, dst_path, dst_pos, remo end end +local function round(value) + -- Amount of digits to round to after floating point. + local digits = 2 + local round_number = 10 ^ digits + return math.floor((value * round_number) + 0.5) / round_number +end + function M.format_bytes(bytes) local units = { "B", "K", "M", "G", "T", "P", "E", "Z", "Y" } + local i = "i" -- bInary bytes = math.max(bytes, 0) local pow = math.floor((bytes and math.log(bytes) or 0) / math.log(1024)) pow = math.min(pow, #units) - local value = bytes / (1024 ^ pow) - value = math.floor((value * 10) + 0.5) / 10 + local value = round(bytes / (1024 ^ pow)) pow = pow + 1 - return (units[pow] == nil) and (bytes .. units[1]) or (value .. units[pow] .. "i" .. units[1]) + -- units[pow] == nil when size == 0 B or size >= 1024 YiB + if units[pow] == nil or pow == 1 then + if bytes < 1024 then + return bytes .. " " .. units[1] + else + -- Use the biggest adopted multiple of 2 instead of bytes. + value = round(bytes / (1024 ^ (#units - 1))) + -- For big numbers decimal part is not useful. + return string.format("%.0f %s%s%s", value, units[#units], i, units[1]) + end + else + return value .. " " .. units[pow] .. i .. units[1] + end end function M.key_by(tbl, key)