Skip to content

fix(#2467): remove newline in git paths #2478

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Oct 30, 2023
Merged
25 changes: 19 additions & 6 deletions doc/nvim-tree-lua.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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|
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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.
Expand All @@ -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.

Expand Down
6 changes: 6 additions & 0 deletions lua/nvim-tree.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -667,6 +670,9 @@ local ACCEPTED_STRINGS = {
bookmarks_placement = { "before", "after", "signcolumn" },
},
},
help = {
sort_by = { "key", "desc" },
},
}

local function validate_options(conf)
Expand Down
8 changes: 6 additions & 2 deletions lua/nvim-tree/actions/fs/copy-paste.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
9 changes: 7 additions & 2 deletions lua/nvim-tree/git/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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", "")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is inside the cygpath block.

I was under the impression that you are using PowerShell. Does it see cygpath?

Copy link
Contributor Author

@mj2068 mj2068 Oct 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologize for didn't fully describe my environment before.
Yes, I use PowerShell, but I also have msys2 installed on my Windows 10.
Yes, PowerShell sees "cygpath", because the POSIX compatible environment provided msys2 is based on Cygwin. So Cygwin tools like "cygpath"(exe files you can run directly) are in the Windows path.

Update:
I have to admit, in my case, the reason PowerShell sees "cygpath" is because it's inside X:/msys2/usr/bin, and this bin path is in the Windows path environment variable.
But I actually forgot whether it's added by the official msys2 installer or manually by me.

And, the situation of this issue has changed a bit due to the new commit, which made using "cygpath" a manual option with a default value: false. This bypassed the two vim.fn.system reassigning statements which were the causes of my original issue(#2467), leaving the paths conversion to these two line:

toplevel = toplevel:gsub("/", "\\")
git_dir = git_dir:gsub("/", "\\")

I thinking making "cygpath" a manual option is a good call, and will test it and report back.
Thx, alex. Peace.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PowerShell sees "cygpath" is because it's inside X:/msys2/usr/bin, and this bin path is in the Windows path environment variable.

That explains a lot - a valid use case that we never expected or handled.

I'm prepared for disappointment after your testing, however we will fix this one way or another.

Big favour, if possible: please run has.lua for neovim inside msys2. It would be great to fill out the entirety of OS Feature Flags

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had to do some reading about how msys2 works. Then I did the following inside the msys2 official shell, with nvim 0.9.4 installed from MSYS2 Packages using pacman, following their doc.

Flags: has_list_msys2_mingw.log

I then did quick git integration tests regarding the new cygwin_support manual option, false and true, using the latest commit.

With the "Clean Room" lua file, test folder "project1" git initialized, which contains one untracked file "README.md".
After "Ready!" message, :NvimTreeOpen, select "project1", hit Enter, the results are:

cygwin_support = false(default):
shown error message: [NvimTree] Could not start the fs_event watcher for path \tmp\project1\.git : ENOENT
log: nvim-tree_cygwin_false.log

cygwin_support = true:
no error, but no git tracking.
log: nvim-tree_cygwin_true.log

I think we need to normalize the paths.

Thx, alex.

Attachs the two screenshots, false and true respectively:
Screenshot 2023-10-23 004555

Screenshot 2023-10-23 004741

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for all your diligent testing with this unfamiliar environment. This is quite the difficult issue...

It looks like the cygwin_support = true case is not matching any toplevel and returning nils. It's definitely hitting the use_cygpath branch as the win32 feature flag is set and we are seeing different results.

To confirm:

  • does this PR fix the above?
  • do we need to do more right now or can we merge this?

Copy link
Contributor Author

@mj2068 mj2068 Oct 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • does this PR fix the above?

It did. Now, I'm not so sure, because the new "cypwin_support" option affected it.

  • do we need to do more right now or can we merge this?

I don't think we can merge this. But the issue is getting clearer to me. I'm working on a fix, can I have few days?

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("/", "\\")
Expand Down
59 changes: 43 additions & 16 deletions lua/nvim-tree/help.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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" }, {
Expand All @@ -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
25 changes: 22 additions & 3 deletions lua/nvim-tree/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down