From e7a7ad7f682821c4c2bfc5d369b57c67d6b10e2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Mandl=C3=ADk?= Date: Fri, 16 May 2025 08:53:39 +0200 Subject: [PATCH 1/4] fix(#2746): fix cursorcolumn and right aligned icons in floating windows --- .../renderer/components/full-name.lua | 40 +++++++++++++++---- lua/nvim-tree/view.lua | 24 +++++++---- 2 files changed, 48 insertions(+), 16 deletions(-) diff --git a/lua/nvim-tree/renderer/components/full-name.lua b/lua/nvim-tree/renderer/components/full-name.lua index 17ed2e31f60..65714dc600b 100644 --- a/lua/nvim-tree/renderer/components/full-name.lua +++ b/lua/nvim-tree/renderer/components/full-name.lua @@ -1,6 +1,7 @@ local M = {} local utils = require("nvim-tree.utils") +local view = require("nvim-tree.view") local function hide(win) if win then @@ -32,7 +33,7 @@ local function effective_win_width() return win_width - win_info[1].textoff end -local function show() +local function show(opts) local line_nr = vim.api.nvim_win_get_cursor(0)[1] if vim.wo.wrap then return @@ -50,6 +51,12 @@ local function show() end local text_width = vim.fn.strdisplaywidth(vim.fn.substitute(line, "[^[:print:]]*$", "", "g")) + + -- also make space for right-aligned icons + local icon_ns_id = vim.api.nvim_get_namespaces()["NvimTreeExtmarks"] + local icon_extmarks = vim.api.nvim_buf_get_extmarks(0, icon_ns_id, { line_nr - 1, 0 }, { line_nr - 1, -1 }, { details = true }) + text_width = text_width + view.extmarks_length(icon_extmarks) + local win_width = effective_win_width() if text_width < win_width then @@ -66,12 +73,26 @@ local function show() style = "minimal", border = "none" }) + vim.wo[M.popup_win].winhl = view.View.winopts.winhl - local ns_id = vim.api.nvim_get_namespaces()["NvimTreeHighlights"] - local extmarks = vim.api.nvim_buf_get_extmarks(0, ns_id, { line_nr - 1, 0 }, { line_nr - 1, -1 }, { details = true }) + local hl_ns_id = vim.api.nvim_get_namespaces()["NvimTreeHighlights"] + local hl_extmarks = vim.api.nvim_buf_get_extmarks(0, hl_ns_id, { line_nr - 1, 0 }, { line_nr - 1, -1 }, { details = true }) vim.api.nvim_win_call(M.popup_win, function() vim.api.nvim_buf_set_lines(0, 0, -1, true, { line }) - for _, extmark in ipairs(extmarks) do + + -- copy also right-aligned icons + for _, extmark in ipairs(icon_extmarks) do + local details = extmark[4] + if details then + vim.api.nvim_buf_set_extmark(0, icon_ns_id, 0, 0, { + virt_text = details.virt_text, + virt_text_pos = details.virt_text_pos, + hl_mode = details.hl_mode, + }) + end + end + + for _, extmark in ipairs(hl_extmarks) do -- nvim 0.10 luadoc is incorrect: vim.api.keyset.get_extmark_item is missing the extmark_id at the start ---@cast extmark table @@ -82,13 +103,16 @@ local function show() if type(details) == "table" then if vim.fn.has("nvim-0.11") == 1 and vim.hl and vim.hl.range then - vim.hl.range(0, ns_id, details.hl_group, { 0, col }, { 0, details.end_col, }, {}) + vim.hl.range(0, hl_ns_id, details.hl_group, { 0, col }, { 0, details.end_col, }, {}) else - vim.api.nvim_buf_add_highlight(0, ns_id, details.hl_group, 0, col, details.end_col) ---@diagnostic disable-line: deprecated + vim.api.nvim_buf_add_highlight(0, hl_ns_id, details.hl_group, 0, col, details.end_col) ---@diagnostic disable-line: deprecated end end end - vim.cmd([[ setlocal nowrap cursorline noswapfile nobuflisted buftype=nofile bufhidden=wipe ]]) + vim.cmd([[ setlocal nowrap noswapfile nobuflisted buftype=nofile bufhidden=wipe ]]) + if opts.view.cursorline then + vim.cmd([[ setlocal cursorline cursorlineopt=both ]]) + end end) end @@ -114,7 +138,7 @@ M.setup = function(opts) pattern = { "NvimTree_*" }, callback = function() if utils.is_nvim_tree_buf(0) then - show() + show(opts) end end, }) diff --git a/lua/nvim-tree/view.lua b/lua/nvim-tree/view.lua index 41b98873ee2..39deaace7ac 100644 --- a/lua/nvim-tree/view.lua +++ b/lua/nvim-tree/view.lua @@ -302,6 +302,21 @@ function M.open(options) log.profile_end(profile) end +---@param extmarks table +---@return number +function M.extmarks_length(extmarks) + local length = 0 + for _, extmark in ipairs(extmarks) do + local details = extmark[4] + if details and details.virt_text then + for _, text in ipairs(details.virt_text) do + length = length + vim.fn.strchars(text[1]) + end + end + end + return length +end + local function grow() local starts_at = M.is_root_folder_visible(require("nvim-tree.core").get_cwd()) and 1 or 0 local lines = vim.api.nvim_buf_get_lines(M.get_bufnr(), starts_at, -1, false) @@ -329,14 +344,7 @@ local function grow() local count = vim.fn.strchars(l) -- also add space for right-aligned icons local extmarks = vim.api.nvim_buf_get_extmarks(M.get_bufnr(), ns_id, { line_nr, 0 }, { line_nr, -1 }, { details = true }) - for _, extmark in ipairs(extmarks) do - local virt_texts = extmark[4].virt_text - if virt_texts then - for _, virt_text in ipairs(virt_texts) do - count = count + vim.fn.strchars(virt_text[1]) - end - end - end + count = count + M.extmarks_length(extmarks) if resizing_width < count then resizing_width = count end From 29c88bbd6f481ddb68935d82edefc433b995e937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Mandl=C3=ADk?= Date: Fri, 16 May 2025 09:36:18 +0200 Subject: [PATCH 2/4] feat: remove right aligned icons from full name float, show float over right aligned icons --- .../renderer/components/full-name.lua | 28 +++++-------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/lua/nvim-tree/renderer/components/full-name.lua b/lua/nvim-tree/renderer/components/full-name.lua index 65714dc600b..c1ddcc8cb86 100644 --- a/lua/nvim-tree/renderer/components/full-name.lua +++ b/lua/nvim-tree/renderer/components/full-name.lua @@ -51,14 +51,13 @@ local function show(opts) end local text_width = vim.fn.strdisplaywidth(vim.fn.substitute(line, "[^[:print:]]*$", "", "g")) + local win_width = effective_win_width() - -- also make space for right-aligned icons + -- windows width reduced by right aligned icons local icon_ns_id = vim.api.nvim_get_namespaces()["NvimTreeExtmarks"] local icon_extmarks = vim.api.nvim_buf_get_extmarks(0, icon_ns_id, { line_nr - 1, 0 }, { line_nr - 1, -1 }, { details = true }) text_width = text_width + view.extmarks_length(icon_extmarks) - local win_width = effective_win_width() - if text_width < win_width then return end @@ -75,24 +74,11 @@ local function show(opts) }) vim.wo[M.popup_win].winhl = view.View.winopts.winhl - local hl_ns_id = vim.api.nvim_get_namespaces()["NvimTreeHighlights"] - local hl_extmarks = vim.api.nvim_buf_get_extmarks(0, hl_ns_id, { line_nr - 1, 0 }, { line_nr - 1, -1 }, { details = true }) + local ns_id = vim.api.nvim_get_namespaces()["NvimTreeHighlights"] + local extmarks = vim.api.nvim_buf_get_extmarks(0, ns_id, { line_nr - 1, 0 }, { line_nr - 1, -1 }, { details = true }) vim.api.nvim_win_call(M.popup_win, function() vim.api.nvim_buf_set_lines(0, 0, -1, true, { line }) - - -- copy also right-aligned icons - for _, extmark in ipairs(icon_extmarks) do - local details = extmark[4] - if details then - vim.api.nvim_buf_set_extmark(0, icon_ns_id, 0, 0, { - virt_text = details.virt_text, - virt_text_pos = details.virt_text_pos, - hl_mode = details.hl_mode, - }) - end - end - - for _, extmark in ipairs(hl_extmarks) do + for _, extmark in ipairs(extmarks) do -- nvim 0.10 luadoc is incorrect: vim.api.keyset.get_extmark_item is missing the extmark_id at the start ---@cast extmark table @@ -103,9 +89,9 @@ local function show(opts) if type(details) == "table" then if vim.fn.has("nvim-0.11") == 1 and vim.hl and vim.hl.range then - vim.hl.range(0, hl_ns_id, details.hl_group, { 0, col }, { 0, details.end_col, }, {}) + vim.hl.range(0, ns_id, details.hl_group, { 0, col }, { 0, details.end_col, }, {}) else - vim.api.nvim_buf_add_highlight(0, hl_ns_id, details.hl_group, 0, col, details.end_col) ---@diagnostic disable-line: deprecated + vim.api.nvim_buf_add_highlight(0, ns_id, details.hl_group, 0, col, details.end_col) ---@diagnostic disable-line: deprecated end end end From 6656d82d63bb2d6f9976e42be3a390449bf06b36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Mandl=C3=ADk?= Date: Sun, 18 May 2025 10:56:12 +0200 Subject: [PATCH 3/4] refactoring: move `extmarks_length` to utils.lua --- lua/nvim-tree/renderer/components/full-name.lua | 2 +- lua/nvim-tree/utils.lua | 15 +++++++++++++++ lua/nvim-tree/view.lua | 17 +---------------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/lua/nvim-tree/renderer/components/full-name.lua b/lua/nvim-tree/renderer/components/full-name.lua index c1ddcc8cb86..96ac19f9e21 100644 --- a/lua/nvim-tree/renderer/components/full-name.lua +++ b/lua/nvim-tree/renderer/components/full-name.lua @@ -56,7 +56,7 @@ local function show(opts) -- windows width reduced by right aligned icons local icon_ns_id = vim.api.nvim_get_namespaces()["NvimTreeExtmarks"] local icon_extmarks = vim.api.nvim_buf_get_extmarks(0, icon_ns_id, { line_nr - 1, 0 }, { line_nr - 1, -1 }, { details = true }) - text_width = text_width + view.extmarks_length(icon_extmarks) + text_width = text_width + utils.extmarks_length(icon_extmarks) if text_width < win_width then return diff --git a/lua/nvim-tree/utils.lua b/lua/nvim-tree/utils.lua index dbf63df329e..0eff04f4ea3 100644 --- a/lua/nvim-tree/utils.lua +++ b/lua/nvim-tree/utils.lua @@ -172,6 +172,21 @@ function M.find_node_line(node) return -1 end +---@param extmarks vim.api.keyset.get_extmark_item[] as per vim.api.nvim_buf_get_extmarks +---@return number +function M.extmarks_length(extmarks) + local length = 0 + for _, extmark in ipairs(extmarks) do + local details = extmark[4] + if details and details.virt_text then + for _, text in ipairs(details.virt_text) do + length = length + vim.fn.strchars(text[1]) + end + end + end + return length +end + -- get the node in the tree state depending on the absolute path of the node -- (grouped or hidden too) ---@param path string diff --git a/lua/nvim-tree/view.lua b/lua/nvim-tree/view.lua index 39deaace7ac..4ce95bfb6f4 100644 --- a/lua/nvim-tree/view.lua +++ b/lua/nvim-tree/view.lua @@ -302,21 +302,6 @@ function M.open(options) log.profile_end(profile) end ----@param extmarks table ----@return number -function M.extmarks_length(extmarks) - local length = 0 - for _, extmark in ipairs(extmarks) do - local details = extmark[4] - if details and details.virt_text then - for _, text in ipairs(details.virt_text) do - length = length + vim.fn.strchars(text[1]) - end - end - end - return length -end - local function grow() local starts_at = M.is_root_folder_visible(require("nvim-tree.core").get_cwd()) and 1 or 0 local lines = vim.api.nvim_buf_get_lines(M.get_bufnr(), starts_at, -1, false) @@ -344,7 +329,7 @@ local function grow() local count = vim.fn.strchars(l) -- also add space for right-aligned icons local extmarks = vim.api.nvim_buf_get_extmarks(M.get_bufnr(), ns_id, { line_nr, 0 }, { line_nr, -1 }, { details = true }) - count = count + M.extmarks_length(extmarks) + count = count + utils.extmarks_length(extmarks) if resizing_width < count then resizing_width = count end From 56ba24bee33cc2d5ea43c98816fecf5ef8a22253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Mandl=C3=ADk?= Date: Sun, 18 May 2025 11:20:38 +0200 Subject: [PATCH 4/4] fix: decrease `win_width` instead of increasing `text_width` when computing condition for full name float to show --- lua/nvim-tree/renderer/components/full-name.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/nvim-tree/renderer/components/full-name.lua b/lua/nvim-tree/renderer/components/full-name.lua index 96ac19f9e21..6c41f3909d9 100644 --- a/lua/nvim-tree/renderer/components/full-name.lua +++ b/lua/nvim-tree/renderer/components/full-name.lua @@ -56,7 +56,7 @@ local function show(opts) -- windows width reduced by right aligned icons local icon_ns_id = vim.api.nvim_get_namespaces()["NvimTreeExtmarks"] local icon_extmarks = vim.api.nvim_buf_get_extmarks(0, icon_ns_id, { line_nr - 1, 0 }, { line_nr - 1, -1 }, { details = true }) - text_width = text_width + utils.extmarks_length(icon_extmarks) + win_width = win_width - utils.extmarks_length(icon_extmarks) if text_width < win_width then return