From e7f69c124274b778ca259a56c5ffbb4e432499d7 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sun, 8 Oct 2023 15:25:06 +1100 Subject: [PATCH 01/37] feat(#2415): granular highlight_diagnostics, normalise groups (#2454) --- doc/nvim-tree-lua.txt | 81 +++++++-- lua/nvim-tree.lua | 3 +- lua/nvim-tree/colors.lua | 162 +++++++++++------- lua/nvim-tree/legacy.lua | 9 + .../renderer/components/diagnostics.lua | 55 +++--- 5 files changed, 208 insertions(+), 102 deletions(-) diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index baec6ca8a26..4323746c58e 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -46,6 +46,7 @@ CONTENTS *nvim-tree* 7. Mappings |nvim-tree-mappings| 7.1 Mappings: Default |nvim-tree-mappings-default| 8. Highlight |nvim-tree-highlight| + 8.1 Highlight Overhaul |nvim-tree-highlight-overhaul| 9. Events |nvim-tree-events| 10. Prompts |nvim-tree-prompts| 11. OS Specific Restrictions |nvim-tree-os-specific| @@ -388,7 +389,7 @@ Following is the default configuration. See |nvim-tree-opts| for details. special_files = { "Cargo.toml", "Makefile", "README.md", "readme.md" }, symlink_destination = true, highlight_git = false, - highlight_diagnostics = false, + highlight_diagnostics = "none", highlight_opened_files = "none", highlight_modified = "none", highlight_bookmarks = "none", @@ -837,9 +838,10 @@ Requires |nvim-tree.git.enable| Type: `boolean`, Default: `false` *nvim-tree.renderer.highlight_diagnostics* -Enable highlight for diagnostics using `LspDiagnosticsError*Text` highlight groups. +Enable highlight for diagnostics using `NvimTreeDiagnostic*HL` highlight groups. Requires |nvim-tree.diagnostics.enable| - Type: `boolean`, Default: `false` +Value can be `"none"`, `"icon"`, `"name"` or `"all"`. + Type: `string`, Default: `"none"` *nvim-tree.renderer.highlight_opened_files* Highlight icons and/or names for |bufloaded()| files using the @@ -2336,22 +2338,67 @@ Git Folder Text: > NvimTreeFolderIgnored NvimTreeFileIgnored < Diagnostics Icon: > - NvimTreeLspDiagnosticsError DiagnosticError - NvimTreeLspDiagnosticsWarning DiagnosticWarn - NvimTreeLspDiagnosticsInformation DiagnosticInfo - NvimTreeLspDiagnosticsHint DiagnosticHint + NvimTreeDiagnosticErrorIcon DiagnosticError + NvimTreeDiagnosticWarnIcon DiagnosticWarn + NvimTreeDiagnosticInfoIcon DiagnosticInfo + NvimTreeDiagnosticHintIcon DiagnosticHint +< +Diagnostics File Highlight: > + NvimTreeDiagnosticErrorFileHL DiagnosticUnderlineError + NvimTreeDiagnosticWarnFileHL DiagnosticUnderlineWarn + NvimTreeDiagnosticInfoFileHL DiagnosticUnderlineInfo + NvimTreeDiagnosticHintFileHL DiagnosticUnderlineHint < -Diagnostics File Text: > - NvimTreeLspDiagnosticsErrorText NvimTreeLspDiagnosticsError - NvimTreeLspDiagnosticsWarningText NvimTreeLspDiagnosticsWarning - NvimTreeLspDiagnosticsInfoText NvimTreeLspDiagnosticsInformation - NvimTreeLspDiagnosticsHintText NvimTreeLspDiagnosticsHint +Diagnostics Folder Highlight: > + NvimTreeDiagnosticErrorFolderHL DiagnosticUnderlineError + NvimTreeDiagnosticWarnFolderHL DiagnosticUnderlineWarn + NvimTreeDiagnosticInfoFolderHL DiagnosticUnderlineInfo + NvimTreeDiagnosticHintFolderHL DiagnosticUnderlineHint +< + +============================================================================== + 8.1 HIGHLIGHT OVERHAUL *nvim-tree-highlight-overhaul* + +2023/10/XX revision xxxxx made significant highlighting changes, some breaking: + +- Highlight groups named consistently +- Standard vim highlight groups such |DiagnosticUnderlineError| are now the + defaults. +- All `highlight_xxx` e.g. |nvim-tree.renderer.highlight_git| are granular, + allowing `"none"`, `"icon"`, `"name"` or `"all"` +- `highlight_xxx` has highlight groups for both File and Folder +- `highlight_xxx` is additive instead of overwriting. See + |nvim-tree-opts-renderer| for precedence. + +Legacy style may be applied: > + + :hi link NvimTreeDiagnosticErrorFileHL DiagnosticError + :hi link NvimTreeDiagnosticWarnFileHL DiagnosticWarn + :hi link NvimTreeDiagnosticInfoFileHL DiagnosticInfo + :hi link NvimTreeDiagnosticHintFileHL DiagnosticHint + + :hi link NvimTreeDiagnosticErrorFolderHL DiagnosticError + :hi link NvimTreeDiagnosticWarnFolderHL DiagnosticWarn + :hi link NvimTreeDiagnosticInfoFolderHL DiagnosticInfo + :hi link NvimTreeDiagnosticHintFolderHL DiagnosticHint < -Diagnostics Folder Text: > - NvimTreeLspDiagnosticsErrorFolderText NvimTreeLspDiagnosticsErrorText - NvimTreeLspDiagnosticsWarningFolderText NvimTreeLspDiagnosticsWarningText - NvimTreeLspDiagnosticsInfoFolderText NvimTreeLspDiagnosticsInfoText - NvimTreeLspDiagnosticsHintFolderText NvimTreeLspDiagnosticsHintText +Legacy highlight group are still obeyed when they are defined and the current +highlight group is not, hard linking as follows: > + + NvimTreeLspDiagnosticsError NvimTreeDiagnosticErrorIcon + NvimTreeLspDiagnosticsWarning NvimTreeDiagnosticWarnIcon + NvimTreeLspDiagnosticsInformation NvimTreeDiagnosticInfoIcon + NvimTreeLspDiagnosticsHint NvimTreeDiagnosticHintIcon + + NvimTreeLspDiagnosticsErrorText NvimTreeDiagnosticErrorFileHL + NvimTreeLspDiagnosticsWarningText NvimTreeDiagnosticWarnFileHL + NvimTreeLspDiagnosticsInformationText NvimTreeDiagnosticInfoFileHL + NvimTreeLspDiagnosticsHintText NvimTreeDiagnosticHintFileHL + + NvimTreeLspDiagnosticsErrorFolderText NvimTreeDiagnosticErrorFolderHL + NvimTreeLspDiagnosticsWarningFolderText NvimTreeDiagnosticWarnFolderHL + NvimTreeLspDiagnosticsInformationFolderText NvimTreeDiagnosticInfoFolderHL + NvimTreeLspDiagnosticsHintFolderText NvimTreeDiagnosticHintFolderHL < ============================================================================== 9. EVENTS *nvim-tree-events* diff --git a/lua/nvim-tree.lua b/lua/nvim-tree.lua index 8c0fb2274aa..038e43e2f1b 100644 --- a/lua/nvim-tree.lua +++ b/lua/nvim-tree.lua @@ -387,7 +387,7 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS special_files = { "Cargo.toml", "Makefile", "README.md", "readme.md" }, symlink_destination = true, highlight_git = false, - highlight_diagnostics = false, + highlight_diagnostics = "none", highlight_opened_files = "none", highlight_modified = "none", highlight_bookmarks = "none", @@ -644,6 +644,7 @@ local ACCEPTED_STRINGS = { highlight_opened_files = { "none", "icon", "name", "all" }, highlight_modified = { "none", "icon", "name", "all" }, highlight_bookmarks = { "none", "icon", "name", "all" }, + highlight_diagnostics = { "none", "icon", "name", "all" }, highlight_clipboard = { "none", "icon", "name", "all" }, icons = { git_placement = { "before", "after", "signcolumn" }, diff --git a/lua/nvim-tree/colors.lua b/lua/nvim-tree/colors.lua index 7487c05e0eb..517f4736b53 100644 --- a/lua/nvim-tree/colors.lua +++ b/lua/nvim-tree/colors.lua @@ -1,11 +1,103 @@ local M = {} +-- nvim-tree default highlight group links +local DEFAULT_LINKS = { + -- File Text + NvimTreeFolderName = "Directory", + NvimTreeEmptyFolderName = "Directory", + NvimTreeOpenedFolderName = "Directory", + NvimTreeSymlinkFolderName = "Directory", + + -- Folder Text + NvimTreeOpenedFileIcon = "NvimTreeOpenedFile", + NvimTreeOpenedFolderIcon = "NvimTreeFolderIcon", + NvimTreeClosedFolderIcon = "NvimTreeFolderIcon", + + -- Standard + NvimTreeNormal = "Normal", + NvimTreeNormalFloat = "NormalFloat", + NvimTreeNormalNC = "NvimTreeNormal", + NvimTreeLineNr = "LineNr", + NvimTreeWinSeparator = "WinSeparator", + NvimTreeEndOfBuffer = "EndOfBuffer", + NvimTreePopup = "Normal", + NvimTreeSignColumn = "NvimTreeNormal", + NvimTreeCursorLine = "CursorLine", + NvimTreeCursorColumn = "CursorColumn", + NvimTreeCursorLineNr = "CursorLineNr", + NvimTreeStatusLine = "StatusLine", + NvimTreeStatusLineNC = "StatusLineNC", + + -- Clipboard + NvimTreeCutHL = "SpellBad", + NvimTreeCopiedHL = "SpellRare", + + -- Bookmark Highlight + NvimTreeBookmarkHL = "SpellLocal", + + -- Git Icon + NvimTreeGitIgnored = "Comment", + + -- Git File Text + NvimTreeFileDirty = "NvimTreeGitDirty", + NvimTreeFileStaged = "NvimTreeGitStaged", + NvimTreeFileMerge = "NvimTreeGitMerge", + NvimTreeFileRenamed = "NvimTreeGitRenamed", + NvimTreeFileNew = "NvimTreeGitNew", + NvimTreeFileDeleted = "NvimTreeGitDeleted", + NvimTreeFileIgnored = "NvimTreeGitIgnored", + + -- Git Folder Text + NvimTreeFolderDirty = "NvimTreeFileDirty", + NvimTreeFolderStaged = "NvimTreeFileStaged", + NvimTreeFolderMerge = "NvimTreeFileMerge", + NvimTreeFolderRenamed = "NvimTreeFileRenamed", + NvimTreeFolderNew = "NvimTreeFileNew", + NvimTreeFolderDeleted = "NvimTreeFileDeleted", + NvimTreeFolderIgnored = "NvimTreeFileIgnored", + + -- Diagnostics Icon + NvimTreeDiagnosticErrorIcon = "DiagnosticError", + NvimTreeDiagnosticWarnIcon = "DiagnosticWarn", + NvimTreeDiagnosticInfoIcon = "DiagnosticInfo", + NvimTreeDiagnosticHintIcon = "DiagnosticHint", + + -- Diagnostics File Highlight + NvimTreeDiagnosticErrorFileHL = "DiagnosticUnderlineError", + NvimTreeDiagnosticWarnFileHL = "DiagnosticUnderlineWarn", + NvimTreeDiagnosticInfoFileHL = "DiagnosticUnderlineInfo", + NvimTreeDiagnosticHintFileHL = "DiagnosticUnderlineHint", + + -- Diagnostics Folder Highlight + NvimTreeDiagnosticErrorFolderHL = "DiagnosticUnderlineError", + NvimTreeDiagnosticWarnFolderHL = "DiagnosticUnderlineWarn", + NvimTreeDiagnosticInfoFolderHL = "DiagnosticUnderlineInfo", + NvimTreeDiagnosticHintFolderHL = "DiagnosticUnderlineHint", +} + +-- nvim-tree highlight groups to legacy +local LEGACY_LINKS = { + NvimTreeDiagnosticErrorIcon = "NvimTreeLspDiagnosticsError", + NvimTreeDiagnosticWarnIcon = "NvimTreeLspDiagnosticsWarning", + NvimTreeDiagnosticInfoIcon = "NvimTreeLspDiagnosticsInformation", + NvimTreeDiagnosticHintIcon = "NvimTreeLspDiagnosticsHint", + NvimTreeDiagnosticErrorFileHL = "NvimTreeLspDiagnosticsErrorText", + NvimTreeDiagnosticWarnFileHL = "NvimTreeLspDiagnosticsWarningText", + NvimTreeDiagnosticInfoFileHL = "NvimTreeLspDiagnosticsInformationText", + NvimTreeDiagnosticHintFileHL = "NvimTreeLspDiagnosticsHintText", + NvimTreeDiagnosticErrorFolderHL = "NvimTreeLspDiagnosticsErrorFolderText", + NvimTreeDiagnosticWarnFolderHL = "NvimTreeLspDiagnosticsWarningFolderText", + NvimTreeDiagnosticInfoFolderHL = "NvimTreeLspDiagnosticsInformationFolderText", + NvimTreeDiagnosticHintFolderHL = "NvimTreeLspDiagnosticsHintFolderText", +} + local function get_color_from_hl(hl_name, fallback) local id = vim.api.nvim_get_hl_id_by_name(hl_name) if not id then return fallback end + -- TODO this is unreachable as nvim_get_hl_id_by_name returns a new ID if not present local foreground = vim.fn.synIDattr(vim.fn.synIDtrans(id), "fg") if not foreground or foreground == "" then return fallback @@ -57,61 +149,6 @@ local function get_hl_groups() } end -local function get_links() - return { - FolderName = "Directory", - EmptyFolderName = "Directory", - OpenedFolderName = "Directory", - SymlinkFolderName = "Directory", - OpenedFolderIcon = "NvimTreeFolderIcon", - ClosedFolderIcon = "NvimTreeFolderIcon", - OpenedFileIcon = "NvimTreeOpenedFile", - Normal = "Normal", - NormalFloat = "NormalFloat", - NormalNC = "NvimTreeNormal", - EndOfBuffer = "EndOfBuffer", - CursorLineNr = "CursorLineNr", - LineNr = "LineNr", - CursorLine = "CursorLine", - WinSeparator = "WinSeparator", - CursorColumn = "CursorColumn", - FileDirty = "NvimTreeGitDirty", - FileNew = "NvimTreeGitNew", - FileRenamed = "NvimTreeGitRenamed", - FileMerge = "NvimTreeGitMerge", - FileStaged = "NvimTreeGitStaged", - FileDeleted = "NvimTreeGitDeleted", - FileIgnored = "NvimTreeGitIgnored", - FolderDirty = "NvimTreeFileDirty", - FolderNew = "NvimTreeFileNew", - FolderRenamed = "NvimTreeFileRenamed", - FolderMerge = "NvimTreeFileMerge", - FolderStaged = "NvimTreeFileStaged", - FolderDeleted = "NvimTreeFileDeleted", - FolderIgnored = "NvimTreeFileIgnored", - LspDiagnosticsError = "DiagnosticError", - LspDiagnosticsWarning = "DiagnosticWarn", - LspDiagnosticsInformation = "DiagnosticInfo", - LspDiagnosticsHint = "DiagnosticHint", - LspDiagnosticsErrorText = "NvimTreeLspDiagnosticsError", - LspDiagnosticsWarningText = "NvimTreeLspDiagnosticsWarning", - LspDiagnosticsInformationText = "NvimTreeLspDiagnosticsInformation", - LspDiagnosticsHintText = "NvimTreeLspDiagnosticsHintFile", - LspDiagnosticsErrorFolderText = "NvimTreeLspDiagnosticsErrorText", - LspDiagnosticsWarningFolderText = "NvimTreeLspDiagnosticsWarningText", - LspDiagnosticsInformationFolderText = "NvimTreeLspDiagnosticsInformationText", - LspDiagnosticsHintFolderText = "NvimTreeLspDiagnosticsHintFileText", - Popup = "Normal", - GitIgnored = "Comment", - StatusLine = "StatusLine", - StatusLineNC = "StatusLineNC", - SignColumn = "NvimTreeNormal", - CutHL = "SpellBad", - CopiedHL = "SpellRare", - BookmarkHL = "SpellLocal", - } -end - function M.setup() local highlight_groups = get_hl_groups() for k, d in pairs(highlight_groups) do @@ -121,9 +158,18 @@ function M.setup() vim.api.nvim_command("hi def NvimTree" .. k .. gui .. fg .. bg) end - local links = get_links() - for k, d in pairs(links) do - vim.api.nvim_command("hi def link NvimTree" .. k .. " " .. d) + -- hard link override when legacy only is present + for from, to in pairs(LEGACY_LINKS) do + local hl_from = vim.api.nvim_get_hl(0, { name = from }) + local hl_to = vim.api.nvim_get_hl(0, { name = to }) + if vim.tbl_isempty(hl_from) and not vim.tbl_isempty(hl_to) then + vim.api.nvim_command("hi link " .. from .. " " .. to) + end + end + + -- default links + for from, to in pairs(DEFAULT_LINKS) do + vim.api.nvim_command("hi def link " .. from .. " " .. to) end end diff --git a/lua/nvim-tree/legacy.lua b/lua/nvim-tree/legacy.lua index 6f8c60c7317..2d6dd9f9582 100644 --- a/lua/nvim-tree/legacy.lua +++ b/lua/nvim-tree/legacy.lua @@ -41,6 +41,15 @@ local function refactored(opts) -- 2023/08/26 utils.move_missing_val(opts, "renderer.icons", "webdev_colors", opts, "renderer.icons.web_devicons.file", "color", true) + + -- 2023/10/08 + if type(opts.renderer) == "table" and type(opts.renderer.highlight_diagnostics) == "boolean" then + if opts.renderer.highlight_diagnostics then + opts.renderer.highlight_diagnostics = "name" + else + opts.renderer.highlight_diagnostics = "none" + end + end end local function deprecated(opts) diff --git a/lua/nvim-tree/renderer/components/diagnostics.lua b/lua/nvim-tree/renderer/components/diagnostics.lua index 1fa864deac9..095757d0848 100644 --- a/lua/nvim-tree/renderer/components/diagnostics.lua +++ b/lua/nvim-tree/renderer/components/diagnostics.lua @@ -2,10 +2,15 @@ local HL_POSITION = require("nvim-tree.enum").HL_POSITION local diagnostics = require "nvim-tree.diagnostics" local M = { - HS_FILE = {}, - HS_FOLDER = {}, - ICON = {}, - hl_pos = HL_POSITION.none, + -- highlight strings for the icons + HS_ICON = {}, + + -- highlight groups for HL + HG_FILE = {}, + HG_FOLDER = {}, + + -- position for HL + HL_POS = HL_POSITION.none, } ---Diagnostics text highlight group when highlight_diagnostics. @@ -13,7 +18,7 @@ local M = { ---@return HL_POSITION position none when no status ---@return string|nil group only when status function M.get_highlight(node) - if not node or M.hl_pos == HL_POSITION.none then + if not node or M.HL_POS == HL_POSITION.none then return HL_POSITION.none, nil end @@ -26,7 +31,7 @@ function M.get_highlight(node) end if group then - return M.hl_pos, group + return M.HL_POS, group else return HL_POSITION.none, nil end @@ -49,40 +54,38 @@ function M.setup(opts) } if opts.diagnostics.enable and opts.renderer.highlight_diagnostics then - -- TODO add a HL_POSITION - -- M.hl_pos = HL_POSITION[opts.renderer.highlight_diagnostics] - M.hl_pos = HL_POSITION.name + M.HL_POS = HL_POSITION[opts.renderer.highlight_diagnostics] end - M.HS_FILE[vim.diagnostic.severity.ERROR] = "NvimTreeLspDiagnosticsErrorText" - M.HS_FILE[vim.diagnostic.severity.WARN] = "NvimTreeLspDiagnosticsWarningText" - M.HS_FILE[vim.diagnostic.severity.INFO] = "NvimTreeLspDiagnosticsInfoText" - M.HS_FILE[vim.diagnostic.severity.HINT] = "NvimTreeLspDiagnosticsHintText" + M.HG_FILE[vim.diagnostic.severity.ERROR] = "NvimTreeDiagnosticErrorFileHL" + M.HG_FILE[vim.diagnostic.severity.WARN] = "NvimTreeDiagnosticWarningFileHL" + M.HG_FILE[vim.diagnostic.severity.INFO] = "NvimTreeDiagnosticInfoFileHL" + M.HG_FILE[vim.diagnostic.severity.HINT] = "NvimTreeDiagnosticHintFileHL" - M.HS_FOLDER[vim.diagnostic.severity.ERROR] = "NvimTreeLspDiagnosticsErrorFolderText" - M.HS_FOLDER[vim.diagnostic.severity.WARN] = "NvimTreeLspDiagnosticsWarningFolderText" - M.HS_FOLDER[vim.diagnostic.severity.INFO] = "NvimTreeLspDiagnosticsInfoFolderText" - M.HS_FOLDER[vim.diagnostic.severity.HINT] = "NvimTreeLspDiagnosticsHintFolderText" + M.HG_FOLDER[vim.diagnostic.severity.ERROR] = "NvimTreeDiagnosticErrorFolderHL" + M.HG_FOLDER[vim.diagnostic.severity.WARN] = "NvimTreeDiagnosticWarningFolderHL" + M.HG_FOLDER[vim.diagnostic.severity.INFO] = "NvimTreeDiagnosticInfoFolderHL" + M.HG_FOLDER[vim.diagnostic.severity.HINT] = "NvimTreeDiagnosticHintFolderHL" - M.ICON[vim.diagnostic.severity.ERROR] = { + M.HS_ICON[vim.diagnostic.severity.ERROR] = { str = M.config.diagnostics.icons.error, - hl = { "NvimTreeLspDiagnosticsError" }, + hl = { "NvimTreeDiagnosticErrorIcon" }, } - M.ICON[vim.diagnostic.severity.WARN] = { + M.HS_ICON[vim.diagnostic.severity.WARN] = { str = M.config.diagnostics.icons.warning, - hl = { "NvimTreeLspDiagnosticsWarning" }, + hl = { "NvimTreeDiagnosticWarningIcon" }, } - M.ICON[vim.diagnostic.severity.INFO] = { + M.HS_ICON[vim.diagnostic.severity.INFO] = { str = M.config.diagnostics.icons.info, - hl = { "NvimTreeLspDiagnosticsInformation" }, + hl = { "NvimTreeDiagnosticInfoIcon" }, } - M.ICON[vim.diagnostic.severity.HINT] = { + M.HS_ICON[vim.diagnostic.severity.HINT] = { str = M.config.diagnostics.icons.hint, - hl = { "NvimTreeLspDiagnosticsHint" }, + hl = { "NvimTreeDiagnosticHintIcon" }, } - for _, i in ipairs(M.ICON) do + for _, i in ipairs(M.HS_ICON) do vim.fn.sign_define(i.hl[1], { text = i.str, texthl = i.hl[1] }) end end From e389c5574a65945e2541834eae939166dda6e8fe Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sun, 15 Oct 2023 17:34:55 +1100 Subject: [PATCH 02/37] chore: normalise colours and enable cterm (#2471) --- README.md | 2 +- doc/nvim-tree-lua.txt | 120 +++++++++++++++++------------------ lua/nvim-tree/colors.lua | 131 ++++++++++++++++----------------------- 3 files changed, 116 insertions(+), 137 deletions(-) diff --git a/README.md b/README.md index 87a16d63860..8ecc7632f77 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ Setup the plugin in your `init.lua` vim.g.loaded_netrw = 1 vim.g.loaded_netrwPlugin = 1 --- set termguicolors to enable highlight groups +-- optionally enable 24-bit colour vim.opt.termguicolors = true -- empty setup using defaults diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index 4323746c58e..c046fc0c68e 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -114,7 +114,7 @@ Setup the plugin in your `init.lua` > vim.g.loaded_netrw = 1 vim.g.loaded_netrwPlugin = 1 - -- set termguicolors to enable highlight groups + -- optionally enable 24-bit colour vim.opt.termguicolors = true -- empty setup using defaults @@ -909,7 +909,7 @@ Icon sign column precedence: Type: `boolean`, Default: `true` *nvim-tree.renderer.icons.web_devicons.file.color* - Use icon colors for files. + Use icon colors for files. Overrides highlight groups. Type: `boolean`, Default: `true` *nvim-tree.renderer.icons.web_devicons.folder* @@ -921,7 +921,7 @@ Icon sign column precedence: Type: `boolean`, Default: `false` *nvim-tree.renderer.icons.web_devicons.folder.color* - Use icon colors for folders. + Use icon colors for folders. Overrides highlight groups. Type: `boolean`, Default: `true` *nvim-tree.renderer.icons.git_placement* @@ -2239,42 +2239,13 @@ groups. Example |:highlight| > :hi NvimTreeSymlink guifg=blue gui=bold,underline < -You should have 'termguicolors' enabled, otherwise, colors will not be -applied. +It is recommended to enable 'termguicolors' for the more pleasant 24-bit colours. To view the active highlight groups run `:so $VIMRUNTIME/syntax/hitest.vim` as per |:highlight| -Default linked group follows name. +Default linked group or definition follows name. -File Text: > - NvimTreeSymlink - NvimTreeExecFile - NvimTreeOpenedFile - NvimTreeModifiedFile - NvimTreeSpecialFile - NvimTreeImageFile -< -Folder Text: > - NvimTreeFolderName Directory - NvimTreeEmptyFolderName Directory - NvimTreeOpenedFolderName Directory - NvimTreeSymlinkFolderName Directory - NvimTreeRootFolder -< -Icon: > - NvimTreeFileIcon - NvimTreeOpenedFileIcon NvimTreeOpenedFile - NvimTreeSymlinkIcon - NvimTreeFolderIcon - NvimTreeOpenedFolderIcon NvimTreeFolderIcon - NvimTreeClosedFolderIcon NvimTreeFolderIcon - NvimTreeFolderArrowClosed NvimTreeIndentMarker - NvimTreeFolderArrowOpen NvimTreeIndentMarker -< -Indent: > - NvimTreeIndentMarker -< Standard: > NvimTreeNormal Normal NvimTreeNormalFloat NormalFloat @@ -2293,49 +2264,77 @@ Standard: > NvimTreeStatusLine StatusLine NvimTreeStatusLineNC StatusLineNC < +File Text: > + NvimTreeExecFile Constant + NvimTreeImageFile PreProc + NvimTreeModifiedFile Constant + NvimTreeOpenedFile Constant + NvimTreeSpecialFile PreProc + NvimTreeSymlink Statement +< +Folder Text: > + NvimTreeRootFolder PreProc + NvimTreeFolderName Directory + NvimTreeEmptyFolderName Directory + NvimTreeOpenedFolderName Directory + NvimTreeSymlinkFolderName Directory +< +Icon: > + NvimTreeFolderIcon "guifg=#8094b4 ctermfg=Blue" + NvimTreeFileIcon NvimTreeNormal + NvimTreeSymlinkIcon NvimTreeNormal + NvimTreeOpenedFileIcon NvimTreeOpenedFile + NvimTreeOpenedFolderIcon NvimTreeFolderIcon + NvimTreeClosedFolderIcon NvimTreeFolderIcon + NvimTreeFolderArrowClosed NvimTreeIndentMarker + NvimTreeFolderArrowOpen NvimTreeIndentMarker +< +Indent: > + NvimTreeIndentMarker NvimTreeFileIcon +< Clipboard: > NvimTreeCopiedHL SpellRare NvimTreeCutHL SpellBad < Bookmark Icon: > - NvimTreeBookmark + NvimTreeBookmark Constant < Bookmark Highlight: > NvimTreeBookmarkHL SpellLocal < Picker: > - NvimTreeWindowPicker + NvimTreeWindowPicker "guifg=#ededed guibg=#4493c8 gui=bold ctermfg=White ctermbg=Cyan" < Live Filter: > - NvimTreeLiveFilterPrefix - NvimTreeLiveFilterValue + NvimTreeLiveFilterPrefix PreProc + NvimTreeLiveFilterValue ModeMsg < Git Icon: > - NvimTreeGitDirty - NvimTreeGitStaged - NvimTreeGitMerge - NvimTreeGitRenamed - NvimTreeGitNew - NvimTreeGitDeleted - NvimTreeGitIgnored Comment + NvimTreeGitDeleted Statement + NvimTreeGitDirty Statement + NvimTreeGitIgnored Comment + NvimTreeGitMerge Constant + NvimTreeGitNew PreProc + NvimTreeGitRenamed PreProc + NvimTreeGitStaged Constant < Git File Text: > - NvimTreeFileDirty NvimTreeGitDirty - NvimTreeFileStaged NvimTreeGitStaged - NvimTreeFileMerge NvimTreeGitMerge - NvimTreeFileRenamed NvimTreeGitRenamed - NvimTreeFileNew NvimTreeGitNew - NvimTreeFileDeleted NvimTreeGitDeleted - NvimTreeFileIgnored NvimTreeGitIgnored + NvimTreeFileDirty NvimTreeGitDirty + NvimTreeFileStaged NvimTreeGitStaged + NvimTreeFileMerge NvimTreeGitMerge + NvimTreeFileRenamed NvimTreeGitRenamed + NvimTreeFileNew NvimTreeGitNew + NvimTreeFileDeleted NvimTreeGitDeleted + NvimTreeFileIgnored NvimTreeGitIgnored < Git Folder Text: > - NvimTreeFolderDirty NvimTreeFileDirty - NvimTreeFolderStaged NvimTreeFileStaged - NvimTreeFolderMerge NvimTreeFileMerge - NvimTreeFolderRenamed NvimTreeFileRenamed - NvimTreeFolderNew NvimTreeFileNew - NvimTreeFolderDeleted NvimTreeFileDeleted - NvimTreeFolderIgnored NvimTreeFileIgnored + NvimTreeFolderDirty NvimTreeFileDirty + NvimTreeFolderStaged NvimTreeFileStaged + NvimTreeFolderMerge NvimTreeFileMerge + NvimTreeFolderRenamed NvimTreeFileRenamed + NvimTreeFolderNew NvimTreeFileNew + NvimTreeFolderDeleted NvimTreeFileDeleted + NvimTreeFolderIgnored NvimTreeFileIgnored < Diagnostics Icon: > NvimTreeDiagnosticErrorIcon DiagnosticError @@ -2361,9 +2360,10 @@ Diagnostics Folder Highlight: > 2023/10/XX revision xxxxx made significant highlighting changes, some breaking: -- Highlight groups named consistently +- Full cterm support. - Standard vim highlight groups such |DiagnosticUnderlineError| are now the defaults. +- Highlight groups named consistently. - All `highlight_xxx` e.g. |nvim-tree.renderer.highlight_git| are granular, allowing `"none"`, `"icon"`, `"name"` or `"all"` - `highlight_xxx` has highlight groups for both File and Folder diff --git a/lua/nvim-tree/colors.lua b/lua/nvim-tree/colors.lua index 517f4736b53..7a6d6983eed 100644 --- a/lua/nvim-tree/colors.lua +++ b/lua/nvim-tree/colors.lua @@ -1,42 +1,82 @@ local M = {} --- nvim-tree default highlight group links -local DEFAULT_LINKS = { - -- File Text - NvimTreeFolderName = "Directory", - NvimTreeEmptyFolderName = "Directory", - NvimTreeOpenedFolderName = "Directory", - NvimTreeSymlinkFolderName = "Directory", +-- directly defined groups, please keep these to an absolute minimum +local DEFAULT_DEFS = { - -- Folder Text - NvimTreeOpenedFileIcon = "NvimTreeOpenedFile", - NvimTreeOpenedFolderIcon = "NvimTreeFolderIcon", - NvimTreeClosedFolderIcon = "NvimTreeFolderIcon", + NvimTreeFolderIcon = "guifg=#8094b4 ctermfg=Blue", + NvimTreeWindowPicker = "guifg=#ededed guibg=#4493c8 gui=bold ctermfg=White ctermbg=Cyan", +} + +-- nvim-tree default highlight group links, please attempt to keep in order with help +local DEFAULT_LINKS = { -- Standard NvimTreeNormal = "Normal", NvimTreeNormalFloat = "NormalFloat", NvimTreeNormalNC = "NvimTreeNormal", + NvimTreeLineNr = "LineNr", NvimTreeWinSeparator = "WinSeparator", NvimTreeEndOfBuffer = "EndOfBuffer", NvimTreePopup = "Normal", NvimTreeSignColumn = "NvimTreeNormal", - NvimTreeCursorLine = "CursorLine", + NvimTreeCursorColumn = "CursorColumn", + NvimTreeCursorLine = "CursorLine", NvimTreeCursorLineNr = "CursorLineNr", + NvimTreeStatusLine = "StatusLine", NvimTreeStatusLineNC = "StatusLineNC", + -- File Text + NvimTreeExecFile = "Constant", + NvimTreeImageFile = "PreProc", + NvimTreeModifiedFile = "Constant", + NvimTreeOpenedFile = "Constant", + NvimTreeSpecialFile = "PreProc", + NvimTreeSymlink = "Statement", + + -- Folder Text + NvimTreeRootFolder = "PreProc", + NvimTreeFolderName = "Directory", + NvimTreeEmptyFolderName = "Directory", + NvimTreeOpenedFolderName = "Directory", + NvimTreeSymlinkFolderName = "Directory", + + -- Icon + NvimTreeFileIcon = "NvimTreeNormal", + NvimTreeSymlinkIcon = "NvimTreeNormal", + NvimTreeOpenedFileIcon = "NvimTreeOpenedFile", + NvimTreeOpenedFolderIcon = "NvimTreeFolderIcon", + NvimTreeClosedFolderIcon = "NvimTreeFolderIcon", + NvimTreeFolderArrowClosed = "NvimTreeIndentMarker", + NvimTreeFolderArrowOpen = "NvimTreeIndentMarker", + + -- Indent + NvimTreeIndentMarker = "NvimTreeFileIcon", + -- Clipboard NvimTreeCutHL = "SpellBad", NvimTreeCopiedHL = "SpellRare", + -- Bookmark Icon + NvimTreeBookmark = "Constant", + -- Bookmark Highlight NvimTreeBookmarkHL = "SpellLocal", + -- LiveFilter + NvimTreeLiveFilterPrefix = "PreProc", + NvimTreeLiveFilterValue = "ModeMsg", + -- Git Icon + NvimTreeGitDeleted = "Statement", + NvimTreeGitDirty = "Statement", NvimTreeGitIgnored = "Comment", + NvimTreeGitMerge = "Constant", + NvimTreeGitNew = "PreProc", + NvimTreeGitRenamed = "PreProc", + NvimTreeGitStaged = "Constant", -- Git File Text NvimTreeFileDirty = "NvimTreeGitDirty", @@ -91,71 +131,10 @@ local LEGACY_LINKS = { NvimTreeDiagnosticHintFolderHL = "NvimTreeLspDiagnosticsHintFolderText", } -local function get_color_from_hl(hl_name, fallback) - local id = vim.api.nvim_get_hl_id_by_name(hl_name) - if not id then - return fallback - end - - -- TODO this is unreachable as nvim_get_hl_id_by_name returns a new ID if not present - local foreground = vim.fn.synIDattr(vim.fn.synIDtrans(id), "fg") - if not foreground or foreground == "" then - return fallback - end - - return foreground -end - -local function get_colors() - return { - red = vim.g.terminal_color_1 or get_color_from_hl("Keyword", "Red"), - green = vim.g.terminal_color_2 or get_color_from_hl("Character", "Green"), - yellow = vim.g.terminal_color_3 or get_color_from_hl("PreProc", "Yellow"), - blue = vim.g.terminal_color_4 or get_color_from_hl("Include", "Blue"), - purple = vim.g.terminal_color_5 or get_color_from_hl("Define", "Purple"), - cyan = vim.g.terminal_color_6 or get_color_from_hl("Conditional", "Cyan"), - dark_red = vim.g.terminal_color_9 or get_color_from_hl("Keyword", "DarkRed"), - orange = vim.g.terminal_color_11 or get_color_from_hl("Number", "Orange"), - } -end - -local function get_hl_groups() - local colors = get_colors() - - return { - IndentMarker = { fg = "#8094b4" }, - Symlink = { gui = "bold", fg = colors.cyan }, - FolderIcon = { fg = "#8094b4" }, - RootFolder = { fg = colors.purple }, - - ExecFile = { gui = "bold", fg = colors.green }, - SpecialFile = { gui = "bold,underline", fg = colors.yellow }, - ImageFile = { gui = "bold", fg = colors.purple }, - OpenedFile = { gui = "bold", fg = colors.green }, - ModifiedFile = { fg = colors.green }, - - GitDirty = { fg = colors.dark_red }, - GitDeleted = { fg = colors.dark_red }, - GitStaged = { fg = colors.green }, - GitMerge = { fg = colors.orange }, - GitRenamed = { fg = colors.purple }, - GitNew = { fg = colors.yellow }, - - WindowPicker = { gui = "bold", fg = "#ededed", bg = "#4493c8" }, - LiveFilterPrefix = { gui = "bold", fg = colors.purple }, - LiveFilterValue = { gui = "bold", fg = "#fff" }, - - Bookmark = { fg = colors.green }, - } -end - function M.setup() - local highlight_groups = get_hl_groups() - for k, d in pairs(highlight_groups) do - local gui = d.gui and " gui=" .. d.gui or "" - local fg = d.fg and " guifg=" .. d.fg or "" - local bg = d.bg and " guibg=" .. d.bg or "" - vim.api.nvim_command("hi def NvimTree" .. k .. gui .. fg .. bg) + -- non-linked + for k, d in pairs(DEFAULT_DEFS) do + vim.api.nvim_command("hi " .. k .. " " .. d) end -- hard link override when legacy only is present From edbda99fdfd93786e64bae16395a5734a9f112a9 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sat, 21 Oct 2023 16:21:55 +1100 Subject: [PATCH 03/37] feat(#2415): granular highlight_git, normalise git groups (#2487) * docs: update CONTRIBUTING.md (#2485) * feat(#2415): granular highlight_git, normalise git groups --- doc/nvim-tree-lua.txt | 90 +++++++----- lua/nvim-tree.lua | 2 +- lua/nvim-tree/colors.lua | 76 ++++++---- lua/nvim-tree/legacy.lua | 11 +- lua/nvim-tree/renderer/builder.lua | 7 +- .../renderer/components/bookmarks.lua | 2 +- .../renderer/components/diagnostics.lua | 2 +- lua/nvim-tree/renderer/components/git.lua | 139 +++++++++--------- 8 files changed, 189 insertions(+), 140 deletions(-) diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index c046fc0c68e..1841fb6439f 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -388,7 +388,7 @@ Following is the default configuration. See |nvim-tree-opts| for details. indent_width = 2, special_files = { "Cargo.toml", "Makefile", "README.md", "readme.md" }, symlink_destination = true, - highlight_git = false, + highlight_git = "none", highlight_diagnostics = "none", highlight_opened_files = "none", highlight_modified = "none", @@ -833,12 +833,13 @@ Whether to show the destination of the symlink. Type: `boolean`, Default: `true` *nvim-tree.renderer.highlight_git* -Enable highlight for git attributes using `NvimTreeGit*` highlight groups. +Enable highlight for git attributes using `NvimTreeGit*HL` highlight groups. Requires |nvim-tree.git.enable| - Type: `boolean`, Default: `false` +Value can be `"none"`, `"icon"`, `"name"` or `"all"`. + Type: `string`, Default: `"none"` *nvim-tree.renderer.highlight_diagnostics* -Enable highlight for diagnostics using `NvimTreeDiagnostic*HL` highlight groups. +Enable highlight for diagnostics using `NvimTreeDiagnostic*HL` highlight groups. Requires |nvim-tree.diagnostics.enable| Value can be `"none"`, `"icon"`, `"name"` or `"all"`. Type: `string`, Default: `"none"` @@ -2280,7 +2281,7 @@ Folder Text: > NvimTreeSymlinkFolderName Directory < Icon: > - NvimTreeFolderIcon "guifg=#8094b4 ctermfg=Blue" + NvimTreeFolderIcon guifg=#8094b4 ctermfg=Blue NvimTreeFileIcon NvimTreeNormal NvimTreeSymlinkIcon NvimTreeNormal NvimTreeOpenedFileIcon NvimTreeOpenedFile @@ -2303,38 +2304,38 @@ Bookmark Highlight: > NvimTreeBookmarkHL SpellLocal < Picker: > - NvimTreeWindowPicker "guifg=#ededed guibg=#4493c8 gui=bold ctermfg=White ctermbg=Cyan" + NvimTreeWindowPicker guifg=#ededed guibg=#4493c8 gui=bold ctermfg=White ctermbg=Cyan < Live Filter: > NvimTreeLiveFilterPrefix PreProc NvimTreeLiveFilterValue ModeMsg < Git Icon: > - NvimTreeGitDeleted Statement - NvimTreeGitDirty Statement - NvimTreeGitIgnored Comment - NvimTreeGitMerge Constant - NvimTreeGitNew PreProc - NvimTreeGitRenamed PreProc - NvimTreeGitStaged Constant + NvimTreeGitDeletedIcon Statement + NvimTreeGitDirtyIcon Statement + NvimTreeGitIgnoredIcon Comment + NvimTreeGitMergeIcon Constant + NvimTreeGitNewIcon PreProc + NvimTreeGitRenamedIcon PreProc + NvimTreeGitStagedIcon Constant < Git File Text: > - NvimTreeFileDirty NvimTreeGitDirty - NvimTreeFileStaged NvimTreeGitStaged - NvimTreeFileMerge NvimTreeGitMerge - NvimTreeFileRenamed NvimTreeGitRenamed - NvimTreeFileNew NvimTreeGitNew - NvimTreeFileDeleted NvimTreeGitDeleted - NvimTreeFileIgnored NvimTreeGitIgnored + NvimTreeGitFileDeletedHL NvimTreeGitDeletedIcon + NvimTreeGitFileDirtyHL NvimTreeGitDirtyIcon + NvimTreeGitFileIgnoredHL NvimTreeGitIgnoredIcon + NvimTreeGitFileMergeHL NvimTreeGitMergeIcon + NvimTreeGitFileNewHL NvimTreeGitNewIcon + NvimTreeGitFileRenamedHL NvimTreeGitRenamedIcon + NvimTreeGitFileStagedHL NvimTreeGitStagedIcon < Git Folder Text: > - NvimTreeFolderDirty NvimTreeFileDirty - NvimTreeFolderStaged NvimTreeFileStaged - NvimTreeFolderMerge NvimTreeFileMerge - NvimTreeFolderRenamed NvimTreeFileRenamed - NvimTreeFolderNew NvimTreeFileNew - NvimTreeFolderDeleted NvimTreeFileDeleted - NvimTreeFolderIgnored NvimTreeFileIgnored + NvimTreeGitFolderDeletedHL NvimTreeGitFileDeletedHL + NvimTreeGitFolderDirtyHL NvimTreeGitFileDirtyHL + NvimTreeGitFolderIgnoredHL NvimTreeGitFileIgnoredHL + NvimTreeGitFolderMergeHL NvimTreeGitFileMergeHL + NvimTreeGitFolderNewHL NvimTreeGitFileNewHL + NvimTreeGitFolderRenamedHL NvimTreeGitFileRenamedHL + NvimTreeGitFolderStagedHL NvimTreeGitFileStagedHL < Diagnostics Icon: > NvimTreeDiagnosticErrorIcon DiagnosticError @@ -2349,12 +2350,11 @@ Diagnostics File Highlight: > NvimTreeDiagnosticHintFileHL DiagnosticUnderlineHint < Diagnostics Folder Highlight: > - NvimTreeDiagnosticErrorFolderHL DiagnosticUnderlineError - NvimTreeDiagnosticWarnFolderHL DiagnosticUnderlineWarn - NvimTreeDiagnosticInfoFolderHL DiagnosticUnderlineInfo - NvimTreeDiagnosticHintFolderHL DiagnosticUnderlineHint + NvimTreeDiagnosticErrorFolderHL NvimTreeDiagnosticErrorFileHL + NvimTreeDiagnosticWarnFolderHL NvimTreeDiagnosticWarnFileHL + NvimTreeDiagnosticInfoFolderHL NvimTreeDiagnosticInfoFileHL + NvimTreeDiagnosticHintFolderHL NvimTreeDiagnosticHintFileHL < - ============================================================================== 8.1 HIGHLIGHT OVERHAUL *nvim-tree-highlight-overhaul* @@ -2370,7 +2370,7 @@ Diagnostics Folder Highlight: > - `highlight_xxx` is additive instead of overwriting. See |nvim-tree-opts-renderer| for precedence. -Legacy style may be applied: > +Legacy diagnostic HL style may be applied: > :hi link NvimTreeDiagnosticErrorFileHL DiagnosticError :hi link NvimTreeDiagnosticWarnFileHL DiagnosticWarn @@ -2385,6 +2385,30 @@ Legacy style may be applied: > Legacy highlight group are still obeyed when they are defined and the current highlight group is not, hard linking as follows: > + NvimTreeGitDeletedIcon NvimTreeGitDeleted + NvimTreeGitDirtyIcon NvimTreeGitDirty + NvimTreeGitIgnoredIcon NvimTreeGitIgnored + NvimTreeGitMergeIcon NvimTreeGitMerge + NvimTreeGitNewIcon NvimTreeGitNew + NvimTreeGitRenamedIcon NvimTreeGitRenamed + NvimTreeGitStagedIcon NvimTreeGitStaged + + NvimTreeGitFileDeletedHL NvimTreeFileDeleted + NvimTreeGitFileDirtyHL NvimTreeFileDirty + NvimTreeGitFileIgnoredHL NvimTreeFileIgnored + NvimTreeGitFileMergeHL NvimTreeFileMerge + NvimTreeGitFileNewHL NvimTreeFileNew + NvimTreeGitFileRenamedHL NvimTreeFileRenamed + NvimTreeGitFileStagedHL NvimTreeFileStaged + + NvimTreeGitFolderDeletedHL NvimTreeFolderDeleted + NvimTreeGitFolderDirtyHL NvimTreeFolderDirty + NvimTreeGitFolderIgnoredHL NvimTreeFolderIgnored + NvimTreeGitFolderMergeHL NvimTreeFolderMerge + NvimTreeGitFolderNewHL NvimTreeFolderNew + NvimTreeGitFolderRenamedHL NvimTreeFolderRenamed + NvimTreeGitFolderStagedHL NvimTreeFolderStaged + NvimTreeLspDiagnosticsError NvimTreeDiagnosticErrorIcon NvimTreeLspDiagnosticsWarning NvimTreeDiagnosticWarnIcon NvimTreeLspDiagnosticsInformation NvimTreeDiagnosticInfoIcon diff --git a/lua/nvim-tree.lua b/lua/nvim-tree.lua index 038e43e2f1b..cfe13124f16 100644 --- a/lua/nvim-tree.lua +++ b/lua/nvim-tree.lua @@ -386,7 +386,7 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS indent_width = 2, special_files = { "Cargo.toml", "Makefile", "README.md", "readme.md" }, symlink_destination = true, - highlight_git = false, + highlight_git = "none", highlight_diagnostics = "none", highlight_opened_files = "none", highlight_modified = "none", diff --git a/lua/nvim-tree/colors.lua b/lua/nvim-tree/colors.lua index 7a6d6983eed..3c91153c539 100644 --- a/lua/nvim-tree/colors.lua +++ b/lua/nvim-tree/colors.lua @@ -70,31 +70,31 @@ local DEFAULT_LINKS = { NvimTreeLiveFilterValue = "ModeMsg", -- Git Icon - NvimTreeGitDeleted = "Statement", - NvimTreeGitDirty = "Statement", - NvimTreeGitIgnored = "Comment", - NvimTreeGitMerge = "Constant", - NvimTreeGitNew = "PreProc", - NvimTreeGitRenamed = "PreProc", - NvimTreeGitStaged = "Constant", + NvimTreeGitDeletedIcon = "Statement", + NvimTreeGitDirtyIcon = "Statement", + NvimTreeGitIgnoredIcon = "Comment", + NvimTreeGitMergeIcon = "Constant", + NvimTreeGitNewIcon = "PreProc", + NvimTreeGitRenamedIcon = "PreProc", + NvimTreeGitStagedIcon = "Constant", -- Git File Text - NvimTreeFileDirty = "NvimTreeGitDirty", - NvimTreeFileStaged = "NvimTreeGitStaged", - NvimTreeFileMerge = "NvimTreeGitMerge", - NvimTreeFileRenamed = "NvimTreeGitRenamed", - NvimTreeFileNew = "NvimTreeGitNew", - NvimTreeFileDeleted = "NvimTreeGitDeleted", - NvimTreeFileIgnored = "NvimTreeGitIgnored", + NvimTreeGitFileDeletedHL = "NvimTreeGitDeletedIcon", + NvimTreeGitFileDirtyHL = "NvimTreeGitDirtyIcon", + NvimTreeGitFileIgnoredHL = "NvimTreeGitIgnoredIcon", + NvimTreeGitFileMergeHL = "NvimTreeGitMergeIcon", + NvimTreeGitFileNewHL = "NvimTreeGitNewIcon", + NvimTreeGitFileRenamedHL = "NvimTreeGitRenamedIcon", + NvimTreeGitFileStagedHL = "NvimTreeGitStagedIcon", -- Git Folder Text - NvimTreeFolderDirty = "NvimTreeFileDirty", - NvimTreeFolderStaged = "NvimTreeFileStaged", - NvimTreeFolderMerge = "NvimTreeFileMerge", - NvimTreeFolderRenamed = "NvimTreeFileRenamed", - NvimTreeFolderNew = "NvimTreeFileNew", - NvimTreeFolderDeleted = "NvimTreeFileDeleted", - NvimTreeFolderIgnored = "NvimTreeFileIgnored", + NvimTreeGitFolderDeletedHL = "NvimTreeGitFileDeletedHL", + NvimTreeGitFolderDirtyHL = "NvimTreeGitFileDirtyHL", + NvimTreeGitFolderIgnoredHL = "NvimTreeGitFileIgnoredHL", + NvimTreeGitFolderMergeHL = "NvimTreeGitFileMergeHL", + NvimTreeGitFolderNewHL = "NvimTreeGitFileNewHL", + NvimTreeGitFolderRenamedHL = "NvimTreeGitFileRenamedHL", + NvimTreeGitFolderStagedHL = "NvimTreeGitFileStagedHL", -- Diagnostics Icon NvimTreeDiagnosticErrorIcon = "DiagnosticError", @@ -109,22 +109,48 @@ local DEFAULT_LINKS = { NvimTreeDiagnosticHintFileHL = "DiagnosticUnderlineHint", -- Diagnostics Folder Highlight - NvimTreeDiagnosticErrorFolderHL = "DiagnosticUnderlineError", - NvimTreeDiagnosticWarnFolderHL = "DiagnosticUnderlineWarn", - NvimTreeDiagnosticInfoFolderHL = "DiagnosticUnderlineInfo", - NvimTreeDiagnosticHintFolderHL = "DiagnosticUnderlineHint", + NvimTreeDiagnosticErrorFolderHL = "NvimTreeDiagnosticErrorFileHL", + NvimTreeDiagnosticWarnFolderHL = "NvimTreeDiagnosticWarnFileHL", + NvimTreeDiagnosticInfoFolderHL = "NvimTreeDiagnosticInfoFileHL", + NvimTreeDiagnosticHintFolderHL = "NvimTreeDiagnosticHintFileHL", } -- nvim-tree highlight groups to legacy local LEGACY_LINKS = { + NvimTreeGitDeletedIcon = "NvimTreeGitDeleted", + NvimTreeGitDirtyIcon = "NvimTreeGitDirty", + NvimTreeGitIgnoredIcon = "NvimTreeGitIgnored", + NvimTreeGitMergeIcon = "NvimTreeGitMerge", + NvimTreeGitNewIcon = "NvimTreeGitNew", + NvimTreeGitRenamedIcon = "NvimTreeGitRenamed", + NvimTreeGitStagedIcon = "NvimTreeGitStaged", + + NvimTreeGitFileDeletedHL = "NvimTreeFileDeleted", + NvimTreeGitFileDirtyHL = "NvimTreeFileDirty", + NvimTreeGitFileIgnoredHL = "NvimTreeFileIgnored", + NvimTreeGitFileMergeHL = "NvimTreeFileMerge", + NvimTreeGitFileNewHL = "NvimTreeFileNew", + NvimTreeGitFileRenamedHL = "NvimTreeFileRenamed", + NvimTreeGitFileStagedHL = "NvimTreeFileStaged", + + NvimTreeGitFolderDeletedHL = "NvimTreeFolderDeleted", + NvimTreeGitFolderDirtyHL = "NvimTreeFolderDirty", + NvimTreeGitFolderIgnoredHL = "NvimTreeFolderIgnored", + NvimTreeGitFolderMergeHL = "NvimTreeFolderMerge", + NvimTreeGitFolderNewHL = "NvimTreeFolderNew", + NvimTreeGitFolderRenamedHL = "NvimTreeFolderRenamed", + NvimTreeGitFolderStagedHL = "NvimTreeFolderStaged", + NvimTreeDiagnosticErrorIcon = "NvimTreeLspDiagnosticsError", NvimTreeDiagnosticWarnIcon = "NvimTreeLspDiagnosticsWarning", NvimTreeDiagnosticInfoIcon = "NvimTreeLspDiagnosticsInformation", NvimTreeDiagnosticHintIcon = "NvimTreeLspDiagnosticsHint", + NvimTreeDiagnosticErrorFileHL = "NvimTreeLspDiagnosticsErrorText", NvimTreeDiagnosticWarnFileHL = "NvimTreeLspDiagnosticsWarningText", NvimTreeDiagnosticInfoFileHL = "NvimTreeLspDiagnosticsInformationText", NvimTreeDiagnosticHintFileHL = "NvimTreeLspDiagnosticsHintText", + NvimTreeDiagnosticErrorFolderHL = "NvimTreeLspDiagnosticsErrorFolderText", NvimTreeDiagnosticWarnFolderHL = "NvimTreeLspDiagnosticsWarningFolderText", NvimTreeDiagnosticInfoFolderHL = "NvimTreeLspDiagnosticsInformationFolderText", diff --git a/lua/nvim-tree/legacy.lua b/lua/nvim-tree/legacy.lua index 2d6dd9f9582..9d95da69326 100644 --- a/lua/nvim-tree/legacy.lua +++ b/lua/nvim-tree/legacy.lua @@ -44,11 +44,12 @@ local function refactored(opts) -- 2023/10/08 if type(opts.renderer) == "table" and type(opts.renderer.highlight_diagnostics) == "boolean" then - if opts.renderer.highlight_diagnostics then - opts.renderer.highlight_diagnostics = "name" - else - opts.renderer.highlight_diagnostics = "none" - end + opts.renderer.highlight_diagnostics = opts.renderer.highlight_diagnostics and "name" or "none" + end + + -- 2023/10/21 + if type(opts.renderer) == "table" and type(opts.renderer.highlight_git) == "boolean" then + opts.renderer.highlight_git = opts.renderer.highlight_git and "name" or "none" end end diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index bfd72f7aac1..44e59e210a5 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -303,12 +303,6 @@ end function Builder:_get_highlight_override(node, unloaded_bufnr) local name_hl, icon_hl - -- git - local git_highlight = git.get_highlight(node) - if git_highlight then - name_hl = git_highlight - end - -- opened file if self.highlight_opened_files and vim.fn.bufloaded(node.absolute_path) > 0 and vim.fn.bufnr(node.absolute_path) ~= unloaded_bufnr then if self.highlight_opened_files == "all" or self.highlight_opened_files == "name" then @@ -445,6 +439,7 @@ function Builder:_build_line(node, idx, num_children, unloaded_bufnr) end -- extra highighting + self:_append_highlight(node, git.get_highlight, icon.hl, name.hl) self:_append_highlight(node, bookmarks.get_highlight, icon.hl, name.hl) self:_append_highlight(node, diagnostics.get_highlight, icon.hl, name.hl) self:_append_highlight(node, copy_paste.get_highlight, icon.hl, name.hl) diff --git a/lua/nvim-tree/renderer/components/bookmarks.lua b/lua/nvim-tree/renderer/components/bookmarks.lua index d9dfb7297d5..4d13881e8a3 100644 --- a/lua/nvim-tree/renderer/components/bookmarks.lua +++ b/lua/nvim-tree/renderer/components/bookmarks.lua @@ -7,7 +7,7 @@ local M = { hl_pos = HL_POSITION.none, } ----Bookmark highlight group and position when highlight_bookmark. +---Bookmark highlight group and position when highlight_bookmark ---@param node table ---@return HL_POSITION position none when clipboard empty ---@return string|nil group only when node present in clipboard diff --git a/lua/nvim-tree/renderer/components/diagnostics.lua b/lua/nvim-tree/renderer/components/diagnostics.lua index 095757d0848..50369ec62f1 100644 --- a/lua/nvim-tree/renderer/components/diagnostics.lua +++ b/lua/nvim-tree/renderer/components/diagnostics.lua @@ -13,7 +13,7 @@ local M = { HL_POS = HL_POSITION.none, } ----Diagnostics text highlight group when highlight_diagnostics. +---Diagnostics highlight group and position when highlight_diagnostics. ---@param node table ---@return HL_POSITION position none when no status ---@return string|nil group only when status diff --git a/lua/nvim-tree/renderer/components/git.lua b/lua/nvim-tree/renderer/components/git.lua index f4d1258bacd..1aad1c02132 100644 --- a/lua/nvim-tree/renderer/components/git.lua +++ b/lua/nvim-tree/renderer/components/git.lua @@ -1,17 +1,22 @@ local notify = require "nvim-tree.notify" local explorer_node = require "nvim-tree.explorer.node" -local M = {} +local HL_POSITION = require("nvim-tree.enum").HL_POSITION + +local M = { + -- position for HL + HL_POS = HL_POSITION.none, +} local function build_icons_table(i) local icons = { - staged = { str = i.staged, hl = { "NvimTreeGitStaged" }, ord = 1 }, - unstaged = { str = i.unstaged, hl = { "NvimTreeGitDirty" }, ord = 2 }, - renamed = { str = i.renamed, hl = { "NvimTreeGitRenamed" }, ord = 3 }, - deleted = { str = i.deleted, hl = { "NvimTreeGitDeleted" }, ord = 4 }, - unmerged = { str = i.unmerged, hl = { "NvimTreeGitMerge" }, ord = 5 }, - untracked = { str = i.untracked, hl = { "NvimTreeGitNew" }, ord = 6 }, - ignored = { str = i.ignored, hl = { "NvimTreeGitIgnored" }, ord = 7 }, + staged = { str = i.staged, hl = { "NvimTreeGitStagedIcon" }, ord = 1 }, + unstaged = { str = i.unstaged, hl = { "NvimTreeGitDirtyIcon" }, ord = 2 }, + renamed = { str = i.renamed, hl = { "NvimTreeGitRenamedIcon" }, ord = 3 }, + deleted = { str = i.deleted, hl = { "NvimTreeGitDeletedIcon" }, ord = 4 }, + unmerged = { str = i.unmerged, hl = { "NvimTreeGitMergeIcon" }, ord = 5 }, + untracked = { str = i.untracked, hl = { "NvimTreeGitNewIcon" }, ord = 6 }, + ignored = { str = i.ignored, hl = { "NvimTreeGitIgnoredIcon" }, ord = 7 }, } return { ["M "] = { icons.staged }, @@ -51,35 +56,35 @@ end local function build_hl_table() local file = { - ["M "] = "NvimTreeFileStaged", - ["C "] = "NvimTreeFileStaged", - ["AA"] = "NvimTreeFileStaged", - ["AD"] = "NvimTreeFileStaged", - ["MD"] = "NvimTreeFileStaged", - ["T "] = "NvimTreeFileStaged", - ["TT"] = "NvimTreeFileStaged", - [" M"] = "NvimTreeFileDirty", - ["CM"] = "NvimTreeFileDirty", - [" C"] = "NvimTreeFileDirty", - [" T"] = "NvimTreeFileDirty", - ["MM"] = "NvimTreeFileDirty", - ["AM"] = "NvimTreeFileDirty", - dirty = "NvimTreeFileDirty", - ["A "] = "NvimTreeFileStaged", - ["??"] = "NvimTreeFileNew", - ["AU"] = "NvimTreeFileMerge", - ["UU"] = "NvimTreeFileMerge", - ["UD"] = "NvimTreeFileMerge", - ["DU"] = "NvimTreeFileMerge", - ["UA"] = "NvimTreeFileMerge", - [" D"] = "NvimTreeFileDeleted", - ["DD"] = "NvimTreeFileDeleted", - ["RD"] = "NvimTreeFileDeleted", - ["D "] = "NvimTreeFileDeleted", - ["R "] = "NvimTreeFileRenamed", - ["RM"] = "NvimTreeFileRenamed", - [" R"] = "NvimTreeFileRenamed", - ["!!"] = "NvimTreeFileIgnored", + ["M "] = "NvimTreeGitFileStagedHL", + ["C "] = "NvimTreeGitFileStagedHL", + ["AA"] = "NvimTreeGitFileStagedHL", + ["AD"] = "NvimTreeGitFileStagedHL", + ["MD"] = "NvimTreeGitFileStagedHL", + ["T "] = "NvimTreeGitFileStagedHL", + ["TT"] = "NvimTreeGitFileStagedHL", + [" M"] = "NvimTreeGitFileDirtyHL", + ["CM"] = "NvimTreeGitFileDirtyHL", + [" C"] = "NvimTreeGitFileDirtyHL", + [" T"] = "NvimTreeGitFileDirtyHL", + ["MM"] = "NvimTreeGitFileDirtyHL", + ["AM"] = "NvimTreeGitFileDirtyHL", + dirty = "NvimTreeGitFileDirtyHL", + ["A "] = "NvimTreeGitFileStagedHL", + ["??"] = "NvimTreeGitFileNewHL", + ["AU"] = "NvimTreeGitFileMergeHL", + ["UU"] = "NvimTreeGitFileMergeHL", + ["UD"] = "NvimTreeGitFileMergeHL", + ["DU"] = "NvimTreeGitFileMergeHL", + ["UA"] = "NvimTreeGitFileMergeHL", + [" D"] = "NvimTreeGitFileDeletedHL", + ["DD"] = "NvimTreeGitFileDeletedHL", + ["RD"] = "NvimTreeGitFileDeletedHL", + ["D "] = "NvimTreeGitFileDeletedHL", + ["R "] = "NvimTreeGitFileRenamedHL", + ["RM"] = "NvimTreeGitFileRenamedHL", + [" R"] = "NvimTreeGitFileRenamedHL", + ["!!"] = "NvimTreeGitFileIgnoredHL", [" A"] = "none", } @@ -91,7 +96,15 @@ local function build_hl_table() return file, folder end -local function nil_() end +local function setup_signs(i) + vim.fn.sign_define("NvimTreeGitDirtyIcon", { text = i.unstaged, texthl = "NvimTreeGitDirtyIcon" }) + vim.fn.sign_define("NvimTreeGitStagedIcon", { text = i.staged, texthl = "NvimTreeGitStagedIcon" }) + vim.fn.sign_define("NvimTreeGitMergeIcon", { text = i.unmerged, texthl = "NvimTreeGitMergeIcon" }) + vim.fn.sign_define("NvimTreeGitRenamedIcon", { text = i.renamed, texthl = "NvimTreeGitRenamedIcon" }) + vim.fn.sign_define("NvimTreeGitNewIcon", { text = i.untracked, texthl = "NvimTreeGitNewIcon" }) + vim.fn.sign_define("NvimTreeGitDeletedIcon", { text = i.deleted, texthl = "NvimTreeGitDeletedIcon" }) + vim.fn.sign_define("NvimTreeGitIgnoredIcon", { text = i.ignored, texthl = "NvimTreeGitIgnoredIcon" }) +end local function warn_status(git_status) notify.warn(string.format("Unrecognized git state '%s'", git_status)) @@ -99,7 +112,11 @@ end ---@param node table ---@return HighlightedString[]|nil -local function get_icons_(node) +function M.get_icons(node) + if not M.config.icons.show.git then + return nil + end + local git_status = explorer_node.get_git_status(node) if git_status == nil then return nil @@ -139,26 +156,24 @@ local function get_icons_(node) return iconss end -function M.setup_signs(i) - vim.fn.sign_define("NvimTreeGitDirty", { text = i.unstaged, texthl = "NvimTreeGitDirty" }) - vim.fn.sign_define("NvimTreeGitStaged", { text = i.staged, texthl = "NvimTreeGitStaged" }) - vim.fn.sign_define("NvimTreeGitMerge", { text = i.unmerged, texthl = "NvimTreeGitMerge" }) - vim.fn.sign_define("NvimTreeGitRenamed", { text = i.renamed, texthl = "NvimTreeGitRenamed" }) - vim.fn.sign_define("NvimTreeGitNew", { text = i.untracked, texthl = "NvimTreeGitNew" }) - vim.fn.sign_define("NvimTreeGitDeleted", { text = i.deleted, texthl = "NvimTreeGitDeleted" }) - vim.fn.sign_define("NvimTreeGitIgnored", { text = i.ignored, texthl = "NvimTreeGitIgnored" }) -end +---Git highlight group and position when highlight_git +---@param node table +---@return HL_POSITION position none when no status +---@return string|nil group only when status +function M.get_highlight(node) + if not node or M.HL_POS == HL_POSITION.none then + return HL_POSITION.none, nil + end -local function get_highlight_(node) local git_status = explorer_node.get_git_status(node) - if git_status == nil then - return + if not git_status then + return HL_POSITION.none, nil end if node.nodes then - return M.folder_hl[git_status[1]] + return M.HL_POS, M.folder_hl[git_status[1]] else - return M.file_hl[git_status[1]] + return M.HL_POS, M.file_hl[git_status[1]] end end @@ -169,23 +184,11 @@ function M.setup(opts) M.file_hl, M.folder_hl = build_hl_table() - if opts.renderer.icons.git_placement == "signcolumn" then - M.setup_signs(opts.renderer.icons.glyphs.git) - end + setup_signs(opts.renderer.icons.glyphs.git) - if opts.renderer.icons.show.git then - M.get_icons = get_icons_ - else - M.get_icons = nil_ + if opts.git.enable and opts.renderer.highlight_git then + M.HL_POS = HL_POSITION[opts.renderer.highlight_git] end - - if opts.renderer.highlight_git then - M.get_highlight = get_highlight_ - else - M.get_highlight = nil_ - end - - M.git_show_on_open_dirs = opts.git.show_on_open_dirs end return M From dfeeb5c501f2ddb5c85ac33ca040b4b7ed37ed53 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sun, 22 Oct 2023 13:59:48 +1100 Subject: [PATCH 04/37] feat(#2415): normalise and add modified groups --- doc/nvim-tree-lua.txt | 16 +++--- lua/nvim-tree/colors.lua | 12 +++-- lua/nvim-tree/renderer/builder.lua | 19 +------ .../renderer/components/bookmarks.lua | 22 ++++---- .../renderer/components/modified.lua | 51 ++++++++++++------- lua/nvim-tree/renderer/init.lua | 1 - 6 files changed, 66 insertions(+), 55 deletions(-) diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index 1841fb6439f..427ec3cb167 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -2268,7 +2268,6 @@ Standard: > File Text: > NvimTreeExecFile Constant NvimTreeImageFile PreProc - NvimTreeModifiedFile Constant NvimTreeOpenedFile Constant NvimTreeSpecialFile PreProc NvimTreeSymlink Statement @@ -2297,12 +2296,15 @@ Clipboard: > NvimTreeCopiedHL SpellRare NvimTreeCutHL SpellBad < -Bookmark Icon: > +Bookmarks: > NvimTreeBookmark Constant -< -Bookmark Highlight: > NvimTreeBookmarkHL SpellLocal < +Modified: > + NvimTreeModifiedIcon Constant + NvimTreeModifiedFileHL NvimTreeModifiedIcon + NvimTreeModifiedFolderHL NvimTreeModifiedIcon +< Picker: > NvimTreeWindowPicker guifg=#ededed guibg=#4493c8 gui=bold ctermfg=White ctermbg=Cyan < @@ -2319,7 +2321,7 @@ Git Icon: > NvimTreeGitRenamedIcon PreProc NvimTreeGitStagedIcon Constant < -Git File Text: > +Git File File Highlight: > NvimTreeGitFileDeletedHL NvimTreeGitDeletedIcon NvimTreeGitFileDirtyHL NvimTreeGitDirtyIcon NvimTreeGitFileIgnoredHL NvimTreeGitIgnoredIcon @@ -2328,7 +2330,7 @@ Git File Text: > NvimTreeGitFileRenamedHL NvimTreeGitRenamedIcon NvimTreeGitFileStagedHL NvimTreeGitStagedIcon < -Git Folder Text: > +Git Folder Folder Highlight: > NvimTreeGitFolderDeletedHL NvimTreeGitFileDeletedHL NvimTreeGitFolderDirtyHL NvimTreeGitFileDirtyHL NvimTreeGitFolderIgnoredHL NvimTreeGitFileIgnoredHL @@ -2385,6 +2387,8 @@ Legacy diagnostic HL style may be applied: > Legacy highlight group are still obeyed when they are defined and the current highlight group is not, hard linking as follows: > + NvimTreeModifiedIcon NvimTreeModifiedFile + NvimTreeGitDeletedIcon NvimTreeGitDeleted NvimTreeGitDirtyIcon NvimTreeGitDirty NvimTreeGitIgnoredIcon NvimTreeGitIgnored diff --git a/lua/nvim-tree/colors.lua b/lua/nvim-tree/colors.lua index 3c91153c539..0dedf5014af 100644 --- a/lua/nvim-tree/colors.lua +++ b/lua/nvim-tree/colors.lua @@ -31,7 +31,6 @@ local DEFAULT_LINKS = { -- File Text NvimTreeExecFile = "Constant", NvimTreeImageFile = "PreProc", - NvimTreeModifiedFile = "Constant", NvimTreeOpenedFile = "Constant", NvimTreeSpecialFile = "PreProc", NvimTreeSymlink = "Statement", @@ -65,6 +64,11 @@ local DEFAULT_LINKS = { -- Bookmark Highlight NvimTreeBookmarkHL = "SpellLocal", + -- Modified + NvimTreeModifiedIcon = "Constant", + NvimTreeModifiedFileHL = "NvimTreeModifiedIcon", + NvimTreeModifiedFolderHL = "NvimTreeModifiedFileHL", + -- LiveFilter NvimTreeLiveFilterPrefix = "PreProc", NvimTreeLiveFilterValue = "ModeMsg", @@ -78,7 +82,7 @@ local DEFAULT_LINKS = { NvimTreeGitRenamedIcon = "PreProc", NvimTreeGitStagedIcon = "Constant", - -- Git File Text + -- Git File Highlight NvimTreeGitFileDeletedHL = "NvimTreeGitDeletedIcon", NvimTreeGitFileDirtyHL = "NvimTreeGitDirtyIcon", NvimTreeGitFileIgnoredHL = "NvimTreeGitIgnoredIcon", @@ -87,7 +91,7 @@ local DEFAULT_LINKS = { NvimTreeGitFileRenamedHL = "NvimTreeGitRenamedIcon", NvimTreeGitFileStagedHL = "NvimTreeGitStagedIcon", - -- Git Folder Text + -- Git Folder Highlight NvimTreeGitFolderDeletedHL = "NvimTreeGitFileDeletedHL", NvimTreeGitFolderDirtyHL = "NvimTreeGitFileDirtyHL", NvimTreeGitFolderIgnoredHL = "NvimTreeGitFileIgnoredHL", @@ -117,6 +121,8 @@ local DEFAULT_LINKS = { -- nvim-tree highlight groups to legacy local LEGACY_LINKS = { + NvimTreeModifiedIcon = "NvimTreeModifiedFile", + NvimTreeGitDeletedIcon = "NvimTreeGitDeleted", NvimTreeGitDirtyIcon = "NvimTreeGitDirty", NvimTreeGitIgnoredIcon = "NvimTreeGitIgnored", diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 44e59e210a5..72964ee835a 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -59,11 +59,6 @@ function Builder:configure_opened_file_highlighting(highlight_opened_files) return self end -function Builder:configure_modified_highlighting(highlight_modified) - self.highlight_modified = highlight_modified - return self -end - function Builder:configure_icon_padding(padding) self.icon_padding = padding or " " return self @@ -312,18 +307,6 @@ function Builder:_get_highlight_override(node, unloaded_bufnr) icon_hl = "NvimTreeOpenedFileIcon" end end - - -- modified file - local modified_highlight = modified.get_highlight(node) - if modified_highlight then - if self.highlight_modified == "all" or self.highlight_modified == "name" then - name_hl = modified_highlight - end - if self.highlight_modified == "all" or self.highlight_modified == "icon" then - icon_hl = modified_highlight - end - end - return icon_hl, name_hl end @@ -440,6 +423,8 @@ function Builder:_build_line(node, idx, num_children, unloaded_bufnr) -- extra highighting self:_append_highlight(node, git.get_highlight, icon.hl, name.hl) + -- TODO opened + self:_append_highlight(node, modified.get_highlight, icon.hl, name.hl) self:_append_highlight(node, bookmarks.get_highlight, icon.hl, name.hl) self:_append_highlight(node, diagnostics.get_highlight, icon.hl, name.hl) self:_append_highlight(node, copy_paste.get_highlight, icon.hl, name.hl) diff --git a/lua/nvim-tree/renderer/components/bookmarks.lua b/lua/nvim-tree/renderer/components/bookmarks.lua index 4d13881e8a3..da5c9937d08 100644 --- a/lua/nvim-tree/renderer/components/bookmarks.lua +++ b/lua/nvim-tree/renderer/components/bookmarks.lua @@ -3,7 +3,7 @@ local marks = require "nvim-tree.marks" local HL_POSITION = require("nvim-tree.enum").HL_POSITION local M = { - ICON = {}, + icon = nil, hl_pos = HL_POSITION.none, } @@ -28,8 +28,8 @@ end ---@param node table ---@return HighlightedString|nil bookmark icon function M.get_icon(node) - if M.config.renderer.icons.show.bookmarks and marks.get_mark(node) then - return M.ICON + if M.icon and marks.get_mark(node) then + return M.icon end end @@ -40,12 +40,16 @@ function M.setup(opts) M.hl_pos = HL_POSITION[opts.renderer.highlight_bookmarks] or HL_POSITION.none - M.ICON = { - str = opts.renderer.icons.glyphs.bookmark, - hl = { "NvimTreeBookmark" }, - } - - vim.fn.sign_define(M.ICON.hl[1], { text = M.ICON.str, texthl = M.ICON.hl[1] }) + if opts.renderer.icons.show.bookmarks then + M.icon = { + str = opts.renderer.icons.glyphs.bookmark, + hl = { "NvimTreeBookmark" }, + } + vim.fn.sign_define(M.icon.hl[1], { + text = M.icon.str, + texthl = M.icon.hl[1], + }) + end end return M diff --git a/lua/nvim-tree/renderer/components/modified.lua b/lua/nvim-tree/renderer/components/modified.lua index f247d7b2046..2571df99757 100644 --- a/lua/nvim-tree/renderer/components/modified.lua +++ b/lua/nvim-tree/renderer/components/modified.lua @@ -1,40 +1,53 @@ local modified = require "nvim-tree.modified" -local M = {} +local HL_POSITION = require("nvim-tree.enum").HL_POSITION -local HIGHLIGHT = "NvimTreeModifiedFile" +local M = { + icon = nil, + hl_pos = HL_POSITION.none, +} ----return modified icon if node is modified, otherwise return empty string +---modified icon if modified ---@param node table ---@return HighlightedString|nil modified icon function M.get_icon(node) - if not modified.is_modified(node) or not M.show_icon then - return nil + if M.icon and modified.is_modified(node) then + return M.icon end - - return { str = M.icon, hl = { HIGHLIGHT } } -end - -function M.setup_signs() - vim.fn.sign_define(HIGHLIGHT, { text = M.icon, texthl = HIGHLIGHT }) end +---Diagnostics highlight group and position when highlight_diagnostics. ---@param node table ----@return string|nil +---@return HL_POSITION position none when no status +---@return string|nil group only when status function M.get_highlight(node) - if not modified.is_modified(node) then - return nil + if M.hl_pos == HL_POSITION.none or not modified.is_modified(node) then + return HL_POSITION.none, nil end - return HIGHLIGHT + if node.nodes then + return M.hl_pos, "NvimTreeModifiedFolderHL" + else + return M.hl_pos, "NvimTreeModifiedFileHL" + end end function M.setup(opts) - M.icon = opts.renderer.icons.glyphs.modified - M.show_icon = opts.renderer.icons.show.modified + if not opts.modified.enable then + return + end - if opts.renderer.icons.modified_placement == "signcolumn" then - M.setup_signs() + M.hl_pos = HL_POSITION[opts.renderer.highlight_modified] or HL_POSITION.none + + if opts.renderer.icons.show.modified then + M.icon = { + str = opts.renderer.icons.glyphs.modified, + hl = { "NvimTreeModifiedIcon" }, + } + vim.fn.sign_define(M.icon.hl[1], { + text = M.icon.str, + texthl = M.icon.hl[1], + }) end end diff --git a/lua/nvim-tree/renderer/init.lua b/lua/nvim-tree/renderer/init.lua index b9908ec8fb8..0d46ab6892b 100644 --- a/lua/nvim-tree/renderer/init.lua +++ b/lua/nvim-tree/renderer/init.lua @@ -72,7 +72,6 @@ function M.draw(unloaded_bufnr) :configure_special_files(M.config.special_files) :configure_picture_map(picture_map) :configure_opened_file_highlighting(M.config.highlight_opened_files) - :configure_modified_highlighting(M.config.highlight_modified) :configure_icon_padding(M.config.icons.padding) :configure_git_icons_placement(M.config.icons.git_placement) :configure_diagnostics_icon_placement(M.config.icons.diagnostics_placement) From 59e43a2b31f77c1f93e8e786e551b2f8e42b2187 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Mon, 23 Oct 2023 13:56:54 +1100 Subject: [PATCH 05/37] feat(#2415): create Decorator class for modified and bookmarks --- lua/nvim-tree/enum.lua | 7 ++- lua/nvim-tree/marks/init.lua | 2 +- lua/nvim-tree/modified.lua | 3 +- lua/nvim-tree/renderer/builder.lua | 62 ++++++++++--------- .../renderer/components/bookmarks.lua | 55 ---------------- .../renderer/components/modified.lua | 54 ---------------- lua/nvim-tree/renderer/decorator/bookmark.lua | 53 ++++++++++++++++ lua/nvim-tree/renderer/decorator/init.lua | 42 +++++++++++++ lua/nvim-tree/renderer/decorator/modified.lua | 58 +++++++++++++++++ lua/nvim-tree/renderer/init.lua | 23 ++++--- 10 files changed, 207 insertions(+), 152 deletions(-) delete mode 100644 lua/nvim-tree/renderer/components/bookmarks.lua delete mode 100644 lua/nvim-tree/renderer/components/modified.lua create mode 100644 lua/nvim-tree/renderer/decorator/bookmark.lua create mode 100644 lua/nvim-tree/renderer/decorator/init.lua create mode 100644 lua/nvim-tree/renderer/decorator/modified.lua diff --git a/lua/nvim-tree/enum.lua b/lua/nvim-tree/enum.lua index e3791427e31..92ea2bb4ca0 100644 --- a/lua/nvim-tree/enum.lua +++ b/lua/nvim-tree/enum.lua @@ -12,9 +12,10 @@ M.HL_POSITION = { ---Setup options for "*_placement" ---@enum ICON_PLACEMENT M.ICON_PLACEMENT = { - signcolumn = 0, - before = 1, - after = 2, + none = 0, + signcolumn = 1, + before = 2, + after = 3, } return M diff --git a/lua/nvim-tree/marks/init.lua b/lua/nvim-tree/marks/init.lua index 10804d5c21c..d92e43e8bc7 100644 --- a/lua/nvim-tree/marks/init.lua +++ b/lua/nvim-tree/marks/init.lua @@ -45,7 +45,7 @@ end ---@param node Node|MinimalNode ---@return table|nil function M.get_mark(node) - return NvimTreeMarks[node.absolute_path] + return node and NvimTreeMarks[node.absolute_path] end ---@return table diff --git a/lua/nvim-tree/modified.lua b/lua/nvim-tree/modified.lua index 8f77ef668fb..e16c0750e7e 100644 --- a/lua/nvim-tree/modified.lua +++ b/lua/nvim-tree/modified.lua @@ -26,7 +26,8 @@ end ---@param node Node ---@return boolean function M.is_modified(node) - return M.config.enable + return node + and M.config.enable and M._record[node.absolute_path] and (not node.nodes or M.config.show_on_dirs) and (not node.open or M.config.show_on_open_dirs) diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 72964ee835a..6e94722c98e 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -5,18 +5,19 @@ local notify = require "nvim-tree.notify" local git = require "nvim-tree.renderer.components.git" local pad = require "nvim-tree.renderer.components.padding" local icons = require "nvim-tree.renderer.components.icons" -local modified = require "nvim-tree.renderer.components.modified" local diagnostics = require "nvim-tree.renderer.components.diagnostics" -local bookmarks = require "nvim-tree.renderer.components.bookmarks" local HL_POSITION = require("nvim-tree.enum").HL_POSITION +local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT +--- @class Builder +--- @field decorators Decorator[] local Builder = {} Builder.__index = Builder local DEFAULT_ROOT_FOLDER_LABEL = ":~:s?$?/..?" -function Builder.new(root_cwd) +function Builder.new(root_cwd, decorators) return setmetatable({ index = 0, depth = 0, @@ -25,6 +26,7 @@ function Builder.new(root_cwd) markers = {}, signs = {}, root_cwd = root_cwd, + decorators = decorators, }, Builder) end @@ -80,22 +82,6 @@ function Builder:configure_diagnostics_icon_placement(where) return self end -function Builder:configure_bookmark_icon_placement(where) - if where ~= "after" and where ~= "before" and where ~= "signcolumn" then - where = "before" -- default before - end - self.bookmarks_placement = where - return self -end - -function Builder:configure_modified_placement(where) - if where ~= "after" and where ~= "before" and where ~= "signcolumn" then - where = "after" -- default after - end - self.modified_placement = where - return self -end - function Builder:configure_symlink_destination(show) self.symlink_destination = show return self @@ -265,8 +251,8 @@ end ---@param node table ---@return HighlightedString|nil icon function Builder:_get_modified_icon(node) - local modified_icon = modified.get_icon(node) - if modified_icon and self.modified_placement == "signcolumn" then + local modified_icon = self.decorators.modified:get_icon(node) + if modified_icon and self.decorators.modified.icon_placement == ICON_PLACEMENT.signcolumn then table.insert(self.signs, { sign = modified_icon.hl[1], lnum = self.index + 1, @@ -280,8 +266,8 @@ end ---@param node table ---@return HighlightedString[]|nil icon function Builder:_get_bookmark_icon(node) - local bookmark_icon = bookmarks.get_icon(node) - if bookmark_icon and self.bookmarks_placement == "signcolumn" then + local bookmark_icon = self.decorators.bookmark:get_icon(node) + if bookmark_icon and self.decorators.bookmark.icon_placement == ICON_PLACEMENT.signcolumn then table.insert(self.signs, { sign = bookmark_icon.hl[1], lnum = self.index + 1, @@ -327,6 +313,23 @@ function Builder:_append_highlight(node, get_hl, icon_hl, name_hl) end end +---Append optional highlighting to icon or name. +---@param node table +---@param decorator Decorator +---@param icon_hl string[] icons to append to +---@param name_hl string[] names to append to +function Builder:_append_dec_highlight(node, decorator, icon_hl, name_hl) + local pos, hl = decorator:get_highlight(node) + if pos ~= HL_POSITION.none and hl then + if pos == HL_POSITION.all or pos == HL_POSITION.icon then + table.insert(icon_hl, hl) + end + if pos == HL_POSITION.all or pos == HL_POSITION.name then + table.insert(name_hl, hl) + end + end +end + ---@param indent_markers HighlightedString[] ---@param arrows HighlightedString[]|nil ---@param icon HighlightedString @@ -359,13 +362,13 @@ function Builder:_format_line(indent_markers, arrows, icon, name, git_icons, dia if git_icons and self.git_placement == "before" then add_to_end(line, git_icons) end - if modified_icon and self.modified_placement == "before" then + if modified_icon and self.decorators.modified.icon_placement == ICON_PLACEMENT.before then add_to_end(line, { modified_icon }) end if diagnostics_icon and self.diagnostics_placement == "before" then add_to_end(line, { diagnostics_icon }) end - if bookmark_icon and self.bookmarks_placement == "before" then + if bookmark_icon and self.decorators.bookmark.icon_placement == ICON_PLACEMENT.before then add_to_end(line, { bookmark_icon }) end @@ -374,13 +377,13 @@ function Builder:_format_line(indent_markers, arrows, icon, name, git_icons, dia if git_icons and self.git_placement == "after" then add_to_end(line, git_icons) end - if modified_icon and self.modified_placement == "after" then + if modified_icon and self.decorators.modified.icon_placement == ICON_PLACEMENT.after then add_to_end(line, { modified_icon }) end if diagnostics_icon and self.diagnostics_placement == "after" then add_to_end(line, { diagnostics_icon }) end - if bookmark_icon and self.bookmarks_placement == "after" then + if bookmark_icon and self.decorators.bookmark.icon_placement == ICON_PLACEMENT.after then add_to_end(line, { bookmark_icon }) end @@ -423,9 +426,8 @@ function Builder:_build_line(node, idx, num_children, unloaded_bufnr) -- extra highighting self:_append_highlight(node, git.get_highlight, icon.hl, name.hl) - -- TODO opened - self:_append_highlight(node, modified.get_highlight, icon.hl, name.hl) - self:_append_highlight(node, bookmarks.get_highlight, icon.hl, name.hl) + self:_append_dec_highlight(node, self.decorators.modified, icon.hl, name.hl) + self:_append_dec_highlight(node, self.decorators.bookmark, icon.hl, name.hl) self:_append_highlight(node, diagnostics.get_highlight, icon.hl, name.hl) self:_append_highlight(node, copy_paste.get_highlight, icon.hl, name.hl) diff --git a/lua/nvim-tree/renderer/components/bookmarks.lua b/lua/nvim-tree/renderer/components/bookmarks.lua deleted file mode 100644 index da5c9937d08..00000000000 --- a/lua/nvim-tree/renderer/components/bookmarks.lua +++ /dev/null @@ -1,55 +0,0 @@ -local marks = require "nvim-tree.marks" - -local HL_POSITION = require("nvim-tree.enum").HL_POSITION - -local M = { - icon = nil, - hl_pos = HL_POSITION.none, -} - ----Bookmark highlight group and position when highlight_bookmark ----@param node table ----@return HL_POSITION position none when clipboard empty ----@return string|nil group only when node present in clipboard -function M.get_highlight(node) - if M.hl_pos == HL_POSITION.none then - return HL_POSITION.none, nil - end - - local mark = marks.get_mark(node) - if mark then - return M.hl_pos, "NvimTreeBookmarkHL" - else - return HL_POSITION.none, nil - end -end - ----bookmark icon if marked ----@param node table ----@return HighlightedString|nil bookmark icon -function M.get_icon(node) - if M.icon and marks.get_mark(node) then - return M.icon - end -end - -function M.setup(opts) - M.config = { - renderer = opts.renderer, - } - - M.hl_pos = HL_POSITION[opts.renderer.highlight_bookmarks] or HL_POSITION.none - - if opts.renderer.icons.show.bookmarks then - M.icon = { - str = opts.renderer.icons.glyphs.bookmark, - hl = { "NvimTreeBookmark" }, - } - vim.fn.sign_define(M.icon.hl[1], { - text = M.icon.str, - texthl = M.icon.hl[1], - }) - end -end - -return M diff --git a/lua/nvim-tree/renderer/components/modified.lua b/lua/nvim-tree/renderer/components/modified.lua deleted file mode 100644 index 2571df99757..00000000000 --- a/lua/nvim-tree/renderer/components/modified.lua +++ /dev/null @@ -1,54 +0,0 @@ -local modified = require "nvim-tree.modified" - -local HL_POSITION = require("nvim-tree.enum").HL_POSITION - -local M = { - icon = nil, - hl_pos = HL_POSITION.none, -} - ----modified icon if modified ----@param node table ----@return HighlightedString|nil modified icon -function M.get_icon(node) - if M.icon and modified.is_modified(node) then - return M.icon - end -end - ----Diagnostics highlight group and position when highlight_diagnostics. ----@param node table ----@return HL_POSITION position none when no status ----@return string|nil group only when status -function M.get_highlight(node) - if M.hl_pos == HL_POSITION.none or not modified.is_modified(node) then - return HL_POSITION.none, nil - end - - if node.nodes then - return M.hl_pos, "NvimTreeModifiedFolderHL" - else - return M.hl_pos, "NvimTreeModifiedFileHL" - end -end - -function M.setup(opts) - if not opts.modified.enable then - return - end - - M.hl_pos = HL_POSITION[opts.renderer.highlight_modified] or HL_POSITION.none - - if opts.renderer.icons.show.modified then - M.icon = { - str = opts.renderer.icons.glyphs.modified, - hl = { "NvimTreeModifiedIcon" }, - } - vim.fn.sign_define(M.icon.hl[1], { - text = M.icon.str, - texthl = M.icon.hl[1], - }) - end -end - -return M diff --git a/lua/nvim-tree/renderer/decorator/bookmark.lua b/lua/nvim-tree/renderer/decorator/bookmark.lua new file mode 100644 index 00000000000..de62d85ae95 --- /dev/null +++ b/lua/nvim-tree/renderer/decorator/bookmark.lua @@ -0,0 +1,53 @@ +local marks = require "nvim-tree.marks" + +local HL_POSITION = require("nvim-tree.enum").HL_POSITION +local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT + +local Decorator = require "nvim-tree.renderer.decorator" + +--- @class DecoratorBookmark: Decorator +--- @field icon HighlightedString +local DecoratorBookmark = Decorator:new() + +--- @param opts table +--- @return DecoratorBookmark +function DecoratorBookmark:new(opts) + local o = Decorator.new(self, { + hl_pos = HL_POSITION[opts.renderer.highlight_bookmarks] or HL_POSITION.none, + icon_placement = ICON_PLACEMENT[opts.renderer.icons.bookmarks_placement] or ICON_PLACEMENT.none, + }) + ---@cast o DecoratorBookmark + + if opts.renderer.icons.show.bookmarks then + o.icon = { + str = opts.renderer.icons.glyphs.bookmark, + hl = { "NvimTreeBookmark" }, + } + o:define_sign(o.icon) + end + + return o +end + +--- Bookmark icon: renderer.icons.show.bookmarks and node is marked +function DecoratorBookmark:get_icon(node) + if marks.get_mark(node) then + return self.icon + end +end + +--- Bookmark highlight: renderer.highlight_bookmarks and node is marked +function DecoratorBookmark:get_highlight(node) + if self.hl_pos == HL_POSITION.none then + return HL_POSITION.none, nil + end + + local mark = marks.get_mark(node) + if mark then + return self.hl_pos, "NvimTreeBookmarkHL" + else + return HL_POSITION.none, nil + end +end + +return DecoratorBookmark diff --git a/lua/nvim-tree/renderer/decorator/init.lua b/lua/nvim-tree/renderer/decorator/init.lua new file mode 100644 index 00000000000..bfacc5a440f --- /dev/null +++ b/lua/nvim-tree/renderer/decorator/init.lua @@ -0,0 +1,42 @@ +--- @class Decorator +--- @field hl_pos HL_POSITION +--- @field icon_placement ICON_PLACEMENT +local Decorator = {} + +--- @param o Decorator|nil +--- @return Decorator +function Decorator:new(o) + o = o or {} + setmetatable(o, self) + self.__index = self + + return o +end + +---@diagnostic disable: unused-local + +--- Node icon +--- @param node table +--- @return HighlightedString|nil modified icon +function Decorator:get_icon(node) end + +--- Node highlight +--- @param node table +--- @return HL_POSITION|nil position +--- @return string|nil group +function Decorator:get_highlight(node) end + +---@diagnostic enable: unused-local + +--- Define a sign +--- @param icon HighlightedString|nil +function Decorator:define_sign(icon) + if icon and #icon.hl > 0 then + vim.fn.sign_define(icon.hl[1], { + text = icon.str, + texthl = icon.hl[1], + }) + end +end + +return Decorator diff --git a/lua/nvim-tree/renderer/decorator/modified.lua b/lua/nvim-tree/renderer/decorator/modified.lua new file mode 100644 index 00000000000..c411dcab2cb --- /dev/null +++ b/lua/nvim-tree/renderer/decorator/modified.lua @@ -0,0 +1,58 @@ +local modified = require "nvim-tree.modified" + +local HL_POSITION = require("nvim-tree.enum").HL_POSITION +local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT + +local Decorator = require "nvim-tree.renderer.decorator" + +--- @class DecoratorModified: Decorator +--- @field enabled boolean +--- @field icon HighlightedString|nil +local DecoratorModified = Decorator:new() + +--- @param opts table +--- @return DecoratorModified +function DecoratorModified:new(opts) + local o = Decorator.new(self, { + hl_pos = HL_POSITION[opts.renderer.highlight_modified] or HL_POSITION.none, + icon_placement = ICON_PLACEMENT[opts.renderer.icons.modified_placement] or ICON_PLACEMENT.none, + }) + ---@cast o DecoratorModified + + o.enabled = opts.modified.enable + if not o.enabled then + return o + end + + if opts.renderer.icons.show.modified then + o.icon = { + str = opts.renderer.icons.glyphs.modified, + hl = { "NvimTreeModifiedIcon" }, + } + o:define_sign(o.icon) + end + + return o +end + +--- Modified icon: modified.enable, renderer.icons.show.modified and node is modified +function DecoratorModified:get_icon(node) + if self.enabled and modified.is_modified(node) then + return self.icon + end +end + +--- Modified highlight: modified.enable, renderer.highlight_modified and node is modified +function DecoratorModified:get_highlight(node) + if not self.enabled or self.hl_pos == HL_POSITION.none or not modified.is_modified(node) then + return HL_POSITION.none, nil + end + + if node.nodes then + return self.hl_pos, "NvimTreeModifiedFolderHL" + else + return self.hl_pos, "NvimTreeModifiedFileHL" + end +end + +return DecoratorModified diff --git a/lua/nvim-tree/renderer/init.lua b/lua/nvim-tree/renderer/init.lua index 0d46ab6892b..3cc99ac6b8a 100644 --- a/lua/nvim-tree/renderer/init.lua +++ b/lua/nvim-tree/renderer/init.lua @@ -2,7 +2,6 @@ local core = require "nvim-tree.core" local log = require "nvim-tree.log" local view = require "nvim-tree.view" local events = require "nvim-tree.events" -local modified = require "nvim-tree.renderer.components.modified" local _padding = require "nvim-tree.renderer.components.padding" local icon_component = require "nvim-tree.renderer.components.icons" @@ -11,10 +10,13 @@ local git = require "nvim-tree.renderer.components.git" local diagnostics = require "nvim-tree.renderer.components.diagnostics" local Builder = require "nvim-tree.renderer.builder" local live_filter = require "nvim-tree.live-filter" -local bookmarks = require "nvim-tree.renderer.components.bookmarks" + +local DecoratorBookmark = require "nvim-tree.renderer.decorator.bookmark" +local DecoratorModified = require "nvim-tree.renderer.decorator.modified" local M = { last_highlights = {}, + decorators = {}, } local SIGN_GROUP = "NvimTreeRendererSigns" @@ -66,7 +68,7 @@ function M.draw(unloaded_bufnr) local cursor = vim.api.nvim_win_get_cursor(view.get_winnr()) icon_component.reset_config() - local lines, hl, signs = Builder.new(core.get_cwd()) + local lines, hl, signs = Builder.new(core.get_cwd(), M.decorators) :configure_root_label(M.config.root_folder_label) :configure_trailing_slash(M.config.add_trailing) :configure_special_files(M.config.special_files) @@ -75,8 +77,6 @@ function M.draw(unloaded_bufnr) :configure_icon_padding(M.config.icons.padding) :configure_git_icons_placement(M.config.icons.git_placement) :configure_diagnostics_icon_placement(M.config.icons.diagnostics_placement) - :configure_bookmark_icon_placement(M.config.icons.bookmarks_placement) - :configure_modified_placement(M.config.icons.modified_placement) :configure_symlink_destination(M.config.symlink_destination) :configure_filter(live_filter.filter, live_filter.prefix) :configure_group_name_modifier(M.config.group_empty) @@ -101,15 +101,22 @@ end function M.setup(opts) M.config = opts.renderer - M.config.modified = opts.modified _padding.setup(opts) full_name.setup(opts) git.setup(opts) - modified.setup(opts) diagnostics.setup(opts) - bookmarks.setup(opts) icon_component.setup(opts) + + -- TODO change to array: precedence should follow order + M.decorators = { + bookmark = DecoratorBookmark:new(opts), + modified = DecoratorModified:new(opts), + } + + for _, d in pairs(M.decorators) do + log.line("dev", "d = %s", vim.inspect(d)) + end end return M From 53948b5c87435ca7adb3e3c41896ee2beb2d64e0 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Mon, 23 Oct 2023 15:05:58 +1100 Subject: [PATCH 06/37] feat(#2415): create DecoratorDiagnostics --- lua/nvim-tree/renderer/builder.lua | 37 +++----- .../decorator/{bookmark.lua => bookmarks.lua} | 29 +++--- .../renderer/decorator/diagnostics.lua | 93 +++++++++++++++++++ lua/nvim-tree/renderer/decorator/init.lua | 4 +- lua/nvim-tree/renderer/decorator/modified.lua | 6 +- lua/nvim-tree/renderer/init.lua | 13 +-- 6 files changed, 127 insertions(+), 55 deletions(-) rename lua/nvim-tree/renderer/decorator/{bookmark.lua => bookmarks.lua} (59%) create mode 100644 lua/nvim-tree/renderer/decorator/diagnostics.lua diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 6e94722c98e..648f52bb7e4 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -5,7 +5,6 @@ local notify = require "nvim-tree.notify" local git = require "nvim-tree.renderer.components.git" local pad = require "nvim-tree.renderer.components.padding" local icons = require "nvim-tree.renderer.components.icons" -local diagnostics = require "nvim-tree.renderer.components.diagnostics" local HL_POSITION = require("nvim-tree.enum").HL_POSITION local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT @@ -74,14 +73,6 @@ function Builder:configure_git_icons_placement(where) return self end -function Builder:configure_diagnostics_icon_placement(where) - if where ~= "after" and where ~= "before" and where ~= "signcolumn" then - where = "before" -- default before - end - self.diagnostics_placement = where - return self -end - function Builder:configure_symlink_destination(show) self.symlink_destination = show return self @@ -236,8 +227,8 @@ end ---@param node table ---@return HighlightedString[]|nil icon function Builder:_get_diagnostics_icon(node) - local diagnostics_icon = diagnostics.get_icon(node) - if diagnostics_icon and self.diagnostics_placement == "signcolumn" then + local diagnostics_icon = self.decorators.diagnostics:get_icon(node) + if diagnostics_icon and self.decorators.diagnostics.icon_placement == ICON_PLACEMENT.signcolumn then table.insert(self.signs, { sign = diagnostics_icon.hl[1], lnum = self.index + 1, @@ -266,8 +257,8 @@ end ---@param node table ---@return HighlightedString[]|nil icon function Builder:_get_bookmark_icon(node) - local bookmark_icon = self.decorators.bookmark:get_icon(node) - if bookmark_icon and self.decorators.bookmark.icon_placement == ICON_PLACEMENT.signcolumn then + local bookmark_icon = self.decorators.bookmarks:get_icon(node) + if bookmark_icon and self.decorators.bookmarks.icon_placement == ICON_PLACEMENT.signcolumn then table.insert(self.signs, { sign = bookmark_icon.hl[1], lnum = self.index + 1, @@ -319,12 +310,12 @@ end ---@param icon_hl string[] icons to append to ---@param name_hl string[] names to append to function Builder:_append_dec_highlight(node, decorator, icon_hl, name_hl) - local pos, hl = decorator:get_highlight(node) - if pos ~= HL_POSITION.none and hl then - if pos == HL_POSITION.all or pos == HL_POSITION.icon then + local hl = decorator:get_highlight(node) + if hl then + if decorator.hl_pos == HL_POSITION.all or decorator.hl_pos == HL_POSITION.icon then table.insert(icon_hl, hl) end - if pos == HL_POSITION.all or pos == HL_POSITION.name then + if decorator.hl_pos == HL_POSITION.all or decorator.hl_pos == HL_POSITION.name then table.insert(name_hl, hl) end end @@ -365,10 +356,10 @@ function Builder:_format_line(indent_markers, arrows, icon, name, git_icons, dia if modified_icon and self.decorators.modified.icon_placement == ICON_PLACEMENT.before then add_to_end(line, { modified_icon }) end - if diagnostics_icon and self.diagnostics_placement == "before" then + if diagnostics_icon and self.decorators.diagnostics.icon_placement == ICON_PLACEMENT.before then add_to_end(line, { diagnostics_icon }) end - if bookmark_icon and self.decorators.bookmark.icon_placement == ICON_PLACEMENT.before then + if bookmark_icon and self.decorators.bookmarks.icon_placement == ICON_PLACEMENT.before then add_to_end(line, { bookmark_icon }) end @@ -380,10 +371,10 @@ function Builder:_format_line(indent_markers, arrows, icon, name, git_icons, dia if modified_icon and self.decorators.modified.icon_placement == ICON_PLACEMENT.after then add_to_end(line, { modified_icon }) end - if diagnostics_icon and self.diagnostics_placement == "after" then + if diagnostics_icon and self.decorators.diagnostics.icon_placement == ICON_PLACEMENT.after then add_to_end(line, { diagnostics_icon }) end - if bookmark_icon and self.decorators.bookmark.icon_placement == ICON_PLACEMENT.after then + if bookmark_icon and self.decorators.bookmarks.icon_placement == ICON_PLACEMENT.after then add_to_end(line, { bookmark_icon }) end @@ -427,8 +418,8 @@ function Builder:_build_line(node, idx, num_children, unloaded_bufnr) -- extra highighting self:_append_highlight(node, git.get_highlight, icon.hl, name.hl) self:_append_dec_highlight(node, self.decorators.modified, icon.hl, name.hl) - self:_append_dec_highlight(node, self.decorators.bookmark, icon.hl, name.hl) - self:_append_highlight(node, diagnostics.get_highlight, icon.hl, name.hl) + self:_append_dec_highlight(node, self.decorators.bookmarks, icon.hl, name.hl) + self:_append_dec_highlight(node, self.decorators.diagnostics, icon.hl, name.hl) self:_append_highlight(node, copy_paste.get_highlight, icon.hl, name.hl) local line = self:_format_line(indent_markers, arrows, icon, name, git_icons, diagnostics_icon, modified_icon, bookmark_icon) diff --git a/lua/nvim-tree/renderer/decorator/bookmark.lua b/lua/nvim-tree/renderer/decorator/bookmarks.lua similarity index 59% rename from lua/nvim-tree/renderer/decorator/bookmark.lua rename to lua/nvim-tree/renderer/decorator/bookmarks.lua index de62d85ae95..b41dbd45508 100644 --- a/lua/nvim-tree/renderer/decorator/bookmark.lua +++ b/lua/nvim-tree/renderer/decorator/bookmarks.lua @@ -5,18 +5,18 @@ local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT local Decorator = require "nvim-tree.renderer.decorator" ---- @class DecoratorBookmark: Decorator +--- @class DecoratorBookmarks: Decorator --- @field icon HighlightedString -local DecoratorBookmark = Decorator:new() +local DecoratorBookmarks = Decorator:new() --- @param opts table ---- @return DecoratorBookmark -function DecoratorBookmark:new(opts) +--- @return DecoratorBookmarks +function DecoratorBookmarks:new(opts) local o = Decorator.new(self, { hl_pos = HL_POSITION[opts.renderer.highlight_bookmarks] or HL_POSITION.none, icon_placement = ICON_PLACEMENT[opts.renderer.icons.bookmarks_placement] or ICON_PLACEMENT.none, }) - ---@cast o DecoratorBookmark + ---@cast o DecoratorBookmarks if opts.renderer.icons.show.bookmarks then o.icon = { @@ -29,25 +29,18 @@ function DecoratorBookmark:new(opts) return o end ---- Bookmark icon: renderer.icons.show.bookmarks and node is marked -function DecoratorBookmark:get_icon(node) +--- Bookmark icon: renderer.icons.show.bookmarks and node is marked +function DecoratorBookmarks:get_icon(node) if marks.get_mark(node) then return self.icon end end --- Bookmark highlight: renderer.highlight_bookmarks and node is marked -function DecoratorBookmark:get_highlight(node) - if self.hl_pos == HL_POSITION.none then - return HL_POSITION.none, nil - end - - local mark = marks.get_mark(node) - if mark then - return self.hl_pos, "NvimTreeBookmarkHL" - else - return HL_POSITION.none, nil +function DecoratorBookmarks:get_highlight(node) + if self.hl_pos ~= HL_POSITION.none and marks.get_mark(node) then + return "NvimTreeBookmarkHL" end end -return DecoratorBookmark +return DecoratorBookmarks diff --git a/lua/nvim-tree/renderer/decorator/diagnostics.lua b/lua/nvim-tree/renderer/decorator/diagnostics.lua new file mode 100644 index 00000000000..9fe2edc9065 --- /dev/null +++ b/lua/nvim-tree/renderer/decorator/diagnostics.lua @@ -0,0 +1,93 @@ +local HL_POSITION = require("nvim-tree.enum").HL_POSITION +local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT + +local Decorator = require "nvim-tree.renderer.decorator" + +-- highlight groups by severity +local HG_ICON = { + [vim.diagnostic.severity.ERROR] = "NvimTreeDiagnosticErrorIcon", + [vim.diagnostic.severity.WARN] = "NvimTreeDiagnosticWarningIcon", + [vim.diagnostic.severity.INFO] = "NvimTreeDiagnosticInfoIcon", + [vim.diagnostic.severity.HINT] = "NvimTreeDiagnosticHintIcon", +} +local HG_FILE = { + [vim.diagnostic.severity.ERROR] = "NvimTreeDiagnosticErrorFileHL", + [vim.diagnostic.severity.WARN] = "NvimTreeDiagnosticWarningFileHL", + [vim.diagnostic.severity.INFO] = "NvimTreeDiagnosticInfoFileHL", + [vim.diagnostic.severity.HINT] = "NvimTreeDiagnosticHintFileHL", +} +local HG_FOLDER = { + [vim.diagnostic.severity.ERROR] = "NvimTreeDiagnosticErrorFolderHL", + [vim.diagnostic.severity.WARN] = "NvimTreeDiagnosticWarningFolderHL", + [vim.diagnostic.severity.INFO] = "NvimTreeDiagnosticInfoFolderHL", + [vim.diagnostic.severity.HINT] = "NvimTreeDiagnosticHintFolderHL", +} +-- opts.diagnostics.icons. +local ICON_KEYS = { + ["error"] = vim.diagnostic.severity.ERROR, + ["warning"] = vim.diagnostic.severity.WARN, + ["info"] = vim.diagnostic.severity.INFO, + ["hint"] = vim.diagnostic.severity.HINT, +} + +--- @class DecoratorDiagnostics: Decorator +--- @field enabled boolean +--- @field icons HighlightedString[] +local DecoratorDiagnostics = Decorator:new() + +--- @param opts table +--- @return DecoratorDiagnostics +function DecoratorDiagnostics:new(opts) + local o = Decorator.new(self, { + hl_pos = HL_POSITION[opts.renderer.highlight_diagnostics] or HL_POSITION.none, + icon_placement = ICON_PLACEMENT[opts.renderer.icons.diagnostics_placement] or ICON_PLACEMENT.none, + }) + ---@cast o DecoratorDiagnostics + + o.enabled = opts.diagnostics.enable + if not o.enabled then + return o + end + + if opts.renderer.icons.show.diagnostics then + o.icons = {} + for name, sev in pairs(ICON_KEYS) do + o.icons[sev] = { + str = opts.diagnostics.icons[name], + hl = { HG_ICON[sev] }, + } + o:define_sign(o.icons[sev]) + end + end + + return o +end + +--- Diagnostic icon: diagnostics.enable, renderer.icons.show.diagnostics and node has status +function DecoratorDiagnostics:get_icon(node) + if node and self.enabled and self.icons then + return self.icons[node.diag_status] + end +end + +--- Diagnostic highlight: diagnostics.enable, renderer.highlight_diagnostics and node has status +function DecoratorDiagnostics:get_highlight(node) + if not node or not self.enabled or self.hl_pos == HL_POSITION.none then + return nil + end + + local group + if node.nodes then + group = HG_FOLDER[node.diag_status] + else + group = HG_FILE[node.diag_status] + end + + if group then + return group + else + return nil + end +end + +return DecoratorDiagnostics diff --git a/lua/nvim-tree/renderer/decorator/init.lua b/lua/nvim-tree/renderer/decorator/init.lua index bfacc5a440f..ee409239ce7 100644 --- a/lua/nvim-tree/renderer/decorator/init.lua +++ b/lua/nvim-tree/renderer/decorator/init.lua @@ -20,15 +20,15 @@ end --- @return HighlightedString|nil modified icon function Decorator:get_icon(node) end ---- Node highlight +--- Node highlight group --- @param node table ---- @return HL_POSITION|nil position --- @return string|nil group function Decorator:get_highlight(node) end ---@diagnostic enable: unused-local --- Define a sign +--- @protected --- @param icon HighlightedString|nil function Decorator:define_sign(icon) if icon and #icon.hl > 0 then diff --git a/lua/nvim-tree/renderer/decorator/modified.lua b/lua/nvim-tree/renderer/decorator/modified.lua index c411dcab2cb..0b58f035e80 100644 --- a/lua/nvim-tree/renderer/decorator/modified.lua +++ b/lua/nvim-tree/renderer/decorator/modified.lua @@ -45,13 +45,13 @@ end --- Modified highlight: modified.enable, renderer.highlight_modified and node is modified function DecoratorModified:get_highlight(node) if not self.enabled or self.hl_pos == HL_POSITION.none or not modified.is_modified(node) then - return HL_POSITION.none, nil + return nil end if node.nodes then - return self.hl_pos, "NvimTreeModifiedFolderHL" + return "NvimTreeModifiedFolderHL" else - return self.hl_pos, "NvimTreeModifiedFileHL" + return "NvimTreeModifiedFileHL" end end diff --git a/lua/nvim-tree/renderer/init.lua b/lua/nvim-tree/renderer/init.lua index 3cc99ac6b8a..f0069f2bc16 100644 --- a/lua/nvim-tree/renderer/init.lua +++ b/lua/nvim-tree/renderer/init.lua @@ -7,11 +7,11 @@ local _padding = require "nvim-tree.renderer.components.padding" local icon_component = require "nvim-tree.renderer.components.icons" local full_name = require "nvim-tree.renderer.components.full-name" local git = require "nvim-tree.renderer.components.git" -local diagnostics = require "nvim-tree.renderer.components.diagnostics" local Builder = require "nvim-tree.renderer.builder" local live_filter = require "nvim-tree.live-filter" -local DecoratorBookmark = require "nvim-tree.renderer.decorator.bookmark" +local DecoratorBookmarks = require "nvim-tree.renderer.decorator.bookmarks" +local DecoratorDiagnostics = require "nvim-tree.renderer.decorator.diagnostics" local DecoratorModified = require "nvim-tree.renderer.decorator.modified" local M = { @@ -76,7 +76,6 @@ function M.draw(unloaded_bufnr) :configure_opened_file_highlighting(M.config.highlight_opened_files) :configure_icon_padding(M.config.icons.padding) :configure_git_icons_placement(M.config.icons.git_placement) - :configure_diagnostics_icon_placement(M.config.icons.diagnostics_placement) :configure_symlink_destination(M.config.symlink_destination) :configure_filter(live_filter.filter, live_filter.prefix) :configure_group_name_modifier(M.config.group_empty) @@ -105,18 +104,14 @@ function M.setup(opts) _padding.setup(opts) full_name.setup(opts) git.setup(opts) - diagnostics.setup(opts) icon_component.setup(opts) -- TODO change to array: precedence should follow order M.decorators = { - bookmark = DecoratorBookmark:new(opts), + bookmarks = DecoratorBookmarks:new(opts), + diagnostics = DecoratorDiagnostics:new(opts), modified = DecoratorModified:new(opts), } - - for _, d in pairs(M.decorators) do - log.line("dev", "d = %s", vim.inspect(d)) - end end return M From f9be51153904fcca2d3827ab3666ca1b3e72ac85 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Mon, 23 Oct 2023 17:14:56 +1100 Subject: [PATCH 07/37] feat(#2415): create DecoratorGit --- lua/nvim-tree/renderer/builder.lua | 5 +- .../{components => decorator}/git.lua | 87 +++++++++++-------- lua/nvim-tree/renderer/init.lua | 4 +- 3 files changed, 53 insertions(+), 43 deletions(-) rename lua/nvim-tree/renderer/{components => decorator}/git.lua (74%) diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 648f52bb7e4..2a74b6b393b 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -2,7 +2,6 @@ local utils = require "nvim-tree.utils" local core = require "nvim-tree.core" local notify = require "nvim-tree.notify" -local git = require "nvim-tree.renderer.components.git" local pad = require "nvim-tree.renderer.components.padding" local icons = require "nvim-tree.renderer.components.icons" @@ -212,7 +211,7 @@ end ---@param node table ---@return HighlightedString[]|nil icon function Builder:_get_git_icons(node) - local git_icons = git.get_icons(node) + local git_icons = self.decorators.git:get_icons(node) if git_icons and #git_icons > 0 and self.git_placement == "signcolumn" then table.insert(self.signs, { sign = git_icons[1].hl[1], @@ -416,7 +415,7 @@ function Builder:_build_line(node, idx, num_children, unloaded_bufnr) end -- extra highighting - self:_append_highlight(node, git.get_highlight, icon.hl, name.hl) + self:_append_dec_highlight(node, self.decorators.git, icon.hl, name.hl) self:_append_dec_highlight(node, self.decorators.modified, icon.hl, name.hl) self:_append_dec_highlight(node, self.decorators.bookmarks, icon.hl, name.hl) self:_append_dec_highlight(node, self.decorators.diagnostics, icon.hl, name.hl) diff --git a/lua/nvim-tree/renderer/components/git.lua b/lua/nvim-tree/renderer/decorator/git.lua similarity index 74% rename from lua/nvim-tree/renderer/components/git.lua rename to lua/nvim-tree/renderer/decorator/git.lua index 1aad1c02132..62e7070cb14 100644 --- a/lua/nvim-tree/renderer/components/git.lua +++ b/lua/nvim-tree/renderer/decorator/git.lua @@ -2,11 +2,16 @@ local notify = require "nvim-tree.notify" local explorer_node = require "nvim-tree.explorer.node" local HL_POSITION = require("nvim-tree.enum").HL_POSITION +local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT -local M = { - -- position for HL - HL_POS = HL_POSITION.none, -} +local Decorator = require "nvim-tree.renderer.decorator" + +--- @class DecoratorGit: Decorator +--- @field enabled boolean +--- @field file_hl string[] +--- @field folder_hl string[] +--- @field git_icons table +local DecoratorGit = Decorator:new() local function build_icons_table(i) local icons = { @@ -106,14 +111,37 @@ local function setup_signs(i) vim.fn.sign_define("NvimTreeGitIgnoredIcon", { text = i.ignored, texthl = "NvimTreeGitIgnoredIcon" }) end -local function warn_status(git_status) - notify.warn(string.format("Unrecognized git state '%s'", git_status)) +--- @param opts table +--- @return DecoratorGit +function DecoratorGit:new(opts) + local o = Decorator.new(self, { + hl_pos = HL_POSITION[opts.renderer.highlight_git] or HL_POSITION.none, + icon_placement = ICON_PLACEMENT[opts.renderer.icons.git_placement] or ICON_PLACEMENT.none, + }) + ---@cast o DecoratorGit + + o.enabled = opts.git.enable + if not o.enabled then + return o + end + + if o.hl_pos ~= HL_POSITION.none then + o.file_hl, o.folder_hl = build_hl_table() + end + + if opts.renderer.icons.show.git then + o.git_icons = build_icons_table(opts.renderer.icons.glyphs.git) + setup_signs(opts.renderer.icons.glyphs.git) + end + + return o end ----@param node table ----@return HighlightedString[]|nil -function M.get_icons(node) - if not M.config.icons.show.git then +--- Git icons: git.enable, renderer.icons.show.git and node has status +--- @param node table +--- @return HighlightedString[]|nil modified icon +function DecoratorGit:get_icons(node) + if not node or not self.enabled or not self.git_icons then return nil end @@ -126,10 +154,10 @@ function M.get_icons(node) local iconss = {} for _, s in pairs(git_status) do - local icons = M.git_icons[s] + local icons = self.git_icons[s] if not icons then - if not M.config.highlight_git then - warn_status(s) + if self.hl_pos == HL_POSITION.none then + notify.warn(string.format("Unrecognized git state '%s'", git_status)) end return nil end @@ -156,39 +184,22 @@ function M.get_icons(node) return iconss end ----Git highlight group and position when highlight_git ----@param node table ----@return HL_POSITION position none when no status ----@return string|nil group only when status -function M.get_highlight(node) - if not node or M.HL_POS == HL_POSITION.none then - return HL_POSITION.none, nil +--- Git highlight: git.enable, renderer.highlight_git and node has status +function DecoratorGit:get_highlight(node) + if not node or not self.enabled or self.hl_pos == HL_POSITION.none then + return nil end local git_status = explorer_node.get_git_status(node) if not git_status then - return HL_POSITION.none, nil + return nil end if node.nodes then - return M.HL_POS, M.folder_hl[git_status[1]] + return self.folder_hl[git_status[1]] else - return M.HL_POS, M.file_hl[git_status[1]] - end -end - -function M.setup(opts) - M.config = opts.renderer - - M.git_icons = build_icons_table(opts.renderer.icons.glyphs.git) - - M.file_hl, M.folder_hl = build_hl_table() - - setup_signs(opts.renderer.icons.glyphs.git) - - if opts.git.enable and opts.renderer.highlight_git then - M.HL_POS = HL_POSITION[opts.renderer.highlight_git] + return self.file_hl[git_status[1]] end end -return M +return DecoratorGit diff --git a/lua/nvim-tree/renderer/init.lua b/lua/nvim-tree/renderer/init.lua index f0069f2bc16..a79b9fb0896 100644 --- a/lua/nvim-tree/renderer/init.lua +++ b/lua/nvim-tree/renderer/init.lua @@ -6,12 +6,12 @@ local events = require "nvim-tree.events" local _padding = require "nvim-tree.renderer.components.padding" local icon_component = require "nvim-tree.renderer.components.icons" local full_name = require "nvim-tree.renderer.components.full-name" -local git = require "nvim-tree.renderer.components.git" local Builder = require "nvim-tree.renderer.builder" local live_filter = require "nvim-tree.live-filter" local DecoratorBookmarks = require "nvim-tree.renderer.decorator.bookmarks" local DecoratorDiagnostics = require "nvim-tree.renderer.decorator.diagnostics" +local DecoratorGit = require "nvim-tree.renderer.decorator.git" local DecoratorModified = require "nvim-tree.renderer.decorator.modified" local M = { @@ -103,11 +103,11 @@ function M.setup(opts) _padding.setup(opts) full_name.setup(opts) - git.setup(opts) icon_component.setup(opts) -- TODO change to array: precedence should follow order M.decorators = { + git = DecoratorGit:new(opts), bookmarks = DecoratorBookmarks:new(opts), diagnostics = DecoratorDiagnostics:new(opts), modified = DecoratorModified:new(opts), From 3f128e347705ffcef68574752035e716f57c1906 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Mon, 23 Oct 2023 17:18:58 +1100 Subject: [PATCH 08/37] feat(#2415): create DecoratorGit --- lua/nvim-tree/renderer/builder.lua | 14 +++----------- lua/nvim-tree/renderer/init.lua | 1 - 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 2a74b6b393b..8099f46293d 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -64,14 +64,6 @@ function Builder:configure_icon_padding(padding) return self end -function Builder:configure_git_icons_placement(where) - if where ~= "after" and where ~= "before" and where ~= "signcolumn" then - where = "before" -- default before - end - self.git_placement = where - return self -end - function Builder:configure_symlink_destination(show) self.symlink_destination = show return self @@ -212,7 +204,7 @@ end ---@return HighlightedString[]|nil icon function Builder:_get_git_icons(node) local git_icons = self.decorators.git:get_icons(node) - if git_icons and #git_icons > 0 and self.git_placement == "signcolumn" then + if git_icons and #git_icons > 0 and self.decorators.git.icon_placement == ICON_PLACEMENT.signcolumn then table.insert(self.signs, { sign = git_icons[1].hl[1], lnum = self.index + 1, @@ -349,7 +341,7 @@ function Builder:_format_line(indent_markers, arrows, icon, name, git_icons, dia local line = { indent_markers, arrows } add_to_end(line, { icon }) - if git_icons and self.git_placement == "before" then + if git_icons and self.decorators.git.icon_placement == ICON_PLACEMENT.before then add_to_end(line, git_icons) end if modified_icon and self.decorators.modified.icon_placement == ICON_PLACEMENT.before then @@ -364,7 +356,7 @@ function Builder:_format_line(indent_markers, arrows, icon, name, git_icons, dia add_to_end(line, { name }) - if git_icons and self.git_placement == "after" then + if git_icons and self.decorators.git.icon_placement == ICON_PLACEMENT.after then add_to_end(line, git_icons) end if modified_icon and self.decorators.modified.icon_placement == ICON_PLACEMENT.after then diff --git a/lua/nvim-tree/renderer/init.lua b/lua/nvim-tree/renderer/init.lua index a79b9fb0896..b97269f8410 100644 --- a/lua/nvim-tree/renderer/init.lua +++ b/lua/nvim-tree/renderer/init.lua @@ -75,7 +75,6 @@ function M.draw(unloaded_bufnr) :configure_picture_map(picture_map) :configure_opened_file_highlighting(M.config.highlight_opened_files) :configure_icon_padding(M.config.icons.padding) - :configure_git_icons_placement(M.config.icons.git_placement) :configure_symlink_destination(M.config.symlink_destination) :configure_filter(live_filter.filter, live_filter.prefix) :configure_group_name_modifier(M.config.group_empty) From 4a7d84986f4fc3589a74d9db20cafd791df4c8b5 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Mon, 6 Nov 2023 11:53:41 +1100 Subject: [PATCH 09/37] add DecoratorCopied DecoratorCut --- doc/nvim-tree-lua.txt | 2 +- lua/nvim-tree/actions/fs/copy-paste.lua | 33 ++++++------------- lua/nvim-tree/renderer/builder.lua | 5 ++- lua/nvim-tree/renderer/decorator/copied.lua | 35 +++++++++++++++++++++ lua/nvim-tree/renderer/decorator/cut.lua | 35 +++++++++++++++++++++ lua/nvim-tree/renderer/init.lua | 6 +++- 6 files changed, 88 insertions(+), 28 deletions(-) create mode 100644 lua/nvim-tree/renderer/decorator/copied.lua create mode 100644 lua/nvim-tree/renderer/decorator/cut.lua diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index 427ec3cb167..a1979b713d5 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -791,7 +791,7 @@ Use nvim-tree in a floating window. 5.3 OPTS: RENDERER *nvim-tree-opts-renderer* Highlight precedence: - clipboard > diagnostics > bookmarked > modified > opened > git + cut > copied > diagnostics > bookmarked > modified > opened > git *nvim-tree.renderer.add_trailing* Appends a trailing slash to folder names. diff --git a/lua/nvim-tree/actions/fs/copy-paste.lua b/lua/nvim-tree/actions/fs/copy-paste.lua index 2c6d701dab1..099e227277e 100644 --- a/lua/nvim-tree/actions/fs/copy-paste.lua +++ b/lua/nvim-tree/actions/fs/copy-paste.lua @@ -7,8 +7,6 @@ local notify = require "nvim-tree.notify" local renderer = require "nvim-tree.renderer" local reloaders = require "nvim-tree.actions.reloaders" -local HL_POSITION = require("nvim-tree.enum").HL_POSITION - local find_file = require("nvim-tree.actions.finders.find-file").fn local M = { @@ -317,34 +315,23 @@ function M.copy_absolute_path(node) copy_to_clipboard(content) end ---- Clipboard text highlight group and position when highlight_clipboard. +---Node is cut. May also be copied. ---@param node Node ----@return HL_POSITION position none when clipboard empty ----@return string|nil group only when node present in clipboard -function M.get_highlight(node) - if M.hl_pos == HL_POSITION.none then - return HL_POSITION.none, nil - end - - for _, n in ipairs(clipboard.cut) do - if node == n then - return M.hl_pos, "NvimTreeCutHL" - end - end - - for _, n in ipairs(clipboard.copy) do - if node == n then - return M.hl_pos, "NvimTreeCopiedHL" - end - end +---@return boolean +function M.is_cut(node) + return vim.tbl_contains(clipboard.cut, node) +end - return HL_POSITION.none, nil +---Node is copied. May also be cut. +---@param node Node +---@return boolean +function M.is_copied(node) + return vim.tbl_contains(clipboard.copy, node) end function M.setup(opts) M.config.filesystem_watchers = opts.filesystem_watchers M.config.actions = opts.actions - M.hl_pos = HL_POSITION[opts.renderer.highlight_clipboard] or HL_POSITION.none end return M diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 8099f46293d..7ca32856832 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -373,8 +373,6 @@ function Builder:_format_line(indent_markers, arrows, icon, name, git_icons, dia end function Builder:_build_line(node, idx, num_children, unloaded_bufnr) - local copy_paste = require "nvim-tree.actions.fs.copy-paste" - -- various components local indent_markers = pad.get_indent_markers(self.depth, idx, num_children, node, self.markers) local arrows = pad.get_arrows(node) @@ -411,7 +409,8 @@ function Builder:_build_line(node, idx, num_children, unloaded_bufnr) self:_append_dec_highlight(node, self.decorators.modified, icon.hl, name.hl) self:_append_dec_highlight(node, self.decorators.bookmarks, icon.hl, name.hl) self:_append_dec_highlight(node, self.decorators.diagnostics, icon.hl, name.hl) - self:_append_highlight(node, copy_paste.get_highlight, icon.hl, name.hl) + self:_append_dec_highlight(node, self.decorators.copied, icon.hl, name.hl) + self:_append_dec_highlight(node, self.decorators.cut, icon.hl, name.hl) local line = self:_format_line(indent_markers, arrows, icon, name, git_icons, diagnostics_icon, modified_icon, bookmark_icon) self:_insert_line(self:_unwrap_highlighted_strings(line)) diff --git a/lua/nvim-tree/renderer/decorator/copied.lua b/lua/nvim-tree/renderer/decorator/copied.lua new file mode 100644 index 00000000000..bd5a078d4aa --- /dev/null +++ b/lua/nvim-tree/renderer/decorator/copied.lua @@ -0,0 +1,35 @@ +local copy_paste + +local HL_POSITION = require("nvim-tree.enum").HL_POSITION +local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT + +local Decorator = require "nvim-tree.renderer.decorator" + +--- @class DecoratorCopied: Decorator +--- @field enabled boolean +--- @field icon HighlightedString|nil +local DecoratorCopied = Decorator:new() + +--- @param opts table +--- @return DecoratorCopied +function DecoratorCopied:new(opts) + local o = Decorator.new(self, { + hl_pos = HL_POSITION[opts.renderer.highlight_clipboard] or HL_POSITION.none, + icon_placement = ICON_PLACEMENT.none, + }) + ---@cast o DecoratorCopied + + -- cyclic + copy_paste = copy_paste or require "nvim-tree.actions.fs.copy-paste" + + return o +end + +--- Cut highlight: renderer.highlight_clipboard and node is copied +function DecoratorCopied:get_highlight(node) + if self.hl_pos ~= HL_POSITION.none and copy_paste.is_copied(node) then + return "NvimTreeCopiedHL" + end +end + +return DecoratorCopied diff --git a/lua/nvim-tree/renderer/decorator/cut.lua b/lua/nvim-tree/renderer/decorator/cut.lua new file mode 100644 index 00000000000..bfac11a40cb --- /dev/null +++ b/lua/nvim-tree/renderer/decorator/cut.lua @@ -0,0 +1,35 @@ +local copy_paste + +local HL_POSITION = require("nvim-tree.enum").HL_POSITION +local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT + +local Decorator = require "nvim-tree.renderer.decorator" + +--- @class DecoratorCut: Decorator +--- @field enabled boolean +--- @field icon HighlightedString|nil +local DecoratorCut = Decorator:new() + +--- @param opts table +--- @return DecoratorCut +function DecoratorCut:new(opts) + local o = Decorator.new(self, { + hl_pos = HL_POSITION[opts.renderer.highlight_clipboard] or HL_POSITION.none, + icon_placement = ICON_PLACEMENT.none, + }) + ---@cast o DecoratorCut + + -- cyclic + copy_paste = copy_paste or require "nvim-tree.actions.fs.copy-paste" + + return o +end + +--- Cut highlight: renderer.highlight_clipboard and node is cut +function DecoratorCut:get_highlight(node) + if self.hl_pos ~= HL_POSITION.none and copy_paste.is_cut(node) then + return "NvimTreeCutHL" + end +end + +return DecoratorCut diff --git a/lua/nvim-tree/renderer/init.lua b/lua/nvim-tree/renderer/init.lua index b97269f8410..9eb95e2fcd1 100644 --- a/lua/nvim-tree/renderer/init.lua +++ b/lua/nvim-tree/renderer/init.lua @@ -10,6 +10,8 @@ local Builder = require "nvim-tree.renderer.builder" local live_filter = require "nvim-tree.live-filter" local DecoratorBookmarks = require "nvim-tree.renderer.decorator.bookmarks" +local DecoratorCopied = require "nvim-tree.renderer.decorator.copied" +local DecoratorCut = require "nvim-tree.renderer.decorator.cut" local DecoratorDiagnostics = require "nvim-tree.renderer.decorator.diagnostics" local DecoratorGit = require "nvim-tree.renderer.decorator.git" local DecoratorModified = require "nvim-tree.renderer.decorator.modified" @@ -106,9 +108,11 @@ function M.setup(opts) -- TODO change to array: precedence should follow order M.decorators = { - git = DecoratorGit:new(opts), bookmarks = DecoratorBookmarks:new(opts), + copied = DecoratorCopied:new(opts), + cut = DecoratorCut:new(opts), diagnostics = DecoratorDiagnostics:new(opts), + git = DecoratorGit:new(opts), modified = DecoratorModified:new(opts), } end From 3ab6dca3d39ad617264345407411ea6a35451ef3 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Mon, 6 Nov 2023 15:43:02 +1100 Subject: [PATCH 10/37] add DecoratorOpened --- doc/nvim-tree-lua.txt | 4 ++ lua/nvim-tree.lua | 4 +- lua/nvim-tree/actions/reloaders.lua | 13 ++-- lua/nvim-tree/buffers.lua | 64 +++++++++++++++++++ lua/nvim-tree/colors.lua | 5 ++ lua/nvim-tree/renderer/builder.lua | 58 ++--------------- lua/nvim-tree/renderer/decorator/init.lua | 16 +++-- lua/nvim-tree/renderer/decorator/modified.lua | 6 +- lua/nvim-tree/renderer/decorator/opened.lua | 33 ++++++++++ lua/nvim-tree/renderer/init.lua | 9 ++- 10 files changed, 138 insertions(+), 74 deletions(-) create mode 100644 lua/nvim-tree/buffers.lua create mode 100644 lua/nvim-tree/renderer/decorator/opened.lua diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index a1979b713d5..f60313fd7fc 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -2305,6 +2305,9 @@ Modified: > NvimTreeModifiedFileHL NvimTreeModifiedIcon NvimTreeModifiedFolderHL NvimTreeModifiedIcon < +Opened: > + NvimTreeOpenedHL Constant +< Picker: > NvimTreeWindowPicker guifg=#ededed guibg=#4493c8 gui=bold ctermfg=White ctermbg=Cyan < @@ -2388,6 +2391,7 @@ Legacy highlight group are still obeyed when they are defined and the current highlight group is not, hard linking as follows: > NvimTreeModifiedIcon NvimTreeModifiedFile + NvimTreeOpenedHL NvimTreeOpenedFile NvimTreeGitDeletedIcon NvimTreeGitDeleted NvimTreeGitDirtyIcon NvimTreeGitDirty diff --git a/lua/nvim-tree.lua b/lua/nvim-tree.lua index cfe13124f16..13d0f4b0316 100644 --- a/lua/nvim-tree.lua +++ b/lua/nvim-tree.lua @@ -210,7 +210,7 @@ local function setup_autocommands(opts) -- update opened file buffers if (filters.config.filter_no_buffer or renderer.config.highlight_opened_files ~= "none") and vim.bo[data.buf].buftype == "" then utils.debounce("Buf:filter_buffer", opts.view.debounce_delay, function() - actions.reloaders.reload_explorer(nil, data.buf) + actions.reloaders.reload_explorer() end) end end, @@ -797,7 +797,7 @@ function M.setup(conf) require("nvim-tree.renderer").setup(opts) require("nvim-tree.live-filter").setup(opts) require("nvim-tree.marks").setup(opts) - require("nvim-tree.modified").setup(opts) + require("nvim-tree.buffers").setup(opts) require("nvim-tree.help").setup(opts) require("nvim-tree.watcher").setup(opts) if M.config.renderer.icons.show.file and pcall(require, "nvim-web-devicons") then diff --git a/lua/nvim-tree/actions/reloaders.lua b/lua/nvim-tree/actions/reloaders.lua index 14f4b0394ec..626b280db7f 100644 --- a/lua/nvim-tree/actions/reloaders.lua +++ b/lua/nvim-tree/actions/reloaders.lua @@ -10,13 +10,12 @@ local M = {} ---@param node Explorer|nil ---@param projects table ----@param unloaded_bufnr number|nil -local function refresh_nodes(node, projects, unloaded_bufnr) +local function refresh_nodes(node, projects) Iterator.builder({ node }) :applier(function(n) if n.nodes then local toplevel = git.get_toplevel(n.cwd or n.link_to or n.absolute_path) - explorer_module.reload(n, projects[toplevel] or {}, unloaded_bufnr) + explorer_module.reload(n, projects[toplevel] or {}) end end) :recursor(function(n) @@ -43,18 +42,16 @@ function M.reload_node_status(parent_node, projects) end local event_running = false ----@param _ table|nil unused node passed by action ----@param unloaded_bufnr number|nil optional bufnr recently unloaded via BufUnload event -function M.reload_explorer(_, unloaded_bufnr) +function M.reload_explorer() if event_running or not core.get_explorer() or vim.v.exiting ~= vim.NIL then return end event_running = true local projects = git.reload() - refresh_nodes(core.get_explorer(), projects, unloaded_bufnr) + refresh_nodes(core.get_explorer(), projects) if view.is_visible() then - renderer.draw(unloaded_bufnr) + renderer.draw() end event_running = false end diff --git a/lua/nvim-tree/buffers.lua b/lua/nvim-tree/buffers.lua new file mode 100644 index 00000000000..937ac4c5248 --- /dev/null +++ b/lua/nvim-tree/buffers.lua @@ -0,0 +1,64 @@ +local M = {} + +---@type table record of which file is modified +M._modified = {} + +---@type number unloaded_bufnr for the duration of BufUnload +M._unloaded_bufnr = nil + +---refresh M._modified +function M.reload_modified() + M._modified = {} + local bufs = vim.fn.getbufinfo { bufmodified = true, buflisted = true } + for _, buf in pairs(bufs) do + local path = buf.name + if path ~= "" then -- not a [No Name] buffer + -- mark all the parent as modified as well + while + M._modified[path] ~= true + -- no need to keep going if already recorded + -- This also prevents an infinite loop + do + M._modified[path] = true + path = vim.fn.fnamemodify(path, ":h") + end + end + end +end + +---@param node table +---@return boolean +function M.is_modified(node) + return node + and M.config.modified.enable + and M._modified[node.absolute_path] + and (not node.nodes or M.config.modified.show_on_dirs) + and (not node.open or M.config.modified.show_on_open_dirs) +end + +---A buffer exists for the node's absolute path and it's not in the middle of a BufUnload handler. +---@param node table +---@return boolean +function M.is_opened(node) + return node and vim.fn.bufloaded(node.absolute_path) > 0 and vim.fn.bufnr(node.absolute_path) ~= M._unloaded_bufnr +end + +---Set the unloaded bufnr - at the start of the BufUnload handler. +---@param bufnr number +function M.set_unloaded_bufnr(bufnr) + M._unloaded_bufnr = bufnr +end + +---Reset the unloaded bufnr - at the end of the BufUnload handler. +function M.reset_unloaded_bufnr() + M._unloaded_bufnr = nil +end + +---@param opts table +function M.setup(opts) + M.config = { + modified = opts.modified, + } +end + +return M diff --git a/lua/nvim-tree/colors.lua b/lua/nvim-tree/colors.lua index 0dedf5014af..e6cc6874147 100644 --- a/lua/nvim-tree/colors.lua +++ b/lua/nvim-tree/colors.lua @@ -69,6 +69,9 @@ local DEFAULT_LINKS = { NvimTreeModifiedFileHL = "NvimTreeModifiedIcon", NvimTreeModifiedFolderHL = "NvimTreeModifiedFileHL", + -- Opened + NvimTreeOpenedHL = "Constant", + -- LiveFilter NvimTreeLiveFilterPrefix = "PreProc", NvimTreeLiveFilterValue = "ModeMsg", @@ -123,6 +126,8 @@ local DEFAULT_LINKS = { local LEGACY_LINKS = { NvimTreeModifiedIcon = "NvimTreeModifiedFile", + NvimTreeOpenedHL = "NvimTreeOpenedFile", + NvimTreeGitDeletedIcon = "NvimTreeGitDeleted", NvimTreeGitDirtyIcon = "NvimTreeGitDirty", NvimTreeGitIgnoredIcon = "NvimTreeGitIgnored", diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 7ca32856832..f6b05511802 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -54,11 +54,6 @@ function Builder:configure_filter(filter, prefix) return self end -function Builder:configure_opened_file_highlighting(highlight_opened_files) - self.highlight_opened_files = highlight_opened_files - return self -end - function Builder:configure_icon_padding(padding) self.icon_padding = padding or " " return self @@ -260,41 +255,6 @@ function Builder:_get_bookmark_icon(node) return bookmark_icon end ----@param node table ----@return string|nil icon_hl ----@return string|nil name_hl -function Builder:_get_highlight_override(node, unloaded_bufnr) - local name_hl, icon_hl - - -- opened file - if self.highlight_opened_files and vim.fn.bufloaded(node.absolute_path) > 0 and vim.fn.bufnr(node.absolute_path) ~= unloaded_bufnr then - if self.highlight_opened_files == "all" or self.highlight_opened_files == "name" then - name_hl = "NvimTreeOpenedFile" - end - if self.highlight_opened_files == "all" or self.highlight_opened_files == "icon" then - icon_hl = "NvimTreeOpenedFileIcon" - end - end - return icon_hl, name_hl -end - ----Append optional highlighting to icon or name. ----@param node table ----@param get_hl fun(node: table): HL_POSITION, string ----@param icon_hl string[] icons to append to ----@param name_hl string[] names to append to -function Builder:_append_highlight(node, get_hl, icon_hl, name_hl) - local pos, hl = get_hl(node) - if pos ~= HL_POSITION.none and hl then - if pos == HL_POSITION.all or pos == HL_POSITION.icon then - table.insert(icon_hl, hl) - end - if pos == HL_POSITION.all or pos == HL_POSITION.name then - table.insert(name_hl, hl) - end - end -end - ---Append optional highlighting to icon or name. ---@param node table ---@param decorator Decorator @@ -372,7 +332,7 @@ function Builder:_format_line(indent_markers, arrows, icon, name, git_icons, dia return line end -function Builder:_build_line(node, idx, num_children, unloaded_bufnr) +function Builder:_build_line(node, idx, num_children) -- various components local indent_markers = pad.get_indent_markers(self.depth, idx, num_children, node, self.markers) local arrows = pad.get_arrows(node) @@ -395,17 +355,9 @@ function Builder:_build_line(node, idx, num_children, unloaded_bufnr) icon, name = self:_build_file(node) end - -- highlight override - local icon_hl_override, name_hl_override = self:_get_highlight_override(node, unloaded_bufnr) - if icon_hl_override then - icon.hl = { icon_hl_override } - end - if name_hl_override then - name.hl = { name_hl_override } - end - -- extra highighting self:_append_dec_highlight(node, self.decorators.git, icon.hl, name.hl) + self:_append_dec_highlight(node, self.decorators.opened, icon.hl, name.hl) self:_append_dec_highlight(node, self.decorators.modified, icon.hl, name.hl) self:_append_dec_highlight(node, self.decorators.bookmarks, icon.hl, name.hl) self:_append_dec_highlight(node, self.decorators.diagnostics, icon.hl, name.hl) @@ -421,7 +373,7 @@ function Builder:_build_line(node, idx, num_children, unloaded_bufnr) if node.open then self.depth = self.depth + 1 - self:build(node, unloaded_bufnr) + self:build(node) self.depth = self.depth - 1 end end @@ -440,12 +392,12 @@ function Builder:_get_nodes_number(nodes) return i end -function Builder:build(tree, unloaded_bufnr) +function Builder:build(tree) local num_children = self:_get_nodes_number(tree.nodes) local idx = 1 for _, node in ipairs(tree.nodes) do if not node.hidden then - self:_build_line(node, idx, num_children, unloaded_bufnr) + self:_build_line(node, idx, num_children) idx = idx + 1 end end diff --git a/lua/nvim-tree/renderer/decorator/init.lua b/lua/nvim-tree/renderer/decorator/init.lua index ee409239ce7..b61813451b3 100644 --- a/lua/nvim-tree/renderer/decorator/init.lua +++ b/lua/nvim-tree/renderer/decorator/init.lua @@ -16,14 +16,14 @@ end ---@diagnostic disable: unused-local --- Node icon ---- @param node table +--- @param _ table node --- @return HighlightedString|nil modified icon -function Decorator:get_icon(node) end +function Decorator:get_icon(_) end --- Node highlight group ---- @param node table +--- @param _ table node --- @return string|nil group -function Decorator:get_highlight(node) end +function Decorator:get_highlight(_) end ---@diagnostic enable: unused-local @@ -32,7 +32,13 @@ function Decorator:get_highlight(node) end --- @param icon HighlightedString|nil function Decorator:define_sign(icon) if icon and #icon.hl > 0 then - vim.fn.sign_define(icon.hl[1], { + local name = icon.hl[1] + + if not vim.tbl_isempty(vim.fn.sign_getdefined(name)) then + vim.fn.sign_undefine(name) + end + + vim.fn.sign_define(name, { text = icon.str, texthl = icon.hl[1], }) diff --git a/lua/nvim-tree/renderer/decorator/modified.lua b/lua/nvim-tree/renderer/decorator/modified.lua index 0b58f035e80..4197b60b300 100644 --- a/lua/nvim-tree/renderer/decorator/modified.lua +++ b/lua/nvim-tree/renderer/decorator/modified.lua @@ -1,4 +1,4 @@ -local modified = require "nvim-tree.modified" +local buffers = require "nvim-tree.buffers" local HL_POSITION = require("nvim-tree.enum").HL_POSITION local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT @@ -37,14 +37,14 @@ end --- Modified icon: modified.enable, renderer.icons.show.modified and node is modified function DecoratorModified:get_icon(node) - if self.enabled and modified.is_modified(node) then + if self.enabled and buffers.is_modified(node) then return self.icon end end --- Modified highlight: modified.enable, renderer.highlight_modified and node is modified function DecoratorModified:get_highlight(node) - if not self.enabled or self.hl_pos == HL_POSITION.none or not modified.is_modified(node) then + if not self.enabled or self.hl_pos == HL_POSITION.none or not buffers.is_modified(node) then return nil end diff --git a/lua/nvim-tree/renderer/decorator/opened.lua b/lua/nvim-tree/renderer/decorator/opened.lua new file mode 100644 index 00000000000..9246fd3a8e1 --- /dev/null +++ b/lua/nvim-tree/renderer/decorator/opened.lua @@ -0,0 +1,33 @@ +local buffers = require "nvim-tree.buffers" + +local HL_POSITION = require("nvim-tree.enum").HL_POSITION +local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT + +local Decorator = require "nvim-tree.renderer.decorator" + +--- @class DecoratorOpened: Decorator +--- @field enabled boolean +--- @field icon HighlightedString|nil +local DecoratorOpened = Decorator:new() + +--- @param opts table +--- @return DecoratorOpened +function DecoratorOpened:new(opts) + local o = Decorator.new(self, { + hl_pos = HL_POSITION[opts.renderer.highlight_opened_files] or HL_POSITION.none, + icon_placement = ICON_PLACEMENT.none, + }) + ---@cast o DecoratorOpened + + return o +end + +--- Opened highlight: renderer.highlight_opened_files and node has an open buffer +--- @param node table +function DecoratorOpened:get_highlight(node) + if self.hl_pos ~= HL_POSITION.none and buffers.is_opened(node) then + return "NvimTreeOpenedHL" + end +end + +return DecoratorOpened diff --git a/lua/nvim-tree/renderer/init.lua b/lua/nvim-tree/renderer/init.lua index 9eb95e2fcd1..7f08e6af226 100644 --- a/lua/nvim-tree/renderer/init.lua +++ b/lua/nvim-tree/renderer/init.lua @@ -15,6 +15,7 @@ local DecoratorCut = require "nvim-tree.renderer.decorator.cut" local DecoratorDiagnostics = require "nvim-tree.renderer.decorator.diagnostics" local DecoratorGit = require "nvim-tree.renderer.decorator.git" local DecoratorModified = require "nvim-tree.renderer.decorator.modified" +local DecoratorOpened = require "nvim-tree.renderer.decorator.opened" local M = { last_highlights = {}, @@ -59,7 +60,7 @@ local picture_map = { jxl = true, } -function M.draw(unloaded_bufnr) +function M.draw() local bufnr = view.get_bufnr() if not core.get_explorer() or not bufnr or not vim.api.nvim_buf_is_loaded(bufnr) then return @@ -75,13 +76,12 @@ function M.draw(unloaded_bufnr) :configure_trailing_slash(M.config.add_trailing) :configure_special_files(M.config.special_files) :configure_picture_map(picture_map) - :configure_opened_file_highlighting(M.config.highlight_opened_files) :configure_icon_padding(M.config.icons.padding) :configure_symlink_destination(M.config.symlink_destination) :configure_filter(live_filter.filter, live_filter.prefix) :configure_group_name_modifier(M.config.group_empty) :build_header(view.is_root_folder_visible(core.get_cwd())) - :build(core.get_explorer(), unloaded_bufnr) + :build(core.get_explorer()) :unwrap() _draw(bufnr, lines, hl, signs) @@ -107,6 +107,8 @@ function M.setup(opts) icon_component.setup(opts) -- TODO change to array: precedence should follow order + -- HL cut > copied > diagnostics > bookmarked > modified > opened > git + -- Sign diagnostics > modified > git > bookmarked M.decorators = { bookmarks = DecoratorBookmarks:new(opts), copied = DecoratorCopied:new(opts), @@ -114,6 +116,7 @@ function M.setup(opts) diagnostics = DecoratorDiagnostics:new(opts), git = DecoratorGit:new(opts), modified = DecoratorModified:new(opts), + opened = DecoratorOpened:new(opts), } end From fb2e4f170e6dcd1ee650e88d5bf9bcb83b6b564f Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Mon, 6 Nov 2023 15:46:39 +1100 Subject: [PATCH 11/37] remove unloaded_bufnr checks as the view debouncer takes care of it --- lua/nvim-tree/buffers.lua | 18 ++---------------- lua/nvim-tree/explorer/filters.lua | 16 ++++------------ lua/nvim-tree/explorer/reload.lua | 5 ++--- 3 files changed, 8 insertions(+), 31 deletions(-) diff --git a/lua/nvim-tree/buffers.lua b/lua/nvim-tree/buffers.lua index 937ac4c5248..04f48a05fcc 100644 --- a/lua/nvim-tree/buffers.lua +++ b/lua/nvim-tree/buffers.lua @@ -3,9 +3,6 @@ local M = {} ---@type table record of which file is modified M._modified = {} ----@type number unloaded_bufnr for the duration of BufUnload -M._unloaded_bufnr = nil - ---refresh M._modified function M.reload_modified() M._modified = {} @@ -36,22 +33,11 @@ function M.is_modified(node) and (not node.open or M.config.modified.show_on_open_dirs) end ----A buffer exists for the node's absolute path and it's not in the middle of a BufUnload handler. +---A buffer exists for the node's absolute path ---@param node table ---@return boolean function M.is_opened(node) - return node and vim.fn.bufloaded(node.absolute_path) > 0 and vim.fn.bufnr(node.absolute_path) ~= M._unloaded_bufnr -end - ----Set the unloaded bufnr - at the start of the BufUnload handler. ----@param bufnr number -function M.set_unloaded_bufnr(bufnr) - M._unloaded_bufnr = bufnr -end - ----Reset the unloaded bufnr - at the end of the BufUnload handler. -function M.reset_unloaded_bufnr() - M._unloaded_bufnr = nil + return node and vim.fn.bufloaded(node.absolute_path) > 0 end ---@param opts table diff --git a/lua/nvim-tree/explorer/filters.lua b/lua/nvim-tree/explorer/filters.lua index 18bce0281b5..b05fe4edbdc 100644 --- a/lua/nvim-tree/explorer/filters.lua +++ b/lua/nvim-tree/explorer/filters.lua @@ -47,16 +47,15 @@ end ---Check if the given path has no listed buffer ---@param path string Absolute path ---@param bufinfo table vim.fn.getbufinfo { buflisted = 1 } ----@param unloaded_bufnr number optional bufnr recently unloaded via BufUnload event ---@return boolean -local function buf(path, bufinfo, unloaded_bufnr) +local function buf(path, bufinfo) if not M.config.filter_no_buffer or type(bufinfo) ~= "table" then return false end -- filter files with no open buffer and directories containing no open buffers for _, b in ipairs(bufinfo) do - if b.name == path or b.name:find(path .. "/", 1, true) and b.bufnr ~= unloaded_bufnr then + if b.name == path or b.name:find(path .. "/", 1, true) then return false end end @@ -105,16 +104,13 @@ end ---Prepare arguments for should_filter. This is done prior to should_filter for efficiency reasons. ---@param git_status table|nil optional results of git.load_project_status(...) ----@param unloaded_bufnr number|nil optional bufnr recently unloaded via BufUnload event ---@return table --- git_status: reference ---- unloaded_bufnr: copy --- bufinfo: empty unless no_buffer set: vim.fn.getbufinfo { buflisted = 1 } --- bookmarks: absolute paths to boolean -function M.prepare(git_status, unloaded_bufnr) +function M.prepare(git_status) local status = { git_status = git_status or {}, - unloaded_bufnr = unloaded_bufnr, bufinfo = {}, bookmarks = {}, } @@ -140,11 +136,7 @@ function M.should_filter(path, status) return false end - return git(path, status.git_status) - or buf(path, status.bufinfo, status.unloaded_bufnr) - or dotfile(path) - or custom(path) - or bookmark(path, status.bookmarks) + return git(path, status.git_status) or buf(path, status.bufinfo) or dotfile(path) or custom(path) or bookmark(path, status.bookmarks) end function M.setup(opts) diff --git a/lua/nvim-tree/explorer/reload.lua b/lua/nvim-tree/explorer/reload.lua index d921d033f97..7444491e39f 100644 --- a/lua/nvim-tree/explorer/reload.lua +++ b/lua/nvim-tree/explorer/reload.lua @@ -69,8 +69,7 @@ end ---@param node Node ---@param git_status table ----@param unloaded_bufnr number|nil -function M.reload(node, git_status, unloaded_bufnr) +function M.reload(node, git_status) local cwd = node.link_to or node.absolute_path local handle = vim.loop.fs_scandir(cwd) if not handle then @@ -79,7 +78,7 @@ function M.reload(node, git_status, unloaded_bufnr) local profile = log.profile_start("reload %s", node.absolute_path) - local filter_status = filters.prepare(git_status, unloaded_bufnr) + local filter_status = filters.prepare(git_status) if node.group_next then node.nodes = { node.group_next } From 63410cc2d287e2e70282bee62aeafb7dfad62b01 Mon Sep 17 00:00:00 2001 From: Akmadan23 Date: Thu, 16 Nov 2023 12:18:54 +0100 Subject: [PATCH 12/37] Add `renderer.highlight_git` to accepted strings --- lua/nvim-tree.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/lua/nvim-tree.lua b/lua/nvim-tree.lua index 13d0f4b0316..532d9ed4f98 100644 --- a/lua/nvim-tree.lua +++ b/lua/nvim-tree.lua @@ -641,6 +641,7 @@ local ACCEPTED_STRINGS = { signcolumn = { "yes", "no", "auto" }, }, renderer = { + highlight_git = { "none", "icon", "name", "all" }, highlight_opened_files = { "none", "icon", "name", "all" }, highlight_modified = { "none", "icon", "name", "all" }, highlight_bookmarks = { "none", "icon", "name", "all" }, From 4cf6b11537b603e7082bc47442684b11168dc75c Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sun, 19 Nov 2023 16:58:19 +1100 Subject: [PATCH 13/37] fix(#2415): builder refactor (#2538) * simplify builder signs * decorators take care of themselves and are priority ordered * simplify builder hl groups * refactor builder for icon arrays * builder use decorators generically --- doc/nvim-tree-lua.txt | 2 +- lua/nvim-tree/renderer/builder.lua | 157 ++++-------------- .../renderer/decorator/bookmarks.lua | 7 +- lua/nvim-tree/renderer/decorator/copied.lua | 3 +- lua/nvim-tree/renderer/decorator/cut.lua | 3 +- .../renderer/decorator/diagnostics.lua | 11 +- lua/nvim-tree/renderer/decorator/git.lua | 19 ++- lua/nvim-tree/renderer/decorator/init.lua | 83 ++++++++- lua/nvim-tree/renderer/decorator/modified.lua | 9 +- lua/nvim-tree/renderer/decorator/opened.lua | 3 +- lua/nvim-tree/renderer/init.lua | 31 ++-- 11 files changed, 156 insertions(+), 172 deletions(-) diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index f60313fd7fc..6de5de9419a 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -896,7 +896,7 @@ Configuration options for tree indent markers. Configuration options for icons. Icon sign column precedence: - diagnostics > modified > git > bookmarked + diagnostics > bookmarked > modified > git *nvim-tree.renderer.icons.web_devicons* Configure optional plugin `"nvim-tree/nvim-web-devicons"` diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index f6b05511802..982eeac9c76 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -5,26 +5,23 @@ local notify = require "nvim-tree.notify" local pad = require "nvim-tree.renderer.components.padding" local icons = require "nvim-tree.renderer.components.icons" -local HL_POSITION = require("nvim-tree.enum").HL_POSITION -local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT - --- @class Builder ---- @field decorators Decorator[] +--- @field deco Decorator[] local Builder = {} Builder.__index = Builder local DEFAULT_ROOT_FOLDER_LABEL = ":~:s?$?/..?" -function Builder.new(root_cwd, decorators) +function Builder.new(root_cwd, deco) return setmetatable({ index = 0, depth = 0, highlights = {}, lines = {}, markers = {}, - signs = {}, + sign_names = {}, root_cwd = root_cwd, - decorators = decorators, + deco = deco, }, Builder) end @@ -195,95 +192,18 @@ function Builder:_build_file(node) return icon, { str = node.name, hl = { hl } } end ----@param node table ----@return HighlightedString[]|nil icon -function Builder:_get_git_icons(node) - local git_icons = self.decorators.git:get_icons(node) - if git_icons and #git_icons > 0 and self.decorators.git.icon_placement == ICON_PLACEMENT.signcolumn then - table.insert(self.signs, { - sign = git_icons[1].hl[1], - lnum = self.index + 1, - priority = 1, - }) - git_icons = nil - end - return git_icons -end - ----@param node table ----@return HighlightedString[]|nil icon -function Builder:_get_diagnostics_icon(node) - local diagnostics_icon = self.decorators.diagnostics:get_icon(node) - if diagnostics_icon and self.decorators.diagnostics.icon_placement == ICON_PLACEMENT.signcolumn then - table.insert(self.signs, { - sign = diagnostics_icon.hl[1], - lnum = self.index + 1, - priority = 2, - }) - diagnostics_icon = nil - end - return diagnostics_icon -end - ----@param node table ----@return HighlightedString|nil icon -function Builder:_get_modified_icon(node) - local modified_icon = self.decorators.modified:get_icon(node) - if modified_icon and self.decorators.modified.icon_placement == ICON_PLACEMENT.signcolumn then - table.insert(self.signs, { - sign = modified_icon.hl[1], - lnum = self.index + 1, - priority = 3, - }) - modified_icon = nil - end - return modified_icon -end - ----@param node table ----@return HighlightedString[]|nil icon -function Builder:_get_bookmark_icon(node) - local bookmark_icon = self.decorators.bookmarks:get_icon(node) - if bookmark_icon and self.decorators.bookmarks.icon_placement == ICON_PLACEMENT.signcolumn then - table.insert(self.signs, { - sign = bookmark_icon.hl[1], - lnum = self.index + 1, - priority = 4, - }) - bookmark_icon = nil - end - return bookmark_icon -end - ----Append optional highlighting to icon or name. ----@param node table ----@param decorator Decorator ----@param icon_hl string[] icons to append to ----@param name_hl string[] names to append to -function Builder:_append_dec_highlight(node, decorator, icon_hl, name_hl) - local hl = decorator:get_highlight(node) - if hl then - if decorator.hl_pos == HL_POSITION.all or decorator.hl_pos == HL_POSITION.icon then - table.insert(icon_hl, hl) - end - if decorator.hl_pos == HL_POSITION.all or decorator.hl_pos == HL_POSITION.name then - table.insert(name_hl, hl) - end - end -end - ---@param indent_markers HighlightedString[] ---@param arrows HighlightedString[]|nil ---@param icon HighlightedString ---@param name HighlightedString ----@param git_icons HighlightedString[]|nil ----@param diagnostics_icon HighlightedString|nil ----@param modified_icon HighlightedString|nil ----@param bookmark_icon HighlightedString|nil +---@param node table ---@return HighlightedString[] -function Builder:_format_line(indent_markers, arrows, icon, name, git_icons, diagnostics_icon, modified_icon, bookmark_icon) +function Builder:_format_line(indent_markers, arrows, icon, name, node) local added_len = 0 local function add_to_end(t1, t2) + if not t2 then + return + end for _, v in ipairs(t2) do if added_len > 0 then table.insert(t1, { str = self.icon_padding }) @@ -301,32 +221,15 @@ function Builder:_format_line(indent_markers, arrows, icon, name, git_icons, dia local line = { indent_markers, arrows } add_to_end(line, { icon }) - if git_icons and self.decorators.git.icon_placement == ICON_PLACEMENT.before then - add_to_end(line, git_icons) - end - if modified_icon and self.decorators.modified.icon_placement == ICON_PLACEMENT.before then - add_to_end(line, { modified_icon }) - end - if diagnostics_icon and self.decorators.diagnostics.icon_placement == ICON_PLACEMENT.before then - add_to_end(line, { diagnostics_icon }) - end - if bookmark_icon and self.decorators.bookmarks.icon_placement == ICON_PLACEMENT.before then - add_to_end(line, { bookmark_icon }) + + for i = #self.deco, 1, -1 do + add_to_end(line, self.deco[i]:icons_before(node)) end add_to_end(line, { name }) - if git_icons and self.decorators.git.icon_placement == ICON_PLACEMENT.after then - add_to_end(line, git_icons) - end - if modified_icon and self.decorators.modified.icon_placement == ICON_PLACEMENT.after then - add_to_end(line, { modified_icon }) - end - if diagnostics_icon and self.decorators.diagnostics.icon_placement == ICON_PLACEMENT.after then - add_to_end(line, { diagnostics_icon }) - end - if bookmark_icon and self.decorators.bookmarks.icon_placement == ICON_PLACEMENT.after then - add_to_end(line, { bookmark_icon }) + for i = #self.deco, 1, -1 do + add_to_end(line, self.deco[i]:icons_after(node)) end return line @@ -337,11 +240,15 @@ function Builder:_build_line(node, idx, num_children) local indent_markers = pad.get_indent_markers(self.depth, idx, num_children, node, self.markers) local arrows = pad.get_arrows(node) - -- adds icons to signcolumn - local bookmark_icon = self:_get_bookmark_icon(node) - local git_icons = self:_get_git_icons(node) - local modified_icon = self:_get_modified_icon(node) - local diagnostics_icon = self:_get_diagnostics_icon(node) + -- signs, use the highest priority + local sign_name + for _, d in ipairs(self.deco) do + sign_name = d:sign_name(node) + if sign_name then + self.sign_names[self.index] = sign_name + break + end + end -- main components local is_folder = node.nodes ~= nil @@ -355,16 +262,14 @@ function Builder:_build_line(node, idx, num_children) icon, name = self:_build_file(node) end - -- extra highighting - self:_append_dec_highlight(node, self.decorators.git, icon.hl, name.hl) - self:_append_dec_highlight(node, self.decorators.opened, icon.hl, name.hl) - self:_append_dec_highlight(node, self.decorators.modified, icon.hl, name.hl) - self:_append_dec_highlight(node, self.decorators.bookmarks, icon.hl, name.hl) - self:_append_dec_highlight(node, self.decorators.diagnostics, icon.hl, name.hl) - self:_append_dec_highlight(node, self.decorators.copied, icon.hl, name.hl) - self:_append_dec_highlight(node, self.decorators.cut, icon.hl, name.hl) + -- highighting + for _, d in ipairs(self.deco) do + local icon_group, name_group = d:groups_icon_name(node) + table.insert(icon.hl, icon_group) + table.insert(name.hl, name_group) + end - local line = self:_format_line(indent_markers, arrows, icon, name, git_icons, diagnostics_icon, modified_icon, bookmark_icon) + local line = self:_format_line(indent_markers, arrows, icon, name, node) self:_insert_line(self:_unwrap_highlighted_strings(line)) self.index = self.index + 1 @@ -438,7 +343,7 @@ function Builder:build_header(show_header) end function Builder:unwrap() - return self.lines, self.highlights, self.signs + return self.lines, self.highlights, self.sign_names end return Builder diff --git a/lua/nvim-tree/renderer/decorator/bookmarks.lua b/lua/nvim-tree/renderer/decorator/bookmarks.lua index b41dbd45508..a37b476e0eb 100644 --- a/lua/nvim-tree/renderer/decorator/bookmarks.lua +++ b/lua/nvim-tree/renderer/decorator/bookmarks.lua @@ -13,6 +13,7 @@ local DecoratorBookmarks = Decorator:new() --- @return DecoratorBookmarks function DecoratorBookmarks:new(opts) local o = Decorator.new(self, { + enabled = true, hl_pos = HL_POSITION[opts.renderer.highlight_bookmarks] or HL_POSITION.none, icon_placement = ICON_PLACEMENT[opts.renderer.icons.bookmarks_placement] or ICON_PLACEMENT.none, }) @@ -30,14 +31,14 @@ function DecoratorBookmarks:new(opts) end --- Bookmark icon: renderer.icons.show.bookmarks and node is marked -function DecoratorBookmarks:get_icon(node) +function DecoratorBookmarks:calculate_icons(node) if marks.get_mark(node) then - return self.icon + return { self.icon } end end --- Bookmark highlight: renderer.highlight_bookmarks and node is marked -function DecoratorBookmarks:get_highlight(node) +function DecoratorBookmarks:calculate_highlight(node) if self.hl_pos ~= HL_POSITION.none and marks.get_mark(node) then return "NvimTreeBookmarkHL" end diff --git a/lua/nvim-tree/renderer/decorator/copied.lua b/lua/nvim-tree/renderer/decorator/copied.lua index bd5a078d4aa..aa5b4bcad0a 100644 --- a/lua/nvim-tree/renderer/decorator/copied.lua +++ b/lua/nvim-tree/renderer/decorator/copied.lua @@ -14,6 +14,7 @@ local DecoratorCopied = Decorator:new() --- @return DecoratorCopied function DecoratorCopied:new(opts) local o = Decorator.new(self, { + enabled = true, hl_pos = HL_POSITION[opts.renderer.highlight_clipboard] or HL_POSITION.none, icon_placement = ICON_PLACEMENT.none, }) @@ -26,7 +27,7 @@ function DecoratorCopied:new(opts) end --- Cut highlight: renderer.highlight_clipboard and node is copied -function DecoratorCopied:get_highlight(node) +function DecoratorCopied:calculate_highlight(node) if self.hl_pos ~= HL_POSITION.none and copy_paste.is_copied(node) then return "NvimTreeCopiedHL" end diff --git a/lua/nvim-tree/renderer/decorator/cut.lua b/lua/nvim-tree/renderer/decorator/cut.lua index bfac11a40cb..6525aaddb1d 100644 --- a/lua/nvim-tree/renderer/decorator/cut.lua +++ b/lua/nvim-tree/renderer/decorator/cut.lua @@ -14,6 +14,7 @@ local DecoratorCut = Decorator:new() --- @return DecoratorCut function DecoratorCut:new(opts) local o = Decorator.new(self, { + enabled = true, hl_pos = HL_POSITION[opts.renderer.highlight_clipboard] or HL_POSITION.none, icon_placement = ICON_PLACEMENT.none, }) @@ -26,7 +27,7 @@ function DecoratorCut:new(opts) end --- Cut highlight: renderer.highlight_clipboard and node is cut -function DecoratorCut:get_highlight(node) +function DecoratorCut:calculate_highlight(node) if self.hl_pos ~= HL_POSITION.none and copy_paste.is_cut(node) then return "NvimTreeCutHL" end diff --git a/lua/nvim-tree/renderer/decorator/diagnostics.lua b/lua/nvim-tree/renderer/decorator/diagnostics.lua index 9fe2edc9065..8dd43b27ae7 100644 --- a/lua/nvim-tree/renderer/decorator/diagnostics.lua +++ b/lua/nvim-tree/renderer/decorator/diagnostics.lua @@ -31,7 +31,6 @@ local ICON_KEYS = { } --- @class DecoratorDiagnostics: Decorator ---- @field enabled boolean --- @field icons HighlightedString[] local DecoratorDiagnostics = Decorator:new() @@ -39,12 +38,12 @@ local DecoratorDiagnostics = Decorator:new() --- @return DecoratorDiagnostics function DecoratorDiagnostics:new(opts) local o = Decorator.new(self, { + enabled = opts.diagnostics.enable, hl_pos = HL_POSITION[opts.renderer.highlight_diagnostics] or HL_POSITION.none, icon_placement = ICON_PLACEMENT[opts.renderer.icons.diagnostics_placement] or ICON_PLACEMENT.none, }) ---@cast o DecoratorDiagnostics - o.enabled = opts.diagnostics.enable if not o.enabled then return o end @@ -64,14 +63,16 @@ function DecoratorDiagnostics:new(opts) end --- Diagnostic icon: diagnostics.enable, renderer.icons.show.diagnostics and node has status -function DecoratorDiagnostics:get_icon(node) +function DecoratorDiagnostics:calculate_icons(node) if node and self.enabled and self.icons then - return self.icons[node.diag_status] + if node.diag_status then + return { self.icons[node.diag_status] } + end end end --- Diagnostic highlight: diagnostics.enable, renderer.highlight_diagnostics and node has status -function DecoratorDiagnostics:get_highlight(node) +function DecoratorDiagnostics:calculate_highlight(node) if not node or not self.enabled or self.hl_pos == HL_POSITION.none then return nil end diff --git a/lua/nvim-tree/renderer/decorator/git.lua b/lua/nvim-tree/renderer/decorator/git.lua index 62e7070cb14..a42721f07ae 100644 --- a/lua/nvim-tree/renderer/decorator/git.lua +++ b/lua/nvim-tree/renderer/decorator/git.lua @@ -7,7 +7,6 @@ local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT local Decorator = require "nvim-tree.renderer.decorator" --- @class DecoratorGit: Decorator ---- @field enabled boolean --- @field file_hl string[] --- @field folder_hl string[] --- @field git_icons table @@ -115,12 +114,12 @@ end --- @return DecoratorGit function DecoratorGit:new(opts) local o = Decorator.new(self, { + enabled = opts.git.enable, hl_pos = HL_POSITION[opts.renderer.highlight_git] or HL_POSITION.none, icon_placement = ICON_PLACEMENT[opts.renderer.icons.git_placement] or ICON_PLACEMENT.none, }) ---@cast o DecoratorGit - o.enabled = opts.git.enable if not o.enabled then return o end @@ -140,7 +139,7 @@ end --- Git icons: git.enable, renderer.icons.show.git and node has status --- @param node table --- @return HighlightedString[]|nil modified icon -function DecoratorGit:get_icons(node) +function DecoratorGit:calculate_icons(node) if not node or not self.enabled or not self.git_icons then return nil end @@ -184,8 +183,20 @@ function DecoratorGit:get_icons(node) return iconss end +--- Get the first icon as the sign if appropriate +function DecoratorGit:sign_name(node) + if self.icon_placement ~= ICON_PLACEMENT.signcolumn then + return + end + + local icons = self:calculate_icons(node) + if icons and #icons > 0 then + return icons[1].hl[1] + end +end + --- Git highlight: git.enable, renderer.highlight_git and node has status -function DecoratorGit:get_highlight(node) +function DecoratorGit:calculate_highlight(node) if not node or not self.enabled or self.hl_pos == HL_POSITION.none then return nil end diff --git a/lua/nvim-tree/renderer/decorator/init.lua b/lua/nvim-tree/renderer/decorator/init.lua index b61813451b3..5c8aece350b 100644 --- a/lua/nvim-tree/renderer/decorator/init.lua +++ b/lua/nvim-tree/renderer/decorator/init.lua @@ -1,6 +1,10 @@ +local HL_POSITION = require("nvim-tree.enum").HL_POSITION +local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT + --- @class Decorator ---- @field hl_pos HL_POSITION ---- @field icon_placement ICON_PLACEMENT +--- @field protected enabled boolean +--- @field protected hl_pos HL_POSITION +--- @field protected icon_placement ICON_PLACEMENT local Decorator = {} --- @param o Decorator|nil @@ -13,19 +17,80 @@ function Decorator:new(o) return o end +--- Maybe highlight groups +--- @param node table +--- @return string|nil icon highlight group +--- @return string|nil name highlight group +function Decorator:groups_icon_name(node) + local icon_hl, name_hl + + if self.enabled and self.hl_pos ~= HL_POSITION.none then + local hl = self:calculate_highlight(node) + + if self.hl_pos == HL_POSITION.all or self.hl_pos == HL_POSITION.icon then + icon_hl = hl + end + if self.hl_pos == HL_POSITION.all or self.hl_pos == HL_POSITION.name then + name_hl = hl + end + end + + return icon_hl, name_hl +end + +--- Maybe icon sign +--- @param node table +--- @return string|nil name +function Decorator:sign_name(node) + if not self.enabled or self.icon_placement ~= ICON_PLACEMENT.signcolumn then + return + end + + local icons = self:calculate_icons(node) + if icons and #icons > 0 then + return icons[1].hl[1] + end +end + +--- Icons when ICON_PLACEMENT.before +--- @param node table +--- @return HighlightedString[]|nil icons +function Decorator:icons_before(node) + if not self.enabled or self.icon_placement ~= ICON_PLACEMENT.before then + return + end + + return self:calculate_icons(node) +end + +--- Icons when ICON_PLACEMENT.after +--- @param node table +--- @return HighlightedString[]|nil icons +function Decorator:icons_after(node) + if not self.enabled or self.icon_placement ~= ICON_PLACEMENT.after then + return + end + + return self:calculate_icons(node) +end + ---@diagnostic disable: unused-local +-- luacheck: push no unused args ---- Node icon ---- @param _ table node ---- @return HighlightedString|nil modified icon -function Decorator:get_icon(_) end +--- Maybe icons - abstract +--- @protected +--- @param node table +--- @return HighlightedString[]|nil icons +function Decorator:calculate_icons(node) end ---- Node highlight group ---- @param _ table node +--- Maybe highlight group - abstract +--- @protected +--- @param node table --- @return string|nil group -function Decorator:get_highlight(_) end +function Decorator:calculate_highlight(node) end ---@diagnostic enable: unused-local +-- luacheck: pop --- Define a sign --- @protected diff --git a/lua/nvim-tree/renderer/decorator/modified.lua b/lua/nvim-tree/renderer/decorator/modified.lua index 4197b60b300..30cc61bbebe 100644 --- a/lua/nvim-tree/renderer/decorator/modified.lua +++ b/lua/nvim-tree/renderer/decorator/modified.lua @@ -6,7 +6,6 @@ local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT local Decorator = require "nvim-tree.renderer.decorator" --- @class DecoratorModified: Decorator ---- @field enabled boolean --- @field icon HighlightedString|nil local DecoratorModified = Decorator:new() @@ -14,12 +13,12 @@ local DecoratorModified = Decorator:new() --- @return DecoratorModified function DecoratorModified:new(opts) local o = Decorator.new(self, { + enabled = opts.modified.enable, hl_pos = HL_POSITION[opts.renderer.highlight_modified] or HL_POSITION.none, icon_placement = ICON_PLACEMENT[opts.renderer.icons.modified_placement] or ICON_PLACEMENT.none, }) ---@cast o DecoratorModified - o.enabled = opts.modified.enable if not o.enabled then return o end @@ -36,14 +35,14 @@ function DecoratorModified:new(opts) end --- Modified icon: modified.enable, renderer.icons.show.modified and node is modified -function DecoratorModified:get_icon(node) +function DecoratorModified:calculate_icons(node) if self.enabled and buffers.is_modified(node) then - return self.icon + return { self.icon } end end --- Modified highlight: modified.enable, renderer.highlight_modified and node is modified -function DecoratorModified:get_highlight(node) +function DecoratorModified:calculate_highlight(node) if not self.enabled or self.hl_pos == HL_POSITION.none or not buffers.is_modified(node) then return nil end diff --git a/lua/nvim-tree/renderer/decorator/opened.lua b/lua/nvim-tree/renderer/decorator/opened.lua index 9246fd3a8e1..50125a9f3e6 100644 --- a/lua/nvim-tree/renderer/decorator/opened.lua +++ b/lua/nvim-tree/renderer/decorator/opened.lua @@ -14,6 +14,7 @@ local DecoratorOpened = Decorator:new() --- @return DecoratorOpened function DecoratorOpened:new(opts) local o = Decorator.new(self, { + enabled = true, hl_pos = HL_POSITION[opts.renderer.highlight_opened_files] or HL_POSITION.none, icon_placement = ICON_PLACEMENT.none, }) @@ -24,7 +25,7 @@ end --- Opened highlight: renderer.highlight_opened_files and node has an open buffer --- @param node table -function DecoratorOpened:get_highlight(node) +function DecoratorOpened:calculate_highlight(node) if self.hl_pos ~= HL_POSITION.none and buffers.is_opened(node) then return "NvimTreeOpenedHL" end diff --git a/lua/nvim-tree/renderer/init.lua b/lua/nvim-tree/renderer/init.lua index 7f08e6af226..dfc45787502 100644 --- a/lua/nvim-tree/renderer/init.lua +++ b/lua/nvim-tree/renderer/init.lua @@ -20,20 +20,21 @@ local DecoratorOpened = require "nvim-tree.renderer.decorator.opened" local M = { last_highlights = {}, decorators = {}, + deco = {}, } local SIGN_GROUP = "NvimTreeRendererSigns" local namespace_id = vim.api.nvim_create_namespace "NvimTreeHighlights" -local function _draw(bufnr, lines, hl, signs) +local function _draw(bufnr, lines, hl, sign_names) vim.api.nvim_buf_set_option(bufnr, "modifiable", true) vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines) M.render_hl(bufnr, hl) vim.api.nvim_buf_set_option(bufnr, "modifiable", false) vim.fn.sign_unplace(SIGN_GROUP) - for _, sign in pairs(signs) do - vim.fn.sign_place(0, SIGN_GROUP, sign.sign, bufnr, { lnum = sign.lnum, priority = sign.priority }) + for i, sign_name in pairs(sign_names) do + vim.fn.sign_place(0, SIGN_GROUP, sign_name, bufnr, { lnum = i + 1 }) end end @@ -71,7 +72,7 @@ function M.draw() local cursor = vim.api.nvim_win_get_cursor(view.get_winnr()) icon_component.reset_config() - local lines, hl, signs = Builder.new(core.get_cwd(), M.decorators) + local lines, hl, sign_names = Builder.new(core.get_cwd(), M.deco) :configure_root_label(M.config.root_folder_label) :configure_trailing_slash(M.config.add_trailing) :configure_special_files(M.config.special_files) @@ -84,7 +85,7 @@ function M.draw() :build(core.get_explorer()) :unwrap() - _draw(bufnr, lines, hl, signs) + _draw(bufnr, lines, hl, sign_names) M.last_highlights = hl @@ -106,17 +107,15 @@ function M.setup(opts) full_name.setup(opts) icon_component.setup(opts) - -- TODO change to array: precedence should follow order - -- HL cut > copied > diagnostics > bookmarked > modified > opened > git - -- Sign diagnostics > modified > git > bookmarked - M.decorators = { - bookmarks = DecoratorBookmarks:new(opts), - copied = DecoratorCopied:new(opts), - cut = DecoratorCut:new(opts), - diagnostics = DecoratorDiagnostics:new(opts), - git = DecoratorGit:new(opts), - modified = DecoratorModified:new(opts), - opened = DecoratorOpened:new(opts), + -- priority order + M.deco = { + DecoratorCut:new(opts), + DecoratorCopied:new(opts), + DecoratorDiagnostics:new(opts), + DecoratorBookmarks:new(opts), + DecoratorModified:new(opts), + DecoratorOpened:new(opts), + DecoratorGit:new(opts), } end From 700c7d66f717a08372683a12d69db1cab5e3acf6 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sun, 19 Nov 2023 17:20:37 +1100 Subject: [PATCH 14/37] fix(#2415): harden sign creation (#2539) --- lua/nvim-tree/renderer/decorator/init.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lua/nvim-tree/renderer/decorator/init.lua b/lua/nvim-tree/renderer/decorator/init.lua index 5c8aece350b..6016474a8e4 100644 --- a/lua/nvim-tree/renderer/decorator/init.lua +++ b/lua/nvim-tree/renderer/decorator/init.lua @@ -103,8 +103,12 @@ function Decorator:define_sign(icon) vim.fn.sign_undefine(name) end + if self.icon_placement ~= ICON_PLACEMENT.signcolumn or #icon.str < 1 then + return + end + vim.fn.sign_define(name, { - text = icon.str, + text = string.sub(icon.str, 1, 1), texthl = icon.hl[1], }) end From 351433dd2a8e3b15ccacf25609eceba950b6bf02 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sun, 26 Nov 2023 17:31:55 +1100 Subject: [PATCH 15/37] fix(#2415): harden unicode signs --- lua/nvim-tree/renderer/builder.lua | 15 +++++++++------ lua/nvim-tree/renderer/decorator/init.lua | 13 ++++++++++--- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 982eeac9c76..53e71277645 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -235,12 +235,8 @@ function Builder:_format_line(indent_markers, arrows, icon, name, node) return line end -function Builder:_build_line(node, idx, num_children) - -- various components - local indent_markers = pad.get_indent_markers(self.depth, idx, num_children, node, self.markers) - local arrows = pad.get_arrows(node) - - -- signs, use the highest priority +function Builder:_build_signs(node) + -- first in priority order local sign_name for _, d in ipairs(self.deco) do sign_name = d:sign_name(node) @@ -249,6 +245,12 @@ function Builder:_build_line(node, idx, num_children) break end end +end + +function Builder:_build_line(node, idx, num_children) + -- various components + local indent_markers = pad.get_indent_markers(self.depth, idx, num_children, node, self.markers) + local arrows = pad.get_arrows(node) -- main components local is_folder = node.nodes ~= nil @@ -302,6 +304,7 @@ function Builder:build(tree) local idx = 1 for _, node in ipairs(tree.nodes) do if not node.hidden then + self:_build_signs(node) self:_build_line(node, idx, num_children) idx = idx + 1 end diff --git a/lua/nvim-tree/renderer/decorator/init.lua b/lua/nvim-tree/renderer/decorator/init.lua index 6016474a8e4..31f85771c58 100644 --- a/lua/nvim-tree/renderer/decorator/init.lua +++ b/lua/nvim-tree/renderer/decorator/init.lua @@ -103,13 +103,20 @@ function Decorator:define_sign(icon) vim.fn.sign_undefine(name) end - if self.icon_placement ~= ICON_PLACEMENT.signcolumn or #icon.str < 1 then + -- don't use sign if not defined + if #icon.str < 1 then + self.icon_placement = ICON_PLACEMENT.none return end + -- byte index of the next character, allowing for wide + local bi = vim.fn.byteidx(icon.str, 1) + + -- first (wide) character, falls back to empty string + local text = string.sub(icon.str, 1, bi) vim.fn.sign_define(name, { - text = string.sub(icon.str, 1, 1), - texthl = icon.hl[1], + text = text, + texthl = name, }) end end From b1ad745930609fc94dbd2434c03d2a82adda352e Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sat, 2 Dec 2023 13:20:15 +1100 Subject: [PATCH 16/37] Decorator tidy --- lua/nvim-tree/renderer/decorator/init.lua | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/lua/nvim-tree/renderer/decorator/init.lua b/lua/nvim-tree/renderer/decorator/init.lua index 31f85771c58..97e7303fff4 100644 --- a/lua/nvim-tree/renderer/decorator/init.lua +++ b/lua/nvim-tree/renderer/decorator/init.lua @@ -74,23 +74,21 @@ function Decorator:icons_after(node) return self:calculate_icons(node) end ----@diagnostic disable: unused-local --- luacheck: push no unused args - ---- Maybe icons - abstract +--- Maybe icons, optionally implemented --- @protected ---- @param node table +--- @param _ table node --- @return HighlightedString[]|nil icons -function Decorator:calculate_icons(node) end +function Decorator:calculate_icons(_) + return nil +end ---- Maybe highlight group - abstract +--- Maybe highlight group, optionally implemented --- @protected ---- @param node table +--- @param _ table node --- @return string|nil group -function Decorator:calculate_highlight(node) end - ----@diagnostic enable: unused-local --- luacheck: pop +function Decorator:calculate_highlight(_) + return nil +end --- Define a sign --- @protected From 6b18f87c1dcba10955cf7153bd21a0f0c3b6bea4 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sat, 2 Dec 2023 14:22:32 +1100 Subject: [PATCH 17/37] normalise git sign creation and tidy --- lua/nvim-tree/renderer/decorator/git.lua | 117 ++++++++++++----------- 1 file changed, 59 insertions(+), 58 deletions(-) diff --git a/lua/nvim-tree/renderer/decorator/git.lua b/lua/nvim-tree/renderer/decorator/git.lua index a42721f07ae..6f025e1281b 100644 --- a/lua/nvim-tree/renderer/decorator/git.lua +++ b/lua/nvim-tree/renderer/decorator/git.lua @@ -6,23 +6,62 @@ local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT local Decorator = require "nvim-tree.renderer.decorator" +--- @class HighlightedStringGit: HighlightedString +--- @field ord number decreasing priority + --- @class DecoratorGit: Decorator ---- @field file_hl string[] ---- @field folder_hl string[] ---- @field git_icons table +--- @field file_hl table by porcelain status e.g. "AM" +--- @field folder_hl table by porcelain status +--- @field icons_by_status HighlightedStringGit[] by human status +--- @field icons_by_xy table by porcelain status local DecoratorGit = Decorator:new() -local function build_icons_table(i) - local icons = { - staged = { str = i.staged, hl = { "NvimTreeGitStagedIcon" }, ord = 1 }, - unstaged = { str = i.unstaged, hl = { "NvimTreeGitDirtyIcon" }, ord = 2 }, - renamed = { str = i.renamed, hl = { "NvimTreeGitRenamedIcon" }, ord = 3 }, - deleted = { str = i.deleted, hl = { "NvimTreeGitDeletedIcon" }, ord = 4 }, - unmerged = { str = i.unmerged, hl = { "NvimTreeGitMergeIcon" }, ord = 5 }, - untracked = { str = i.untracked, hl = { "NvimTreeGitNewIcon" }, ord = 6 }, - ignored = { str = i.ignored, hl = { "NvimTreeGitIgnoredIcon" }, ord = 7 }, +--- @param opts table +--- @return DecoratorGit +function DecoratorGit:new(opts) + local o = Decorator.new(self, { + enabled = opts.git.enable, + hl_pos = HL_POSITION[opts.renderer.highlight_git] or HL_POSITION.none, + icon_placement = ICON_PLACEMENT[opts.renderer.icons.git_placement] or ICON_PLACEMENT.none, + }) + ---@cast o DecoratorGit + + if not o.enabled then + return o + end + + if o.hl_pos ~= HL_POSITION.none then + o:build_hl_table() + end + + if opts.renderer.icons.show.git then + o:build_icons_by_status(opts.renderer.icons.glyphs.git) + o:build_icons_by_xy(o.icons_by_status) + + for _, icon in pairs(o.icons_by_status) do + self:define_sign(icon) + end + end + + return o +end + +--- @param glyphs table user glyps +function DecoratorGit:build_icons_by_status(glyphs) + self.icons_by_status = { + staged = { str = glyphs.staged, hl = { "NvimTreeGitStagedIcon" }, ord = 1 }, + unstaged = { str = glyphs.unstaged, hl = { "NvimTreeGitDirtyIcon" }, ord = 2 }, + renamed = { str = glyphs.renamed, hl = { "NvimTreeGitRenamedIcon" }, ord = 3 }, + deleted = { str = glyphs.deleted, hl = { "NvimTreeGitDeletedIcon" }, ord = 4 }, + unmerged = { str = glyphs.unmerged, hl = { "NvimTreeGitMergeIcon" }, ord = 5 }, + untracked = { str = glyphs.untracked, hl = { "NvimTreeGitNewIcon" }, ord = 6 }, + ignored = { str = glyphs.ignored, hl = { "NvimTreeGitIgnoredIcon" }, ord = 7 }, } - return { +end + +---@param icons HighlightedStringGit[] +function DecoratorGit:build_icons_by_xy(icons) + self.icons_by_xy = { ["M "] = { icons.staged }, [" M"] = { icons.unstaged }, ["C "] = { icons.staged }, @@ -58,8 +97,8 @@ local function build_icons_table(i) } end -local function build_hl_table() - local file = { +function DecoratorGit:build_hl_table() + self.file_hl = { ["M "] = "NvimTreeGitFileStagedHL", ["C "] = "NvimTreeGitFileStagedHL", ["AA"] = "NvimTreeGitFileStagedHL", @@ -92,55 +131,17 @@ local function build_hl_table() [" A"] = "none", } - local folder = {} - for k, v in pairs(file) do - folder[k] = v:gsub("File", "Folder") + self.folder_hl = {} + for k, v in pairs(self.file_hl) do + self.folder_hl[k] = v:gsub("File", "Folder") end - - return file, folder -end - -local function setup_signs(i) - vim.fn.sign_define("NvimTreeGitDirtyIcon", { text = i.unstaged, texthl = "NvimTreeGitDirtyIcon" }) - vim.fn.sign_define("NvimTreeGitStagedIcon", { text = i.staged, texthl = "NvimTreeGitStagedIcon" }) - vim.fn.sign_define("NvimTreeGitMergeIcon", { text = i.unmerged, texthl = "NvimTreeGitMergeIcon" }) - vim.fn.sign_define("NvimTreeGitRenamedIcon", { text = i.renamed, texthl = "NvimTreeGitRenamedIcon" }) - vim.fn.sign_define("NvimTreeGitNewIcon", { text = i.untracked, texthl = "NvimTreeGitNewIcon" }) - vim.fn.sign_define("NvimTreeGitDeletedIcon", { text = i.deleted, texthl = "NvimTreeGitDeletedIcon" }) - vim.fn.sign_define("NvimTreeGitIgnoredIcon", { text = i.ignored, texthl = "NvimTreeGitIgnoredIcon" }) -end - ---- @param opts table ---- @return DecoratorGit -function DecoratorGit:new(opts) - local o = Decorator.new(self, { - enabled = opts.git.enable, - hl_pos = HL_POSITION[opts.renderer.highlight_git] or HL_POSITION.none, - icon_placement = ICON_PLACEMENT[opts.renderer.icons.git_placement] or ICON_PLACEMENT.none, - }) - ---@cast o DecoratorGit - - if not o.enabled then - return o - end - - if o.hl_pos ~= HL_POSITION.none then - o.file_hl, o.folder_hl = build_hl_table() - end - - if opts.renderer.icons.show.git then - o.git_icons = build_icons_table(opts.renderer.icons.glyphs.git) - setup_signs(opts.renderer.icons.glyphs.git) - end - - return o end --- Git icons: git.enable, renderer.icons.show.git and node has status --- @param node table --- @return HighlightedString[]|nil modified icon function DecoratorGit:calculate_icons(node) - if not node or not self.enabled or not self.git_icons then + if not node or not self.enabled or not self.icons_by_xy then return nil end @@ -153,7 +154,7 @@ function DecoratorGit:calculate_icons(node) local iconss = {} for _, s in pairs(git_status) do - local icons = self.git_icons[s] + local icons = self.icons_by_xy[s] if not icons then if self.hl_pos == HL_POSITION.none then notify.warn(string.format("Unrecognized git state '%s'", git_status)) From 6c9172a351eac6e2be1e80be9e33ad89560440c0 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sat, 2 Dec 2023 14:25:49 +1100 Subject: [PATCH 18/37] tidy builder --- lua/nvim-tree/renderer/builder.lua | 5 ++--- lua/nvim-tree/renderer/init.lua | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 53e71277645..9a09dc24bac 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -1,5 +1,4 @@ local utils = require "nvim-tree.utils" -local core = require "nvim-tree.core" local notify = require "nvim-tree.notify" local pad = require "nvim-tree.renderer.components.padding" @@ -138,7 +137,7 @@ function Builder:_build_folder(node) local foldername_hl = "NvimTreeFolderName" if node.link_to and self.symlink_destination then local arrow = icons.i.symlink_arrow - local link_to = utils.path_relative(node.link_to, core.get_cwd()) + local link_to = utils.path_relative(node.link_to, self.root_cwd) foldername = foldername .. arrow .. link_to foldername_hl = "NvimTreeSymlinkFolderName" elseif vim.tbl_contains(self.special_files, node.absolute_path) or vim.tbl_contains(self.special_files, node.name) then @@ -160,7 +159,7 @@ function Builder:_build_symlink(node) local arrow = icons.i.symlink_arrow local symlink_formatted = node.name if self.symlink_destination then - local link_to = utils.path_relative(node.link_to, core.get_cwd()) + local link_to = utils.path_relative(node.link_to, self.root_cwd) symlink_formatted = symlink_formatted .. arrow .. link_to end diff --git a/lua/nvim-tree/renderer/init.lua b/lua/nvim-tree/renderer/init.lua index dfc45787502..c275dcce79e 100644 --- a/lua/nvim-tree/renderer/init.lua +++ b/lua/nvim-tree/renderer/init.lua @@ -20,7 +20,6 @@ local DecoratorOpened = require "nvim-tree.renderer.decorator.opened" local M = { last_highlights = {}, decorators = {}, - deco = {}, } local SIGN_GROUP = "NvimTreeRendererSigns" @@ -72,7 +71,7 @@ function M.draw() local cursor = vim.api.nvim_win_get_cursor(view.get_winnr()) icon_component.reset_config() - local lines, hl, sign_names = Builder.new(core.get_cwd(), M.deco) + local lines, hl, sign_names = Builder.new(core.get_cwd(), M.decorators) :configure_root_label(M.config.root_folder_label) :configure_trailing_slash(M.config.add_trailing) :configure_special_files(M.config.special_files) @@ -108,7 +107,7 @@ function M.setup(opts) icon_component.setup(opts) -- priority order - M.deco = { + M.decorators = { DecoratorCut:new(opts), DecoratorCopied:new(opts), DecoratorDiagnostics:new(opts), From 1427bb6ad1b0c6abbc392191377f10abf61919fe Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sat, 2 Dec 2023 14:31:51 +1100 Subject: [PATCH 19/37] NvimTreeBookmarkIcon --- doc/nvim-tree-lua.txt | 3 ++- lua/nvim-tree/colors.lua | 4 +++- lua/nvim-tree/renderer/decorator/bookmarks.lua | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index 6de5de9419a..32218b24347 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -2297,7 +2297,7 @@ Clipboard: > NvimTreeCutHL SpellBad < Bookmarks: > - NvimTreeBookmark Constant + NvimTreeBookmarkIcon Constant NvimTreeBookmarkHL SpellLocal < Modified: > @@ -2392,6 +2392,7 @@ highlight group is not, hard linking as follows: > NvimTreeModifiedIcon NvimTreeModifiedFile NvimTreeOpenedHL NvimTreeOpenedFile + NvimTreeBookmarkIcon NvimTreeBookmark NvimTreeGitDeletedIcon NvimTreeGitDeleted NvimTreeGitDirtyIcon NvimTreeGitDirty diff --git a/lua/nvim-tree/colors.lua b/lua/nvim-tree/colors.lua index e6cc6874147..316691218ec 100644 --- a/lua/nvim-tree/colors.lua +++ b/lua/nvim-tree/colors.lua @@ -59,7 +59,7 @@ local DEFAULT_LINKS = { NvimTreeCopiedHL = "SpellRare", -- Bookmark Icon - NvimTreeBookmark = "Constant", + NvimTreeBookmarkIcon = "Constant", -- Bookmark Highlight NvimTreeBookmarkHL = "SpellLocal", @@ -128,6 +128,8 @@ local LEGACY_LINKS = { NvimTreeOpenedHL = "NvimTreeOpenedFile", + NvimTreeBookmarkIcon = "NvimTreeBookmark", + NvimTreeGitDeletedIcon = "NvimTreeGitDeleted", NvimTreeGitDirtyIcon = "NvimTreeGitDirty", NvimTreeGitIgnoredIcon = "NvimTreeGitIgnored", diff --git a/lua/nvim-tree/renderer/decorator/bookmarks.lua b/lua/nvim-tree/renderer/decorator/bookmarks.lua index a37b476e0eb..05410784c3b 100644 --- a/lua/nvim-tree/renderer/decorator/bookmarks.lua +++ b/lua/nvim-tree/renderer/decorator/bookmarks.lua @@ -22,7 +22,7 @@ function DecoratorBookmarks:new(opts) if opts.renderer.icons.show.bookmarks then o.icon = { str = opts.renderer.icons.glyphs.bookmark, - hl = { "NvimTreeBookmark" }, + hl = { "NvimTreeBookmarkIcon" }, } o:define_sign(o.icon) end From 3cd918edd8127560e3a7207416ee8a0e253ab092 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sat, 2 Dec 2023 14:38:26 +1100 Subject: [PATCH 20/37] tidy HL doc --- doc/nvim-tree-lua.txt | 20 +++++++++++--------- lua/nvim-tree/colors.lua | 16 ++++++++-------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index 32218b24347..122e8be430b 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -2279,11 +2279,13 @@ Folder Text: > NvimTreeOpenedFolderName Directory NvimTreeSymlinkFolderName Directory < -Icon: > - NvimTreeFolderIcon guifg=#8094b4 ctermfg=Blue +File Icons: > NvimTreeFileIcon NvimTreeNormal NvimTreeSymlinkIcon NvimTreeNormal NvimTreeOpenedFileIcon NvimTreeOpenedFile +< +Folder Icons: > + NvimTreeFolderIcon guifg=#8094b4 ctermfg=Blue NvimTreeOpenedFolderIcon NvimTreeFolderIcon NvimTreeClosedFolderIcon NvimTreeFolderIcon NvimTreeFolderArrowClosed NvimTreeIndentMarker @@ -2292,6 +2294,13 @@ Icon: > Indent: > NvimTreeIndentMarker NvimTreeFileIcon < +Picker: > + NvimTreeWindowPicker guifg=#ededed guibg=#4493c8 gui=bold ctermfg=White ctermbg=Cyan +< +Live Filter: > + NvimTreeLiveFilterPrefix PreProc + NvimTreeLiveFilterValue ModeMsg +< Clipboard: > NvimTreeCopiedHL SpellRare NvimTreeCutHL SpellBad @@ -2308,13 +2317,6 @@ Modified: > Opened: > NvimTreeOpenedHL Constant < -Picker: > - NvimTreeWindowPicker guifg=#ededed guibg=#4493c8 gui=bold ctermfg=White ctermbg=Cyan -< -Live Filter: > - NvimTreeLiveFilterPrefix PreProc - NvimTreeLiveFilterValue ModeMsg -< Git Icon: > NvimTreeGitDeletedIcon Statement NvimTreeGitDirtyIcon Statement diff --git a/lua/nvim-tree/colors.lua b/lua/nvim-tree/colors.lua index 316691218ec..2f3752da70e 100644 --- a/lua/nvim-tree/colors.lua +++ b/lua/nvim-tree/colors.lua @@ -42,10 +42,12 @@ local DEFAULT_LINKS = { NvimTreeOpenedFolderName = "Directory", NvimTreeSymlinkFolderName = "Directory", - -- Icon + -- File Icons NvimTreeFileIcon = "NvimTreeNormal", NvimTreeSymlinkIcon = "NvimTreeNormal", NvimTreeOpenedFileIcon = "NvimTreeOpenedFile", + + -- Folder Icons NvimTreeOpenedFolderIcon = "NvimTreeFolderIcon", NvimTreeClosedFolderIcon = "NvimTreeFolderIcon", NvimTreeFolderArrowClosed = "NvimTreeIndentMarker", @@ -54,14 +56,16 @@ local DEFAULT_LINKS = { -- Indent NvimTreeIndentMarker = "NvimTreeFileIcon", + -- LiveFilter + NvimTreeLiveFilterPrefix = "PreProc", + NvimTreeLiveFilterValue = "ModeMsg", + -- Clipboard NvimTreeCutHL = "SpellBad", NvimTreeCopiedHL = "SpellRare", - -- Bookmark Icon + -- Bookmark NvimTreeBookmarkIcon = "Constant", - - -- Bookmark Highlight NvimTreeBookmarkHL = "SpellLocal", -- Modified @@ -72,10 +76,6 @@ local DEFAULT_LINKS = { -- Opened NvimTreeOpenedHL = "Constant", - -- LiveFilter - NvimTreeLiveFilterPrefix = "PreProc", - NvimTreeLiveFilterValue = "ModeMsg", - -- Git Icon NvimTreeGitDeletedIcon = "Statement", NvimTreeGitDirtyIcon = "Statement", From 54d52ef7ae9bd80cfe71520867d5f81e1f822d8e Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sat, 2 Dec 2023 14:52:11 +1100 Subject: [PATCH 21/37] tidy HL doc --- doc/nvim-tree-lua.txt | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index 122e8be430b..96eba6f9cee 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -2377,18 +2377,6 @@ Diagnostics Folder Highlight: > - `highlight_xxx` is additive instead of overwriting. See |nvim-tree-opts-renderer| for precedence. -Legacy diagnostic HL style may be applied: > - - :hi link NvimTreeDiagnosticErrorFileHL DiagnosticError - :hi link NvimTreeDiagnosticWarnFileHL DiagnosticWarn - :hi link NvimTreeDiagnosticInfoFileHL DiagnosticInfo - :hi link NvimTreeDiagnosticHintFileHL DiagnosticHint - - :hi link NvimTreeDiagnosticErrorFolderHL DiagnosticError - :hi link NvimTreeDiagnosticWarnFolderHL DiagnosticWarn - :hi link NvimTreeDiagnosticInfoFolderHL DiagnosticInfo - :hi link NvimTreeDiagnosticHintFolderHL DiagnosticHint -< Legacy highlight group are still obeyed when they are defined and the current highlight group is not, hard linking as follows: > From f499aa41a2186d8a2956300b3fbc0d88d254d8f7 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sat, 2 Dec 2023 14:56:28 +1100 Subject: [PATCH 22/37] tidy HL doc --- lua/nvim-tree/renderer/builder.lua | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 9a09dc24bac..2d40ae61769 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -5,7 +5,7 @@ local pad = require "nvim-tree.renderer.components.padding" local icons = require "nvim-tree.renderer.components.icons" --- @class Builder ---- @field deco Decorator[] +--- @field decorators Decorator[] local Builder = {} Builder.__index = Builder @@ -221,14 +221,14 @@ function Builder:_format_line(indent_markers, arrows, icon, name, node) local line = { indent_markers, arrows } add_to_end(line, { icon }) - for i = #self.deco, 1, -1 do - add_to_end(line, self.deco[i]:icons_before(node)) + for i = #self.decorators, 1, -1 do + add_to_end(line, self.decorators[i]:icons_before(node)) end add_to_end(line, { name }) - for i = #self.deco, 1, -1 do - add_to_end(line, self.deco[i]:icons_after(node)) + for i = #self.decorators, 1, -1 do + add_to_end(line, self.decorators[i]:icons_after(node)) end return line @@ -237,7 +237,7 @@ end function Builder:_build_signs(node) -- first in priority order local sign_name - for _, d in ipairs(self.deco) do + for _, d in ipairs(self.decorators) do sign_name = d:sign_name(node) if sign_name then self.sign_names[self.index] = sign_name @@ -264,7 +264,7 @@ function Builder:_build_line(node, idx, num_children) end -- highighting - for _, d in ipairs(self.deco) do + for _, d in ipairs(self.decorators) do local icon_group, name_group = d:groups_icon_name(node) table.insert(icon.hl, icon_group) table.insert(name.hl, name_group) From 5a7be0b065811bd765ec07aa1b3b54f669a7d1d9 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sat, 2 Dec 2023 15:22:50 +1100 Subject: [PATCH 23/37] tidy builder doc --- lua/nvim-tree/renderer/builder.lua | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 2d40ae61769..531b3f90a52 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -5,13 +5,20 @@ local pad = require "nvim-tree.renderer.components.padding" local icons = require "nvim-tree.renderer.components.icons" --- @class Builder ---- @field decorators Decorator[] +--- @field private index number +--- @field private depth number +--- @field private highlights table[] hl_group, line, col_start, col_end arguments for vim.api.nvim_buf_add_highlight +--- @field private lines string[] includes icons etc. +--- @field private markers boolean[] indent markers +--- @field private sign_names string[] line signs +--- @field private root_cwd string absolute path +--- @field private decorators Decorator[] in priority order local Builder = {} Builder.__index = Builder local DEFAULT_ROOT_FOLDER_LABEL = ":~:s?$?/..?" -function Builder.new(root_cwd, deco) +function Builder.new(root_cwd, decorators) return setmetatable({ index = 0, depth = 0, @@ -20,7 +27,7 @@ function Builder.new(root_cwd, deco) markers = {}, sign_names = {}, root_cwd = root_cwd, - deco = deco, + decorators = decorators, }, Builder) end From d23d33fc93b00fa4527c90b1e7ecf636dbd877b5 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sun, 3 Dec 2023 11:57:44 +1100 Subject: [PATCH 24/37] standardise on '---@param' --- lua/nvim-tree/renderer/builder.lua | 18 ++++---- .../renderer/decorator/bookmarks.lua | 8 ++-- lua/nvim-tree/renderer/decorator/copied.lua | 10 ++-- lua/nvim-tree/renderer/decorator/cut.lua | 10 ++-- .../renderer/decorator/diagnostics.lua | 8 ++-- lua/nvim-tree/renderer/decorator/git.lua | 26 +++++------ lua/nvim-tree/renderer/decorator/init.lua | 46 +++++++++---------- lua/nvim-tree/renderer/decorator/modified.lua | 8 ++-- lua/nvim-tree/renderer/decorator/opened.lua | 12 ++--- 9 files changed, 73 insertions(+), 73 deletions(-) diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 531b3f90a52..c91dc9bd3fd 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -4,15 +4,15 @@ local notify = require "nvim-tree.notify" local pad = require "nvim-tree.renderer.components.padding" local icons = require "nvim-tree.renderer.components.icons" ---- @class Builder ---- @field private index number ---- @field private depth number ---- @field private highlights table[] hl_group, line, col_start, col_end arguments for vim.api.nvim_buf_add_highlight ---- @field private lines string[] includes icons etc. ---- @field private markers boolean[] indent markers ---- @field private sign_names string[] line signs ---- @field private root_cwd string absolute path ---- @field private decorators Decorator[] in priority order +---@class Builder +---@field private index number +---@field private depth number +---@field private highlights table[] hl_group, line, col_start, col_end arguments for vim.api.nvim_buf_add_highlight +---@field private lines string[] includes icons etc. +---@field private markers boolean[] indent markers +---@field private sign_names string[] line signs +---@field private root_cwd string absolute path +---@field private decorators Decorator[] in priority order local Builder = {} Builder.__index = Builder diff --git a/lua/nvim-tree/renderer/decorator/bookmarks.lua b/lua/nvim-tree/renderer/decorator/bookmarks.lua index 05410784c3b..f72216a86ff 100644 --- a/lua/nvim-tree/renderer/decorator/bookmarks.lua +++ b/lua/nvim-tree/renderer/decorator/bookmarks.lua @@ -5,12 +5,12 @@ local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT local Decorator = require "nvim-tree.renderer.decorator" ---- @class DecoratorBookmarks: Decorator ---- @field icon HighlightedString +---@class DecoratorBookmarks: Decorator +---@field icon HighlightedString local DecoratorBookmarks = Decorator:new() ---- @param opts table ---- @return DecoratorBookmarks +---@param opts table +---@return DecoratorBookmarks function DecoratorBookmarks:new(opts) local o = Decorator.new(self, { enabled = true, diff --git a/lua/nvim-tree/renderer/decorator/copied.lua b/lua/nvim-tree/renderer/decorator/copied.lua index aa5b4bcad0a..a98486b2720 100644 --- a/lua/nvim-tree/renderer/decorator/copied.lua +++ b/lua/nvim-tree/renderer/decorator/copied.lua @@ -5,13 +5,13 @@ local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT local Decorator = require "nvim-tree.renderer.decorator" ---- @class DecoratorCopied: Decorator ---- @field enabled boolean ---- @field icon HighlightedString|nil +---@class DecoratorCopied: Decorator +---@field enabled boolean +---@field icon HighlightedString|nil local DecoratorCopied = Decorator:new() ---- @param opts table ---- @return DecoratorCopied +---@param opts table +---@return DecoratorCopied function DecoratorCopied:new(opts) local o = Decorator.new(self, { enabled = true, diff --git a/lua/nvim-tree/renderer/decorator/cut.lua b/lua/nvim-tree/renderer/decorator/cut.lua index 6525aaddb1d..98c8f30cb1f 100644 --- a/lua/nvim-tree/renderer/decorator/cut.lua +++ b/lua/nvim-tree/renderer/decorator/cut.lua @@ -5,13 +5,13 @@ local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT local Decorator = require "nvim-tree.renderer.decorator" ---- @class DecoratorCut: Decorator ---- @field enabled boolean ---- @field icon HighlightedString|nil +---@class DecoratorCut: Decorator +---@field enabled boolean +---@field icon HighlightedString|nil local DecoratorCut = Decorator:new() ---- @param opts table ---- @return DecoratorCut +---@param opts table +---@return DecoratorCut function DecoratorCut:new(opts) local o = Decorator.new(self, { enabled = true, diff --git a/lua/nvim-tree/renderer/decorator/diagnostics.lua b/lua/nvim-tree/renderer/decorator/diagnostics.lua index 8dd43b27ae7..34548f89435 100644 --- a/lua/nvim-tree/renderer/decorator/diagnostics.lua +++ b/lua/nvim-tree/renderer/decorator/diagnostics.lua @@ -30,12 +30,12 @@ local ICON_KEYS = { ["hint"] = vim.diagnostic.severity.HINT, } ---- @class DecoratorDiagnostics: Decorator ---- @field icons HighlightedString[] +---@class DecoratorDiagnostics: Decorator +---@field icons HighlightedString[] local DecoratorDiagnostics = Decorator:new() ---- @param opts table ---- @return DecoratorDiagnostics +---@param opts table +---@return DecoratorDiagnostics function DecoratorDiagnostics:new(opts) local o = Decorator.new(self, { enabled = opts.diagnostics.enable, diff --git a/lua/nvim-tree/renderer/decorator/git.lua b/lua/nvim-tree/renderer/decorator/git.lua index 6f025e1281b..c59f04af7a8 100644 --- a/lua/nvim-tree/renderer/decorator/git.lua +++ b/lua/nvim-tree/renderer/decorator/git.lua @@ -6,18 +6,18 @@ local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT local Decorator = require "nvim-tree.renderer.decorator" ---- @class HighlightedStringGit: HighlightedString ---- @field ord number decreasing priority - ---- @class DecoratorGit: Decorator ---- @field file_hl table by porcelain status e.g. "AM" ---- @field folder_hl table by porcelain status ---- @field icons_by_status HighlightedStringGit[] by human status ---- @field icons_by_xy table by porcelain status +---@class HighlightedStringGit: HighlightedString +---@field ord number decreasing priority + +---@class DecoratorGit: Decorator +---@field file_hl table by porcelain status e.g. "AM" +---@field folder_hl table by porcelain status +---@field icons_by_status HighlightedStringGit[] by human status +---@field icons_by_xy table by porcelain status local DecoratorGit = Decorator:new() ---- @param opts table ---- @return DecoratorGit +---@param opts table +---@return DecoratorGit function DecoratorGit:new(opts) local o = Decorator.new(self, { enabled = opts.git.enable, @@ -46,7 +46,7 @@ function DecoratorGit:new(opts) return o end ---- @param glyphs table user glyps +---@param glyphs table user glyps function DecoratorGit:build_icons_by_status(glyphs) self.icons_by_status = { staged = { str = glyphs.staged, hl = { "NvimTreeGitStagedIcon" }, ord = 1 }, @@ -138,8 +138,8 @@ function DecoratorGit:build_hl_table() end --- Git icons: git.enable, renderer.icons.show.git and node has status ---- @param node table ---- @return HighlightedString[]|nil modified icon +---@param node table +---@return HighlightedString[]|nil modified icon function DecoratorGit:calculate_icons(node) if not node or not self.enabled or not self.icons_by_xy then return nil diff --git a/lua/nvim-tree/renderer/decorator/init.lua b/lua/nvim-tree/renderer/decorator/init.lua index 97e7303fff4..72888ff19e6 100644 --- a/lua/nvim-tree/renderer/decorator/init.lua +++ b/lua/nvim-tree/renderer/decorator/init.lua @@ -1,14 +1,14 @@ local HL_POSITION = require("nvim-tree.enum").HL_POSITION local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT ---- @class Decorator ---- @field protected enabled boolean ---- @field protected hl_pos HL_POSITION ---- @field protected icon_placement ICON_PLACEMENT +---@class Decorator +---@field protected enabled boolean +---@field protected hl_pos HL_POSITION +---@field protected icon_placement ICON_PLACEMENT local Decorator = {} ---- @param o Decorator|nil ---- @return Decorator +---@param o Decorator|nil +---@return Decorator function Decorator:new(o) o = o or {} setmetatable(o, self) @@ -18,9 +18,9 @@ function Decorator:new(o) end --- Maybe highlight groups ---- @param node table ---- @return string|nil icon highlight group ---- @return string|nil name highlight group +---@param node table +---@return string|nil icon highlight group +---@return string|nil name highlight group function Decorator:groups_icon_name(node) local icon_hl, name_hl @@ -39,8 +39,8 @@ function Decorator:groups_icon_name(node) end --- Maybe icon sign ---- @param node table ---- @return string|nil name +---@param node table +---@return string|nil name function Decorator:sign_name(node) if not self.enabled or self.icon_placement ~= ICON_PLACEMENT.signcolumn then return @@ -53,8 +53,8 @@ function Decorator:sign_name(node) end --- Icons when ICON_PLACEMENT.before ---- @param node table ---- @return HighlightedString[]|nil icons +---@param node table +---@return HighlightedString[]|nil icons function Decorator:icons_before(node) if not self.enabled or self.icon_placement ~= ICON_PLACEMENT.before then return @@ -64,8 +64,8 @@ function Decorator:icons_before(node) end --- Icons when ICON_PLACEMENT.after ---- @param node table ---- @return HighlightedString[]|nil icons +---@param node table +---@return HighlightedString[]|nil icons function Decorator:icons_after(node) if not self.enabled or self.icon_placement ~= ICON_PLACEMENT.after then return @@ -75,24 +75,24 @@ function Decorator:icons_after(node) end --- Maybe icons, optionally implemented ---- @protected ---- @param _ table node ---- @return HighlightedString[]|nil icons +---@protected +---@param _ table node +---@return HighlightedString[]|nil icons function Decorator:calculate_icons(_) return nil end --- Maybe highlight group, optionally implemented ---- @protected ---- @param _ table node ---- @return string|nil group +---@protected +---@param _ table node +---@return string|nil group function Decorator:calculate_highlight(_) return nil end --- Define a sign ---- @protected ---- @param icon HighlightedString|nil +---@protected +---@param icon HighlightedString|nil function Decorator:define_sign(icon) if icon and #icon.hl > 0 then local name = icon.hl[1] diff --git a/lua/nvim-tree/renderer/decorator/modified.lua b/lua/nvim-tree/renderer/decorator/modified.lua index 30cc61bbebe..1fc312ce4d5 100644 --- a/lua/nvim-tree/renderer/decorator/modified.lua +++ b/lua/nvim-tree/renderer/decorator/modified.lua @@ -5,12 +5,12 @@ local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT local Decorator = require "nvim-tree.renderer.decorator" ---- @class DecoratorModified: Decorator ---- @field icon HighlightedString|nil +---@class DecoratorModified: Decorator +---@field icon HighlightedString|nil local DecoratorModified = Decorator:new() ---- @param opts table ---- @return DecoratorModified +---@param opts table +---@return DecoratorModified function DecoratorModified:new(opts) local o = Decorator.new(self, { enabled = opts.modified.enable, diff --git a/lua/nvim-tree/renderer/decorator/opened.lua b/lua/nvim-tree/renderer/decorator/opened.lua index 50125a9f3e6..1ba0045d9b7 100644 --- a/lua/nvim-tree/renderer/decorator/opened.lua +++ b/lua/nvim-tree/renderer/decorator/opened.lua @@ -5,13 +5,13 @@ local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT local Decorator = require "nvim-tree.renderer.decorator" ---- @class DecoratorOpened: Decorator ---- @field enabled boolean ---- @field icon HighlightedString|nil +---@class DecoratorOpened: Decorator +---@field enabled boolean +---@field icon HighlightedString|nil local DecoratorOpened = Decorator:new() ---- @param opts table ---- @return DecoratorOpened +---@param opts table +---@return DecoratorOpened function DecoratorOpened:new(opts) local o = Decorator.new(self, { enabled = true, @@ -24,7 +24,7 @@ function DecoratorOpened:new(opts) end --- Opened highlight: renderer.highlight_opened_files and node has an open buffer ---- @param node table +---@param node table function DecoratorOpened:calculate_highlight(node) if self.hl_pos ~= HL_POSITION.none and buffers.is_opened(node) then return "NvimTreeOpenedHL" From a825395f3e9cd1b2c21fff815565f9eba94251ef Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sun, 3 Dec 2023 12:41:58 +1100 Subject: [PATCH 25/37] DiagnosticWarning -> DiagnosticWarn --- lua/nvim-tree/renderer/decorator/diagnostics.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lua/nvim-tree/renderer/decorator/diagnostics.lua b/lua/nvim-tree/renderer/decorator/diagnostics.lua index 34548f89435..e43399bef52 100644 --- a/lua/nvim-tree/renderer/decorator/diagnostics.lua +++ b/lua/nvim-tree/renderer/decorator/diagnostics.lua @@ -6,19 +6,19 @@ local Decorator = require "nvim-tree.renderer.decorator" -- highlight groups by severity local HG_ICON = { [vim.diagnostic.severity.ERROR] = "NvimTreeDiagnosticErrorIcon", - [vim.diagnostic.severity.WARN] = "NvimTreeDiagnosticWarningIcon", + [vim.diagnostic.severity.WARN] = "NvimTreeDiagnosticWarnIcon", [vim.diagnostic.severity.INFO] = "NvimTreeDiagnosticInfoIcon", [vim.diagnostic.severity.HINT] = "NvimTreeDiagnosticHintIcon", } local HG_FILE = { [vim.diagnostic.severity.ERROR] = "NvimTreeDiagnosticErrorFileHL", - [vim.diagnostic.severity.WARN] = "NvimTreeDiagnosticWarningFileHL", + [vim.diagnostic.severity.WARN] = "NvimTreeDiagnosticWarnFileHL", [vim.diagnostic.severity.INFO] = "NvimTreeDiagnosticInfoFileHL", [vim.diagnostic.severity.HINT] = "NvimTreeDiagnosticHintFileHL", } local HG_FOLDER = { [vim.diagnostic.severity.ERROR] = "NvimTreeDiagnosticErrorFolderHL", - [vim.diagnostic.severity.WARN] = "NvimTreeDiagnosticWarningFolderHL", + [vim.diagnostic.severity.WARN] = "NvimTreeDiagnosticWarnFolderHL", [vim.diagnostic.severity.INFO] = "NvimTreeDiagnosticInfoFolderHL", [vim.diagnostic.severity.HINT] = "NvimTreeDiagnosticHintFolderHL", } From 1f89a51b78f6bc6eb57e25454cb8b7d1a2f8f1db Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sat, 9 Dec 2023 14:45:34 +1100 Subject: [PATCH 26/37] annotate decorators --- .../renderer/decorator/bookmarks.lua | 8 ++++-- lua/nvim-tree/renderer/decorator/copied.lua | 4 ++- lua/nvim-tree/renderer/decorator/cut.lua | 4 ++- .../renderer/decorator/diagnostics.lua | 8 ++++-- lua/nvim-tree/renderer/decorator/git.lua | 12 ++++++--- lua/nvim-tree/renderer/decorator/init.lua | 26 +++++++++---------- lua/nvim-tree/renderer/decorator/modified.lua | 8 ++++-- lua/nvim-tree/renderer/decorator/opened.lua | 5 ++-- 8 files changed, 48 insertions(+), 27 deletions(-) diff --git a/lua/nvim-tree/renderer/decorator/bookmarks.lua b/lua/nvim-tree/renderer/decorator/bookmarks.lua index f72216a86ff..8692c22b579 100644 --- a/lua/nvim-tree/renderer/decorator/bookmarks.lua +++ b/lua/nvim-tree/renderer/decorator/bookmarks.lua @@ -30,14 +30,18 @@ function DecoratorBookmarks:new(opts) return o end ---- Bookmark icon: renderer.icons.show.bookmarks and node is marked +---Bookmark icon: renderer.icons.show.bookmarks and node is marked +---@param node Node +---@return HighlightedString[]|nil icons function DecoratorBookmarks:calculate_icons(node) if marks.get_mark(node) then return { self.icon } end end ---- Bookmark highlight: renderer.highlight_bookmarks and node is marked +---Bookmark highlight: renderer.highlight_bookmarks and node is marked +---@param node Node +---@return string|nil group function DecoratorBookmarks:calculate_highlight(node) if self.hl_pos ~= HL_POSITION.none and marks.get_mark(node) then return "NvimTreeBookmarkHL" diff --git a/lua/nvim-tree/renderer/decorator/copied.lua b/lua/nvim-tree/renderer/decorator/copied.lua index a98486b2720..f7ceba0a293 100644 --- a/lua/nvim-tree/renderer/decorator/copied.lua +++ b/lua/nvim-tree/renderer/decorator/copied.lua @@ -26,7 +26,9 @@ function DecoratorCopied:new(opts) return o end ---- Cut highlight: renderer.highlight_clipboard and node is copied +---Copied highlight: renderer.highlight_clipboard and node is copied +---@param node Node +---@return string|nil group function DecoratorCopied:calculate_highlight(node) if self.hl_pos ~= HL_POSITION.none and copy_paste.is_copied(node) then return "NvimTreeCopiedHL" diff --git a/lua/nvim-tree/renderer/decorator/cut.lua b/lua/nvim-tree/renderer/decorator/cut.lua index 98c8f30cb1f..f02872ff6f5 100644 --- a/lua/nvim-tree/renderer/decorator/cut.lua +++ b/lua/nvim-tree/renderer/decorator/cut.lua @@ -26,7 +26,9 @@ function DecoratorCut:new(opts) return o end ---- Cut highlight: renderer.highlight_clipboard and node is cut +---Cut highlight: renderer.highlight_clipboard and node is cut +---@param node Node +---@return string|nil group function DecoratorCut:calculate_highlight(node) if self.hl_pos ~= HL_POSITION.none and copy_paste.is_cut(node) then return "NvimTreeCutHL" diff --git a/lua/nvim-tree/renderer/decorator/diagnostics.lua b/lua/nvim-tree/renderer/decorator/diagnostics.lua index e43399bef52..2473f2b08c0 100644 --- a/lua/nvim-tree/renderer/decorator/diagnostics.lua +++ b/lua/nvim-tree/renderer/decorator/diagnostics.lua @@ -62,7 +62,9 @@ function DecoratorDiagnostics:new(opts) return o end ---- Diagnostic icon: diagnostics.enable, renderer.icons.show.diagnostics and node has status +---Diagnostic icon: diagnostics.enable, renderer.icons.show.diagnostics and node has status +---@param node Node +---@return HighlightedString[]|nil icons function DecoratorDiagnostics:calculate_icons(node) if node and self.enabled and self.icons then if node.diag_status then @@ -71,7 +73,9 @@ function DecoratorDiagnostics:calculate_icons(node) end end ---- Diagnostic highlight: diagnostics.enable, renderer.highlight_diagnostics and node has status +---Diagnostic highlight: diagnostics.enable, renderer.highlight_diagnostics and node has status +---@param node Node +---@return string|nil group function DecoratorDiagnostics:calculate_highlight(node) if not node or not self.enabled or self.hl_pos == HL_POSITION.none then return nil diff --git a/lua/nvim-tree/renderer/decorator/git.lua b/lua/nvim-tree/renderer/decorator/git.lua index c59f04af7a8..de2477880bd 100644 --- a/lua/nvim-tree/renderer/decorator/git.lua +++ b/lua/nvim-tree/renderer/decorator/git.lua @@ -137,8 +137,8 @@ function DecoratorGit:build_hl_table() end end ---- Git icons: git.enable, renderer.icons.show.git and node has status ----@param node table +---Git icons: git.enable, renderer.icons.show.git and node has status +---@param node Node ---@return HighlightedString[]|nil modified icon function DecoratorGit:calculate_icons(node) if not node or not self.enabled or not self.icons_by_xy then @@ -184,7 +184,9 @@ function DecoratorGit:calculate_icons(node) return iconss end ---- Get the first icon as the sign if appropriate +---Get the first icon as the sign if appropriate +---@param node Node +---@return string|nil name function DecoratorGit:sign_name(node) if self.icon_placement ~= ICON_PLACEMENT.signcolumn then return @@ -196,7 +198,9 @@ function DecoratorGit:sign_name(node) end end ---- Git highlight: git.enable, renderer.highlight_git and node has status +---Git highlight: git.enable, renderer.highlight_git and node has status +---@param node Node +---@return string|nil group function DecoratorGit:calculate_highlight(node) if not node or not self.enabled or self.hl_pos == HL_POSITION.none then return nil diff --git a/lua/nvim-tree/renderer/decorator/init.lua b/lua/nvim-tree/renderer/decorator/init.lua index 72888ff19e6..7748b11cf49 100644 --- a/lua/nvim-tree/renderer/decorator/init.lua +++ b/lua/nvim-tree/renderer/decorator/init.lua @@ -17,8 +17,8 @@ function Decorator:new(o) return o end ---- Maybe highlight groups ----@param node table +---Maybe highlight groups +---@param node Node ---@return string|nil icon highlight group ---@return string|nil name highlight group function Decorator:groups_icon_name(node) @@ -38,8 +38,8 @@ function Decorator:groups_icon_name(node) return icon_hl, name_hl end ---- Maybe icon sign ----@param node table +---Maybe icon sign +---@param node Node ---@return string|nil name function Decorator:sign_name(node) if not self.enabled or self.icon_placement ~= ICON_PLACEMENT.signcolumn then @@ -52,8 +52,8 @@ function Decorator:sign_name(node) end end ---- Icons when ICON_PLACEMENT.before ----@param node table +---Icons when ICON_PLACEMENT.before +---@param node Node ---@return HighlightedString[]|nil icons function Decorator:icons_before(node) if not self.enabled or self.icon_placement ~= ICON_PLACEMENT.before then @@ -63,8 +63,8 @@ function Decorator:icons_before(node) return self:calculate_icons(node) end ---- Icons when ICON_PLACEMENT.after ----@param node table +---Icons when ICON_PLACEMENT.after +---@param node Node ---@return HighlightedString[]|nil icons function Decorator:icons_after(node) if not self.enabled or self.icon_placement ~= ICON_PLACEMENT.after then @@ -74,23 +74,23 @@ function Decorator:icons_after(node) return self:calculate_icons(node) end ---- Maybe icons, optionally implemented +---Maybe icons, optionally implemented ---@protected ----@param _ table node +---@param _ Node ---@return HighlightedString[]|nil icons function Decorator:calculate_icons(_) return nil end ---- Maybe highlight group, optionally implemented +---Maybe highlight group, optionally implemented ---@protected ----@param _ table node +---@param _ Node ---@return string|nil group function Decorator:calculate_highlight(_) return nil end ---- Define a sign +---Define a sign ---@protected ---@param icon HighlightedString|nil function Decorator:define_sign(icon) diff --git a/lua/nvim-tree/renderer/decorator/modified.lua b/lua/nvim-tree/renderer/decorator/modified.lua index 1fc312ce4d5..1ec546d1d65 100644 --- a/lua/nvim-tree/renderer/decorator/modified.lua +++ b/lua/nvim-tree/renderer/decorator/modified.lua @@ -34,14 +34,18 @@ function DecoratorModified:new(opts) return o end ---- Modified icon: modified.enable, renderer.icons.show.modified and node is modified +---Modified icon: modified.enable, renderer.icons.show.modified and node is modified +---@param node Node +---@return HighlightedString[]|nil icons function DecoratorModified:calculate_icons(node) if self.enabled and buffers.is_modified(node) then return { self.icon } end end ---- Modified highlight: modified.enable, renderer.highlight_modified and node is modified +---Modified highlight: modified.enable, renderer.highlight_modified and node is modified +---@param node Node +---@return string|nil group function DecoratorModified:calculate_highlight(node) if not self.enabled or self.hl_pos == HL_POSITION.none or not buffers.is_modified(node) then return nil diff --git a/lua/nvim-tree/renderer/decorator/opened.lua b/lua/nvim-tree/renderer/decorator/opened.lua index 1ba0045d9b7..848faae42e6 100644 --- a/lua/nvim-tree/renderer/decorator/opened.lua +++ b/lua/nvim-tree/renderer/decorator/opened.lua @@ -23,8 +23,9 @@ function DecoratorOpened:new(opts) return o end ---- Opened highlight: renderer.highlight_opened_files and node has an open buffer ----@param node table +---Opened highlight: renderer.highlight_opened_files and node has an open buffer +---@param node Node +---@return string|nil group function DecoratorOpened:calculate_highlight(node) if self.hl_pos ~= HL_POSITION.none and buffers.is_opened(node) then return "NvimTreeOpenedHL" From 9ac079a583c8d1a2336a87eb9e16362f06d124f3 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Mon, 25 Dec 2023 13:48:11 +1100 Subject: [PATCH 27/37] limit to two highlight groups for line rendering --- doc/nvim-tree-lua.txt | 13 ++++++++----- lua/nvim-tree/renderer/builder.lua | 15 ++++++++++++--- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index 96eba6f9cee..a7a4bd94ca3 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -790,8 +790,8 @@ Use nvim-tree in a floating window. ============================================================================== 5.3 OPTS: RENDERER *nvim-tree-opts-renderer* -Highlight precedence: - cut > copied > diagnostics > bookmarked > modified > opened > git +Highlight precedence, additive: + git < opened < modified < bookmarked < diagnostics < copied < cut *nvim-tree.renderer.add_trailing* Appends a trailing slash to folder names. @@ -895,8 +895,8 @@ Configuration options for tree indent markers. *nvim-tree.renderer.icons* Configuration options for icons. -Icon sign column precedence: - diagnostics > bookmarked > modified > git +Icon order and sign column precedence: + git < modified < bookmarked < diagnostics *nvim-tree.renderer.icons.web_devicons* Configure optional plugin `"nvim-tree/nvim-web-devicons"` @@ -2247,6 +2247,9 @@ as per |:highlight| Default linked group or definition follows name. +neovim 0.9 has a limit of two highlight groups per range. The two highest +priority groups as per |nvim-tree-opts-renderer| will be used. + Standard: > NvimTreeNormal Normal NvimTreeNormalFloat NormalFloat @@ -2365,7 +2368,7 @@ Diagnostics Folder Highlight: > ============================================================================== 8.1 HIGHLIGHT OVERHAUL *nvim-tree-highlight-overhaul* -2023/10/XX revision xxxxx made significant highlighting changes, some breaking: +2023-12: significant highlighting changes, some breaking: - Full cterm support. - Standard vim highlight groups such |DiagnosticUnderlineError| are now the diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index c91dc9bd3fd..ae37a80c5a9 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -74,8 +74,16 @@ function Builder:configure_group_name_modifier(group_name_modifier) return self end -function Builder:_insert_highlight(group, start, end_) - table.insert(self.highlights, { group, self.index, start, end_ or -1 }) +--- Insert ranged highlight groups into self.highlights +--- neovim 0.9 is limited to two highlight groups for a range so choose the highest two +--- @param groups string[] +--- @param start number +--- @param end_ number|nil +function Builder:_insert_highlight(groups, start, end_) + local top_two_groups = {} + table.insert(top_two_groups, groups[#groups - 1]) + table.insert(top_two_groups, groups[#groups]) + table.insert(self.highlights, { top_two_groups, self.index, start, end_ or -1 }) end function Builder:_insert_line(line) @@ -271,7 +279,8 @@ function Builder:_build_line(node, idx, num_children) end -- highighting - for _, d in ipairs(self.decorators) do + for i = #self.decorators, 1, -1 do + local d = self.decorators[i] local icon_group, name_group = d:groups_icon_name(node) table.insert(icon.hl, icon_group) table.insert(name.hl, name_group) From 3bb124a3a73634ead2e28a527e89caa1d65991f6 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sat, 6 Jan 2024 13:30:58 +1100 Subject: [PATCH 28/37] style --- lua/nvim-tree/renderer/builder.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index ae37a80c5a9..a3fa3ce2009 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -74,11 +74,11 @@ function Builder:configure_group_name_modifier(group_name_modifier) return self end ---- Insert ranged highlight groups into self.highlights ---- neovim 0.9 is limited to two highlight groups for a range so choose the highest two ---- @param groups string[] ---- @param start number ---- @param end_ number|nil +---Insert ranged highlight groups into self.highlights +---neovim 0.9 is limited to two highlight groups for a range so choose the highest two +---@param groups string[] +---@param start number +---@param end_ number|nil function Builder:_insert_highlight(groups, start, end_) local top_two_groups = {} table.insert(top_two_groups, groups[#groups - 1]) From 11c07206fc9bb7c412839cf7389149feaeb564a4 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sun, 7 Jan 2024 10:34:09 +1100 Subject: [PATCH 29/37] apply #2519 --- .../renderer/decorator/diagnostics.lua | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/lua/nvim-tree/renderer/decorator/diagnostics.lua b/lua/nvim-tree/renderer/decorator/diagnostics.lua index 2473f2b08c0..d18ff4d43d2 100644 --- a/lua/nvim-tree/renderer/decorator/diagnostics.lua +++ b/lua/nvim-tree/renderer/decorator/diagnostics.lua @@ -1,3 +1,5 @@ +local diagnostics = require "nvim-tree.diagnostics" + local HL_POSITION = require("nvim-tree.enum").HL_POSITION local ICON_PLACEMENT = require("nvim-tree.enum").ICON_PLACEMENT @@ -67,8 +69,11 @@ end ---@return HighlightedString[]|nil icons function DecoratorDiagnostics:calculate_icons(node) if node and self.enabled and self.icons then - if node.diag_status then - return { self.icons[node.diag_status] } + local diag_status = diagnostics.get_diag_status(node) + local diag_value = diag_status and diag_status.value + + if diag_value then + return { self.icons[diag_value] } end end end @@ -81,11 +86,18 @@ function DecoratorDiagnostics:calculate_highlight(node) return nil end + local diag_status = diagnostics.get_diag_status(node) + local diag_value = diag_status and diag_status.value + + if not diag_value then + return nil + end + local group if node.nodes then - group = HG_FOLDER[node.diag_status] + group = HG_FOLDER[diag_value] else - group = HG_FILE[node.diag_status] + group = HG_FILE[diag_value] end if group then From 145d09c1bf5f3deedc48d745090a7ad8b7e2c08e Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sun, 7 Jan 2024 12:17:42 +1100 Subject: [PATCH 30/37] feat(#2415): combined hl groups (#2601) * feat(#2415): create combined highlight groups * feat(#2415): create combined highlight groups * feat(#2415): create combined highlight groups * ci: allow workflow_dispatch (#2620) * one and only one hl namespace, required winhl removal --- doc/nvim-tree-lua.txt | 3 - lua/nvim-tree.lua | 15 +++-- lua/nvim-tree/colors.lua | 25 ++++++++- lua/nvim-tree/renderer/builder.lua | 88 ++++++++++++++++++++++++++---- lua/nvim-tree/renderer/init.lua | 7 +-- lua/nvim-tree/view.lua | 22 +------- 6 files changed, 113 insertions(+), 47 deletions(-) diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index a7a4bd94ca3..f87c0d7a24b 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -2247,9 +2247,6 @@ as per |:highlight| Default linked group or definition follows name. -neovim 0.9 has a limit of two highlight groups per range. The two highest -priority groups as per |nvim-tree-opts-renderer| will be used. - Standard: > NvimTreeNormal Normal NvimTreeNormalFloat NormalFloat diff --git a/lua/nvim-tree.lua b/lua/nvim-tree.lua index 532d9ed4f98..a6ed2ac520a 100644 --- a/lua/nvim-tree.lua +++ b/lua/nvim-tree.lua @@ -104,12 +104,6 @@ function M.open_on_directory() actions.root.change_dir.force_dirchange(bufname, true) end -function M.reset_highlight() - colors.setup() - view.reset_winhl() - renderer.render_hl(view.get_bufnr()) -end - function M.place_cursor_on_node() local search = vim.fn.searchcount() if search and search.exact_match == 1 then @@ -168,8 +162,13 @@ local function setup_autocommands(opts) vim.api.nvim_create_autocmd(name, vim.tbl_extend("force", default_opts, custom_opts)) end - -- reset highlights when colorscheme is changed - create_nvim_tree_autocmd("ColorScheme", { callback = M.reset_highlight }) + -- reset and draw highlights when colorscheme is changed + create_nvim_tree_autocmd("ColorScheme", { + callback = function() + colors.setup() + renderer.render_hl(view.get_bufnr()) + end, + }) -- prevent new opened file from opening in the same window as nvim-tree create_nvim_tree_autocmd("BufWipeout", { diff --git a/lua/nvim-tree/colors.lua b/lua/nvim-tree/colors.lua index 2f3752da70e..f0b3f8b72bf 100644 --- a/lua/nvim-tree/colors.lua +++ b/lua/nvim-tree/colors.lua @@ -1,4 +1,7 @@ -local M = {} +local M = { + -- namespace for all tree window highlights + NS_ID = vim.api.nvim_create_namespace "nvim_tree", +} -- directly defined groups, please keep these to an absolute minimum local DEFAULT_DEFS = { @@ -122,6 +125,21 @@ local DEFAULT_LINKS = { NvimTreeDiagnosticHintFolderHL = "NvimTreeDiagnosticHintFileHL", } +-- namespace standard links +local NS_LINKS = { + EndOfBuffer = "NvimTreeEndOfBuffer", + CursorLine = "NvimTreeCursorLine", + CursorLineNr = "NvimTreeCursorLineNr", + LineNr = "NvimTreeLineNr", + WinSeparator = "NvimTreeWinSeparator", + StatusLine = "NvimTreeStatusLine", + StatusLineNC = "NvimTreeStatuslineNC", + SignColumn = "NvimTreeSignColumn", + Normal = "NvimTreeNormal", + NormalNC = "NvimTreeNormalNC", + NormalFloat = "NvimTreeNormalFloat", +} + -- nvim-tree highlight groups to legacy local LEGACY_LINKS = { NvimTreeModifiedIcon = "NvimTreeModifiedFile", @@ -189,6 +207,11 @@ function M.setup() for from, to in pairs(DEFAULT_LINKS) do vim.api.nvim_command("hi def link " .. from .. " " .. to) end + + -- window namespace; these don't appear to be cleared on colorscheme however err on the side of caution + for from, to in pairs(NS_LINKS) do + vim.api.nvim_set_hl(M.NS_ID, from, { link = to }) + end end return M diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index a3fa3ce2009..381f22336e5 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -1,3 +1,4 @@ +local colors = require "nvim-tree.colors" local utils = require "nvim-tree.utils" local notify = require "nvim-tree.notify" @@ -8,6 +9,7 @@ local icons = require "nvim-tree.renderer.components.icons" ---@field private index number ---@field private depth number ---@field private highlights table[] hl_group, line, col_start, col_end arguments for vim.api.nvim_buf_add_highlight +---@field private combined_groups boolean[] combined group names ---@field private lines string[] includes icons etc. ---@field private markers boolean[] indent markers ---@field private sign_names string[] line signs @@ -23,6 +25,7 @@ function Builder.new(root_cwd, decorators) index = 0, depth = 0, highlights = {}, + combined_groups = {}, lines = {}, markers = {}, sign_names = {}, @@ -75,15 +78,11 @@ function Builder:configure_group_name_modifier(group_name_modifier) end ---Insert ranged highlight groups into self.highlights ----neovim 0.9 is limited to two highlight groups for a range so choose the highest two ---@param groups string[] ---@param start number ---@param end_ number|nil function Builder:_insert_highlight(groups, start, end_) - local top_two_groups = {} - table.insert(top_two_groups, groups[#groups - 1]) - table.insert(top_two_groups, groups[#groups]) - table.insert(self.highlights, { top_two_groups, self.index, start, end_ or -1 }) + table.insert(self.highlights, { groups, self.index, start, end_ or -1 }) end function Builder:_insert_line(line) @@ -261,6 +260,76 @@ function Builder:_build_signs(node) end end +---Combined group name less than the 200 byte limit of highlight group names +---@param groups string[] highlight group names +---@return string name "NvimTreeCombinedHL" .. sha256 +function Builder:_combined_group_name(groups) + return string.format("NvimTreeCombinedHL%s", vim.fn.sha256(table.concat(groups))) +end + +---Create a highlight group for groups with later groups overriding previous. +---@param groups string[] highlight group names +function Builder:_create_combined_group(groups) + local combined_name = self:_combined_group_name(groups) + + -- only create if necessary + if not self.combined_groups[combined_name] then + local combined_hl = {} + + -- build the highlight, overriding values + for _, group in ipairs(groups) do + local hl = vim.api.nvim_get_hl(0, { name = group, link = false }) + combined_hl = vim.tbl_extend("force", combined_hl, hl) + end + + -- highlight directly in the namespace + vim.api.nvim_set_hl_ns_fast(colors.NS_ID) + vim.api.nvim_set_hl(colors.NS_ID, combined_name, combined_hl) + + self.combined_groups[combined_name] = true + end +end + +---Calculate highlight group for icon and name. A combined highlight group will be created +---when there is more than one highlight. +---A highlight group is always calculated and upserted for the case of highlights changing. +---@param node Node +---@return string|nil icon_hl_group +---@return string|nil name_hl_group +function Builder:_add_highlights(node) + -- result + local icon_hl_group, name_hl_group + + -- calculate all groups + local icon_groups = {} + local name_groups = {} + local d, icon, name + for i = #self.decorators, 1, -1 do + d = self.decorators[i] + icon, name = d:groups_icon_name(node) + table.insert(icon_groups, icon) + table.insert(name_groups, name) + end + + -- one or many icon groups + if #icon_groups > 1 then + icon_hl_group = self:_combined_group_name(icon_groups) + self:_create_combined_group(icon_groups) + else + icon_hl_group = icon_groups[1] + end + + -- one or many name groups + if #name_groups > 1 then + name_hl_group = self:_combined_group_name(name_groups) + self:_create_combined_group(name_groups) + else + name_hl_group = name_groups[1] + end + + return icon_hl_group, name_hl_group +end + function Builder:_build_line(node, idx, num_children) -- various components local indent_markers = pad.get_indent_markers(self.depth, idx, num_children, node, self.markers) @@ -279,12 +348,9 @@ function Builder:_build_line(node, idx, num_children) end -- highighting - for i = #self.decorators, 1, -1 do - local d = self.decorators[i] - local icon_group, name_group = d:groups_icon_name(node) - table.insert(icon.hl, icon_group) - table.insert(name.hl, name_group) - end + local icon_hl_group, name_hl_group = self:_add_highlights(node) + table.insert(icon.hl, icon_hl_group) + table.insert(name.hl, name_hl_group) local line = self:_format_line(indent_markers, arrows, icon, name, node) self:_insert_line(self:_unwrap_highlighted_strings(line)) diff --git a/lua/nvim-tree/renderer/init.lua b/lua/nvim-tree/renderer/init.lua index c275dcce79e..13b90824315 100644 --- a/lua/nvim-tree/renderer/init.lua +++ b/lua/nvim-tree/renderer/init.lua @@ -1,3 +1,4 @@ +local colors = require "nvim-tree.colors" local core = require "nvim-tree.core" local log = require "nvim-tree.log" local view = require "nvim-tree.view" @@ -24,8 +25,6 @@ local M = { local SIGN_GROUP = "NvimTreeRendererSigns" -local namespace_id = vim.api.nvim_create_namespace "NvimTreeHighlights" - local function _draw(bufnr, lines, hl, sign_names) vim.api.nvim_buf_set_option(bufnr, "modifiable", true) vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines) @@ -41,11 +40,11 @@ function M.render_hl(bufnr, hl) if not bufnr or not vim.api.nvim_buf_is_loaded(bufnr) then return end - vim.api.nvim_buf_clear_namespace(bufnr, namespace_id, 0, -1) + vim.api.nvim_buf_clear_namespace(bufnr, colors.NS_ID, 0, -1) for _, data in ipairs(hl or M.last_highlights) do if type(data[1]) == "table" then for _, group in ipairs(data[1]) do - vim.api.nvim_buf_add_highlight(bufnr, namespace_id, group, data[2], data[3], data[4]) + vim.api.nvim_buf_add_highlight(bufnr, colors.NS_ID, group, data[2], data[3], data[4]) end end end diff --git a/lua/nvim-tree/view.lua b/lua/nvim-tree/view.lua index 81fe36e96c7..25383c4e978 100644 --- a/lua/nvim-tree/view.lua +++ b/lua/nvim-tree/view.lua @@ -1,3 +1,4 @@ +local colors = require "nvim-tree.colors" local events = require "nvim-tree.events" local utils = require "nvim-tree.utils" local log = require "nvim-tree.log" @@ -38,19 +39,6 @@ M.View = { cursorlineopt = "both", colorcolumn = "0", wrap = false, - winhl = table.concat({ - "EndOfBuffer:NvimTreeEndOfBuffer", - "CursorLine:NvimTreeCursorLine", - "CursorLineNr:NvimTreeCursorLineNr", - "LineNr:NvimTreeLineNr", - "WinSeparator:NvimTreeWinSeparator", - "StatusLine:NvimTreeStatusLine", - "StatusLineNC:NvimTreeStatuslineNC", - "SignColumn:NvimTreeSignColumn", - "Normal:NvimTreeNormal", - "NormalNC:NvimTreeNormalNC", - "NormalFloat:NvimTreeNormalFloat", - }, ","), }, } @@ -147,6 +135,7 @@ local function set_window_options_and_buffer() vim.opt_local[k] = v end vim.opt.eventignore = eventignore + vim.api.nvim_win_set_hl_ns(0, colors.NS_ID) end ---@return table @@ -539,13 +528,6 @@ function M.is_root_folder_visible(cwd) return cwd ~= "/" and not M.View.hide_root_folder end --- used on ColorScheme event -function M.reset_winhl() - if M.get_winnr() and vim.api.nvim_win_is_valid(M.get_winnr()) then - vim.wo[M.get_winnr()].winhl = M.View.winopts.winhl - end -end - function M.setup(opts) local options = opts.view or {} M.View.centralize_selection = options.centralize_selection From 6029bcd61974b16dce5a995d302407d9616e252a Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sun, 7 Jan 2024 12:50:18 +1100 Subject: [PATCH 31/37] small tidies --- lua/nvim-tree/actions/fs/copy-paste.lua | 4 ++-- lua/nvim-tree/renderer/builder.lua | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lua/nvim-tree/actions/fs/copy-paste.lua b/lua/nvim-tree/actions/fs/copy-paste.lua index 099e227277e..87f9bbb545b 100644 --- a/lua/nvim-tree/actions/fs/copy-paste.lua +++ b/lua/nvim-tree/actions/fs/copy-paste.lua @@ -315,14 +315,14 @@ function M.copy_absolute_path(node) copy_to_clipboard(content) end ----Node is cut. May also be copied. +---Node is cut. Will not be copied. ---@param node Node ---@return boolean function M.is_cut(node) return vim.tbl_contains(clipboard.cut, node) end ----Node is copied. May also be cut. +---Node is copied. Will not be cut. ---@param node Node ---@return boolean function M.is_copied(node) diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 381f22336e5..10293110b87 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -9,7 +9,7 @@ local icons = require "nvim-tree.renderer.components.icons" ---@field private index number ---@field private depth number ---@field private highlights table[] hl_group, line, col_start, col_end arguments for vim.api.nvim_buf_add_highlight ----@field private combined_groups boolean[] combined group names +---@field private combined_groups string[] combined group names ---@field private lines string[] includes icons etc. ---@field private markers boolean[] indent markers ---@field private sign_names string[] line signs @@ -273,7 +273,7 @@ function Builder:_create_combined_group(groups) local combined_name = self:_combined_group_name(groups) -- only create if necessary - if not self.combined_groups[combined_name] then + if not vim.tbl_contains(self.combined_groups, combined_name) then local combined_hl = {} -- build the highlight, overriding values @@ -286,7 +286,7 @@ function Builder:_create_combined_group(groups) vim.api.nvim_set_hl_ns_fast(colors.NS_ID) vim.api.nvim_set_hl(colors.NS_ID, combined_name, combined_hl) - self.combined_groups[combined_name] = true + table.insert(self.combined_groups, combined_name) end end From 82e1ac813dffe1732a920dc38ec8606b5bf90507 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sun, 7 Jan 2024 12:53:46 +1100 Subject: [PATCH 32/37] colors.lua -> appearance.lua --- lua/nvim-tree.lua | 10 +++++----- lua/nvim-tree/{colors.lua => appearance.lua} | 0 lua/nvim-tree/renderer/builder.lua | 6 +++--- lua/nvim-tree/renderer/init.lua | 6 +++--- lua/nvim-tree/view.lua | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) rename lua/nvim-tree/{colors.lua => appearance.lua} (100%) diff --git a/lua/nvim-tree.lua b/lua/nvim-tree.lua index a6ed2ac520a..9584ab5e2b6 100644 --- a/lua/nvim-tree.lua +++ b/lua/nvim-tree.lua @@ -1,6 +1,6 @@ local lib = require "nvim-tree.lib" local log = require "nvim-tree.log" -local colors = require "nvim-tree.colors" +local appearance = require "nvim-tree.appearance" local renderer = require "nvim-tree.renderer" local view = require "nvim-tree.view" local commands = require "nvim-tree.commands" @@ -162,10 +162,10 @@ local function setup_autocommands(opts) vim.api.nvim_create_autocmd(name, vim.tbl_extend("force", default_opts, custom_opts)) end - -- reset and draw highlights when colorscheme is changed - create_nvim_tree_autocmd("ColorScheme", { + -- reset and draw highlights when appearancecheme is changed + create_nvim_tree_autocmd("appearancecheme", { callback = function() - colors.setup() + appearance.setup() renderer.render_hl(view.get_bufnr()) end, }) @@ -787,7 +787,7 @@ function M.setup(conf) require("nvim-tree.actions").setup(opts) require("nvim-tree.keymap").setup(opts) - require("nvim-tree.colors").setup() + require("nvim-tree.appearance").setup() require("nvim-tree.diagnostics").setup(opts) require("nvim-tree.explorer").setup(opts) require("nvim-tree.git").setup(opts) diff --git a/lua/nvim-tree/colors.lua b/lua/nvim-tree/appearance.lua similarity index 100% rename from lua/nvim-tree/colors.lua rename to lua/nvim-tree/appearance.lua diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 10293110b87..d8247354352 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -1,4 +1,4 @@ -local colors = require "nvim-tree.colors" +local appearance = require "nvim-tree.appearance" local utils = require "nvim-tree.utils" local notify = require "nvim-tree.notify" @@ -283,8 +283,8 @@ function Builder:_create_combined_group(groups) end -- highlight directly in the namespace - vim.api.nvim_set_hl_ns_fast(colors.NS_ID) - vim.api.nvim_set_hl(colors.NS_ID, combined_name, combined_hl) + vim.api.nvim_set_hl_ns_fast(appearance.NS_ID) + vim.api.nvim_set_hl(appearance.NS_ID, combined_name, combined_hl) table.insert(self.combined_groups, combined_name) end diff --git a/lua/nvim-tree/renderer/init.lua b/lua/nvim-tree/renderer/init.lua index 13b90824315..351c54b5306 100644 --- a/lua/nvim-tree/renderer/init.lua +++ b/lua/nvim-tree/renderer/init.lua @@ -1,4 +1,4 @@ -local colors = require "nvim-tree.colors" +local appearance = require "nvim-tree.appearance" local core = require "nvim-tree.core" local log = require "nvim-tree.log" local view = require "nvim-tree.view" @@ -40,11 +40,11 @@ function M.render_hl(bufnr, hl) if not bufnr or not vim.api.nvim_buf_is_loaded(bufnr) then return end - vim.api.nvim_buf_clear_namespace(bufnr, colors.NS_ID, 0, -1) + vim.api.nvim_buf_clear_namespace(bufnr, appearance.NS_ID, 0, -1) for _, data in ipairs(hl or M.last_highlights) do if type(data[1]) == "table" then for _, group in ipairs(data[1]) do - vim.api.nvim_buf_add_highlight(bufnr, colors.NS_ID, group, data[2], data[3], data[4]) + vim.api.nvim_buf_add_highlight(bufnr, appearance.NS_ID, group, data[2], data[3], data[4]) end end end diff --git a/lua/nvim-tree/view.lua b/lua/nvim-tree/view.lua index 25383c4e978..96c187b022c 100644 --- a/lua/nvim-tree/view.lua +++ b/lua/nvim-tree/view.lua @@ -1,4 +1,4 @@ -local colors = require "nvim-tree.colors" +local appearance = require "nvim-tree.appearance" local events = require "nvim-tree.events" local utils = require "nvim-tree.utils" local log = require "nvim-tree.log" @@ -135,7 +135,7 @@ local function set_window_options_and_buffer() vim.opt_local[k] = v end vim.opt.eventignore = eventignore - vim.api.nvim_win_set_hl_ns(0, colors.NS_ID) + vim.api.nvim_win_set_hl_ns(0, appearance.NS_ID) end ---@return table From 0a2c4604233396fa4639e12e9b49039c2f5b348d Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sun, 7 Jan 2024 13:04:37 +1100 Subject: [PATCH 33/37] full-name uses one and only namespace --- lua/nvim-tree.lua | 4 ++-- lua/nvim-tree/renderer/components/full-name.lua | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lua/nvim-tree.lua b/lua/nvim-tree.lua index 9584ab5e2b6..15e229b667a 100644 --- a/lua/nvim-tree.lua +++ b/lua/nvim-tree.lua @@ -162,8 +162,8 @@ local function setup_autocommands(opts) vim.api.nvim_create_autocmd(name, vim.tbl_extend("force", default_opts, custom_opts)) end - -- reset and draw highlights when appearancecheme is changed - create_nvim_tree_autocmd("appearancecheme", { + -- reset and draw highlights when colorscheme is changed + create_nvim_tree_autocmd("ColorScheme", { callback = function() appearance.setup() renderer.render_hl(view.get_bufnr()) diff --git a/lua/nvim-tree/renderer/components/full-name.lua b/lua/nvim-tree/renderer/components/full-name.lua index 7ab5e6b3efe..b937e6ca1a5 100644 --- a/lua/nvim-tree/renderer/components/full-name.lua +++ b/lua/nvim-tree/renderer/components/full-name.lua @@ -1,3 +1,5 @@ +local appearance = require "nvim-tree.appearance" + local M = {} local utils = require "nvim-tree.utils" @@ -66,13 +68,12 @@ local function show() style = "minimal", }) - 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 = 1 }) + local extmarks = vim.api.nvim_buf_get_extmarks(0, appearance.NS_ID, { line_nr - 1, 0 }, { line_nr - 1, -1 }, { details = 1 }) 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 local hl = extmark[4] - vim.api.nvim_buf_add_highlight(0, ns_id, hl.hl_group, 0, extmark[3], hl.end_col) + vim.api.nvim_buf_add_highlight(0, appearance.NS_ID, hl.hl_group, 0, extmark[3], hl.end_col) end vim.cmd [[ setlocal nowrap cursorline noswapfile nobuflisted buftype=nofile bufhidden=hide ]] end) From cde93f3b67f697bd29b4374781edee425232d382 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sun, 7 Jan 2024 13:52:20 +1100 Subject: [PATCH 34/37] don't highlight fast, just apply to namespace, safer win_set_hl --- lua/nvim-tree/appearance.lua | 2 +- lua/nvim-tree/renderer/builder.lua | 1 - lua/nvim-tree/view.lua | 4 +++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lua/nvim-tree/appearance.lua b/lua/nvim-tree/appearance.lua index f0b3f8b72bf..dcddf29b459 100644 --- a/lua/nvim-tree/appearance.lua +++ b/lua/nvim-tree/appearance.lua @@ -208,7 +208,7 @@ function M.setup() vim.api.nvim_command("hi def link " .. from .. " " .. to) end - -- window namespace; these don't appear to be cleared on colorscheme however err on the side of caution + -- window standard; this doesn't appear to clear on ColorScheme however we err on the side of caution for from, to in pairs(NS_LINKS) do vim.api.nvim_set_hl(M.NS_ID, from, { link = to }) end diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index d8247354352..c0d3dcc4e92 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -283,7 +283,6 @@ function Builder:_create_combined_group(groups) end -- highlight directly in the namespace - vim.api.nvim_set_hl_ns_fast(appearance.NS_ID) vim.api.nvim_set_hl(appearance.NS_ID, combined_name, combined_hl) table.insert(self.combined_groups, combined_name) diff --git a/lua/nvim-tree/view.lua b/lua/nvim-tree/view.lua index 96c187b022c..6cb59534ff0 100644 --- a/lua/nvim-tree/view.lua +++ b/lua/nvim-tree/view.lua @@ -135,7 +135,9 @@ local function set_window_options_and_buffer() vim.opt_local[k] = v end vim.opt.eventignore = eventignore - vim.api.nvim_win_set_hl_ns(0, appearance.NS_ID) + + -- use highlights from the nvim_tree namespace + vim.api.nvim_win_set_hl_ns(M.get_winnr(), appearance.NS_ID) end ---@return table From 874e5392acb2a56fb809018102751dd506ac6cc9 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sun, 7 Jan 2024 16:06:11 +1100 Subject: [PATCH 35/37] gut builder (#2622) collapse Builder --- lua/nvim-tree/renderer/builder.lua | 318 +++++++++++++++-------------- lua/nvim-tree/renderer/init.lua | 63 ++---- 2 files changed, 181 insertions(+), 200 deletions(-) diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index c0d3dcc4e92..2b21318c909 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -1,104 +1,94 @@ local appearance = require "nvim-tree.appearance" -local utils = require "nvim-tree.utils" +local core = require "nvim-tree.core" +local live_filter = require "nvim-tree.live-filter" local notify = require "nvim-tree.notify" +local utils = require "nvim-tree.utils" +local view = require "nvim-tree.view" +local log = require "nvim-tree.log" + +local DecoratorBookmarks = require "nvim-tree.renderer.decorator.bookmarks" +local DecoratorCopied = require "nvim-tree.renderer.decorator.copied" +local DecoratorCut = require "nvim-tree.renderer.decorator.cut" +local DecoratorDiagnostics = require "nvim-tree.renderer.decorator.diagnostics" +local DecoratorGit = require "nvim-tree.renderer.decorator.git" +local DecoratorModified = require "nvim-tree.renderer.decorator.modified" +local DecoratorOpened = require "nvim-tree.renderer.decorator.opened" local pad = require "nvim-tree.renderer.components.padding" local icons = require "nvim-tree.renderer.components.icons" +local M = { + opts = {}, + decorators = {}, + picture_map = { + jpg = true, + jpeg = true, + png = true, + gif = true, + webp = true, + jxl = true, + }, +} + +---@class HighlightedString +---@field str string +---@field hl string[] + +---@class AddHighlightArgs +---@field group string[] +---@field line number +---@field col_start number +---@field col_end number + ---@class Builder +---@field lines string[] includes icons etc. +---@field hl_args AddHighlightArgs[] line highlights +---@field signs string[] line signs +---@field private root_cwd string absolute path ---@field private index number ---@field private depth number ----@field private highlights table[] hl_group, line, col_start, col_end arguments for vim.api.nvim_buf_add_highlight ---@field private combined_groups string[] combined group names ----@field private lines string[] includes icons etc. ---@field private markers boolean[] indent markers ----@field private sign_names string[] line signs ----@field private root_cwd string absolute path ----@field private decorators Decorator[] in priority order local Builder = {} -Builder.__index = Builder -local DEFAULT_ROOT_FOLDER_LABEL = ":~:s?$?/..?" - -function Builder.new(root_cwd, decorators) - return setmetatable({ +---@return Builder +function Builder:new() + local o = { + root_cwd = core.get_cwd(), index = 0, depth = 0, - highlights = {}, + hl_args = {}, combined_groups = {}, lines = {}, markers = {}, - sign_names = {}, - root_cwd = root_cwd, - decorators = decorators, - }, Builder) -end - -function Builder:configure_root_label(root_folder_label) - self.root_folder_label = root_folder_label or DEFAULT_ROOT_FOLDER_LABEL - return self -end - -function Builder:configure_trailing_slash(with_trailing) - self.trailing_slash = with_trailing and "/" or "" - return self -end - -function Builder:configure_special_files(special_files) - self.special_files = special_files - return self -end - -function Builder:configure_picture_map(picture_map) - self.picture_map = picture_map - return self -end - -function Builder:configure_filter(filter, prefix) - self.filter_prefix = prefix - self.filter = filter - return self -end + signs = {}, + } + setmetatable(o, self) + self.__index = self -function Builder:configure_icon_padding(padding) - self.icon_padding = padding or " " - return self -end - -function Builder:configure_symlink_destination(show) - self.symlink_destination = show - return self -end - -function Builder:configure_group_name_modifier(group_name_modifier) - if type(group_name_modifier) == "function" then - self.group_name_modifier = group_name_modifier - end - return self + return o end ---Insert ranged highlight groups into self.highlights +---@private ---@param groups string[] ---@param start number ---@param end_ number|nil -function Builder:_insert_highlight(groups, start, end_) - table.insert(self.highlights, { groups, self.index, start, end_ or -1 }) -end - -function Builder:_insert_line(line) - table.insert(self.lines, line) +function Builder:insert_highlight(groups, start, end_) + table.insert(self.hl_args, { groups, self.index, start, end_ or -1 }) end -function Builder:_get_folder_name(node) +---@private +function Builder:get_folder_name(node) local name = node.name local next = node.group_next while next do - name = name .. "/" .. next.name + name = string.format("%s/%s", name, next.name) next = next.group_next end - if node.group_next and self.group_name_modifier then - local new_name = self.group_name_modifier(name) + if node.group_next and type(M.opts.renderer.group_empty == "function") then + local new_name = M.opts.renderer.group_empty(name) if type(new_name) == "string" then name = new_name else @@ -106,16 +96,13 @@ function Builder:_get_folder_name(node) end end - return name .. self.trailing_slash + return string.format("%s%s", name, M.opts.renderer.add_trailing and "/" or "") end ----@class HighlightedString ----@field str string ----@field hl string[] - +---@private ---@param highlighted_strings HighlightedString[] ---@return string -function Builder:_unwrap_highlighted_strings(highlighted_strings) +function Builder:unwrap_highlighted_strings(highlighted_strings) if not highlighted_strings then return "" end @@ -124,21 +111,22 @@ function Builder:_unwrap_highlighted_strings(highlighted_strings) for _, v in ipairs(highlighted_strings) do if #v.str > 0 then if v.hl and type(v.hl) == "table" then - self:_insert_highlight(v.hl, #string, #string + #v.str) + self:insert_highlight(v.hl, #string, #string + #v.str) end - string = string .. v.str + string = string.format("%s%s", string, v.str) end end return string end +---@private ---@param node table ---@return HighlightedString icon ---@return HighlightedString name -function Builder:_build_folder(node) +function Builder:build_folder(node) local has_children = #node.nodes ~= 0 or node.has_children local icon, icon_hl = icons.get_folder_icon(node, has_children) - local foldername = self:_get_folder_name(node) + local foldername = self:get_folder_name(node) if #icon > 0 and icon_hl == nil then if node.open then @@ -149,12 +137,14 @@ function Builder:_build_folder(node) end local foldername_hl = "NvimTreeFolderName" - if node.link_to and self.symlink_destination then + if node.link_to and M.opts.renderer.symlink_destination then local arrow = icons.i.symlink_arrow local link_to = utils.path_relative(node.link_to, self.root_cwd) - foldername = foldername .. arrow .. link_to + foldername = string.format("%s%s%s", foldername, arrow, link_to) foldername_hl = "NvimTreeSymlinkFolderName" - elseif vim.tbl_contains(self.special_files, node.absolute_path) or vim.tbl_contains(self.special_files, node.name) then + elseif + vim.tbl_contains(M.opts.renderer.special_files, node.absolute_path) or vim.tbl_contains(M.opts.renderer.special_files, node.name) + then foldername_hl = "NvimTreeSpecialFolderName" elseif node.open then foldername_hl = "NvimTreeOpenedFolderName" @@ -165,53 +155,48 @@ function Builder:_build_folder(node) return { str = icon, hl = { icon_hl } }, { str = foldername, hl = { foldername_hl } } end +---@private ---@param node table ---@return HighlightedString icon ---@return HighlightedString name -function Builder:_build_symlink(node) +function Builder:build_symlink(node) local icon = icons.i.symlink local arrow = icons.i.symlink_arrow local symlink_formatted = node.name - if self.symlink_destination then + if M.opts.renderer.symlink_destination then local link_to = utils.path_relative(node.link_to, self.root_cwd) - symlink_formatted = symlink_formatted .. arrow .. link_to + symlink_formatted = string.format("%s%s%s", symlink_formatted, arrow, link_to) end return { str = icon, hl = { "NvimTreeSymlinkIcon" } }, { str = symlink_formatted, hl = { "NvimTreeSymlink" } } end ----@param node table ----@return HighlightedString icon -function Builder:_build_file_icon(node) - local icon, hl_group = icons.get_file_icon(node.name, node.extension) - return { str = icon, hl = { hl_group } } -end - +---@private ---@param node table ---@return HighlightedString icon ---@return HighlightedString name -function Builder:_build_file(node) - local icon = self:_build_file_icon(node) - +function Builder:build_file(node) local hl - if vim.tbl_contains(self.special_files, node.absolute_path) or vim.tbl_contains(self.special_files, node.name) then + if vim.tbl_contains(M.opts.renderer.special_files, node.absolute_path) or vim.tbl_contains(M.opts.renderer.special_files, node.name) then hl = "NvimTreeSpecialFile" elseif node.executable then hl = "NvimTreeExecFile" - elseif self.picture_map[node.extension] then + elseif M.picture_map[node.extension] then hl = "NvimTreeImageFile" end - return icon, { str = node.name, hl = { hl } } + local icon, hl_group = icons.get_file_icon(node.name, node.extension) + return { str = icon, hl = { hl_group } }, { str = node.name, hl = { hl } } end +---@private ---@param indent_markers HighlightedString[] ---@param arrows HighlightedString[]|nil ---@param icon HighlightedString ---@param name HighlightedString ---@param node table ---@return HighlightedString[] -function Builder:_format_line(indent_markers, arrows, icon, name, node) +function Builder:format_line(indent_markers, arrows, icon, name, node) local added_len = 0 local function add_to_end(t1, t2) if not t2 then @@ -219,7 +204,7 @@ function Builder:_format_line(indent_markers, arrows, icon, name, node) end for _, v in ipairs(t2) do if added_len > 0 then - table.insert(t1, { str = self.icon_padding }) + table.insert(t1, { str = M.opts.renderer.icons.padding }) end table.insert(t1, v) end @@ -235,42 +220,47 @@ function Builder:_format_line(indent_markers, arrows, icon, name, node) local line = { indent_markers, arrows } add_to_end(line, { icon }) - for i = #self.decorators, 1, -1 do - add_to_end(line, self.decorators[i]:icons_before(node)) + for i = #M.decorators, 1, -1 do + add_to_end(line, M.decorators[i]:icons_before(node)) end add_to_end(line, { name }) - for i = #self.decorators, 1, -1 do - add_to_end(line, self.decorators[i]:icons_after(node)) + for i = #M.decorators, 1, -1 do + add_to_end(line, M.decorators[i]:icons_after(node)) end + log.line("dev", "line = %s", vim.inspect(line)) return line end -function Builder:_build_signs(node) +---@private +---@param node Node +function Builder:build_signs(node) -- first in priority order local sign_name - for _, d in ipairs(self.decorators) do + for _, d in ipairs(M.decorators) do sign_name = d:sign_name(node) if sign_name then - self.sign_names[self.index] = sign_name + self.signs[self.index] = sign_name break end end end ---Combined group name less than the 200 byte limit of highlight group names +---@private ---@param groups string[] highlight group names ---@return string name "NvimTreeCombinedHL" .. sha256 -function Builder:_combined_group_name(groups) +function Builder:combined_group_name(groups) return string.format("NvimTreeCombinedHL%s", vim.fn.sha256(table.concat(groups))) end ---Create a highlight group for groups with later groups overriding previous. +---@private ---@param groups string[] highlight group names -function Builder:_create_combined_group(groups) - local combined_name = self:_combined_group_name(groups) +function Builder:create_combined_group(groups) + local combined_name = self:combined_group_name(groups) -- only create if necessary if not vim.tbl_contains(self.combined_groups, combined_name) then @@ -292,10 +282,11 @@ end ---Calculate highlight group for icon and name. A combined highlight group will be created ---when there is more than one highlight. ---A highlight group is always calculated and upserted for the case of highlights changing. +---@private ---@param node Node ---@return string|nil icon_hl_group ---@return string|nil name_hl_group -function Builder:_add_highlights(node) +function Builder:add_highlights(node) -- result local icon_hl_group, name_hl_group @@ -303,8 +294,8 @@ function Builder:_add_highlights(node) local icon_groups = {} local name_groups = {} local d, icon, name - for i = #self.decorators, 1, -1 do - d = self.decorators[i] + for i = #M.decorators, 1, -1 do + d = M.decorators[i] icon, name = d:groups_icon_name(node) table.insert(icon_groups, icon) table.insert(name_groups, name) @@ -312,16 +303,16 @@ function Builder:_add_highlights(node) -- one or many icon groups if #icon_groups > 1 then - icon_hl_group = self:_combined_group_name(icon_groups) - self:_create_combined_group(icon_groups) + icon_hl_group = self:combined_group_name(icon_groups) + self:create_combined_group(icon_groups) else icon_hl_group = icon_groups[1] end -- one or many name groups if #name_groups > 1 then - name_hl_group = self:_combined_group_name(name_groups) - self:_create_combined_group(name_groups) + name_hl_group = self:combined_group_name(name_groups) + self:create_combined_group(name_groups) else name_hl_group = name_groups[1] end @@ -329,7 +320,8 @@ function Builder:_add_highlights(node) return icon_hl_group, name_hl_group end -function Builder:_build_line(node, idx, num_children) +---@private +function Builder:build_line(node, idx, num_children) -- various components local indent_markers = pad.get_indent_markers(self.depth, idx, num_children, node, self.markers) local arrows = pad.get_arrows(node) @@ -339,20 +331,20 @@ function Builder:_build_line(node, idx, num_children) local is_symlink = node.link_to ~= nil local icon, name if is_folder then - icon, name = self:_build_folder(node) + icon, name = self:build_folder(node) elseif is_symlink then - icon, name = self:_build_symlink(node) + icon, name = self:build_symlink(node) else - icon, name = self:_build_file(node) + icon, name = self:build_file(node) end -- highighting - local icon_hl_group, name_hl_group = self:_add_highlights(node) + local icon_hl_group, name_hl_group = self:add_highlights(node) table.insert(icon.hl, icon_hl_group) table.insert(name.hl, name_hl_group) - local line = self:_format_line(indent_markers, arrows, icon, name, node) - self:_insert_line(self:_unwrap_highlighted_strings(line)) + local line = self:format_line(indent_markers, arrows, icon, name, node) + table.insert(self.lines, self:unwrap_highlighted_strings(line)) self.index = self.index + 1 @@ -360,13 +352,14 @@ function Builder:_build_line(node, idx, num_children) if node.open then self.depth = self.depth + 1 - self:build(node) + self:build_lines(node) self.depth = self.depth - 1 end end -function Builder:_get_nodes_number(nodes) - if not self.filter then +---@private +function Builder:get_nodes_number(nodes) + if not live_filter.filter then return #nodes end @@ -379,54 +372,77 @@ function Builder:_get_nodes_number(nodes) return i end -function Builder:build(tree) - local num_children = self:_get_nodes_number(tree.nodes) +---@private +function Builder:build_lines(node) + if not node then + node = core.get_explorer() + end + local num_children = self:get_nodes_number(node.nodes) local idx = 1 - for _, node in ipairs(tree.nodes) do - if not node.hidden then - self:_build_signs(node) - self:_build_line(node, idx, num_children) + for _, n in ipairs(node.nodes) do + if not n.hidden then + self:build_signs(n) + self:build_line(n, idx, num_children) idx = idx + 1 end end - - return self end -local function format_root_name(root_cwd, root_label) +---@private +---@param root_label function|string +---@return string +function Builder:format_root_name(root_label) if type(root_label) == "function" then - local label = root_label(root_cwd) + local label = root_label(self.root_cwd) if type(label) == "string" then return label else - root_label = DEFAULT_ROOT_FOLDER_LABEL + return "???" end end - return utils.path_remove_trailing(vim.fn.fnamemodify(root_cwd, root_label)) + return utils.path_remove_trailing(vim.fn.fnamemodify(self.root_cwd, root_label)) end -function Builder:build_header(show_header) - if show_header then - local root_name = format_root_name(self.root_cwd, self.root_folder_label) - self:_insert_line(root_name) - self:_insert_highlight({ "NvimTreeRootFolder" }, 0, string.len(root_name)) +---@private +function Builder:build_header() + if view.is_root_folder_visible(core.get_cwd()) then + local root_name = self:format_root_name(M.opts.renderer.root_folder_label) + table.insert(self.lines, root_name) + self:insert_highlight({ "NvimTreeRootFolder" }, 0, string.len(root_name)) self.index = 1 end - if self.filter then - local filter_line = self.filter_prefix .. "/" .. self.filter .. "/" - self:_insert_line(filter_line) - local prefix_length = string.len(self.filter_prefix) - self:_insert_highlight({ "NvimTreeLiveFilterPrefix" }, 0, prefix_length) - self:_insert_highlight({ "NvimTreeLiveFilterValue" }, prefix_length, string.len(filter_line)) + if live_filter.filter then + local filter_line = string.format("%s/%s/", M.opts.live_filter.prefix, live_filter.filter) + table.insert(self.lines, filter_line) + local prefix_length = string.len(M.opts.live_filter.prefix) + self:insert_highlight({ "NvimTreeLiveFilterPrefix" }, 0, prefix_length) + self:insert_highlight({ "NvimTreeLiveFilterValue" }, prefix_length, string.len(filter_line)) self.index = self.index + 1 end +end +---Build all lines with highlights and signs +---@return Builder +function Builder:build() + self:build_header() + self:build_lines() return self end -function Builder:unwrap() - return self.lines, self.highlights, self.sign_names +function Builder.setup(opts) + M.opts = opts + + -- priority order + M.decorators = { + DecoratorCut:new(opts), + DecoratorCopied:new(opts), + DecoratorDiagnostics:new(opts), + DecoratorBookmarks:new(opts), + DecoratorModified:new(opts), + DecoratorOpened:new(opts), + DecoratorGit:new(opts), + } end return Builder diff --git a/lua/nvim-tree/renderer/init.lua b/lua/nvim-tree/renderer/init.lua index 351c54b5306..ce918682743 100644 --- a/lua/nvim-tree/renderer/init.lua +++ b/lua/nvim-tree/renderer/init.lua @@ -8,30 +8,24 @@ local _padding = require "nvim-tree.renderer.components.padding" local icon_component = require "nvim-tree.renderer.components.icons" local full_name = require "nvim-tree.renderer.components.full-name" local Builder = require "nvim-tree.renderer.builder" -local live_filter = require "nvim-tree.live-filter" - -local DecoratorBookmarks = require "nvim-tree.renderer.decorator.bookmarks" -local DecoratorCopied = require "nvim-tree.renderer.decorator.copied" -local DecoratorCut = require "nvim-tree.renderer.decorator.cut" -local DecoratorDiagnostics = require "nvim-tree.renderer.decorator.diagnostics" -local DecoratorGit = require "nvim-tree.renderer.decorator.git" -local DecoratorModified = require "nvim-tree.renderer.decorator.modified" -local DecoratorOpened = require "nvim-tree.renderer.decorator.opened" local M = { - last_highlights = {}, - decorators = {}, + last_hl_args = {}, } local SIGN_GROUP = "NvimTreeRendererSigns" -local function _draw(bufnr, lines, hl, sign_names) +---@param bufnr number +---@param lines string[] +---@param hl_args AddHighlightArgs[] +---@param signs string[] +local function _draw(bufnr, lines, hl_args, signs) vim.api.nvim_buf_set_option(bufnr, "modifiable", true) vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines) - M.render_hl(bufnr, hl) + M.render_hl(bufnr, hl_args) vim.api.nvim_buf_set_option(bufnr, "modifiable", false) vim.fn.sign_unplace(SIGN_GROUP) - for i, sign_name in pairs(sign_names) do + for i, sign_name in pairs(signs) do vim.fn.sign_place(0, SIGN_GROUP, sign_name, bufnr, { lnum = i + 1 }) end end @@ -41,7 +35,7 @@ function M.render_hl(bufnr, hl) return end vim.api.nvim_buf_clear_namespace(bufnr, appearance.NS_ID, 0, -1) - for _, data in ipairs(hl or M.last_highlights) do + for _, data in ipairs(hl or M.last_hl_args) do if type(data[1]) == "table" then for _, group in ipairs(data[1]) do vim.api.nvim_buf_add_highlight(bufnr, appearance.NS_ID, group, data[2], data[3], data[4]) @@ -50,15 +44,6 @@ function M.render_hl(bufnr, hl) end end -local picture_map = { - jpg = true, - jpeg = true, - png = true, - gif = true, - webp = true, - jxl = true, -} - function M.draw() local bufnr = view.get_bufnr() if not core.get_explorer() or not bufnr or not vim.api.nvim_buf_is_loaded(bufnr) then @@ -70,24 +55,13 @@ function M.draw() local cursor = vim.api.nvim_win_get_cursor(view.get_winnr()) icon_component.reset_config() - local lines, hl, sign_names = Builder.new(core.get_cwd(), M.decorators) - :configure_root_label(M.config.root_folder_label) - :configure_trailing_slash(M.config.add_trailing) - :configure_special_files(M.config.special_files) - :configure_picture_map(picture_map) - :configure_icon_padding(M.config.icons.padding) - :configure_symlink_destination(M.config.symlink_destination) - :configure_filter(live_filter.filter, live_filter.prefix) - :configure_group_name_modifier(M.config.group_empty) - :build_header(view.is_root_folder_visible(core.get_cwd())) - :build(core.get_explorer()) - :unwrap() + local builder = Builder:new():build() - _draw(bufnr, lines, hl, sign_names) + _draw(bufnr, builder.lines, builder.hl_args, builder.signs) - M.last_highlights = hl + M.last_hl_args = builder.hl_args - if cursor and #lines >= cursor[1] then + if cursor and #builder.lines >= cursor[1] then vim.api.nvim_win_set_cursor(view.get_winnr(), cursor) end @@ -105,16 +79,7 @@ function M.setup(opts) full_name.setup(opts) icon_component.setup(opts) - -- priority order - M.decorators = { - DecoratorCut:new(opts), - DecoratorCopied:new(opts), - DecoratorDiagnostics:new(opts), - DecoratorBookmarks:new(opts), - DecoratorModified:new(opts), - DecoratorOpened:new(opts), - DecoratorGit:new(opts), - } + Builder.setup(opts) end return M From 28d0d82a1f24e0ce7e91f39d33cc079fcc73ffb0 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Mon, 8 Jan 2024 14:08:31 +1100 Subject: [PATCH 36/37] fix group_empty function check --- lua/nvim-tree/renderer/builder.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 2b21318c909..fd2771c0712 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -87,7 +87,7 @@ function Builder:get_folder_name(node) next = next.group_next end - if node.group_next and type(M.opts.renderer.group_empty == "function") then + if node.group_next and type(M.opts.renderer.group_empty) == "function" then local new_name = M.opts.renderer.group_empty(name) if type(new_name) == "string" then name = new_name From f74aa5b4d30f268cca3e70384f5893a3ca034473 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sat, 20 Jan 2024 16:10:43 +1100 Subject: [PATCH 37/37] feat(#2415): highlight-overhaul release date --- doc/nvim-tree-lua.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index f87c0d7a24b..4a4dee03612 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -2365,7 +2365,7 @@ Diagnostics Folder Highlight: > ============================================================================== 8.1 HIGHLIGHT OVERHAUL *nvim-tree-highlight-overhaul* -2023-12: significant highlighting changes, some breaking: +2024-01-20: significant highlighting changes, some breaking: - Full cterm support. - Standard vim highlight groups such |DiagnosticUnderlineError| are now the