Merge branch 'master' into ci-lua-language-server
This commit is contained in:
@@ -170,14 +170,15 @@ Show the mappings: `g?`
|
|||||||
`e` Rename: Basename |nvim-tree-api.fs.rename_basename()|
|
`e` Rename: Basename |nvim-tree-api.fs.rename_basename()|
|
||||||
`]e` Next Diagnostic |nvim-tree-api.node.navigate.diagnostics.next()|
|
`]e` Next Diagnostic |nvim-tree-api.node.navigate.diagnostics.next()|
|
||||||
`[e` Prev Diagnostic |nvim-tree-api.node.navigate.diagnostics.prev()|
|
`[e` Prev Diagnostic |nvim-tree-api.node.navigate.diagnostics.prev()|
|
||||||
`F` Clean Filter |nvim-tree-api.live_filter.clear()|
|
`F` Live Filter: Clear |nvim-tree-api.live_filter.clear()|
|
||||||
`f` Filter |nvim-tree-api.live_filter.start()|
|
`f` Live Filter: Start |nvim-tree-api.live_filter.start()|
|
||||||
`g?` Help |nvim-tree-api.tree.toggle_help()|
|
`g?` Help |nvim-tree-api.tree.toggle_help()|
|
||||||
`gy` Copy Absolute Path |nvim-tree-api.fs.copy.absolute_path()|
|
`gy` Copy Absolute Path |nvim-tree-api.fs.copy.absolute_path()|
|
||||||
`H` Toggle Filter: Dotfiles |nvim-tree-api.tree.toggle_hidden_filter()|
|
`H` Toggle Filter: Dotfiles |nvim-tree-api.tree.toggle_hidden_filter()|
|
||||||
`I` Toggle Filter: Git Ignore |nvim-tree-api.tree.toggle_gitignore_filter()|
|
`I` Toggle Filter: Git Ignore |nvim-tree-api.tree.toggle_gitignore_filter()|
|
||||||
`J` Last Sibling |nvim-tree-api.node.navigate.sibling.last()|
|
`J` Last Sibling |nvim-tree-api.node.navigate.sibling.last()|
|
||||||
`K` First Sibling |nvim-tree-api.node.navigate.sibling.first()|
|
`K` First Sibling |nvim-tree-api.node.navigate.sibling.first()|
|
||||||
|
`M` Toggle Filter: No Bookmark |nvim-tree-api.tree.toggle_no_bookmark_filter()|
|
||||||
`m` Toggle Bookmark |nvim-tree-api.marks.toggle()|
|
`m` Toggle Bookmark |nvim-tree-api.marks.toggle()|
|
||||||
`o` Open |nvim-tree-api.node.open.edit()|
|
`o` Open |nvim-tree-api.node.open.edit()|
|
||||||
`O` Open: No Window Picker |nvim-tree-api.node.open.no_window_picker()|
|
`O` Open: No Window Picker |nvim-tree-api.node.open.no_window_picker()|
|
||||||
@@ -502,6 +503,7 @@ Following is the default configuration. See |nvim-tree-opts| for details.
|
|||||||
dotfiles = false,
|
dotfiles = false,
|
||||||
git_clean = false,
|
git_clean = false,
|
||||||
no_buffer = false,
|
no_buffer = false,
|
||||||
|
no_bookmark = false,
|
||||||
custom = {},
|
custom = {},
|
||||||
exclude = {},
|
exclude = {},
|
||||||
},
|
},
|
||||||
@@ -1223,6 +1225,12 @@ For performance reasons this may not immediately update on buffer
|
|||||||
delete/wipe. A reload or filesystem event will result in an update.
|
delete/wipe. A reload or filesystem event will result in an update.
|
||||||
Type: `boolean`, Default: `false`
|
Type: `boolean`, Default: `false`
|
||||||
|
|
||||||
|
*nvim-tree.filters.no_bookmark*
|
||||||
|
Do not show files that are not bookarked.
|
||||||
|
Toggle via |nvim-tree-api.tree.toggle_no_bookmark_filter()|, default `M`
|
||||||
|
Enabling this is not useful as there is no means yet to persist bookmarks.
|
||||||
|
Type: `boolean`, Default: `false`
|
||||||
|
|
||||||
*nvim-tree.filters.custom*
|
*nvim-tree.filters.custom*
|
||||||
Custom list of vim regex for file/directory names that will not be shown.
|
Custom list of vim regex for file/directory names that will not be shown.
|
||||||
Backslashes must be escaped e.g. "^\\.git". See |string-match|.
|
Backslashes must be escaped e.g. "^\\.git". See |string-match|.
|
||||||
@@ -1666,6 +1674,10 @@ tree.toggle_git_clean_filter()
|
|||||||
tree.toggle_no_buffer_filter()
|
tree.toggle_no_buffer_filter()
|
||||||
Toggle |nvim-tree.filters.no_buffer| filter.
|
Toggle |nvim-tree.filters.no_buffer| filter.
|
||||||
|
|
||||||
|
*nvim-tree-api.tree.toggle_no_bookmark_filter()*
|
||||||
|
tree.toggle_no_bookmark_filter()
|
||||||
|
Toggle |nvim-tree.filters.no_bookmark| filter.
|
||||||
|
|
||||||
*nvim-tree-api.tree.toggle_custom_filter()*
|
*nvim-tree-api.tree.toggle_custom_filter()*
|
||||||
tree.toggle_custom_filter()
|
tree.toggle_custom_filter()
|
||||||
Toggle |nvim-tree.filters.custom| filter.
|
Toggle |nvim-tree.filters.custom| filter.
|
||||||
@@ -1862,9 +1874,17 @@ node.open.preview_no_picker() *nvim-tree-api.node.open.preview_no_picker()*
|
|||||||
node.navigate.git.next() *nvim-tree-api.node.navigate.git.next()*
|
node.navigate.git.next() *nvim-tree-api.node.navigate.git.next()*
|
||||||
Navigate to the next item showing git status.
|
Navigate to the next item showing git status.
|
||||||
|
|
||||||
|
*nvim-tree-api.node.navigate.git.next_skip_gitignored()*
|
||||||
|
node.navigate.git.next_skip_gitignored()
|
||||||
|
Same as |node.navigate.git.next()|, but skips gitignored files.
|
||||||
|
|
||||||
node.navigate.git.prev() *nvim-tree-api.node.navigate.git.prev()*
|
node.navigate.git.prev() *nvim-tree-api.node.navigate.git.prev()*
|
||||||
Navigate to the previous item showing git status.
|
Navigate to the previous item showing git status.
|
||||||
|
|
||||||
|
*nvim-tree-api.node.navigate.git.prev_skip_gitignored()*
|
||||||
|
node.navigate.git.prev_skip_gitignored()
|
||||||
|
Same as |node.navigate.git.prev()|, but skips gitignored files.
|
||||||
|
|
||||||
*nvim-tree-api.node.navigate.diagnostics.next()*
|
*nvim-tree-api.node.navigate.diagnostics.next()*
|
||||||
node.navigate.diagnostics.next()
|
node.navigate.diagnostics.next()
|
||||||
Navigate to the next item showing diagnostic status.
|
Navigate to the next item showing diagnostic status.
|
||||||
@@ -2138,14 +2158,15 @@ You are encouraged to copy these to your own |nvim-tree.on_attach| function.
|
|||||||
vim.keymap.set('n', 'e', api.fs.rename_basename, opts('Rename: Basename'))
|
vim.keymap.set('n', 'e', api.fs.rename_basename, opts('Rename: Basename'))
|
||||||
vim.keymap.set('n', ']e', api.node.navigate.diagnostics.next, opts('Next Diagnostic'))
|
vim.keymap.set('n', ']e', api.node.navigate.diagnostics.next, opts('Next Diagnostic'))
|
||||||
vim.keymap.set('n', '[e', api.node.navigate.diagnostics.prev, opts('Prev Diagnostic'))
|
vim.keymap.set('n', '[e', api.node.navigate.diagnostics.prev, opts('Prev Diagnostic'))
|
||||||
vim.keymap.set('n', 'F', api.live_filter.clear, opts('Clean Filter'))
|
vim.keymap.set('n', 'F', api.live_filter.clear, opts('Live Filter: Clear'))
|
||||||
vim.keymap.set('n', 'f', api.live_filter.start, opts('Filter'))
|
vim.keymap.set('n', 'f', api.live_filter.start, opts('Live Filter: Start'))
|
||||||
vim.keymap.set('n', 'g?', api.tree.toggle_help, opts('Help'))
|
vim.keymap.set('n', 'g?', api.tree.toggle_help, opts('Help'))
|
||||||
vim.keymap.set('n', 'gy', api.fs.copy.absolute_path, opts('Copy Absolute Path'))
|
vim.keymap.set('n', 'gy', api.fs.copy.absolute_path, opts('Copy Absolute Path'))
|
||||||
vim.keymap.set('n', 'H', api.tree.toggle_hidden_filter, opts('Toggle Filter: Dotfiles'))
|
vim.keymap.set('n', 'H', api.tree.toggle_hidden_filter, opts('Toggle Filter: Dotfiles'))
|
||||||
vim.keymap.set('n', 'I', api.tree.toggle_gitignore_filter, opts('Toggle Filter: Git Ignore'))
|
vim.keymap.set('n', 'I', api.tree.toggle_gitignore_filter, opts('Toggle Filter: Git Ignore'))
|
||||||
vim.keymap.set('n', 'J', api.node.navigate.sibling.last, opts('Last Sibling'))
|
vim.keymap.set('n', 'J', api.node.navigate.sibling.last, opts('Last Sibling'))
|
||||||
vim.keymap.set('n', 'K', api.node.navigate.sibling.first, opts('First Sibling'))
|
vim.keymap.set('n', 'K', api.node.navigate.sibling.first, opts('First Sibling'))
|
||||||
|
vim.keymap.set('n', 'M', api.tree.toggle_no_bookmark_filter, opts('Toggle Filter: No Bookmark'))
|
||||||
vim.keymap.set('n', 'm', api.marks.toggle, opts('Toggle Bookmark'))
|
vim.keymap.set('n', 'm', api.marks.toggle, opts('Toggle Bookmark'))
|
||||||
vim.keymap.set('n', 'o', api.node.open.edit, opts('Open'))
|
vim.keymap.set('n', 'o', api.node.open.edit, opts('Open'))
|
||||||
vim.keymap.set('n', 'O', api.node.open.no_window_picker, opts('Open: No Window Picker'))
|
vim.keymap.set('n', 'O', api.node.open.no_window_picker, opts('Open: No Window Picker'))
|
||||||
|
|||||||
@@ -507,6 +507,7 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
|
|||||||
dotfiles = false,
|
dotfiles = false,
|
||||||
git_clean = false,
|
git_clean = false,
|
||||||
no_buffer = false,
|
no_buffer = false,
|
||||||
|
no_bookmark = false,
|
||||||
custom = {},
|
custom = {},
|
||||||
exclude = {},
|
exclude = {},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ local view = require "nvim-tree.view"
|
|||||||
local core = require "nvim-tree.core"
|
local core = require "nvim-tree.core"
|
||||||
local lib = require "nvim-tree.lib"
|
local lib = require "nvim-tree.lib"
|
||||||
local explorer_node = require "nvim-tree.explorer.node"
|
local explorer_node = require "nvim-tree.explorer.node"
|
||||||
|
local diagnostics = require "nvim-tree.diagnostics"
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
@@ -30,9 +31,11 @@ function M.fn(opts)
|
|||||||
local valid = false
|
local valid = false
|
||||||
|
|
||||||
if opts.what == "git" then
|
if opts.what == "git" then
|
||||||
valid = explorer_node.get_git_status(node) ~= nil
|
local git_status = explorer_node.get_git_status(node)
|
||||||
|
valid = git_status ~= nil and (not opts.skip_gitignored or git_status[1] ~= "!!")
|
||||||
elseif opts.what == "diag" then
|
elseif opts.what == "diag" then
|
||||||
valid = node.diag_status ~= nil
|
local diag_status = diagnostics.get_diag_status(node)
|
||||||
|
valid = diag_status ~= nil and diag_status.value ~= nil
|
||||||
elseif opts.what == "opened" then
|
elseif opts.what == "opened" then
|
||||||
valid = vim.fn.bufloaded(node.absolute_path) ~= 0
|
valid = vim.fn.bufloaded(node.absolute_path) ~= 0
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -31,6 +31,11 @@ function M.no_buffer()
|
|||||||
reload()
|
reload()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function M.no_bookmark()
|
||||||
|
filters.config.filter_no_bookmark = not filters.config.filter_no_bookmark
|
||||||
|
reload()
|
||||||
|
end
|
||||||
|
|
||||||
function M.dotfiles()
|
function M.dotfiles()
|
||||||
filters.config.filter_dotfiles = not filters.config.filter_dotfiles
|
filters.config.filter_dotfiles = not filters.config.filter_dotfiles
|
||||||
reload()
|
reload()
|
||||||
|
|||||||
@@ -136,6 +136,8 @@ Api.tree.toggle_custom_filter = wrap(require("nvim-tree.actions.tree-modifiers.t
|
|||||||
|
|
||||||
Api.tree.toggle_hidden_filter = wrap(require("nvim-tree.actions.tree-modifiers.toggles").dotfiles)
|
Api.tree.toggle_hidden_filter = wrap(require("nvim-tree.actions.tree-modifiers.toggles").dotfiles)
|
||||||
|
|
||||||
|
Api.tree.toggle_no_bookmark_filter = wrap(require("nvim-tree.actions.tree-modifiers.toggles").no_bookmark)
|
||||||
|
|
||||||
Api.tree.toggle_help = wrap(require("nvim-tree.help").toggle)
|
Api.tree.toggle_help = wrap(require("nvim-tree.help").toggle)
|
||||||
|
|
||||||
Api.tree.is_tree_buf = wrap(require("nvim-tree.utils").is_nvim_tree_buf)
|
Api.tree.is_tree_buf = wrap(require("nvim-tree.utils").is_nvim_tree_buf)
|
||||||
@@ -214,6 +216,10 @@ Api.node.navigate.parent = wrap_node(require("nvim-tree.actions.moves.parent").f
|
|||||||
Api.node.navigate.parent_close = wrap_node(require("nvim-tree.actions.moves.parent").fn(true))
|
Api.node.navigate.parent_close = wrap_node(require("nvim-tree.actions.moves.parent").fn(true))
|
||||||
Api.node.navigate.git.next = wrap_node(require("nvim-tree.actions.moves.item").fn { where = "next", what = "git" })
|
Api.node.navigate.git.next = wrap_node(require("nvim-tree.actions.moves.item").fn { where = "next", what = "git" })
|
||||||
Api.node.navigate.git.prev = wrap_node(require("nvim-tree.actions.moves.item").fn { where = "prev", what = "git" })
|
Api.node.navigate.git.prev = wrap_node(require("nvim-tree.actions.moves.item").fn { where = "prev", what = "git" })
|
||||||
|
-- stylua: ignore
|
||||||
|
Api.node.navigate.git.next_skip_gitignored = wrap_node(require("nvim-tree.actions.moves.item").fn { where = "next", what = "git", skip_gitignored = true })
|
||||||
|
-- stylua: ignore
|
||||||
|
Api.node.navigate.git.prev_skip_gitignored = wrap_node(require("nvim-tree.actions.moves.item").fn { where = "prev", what = "git", skip_gitignored = true })
|
||||||
Api.node.navigate.diagnostics.next = wrap_node(require("nvim-tree.actions.moves.item").fn { where = "next", what = "diag" })
|
Api.node.navigate.diagnostics.next = wrap_node(require("nvim-tree.actions.moves.item").fn { where = "next", what = "diag" })
|
||||||
Api.node.navigate.diagnostics.prev = wrap_node(require("nvim-tree.actions.moves.item").fn { where = "prev", what = "diag" })
|
Api.node.navigate.diagnostics.prev = wrap_node(require("nvim-tree.actions.moves.item").fn { where = "prev", what = "diag" })
|
||||||
Api.node.navigate.opened.next = wrap_node(require("nvim-tree.actions.moves.item").fn { where = "next", what = "opened" })
|
Api.node.navigate.opened.next = wrap_node(require("nvim-tree.actions.moves.item").fn { where = "next", what = "opened" })
|
||||||
|
|||||||
@@ -1,18 +1,44 @@
|
|||||||
local utils = require "nvim-tree.utils"
|
local utils = require "nvim-tree.utils"
|
||||||
local view = require "nvim-tree.view"
|
local view = require "nvim-tree.view"
|
||||||
local core = require "nvim-tree.core"
|
|
||||||
local log = require "nvim-tree.log"
|
local log = require "nvim-tree.log"
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
local severity_levels = {
|
---TODO add "$VIMRUNTIME" to "workspace.library" and use the @enum instead of this integer
|
||||||
|
---@alias lsp.DiagnosticSeverity integer
|
||||||
|
|
||||||
|
---COC severity level strings to LSP severity levels
|
||||||
|
---@enum COC_SEVERITY_LEVELS
|
||||||
|
local COC_SEVERITY_LEVELS = {
|
||||||
Error = 1,
|
Error = 1,
|
||||||
Warning = 2,
|
Warning = 2,
|
||||||
Information = 3,
|
Information = 3,
|
||||||
Hint = 4,
|
Hint = 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
---@return table
|
---Absolute Node path to LSP severity level
|
||||||
|
---@alias NodeSeverities table<string, lsp.DiagnosticSeverity>
|
||||||
|
|
||||||
|
---@class DiagStatus
|
||||||
|
---@field value lsp.DiagnosticSeverity|nil
|
||||||
|
---@field cache_version integer
|
||||||
|
|
||||||
|
--- The buffer-severity mappings derived during the last diagnostic list update.
|
||||||
|
---@type NodeSeverities
|
||||||
|
local NODE_SEVERITIES = {}
|
||||||
|
|
||||||
|
---The cache version number of the buffer-severity mappings.
|
||||||
|
---@type integer
|
||||||
|
local NODE_SEVERITIES_VERSION = 0
|
||||||
|
|
||||||
|
---@param path string
|
||||||
|
---@return string
|
||||||
|
local function uniformize_path(path)
|
||||||
|
return utils.canonical_path(path:gsub("\\", "/"))
|
||||||
|
end
|
||||||
|
|
||||||
|
---Marshal severities from LSP. Does nothing when LSP disabled.
|
||||||
|
---@return NodeSeverities
|
||||||
local function from_nvim_lsp()
|
local function from_nvim_lsp()
|
||||||
local buffer_severity = {}
|
local buffer_severity = {}
|
||||||
|
|
||||||
@@ -25,11 +51,10 @@ local function from_nvim_lsp()
|
|||||||
for _, diagnostic in ipairs(vim.diagnostic.get(nil, { severity = M.severity })) do
|
for _, diagnostic in ipairs(vim.diagnostic.get(nil, { severity = M.severity })) do
|
||||||
local buf = diagnostic.bufnr
|
local buf = diagnostic.bufnr
|
||||||
if vim.api.nvim_buf_is_valid(buf) then
|
if vim.api.nvim_buf_is_valid(buf) then
|
||||||
local bufname = vim.api.nvim_buf_get_name(buf)
|
local bufname = uniformize_path(vim.api.nvim_buf_get_name(buf))
|
||||||
local lowest_severity = buffer_severity[bufname]
|
local severity = diagnostic.severity
|
||||||
if not lowest_severity or diagnostic.severity < lowest_severity then
|
local highest_severity = buffer_severity[bufname] or severity
|
||||||
buffer_severity[bufname] = diagnostic.severity
|
buffer_severity[bufname] = math.min(highest_severity, severity)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -37,91 +62,148 @@ local function from_nvim_lsp()
|
|||||||
return buffer_severity
|
return buffer_severity
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param severity integer
|
---Severity is within diagnostics.severity.min, diagnostics.severity.max
|
||||||
|
---@param severity lsp.DiagnosticSeverity
|
||||||
---@param config table
|
---@param config table
|
||||||
---@return boolean
|
---@return boolean
|
||||||
local function is_severity_in_range(severity, config)
|
local function is_severity_in_range(severity, config)
|
||||||
return config.max <= severity and severity <= config.min
|
return config.max <= severity and severity <= config.min
|
||||||
end
|
end
|
||||||
|
|
||||||
---@return table
|
---Handle any COC exceptions, preventing any propagation
|
||||||
|
---@param err string
|
||||||
|
local function handle_coc_exception(err)
|
||||||
|
log.line("diagnostics", "handle_coc_exception: %s", vim.inspect(err))
|
||||||
|
local notify = true
|
||||||
|
|
||||||
|
-- avoid distractions on interrupts (CTRL-C)
|
||||||
|
if err:find "Vim:Interrupt" or err:find "Keyboard interrupt" then
|
||||||
|
notify = false
|
||||||
|
end
|
||||||
|
|
||||||
|
if notify then
|
||||||
|
require("nvim-tree.notify").error("Diagnostics update from coc.nvim failed. " .. vim.inspect(err))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---COC service initialized
|
||||||
|
---@return boolean
|
||||||
|
local function is_using_coc()
|
||||||
|
return vim.g.coc_service_initialized == 1
|
||||||
|
end
|
||||||
|
|
||||||
|
---Marshal severities from COC. Does nothing when COC service not started.
|
||||||
|
---@return NodeSeverities
|
||||||
local function from_coc()
|
local function from_coc()
|
||||||
if vim.g.coc_service_initialized ~= 1 then
|
if not is_using_coc() then
|
||||||
return {}
|
return {}
|
||||||
end
|
end
|
||||||
|
|
||||||
local diagnostic_list = vim.fn.CocAction "diagnosticList"
|
local ok, diagnostic_list = xpcall(function()
|
||||||
if type(diagnostic_list) ~= "table" or vim.tbl_isempty(diagnostic_list) then
|
return vim.fn.CocAction "diagnosticList"
|
||||||
|
end, handle_coc_exception)
|
||||||
|
if not ok or type(diagnostic_list) ~= "table" or vim.tbl_isempty(diagnostic_list) then
|
||||||
return {}
|
return {}
|
||||||
end
|
end
|
||||||
|
|
||||||
local diagnostics = {}
|
|
||||||
for _, diagnostic in ipairs(diagnostic_list) do
|
|
||||||
local bufname = diagnostic.file
|
|
||||||
local coc_severity = severity_levels[diagnostic.severity]
|
|
||||||
|
|
||||||
local serverity = diagnostics[bufname] or vim.diagnostic.severity.HINT
|
|
||||||
diagnostics[bufname] = math.min(coc_severity, serverity)
|
|
||||||
end
|
|
||||||
|
|
||||||
local buffer_severity = {}
|
local buffer_severity = {}
|
||||||
for bufname, severity in pairs(diagnostics) do
|
for _, diagnostic in ipairs(diagnostic_list) do
|
||||||
if is_severity_in_range(severity, M.severity) then
|
local bufname = uniformize_path(diagnostic.file)
|
||||||
buffer_severity[bufname] = severity
|
local coc_severity = COC_SEVERITY_LEVELS[diagnostic.severity]
|
||||||
|
local highest_severity = buffer_severity[bufname] or coc_severity
|
||||||
|
if is_severity_in_range(highest_severity, M.severity) then
|
||||||
|
buffer_severity[bufname] = math.min(highest_severity, coc_severity)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return buffer_severity
|
return buffer_severity
|
||||||
end
|
end
|
||||||
|
|
||||||
local function is_using_coc()
|
---Maybe retrieve severity level from the cache
|
||||||
return vim.g.coc_service_initialized == 1
|
---@param node Node
|
||||||
|
---@return DiagStatus
|
||||||
|
local function from_cache(node)
|
||||||
|
local nodepath = uniformize_path(node.absolute_path)
|
||||||
|
local max_severity = nil
|
||||||
|
if not node.nodes then
|
||||||
|
-- direct cache hit for files
|
||||||
|
max_severity = NODE_SEVERITIES[nodepath]
|
||||||
|
else
|
||||||
|
-- dirs should be searched in the list of cached buffer names by prefix
|
||||||
|
for bufname, severity in pairs(NODE_SEVERITIES) do
|
||||||
|
local node_contains_buf = vim.startswith(bufname, nodepath .. "/")
|
||||||
|
if node_contains_buf then
|
||||||
|
if severity == M.severity.max then
|
||||||
|
max_severity = severity
|
||||||
|
break
|
||||||
|
else
|
||||||
|
max_severity = math.min(max_severity or severity, severity)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return { value = max_severity, cache_version = NODE_SEVERITIES_VERSION }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---Fired on DiagnosticChanged and CocDiagnosticChanged events:
|
||||||
|
---debounced retrieval, cache update, version increment and draw
|
||||||
function M.update()
|
function M.update()
|
||||||
if not M.enable or not core.get_explorer() or not view.is_buf_valid(view.get_bufnr()) then
|
if not M.enable then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
utils.debounce("diagnostics", M.debounce_delay, function()
|
utils.debounce("diagnostics", M.debounce_delay, function()
|
||||||
local profile = log.profile_start "diagnostics update"
|
local profile = log.profile_start "diagnostics update"
|
||||||
log.line("diagnostics", "update")
|
|
||||||
|
|
||||||
local buffer_severity
|
|
||||||
if is_using_coc() then
|
if is_using_coc() then
|
||||||
buffer_severity = from_coc()
|
NODE_SEVERITIES = from_coc()
|
||||||
else
|
else
|
||||||
buffer_severity = from_nvim_lsp()
|
NODE_SEVERITIES = from_nvim_lsp()
|
||||||
end
|
|
||||||
|
|
||||||
local nodes_by_line = utils.get_nodes_by_line(core.get_explorer().nodes, core.get_nodes_starting_line())
|
|
||||||
for _, node in pairs(nodes_by_line) do
|
|
||||||
node.diag_status = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
for bufname, severity in pairs(buffer_severity) do
|
|
||||||
local bufpath = utils.canonical_path(bufname)
|
|
||||||
log.line("diagnostics", " bufpath '%s' severity %d", bufpath, severity)
|
|
||||||
if 0 < severity and severity < 5 then
|
|
||||||
for line, node in pairs(nodes_by_line) do
|
|
||||||
local nodepath = utils.canonical_path(node.absolute_path)
|
|
||||||
log.line("diagnostics", " %d checking nodepath '%s'", line, nodepath)
|
|
||||||
|
|
||||||
local node_contains_buf = vim.startswith(bufpath:gsub("\\", "/"), nodepath:gsub("\\", "/") .. "/")
|
|
||||||
if M.show_on_dirs and node_contains_buf and (not node.open or M.show_on_open_dirs) then
|
|
||||||
log.line("diagnostics", " matched fold node '%s'", node.absolute_path)
|
|
||||||
node.diag_status = severity
|
|
||||||
elseif nodepath == bufpath then
|
|
||||||
log.line("diagnostics", " matched file node '%s'", node.absolute_path)
|
|
||||||
node.diag_status = severity
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
NODE_SEVERITIES_VERSION = NODE_SEVERITIES_VERSION + 1
|
||||||
|
if log.enabled "diagnostics" then
|
||||||
|
for bufname, severity in pairs(NODE_SEVERITIES) do
|
||||||
|
log.line("diagnostics", "Indexing bufname '%s' with severity %d", bufname, severity)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
log.profile_end(profile)
|
log.profile_end(profile)
|
||||||
|
if view.is_buf_valid(view.get_bufnr()) then
|
||||||
require("nvim-tree.renderer").draw()
|
require("nvim-tree.renderer").draw()
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---Maybe retrieve diagnostic status for a node.
|
||||||
|
---Returns cached value when node's version matches.
|
||||||
|
---@param node Node
|
||||||
|
---@return DiagStatus|nil
|
||||||
|
function M.get_diag_status(node)
|
||||||
|
if not M.enable then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- dir but we shouldn't show on dirs at all
|
||||||
|
if node.nodes ~= nil and not M.show_on_dirs then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- here, we do a lazy update of the diagnostic status carried by the node.
|
||||||
|
-- This is by design, as diagnostics and nodes live in completely separate
|
||||||
|
-- worlds, and this module is the link between the two
|
||||||
|
if not node.diag_status or node.diag_status.cache_version < NODE_SEVERITIES_VERSION then
|
||||||
|
node.diag_status = from_cache(node)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- file
|
||||||
|
if not node.nodes then
|
||||||
|
return node.diag_status
|
||||||
|
end
|
||||||
|
|
||||||
|
-- dir is closed or we should show on open_dirs
|
||||||
|
if not node.open or M.show_on_open_dirs then
|
||||||
|
return node.diag_status
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
function M.setup(opts)
|
function M.setup(opts)
|
||||||
M.enable = opts.diagnostics.enable
|
M.enable = opts.diagnostics.enable
|
||||||
M.debounce_delay = opts.diagnostics.debounce_delay
|
M.debounce_delay = opts.diagnostics.debounce_delay
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
local utils = require "nvim-tree.utils"
|
local utils = require "nvim-tree.utils"
|
||||||
|
local marks = require "nvim-tree.marks"
|
||||||
|
|
||||||
local M = {
|
local M = {
|
||||||
ignore_list = {},
|
ignore_list = {},
|
||||||
@@ -69,6 +70,12 @@ local function dotfile(path)
|
|||||||
return M.config.filter_dotfiles and utils.path_basename(path):sub(1, 1) == "."
|
return M.config.filter_dotfiles and utils.path_basename(path):sub(1, 1) == "."
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param path string
|
||||||
|
---@param bookmarks table<string, boolean> absolute paths bookmarked
|
||||||
|
local function bookmark(path, bookmarks)
|
||||||
|
return M.config.filter_no_bookmark and not bookmarks[path]
|
||||||
|
end
|
||||||
|
|
||||||
---@param path string
|
---@param path string
|
||||||
---@return boolean
|
---@return boolean
|
||||||
local function custom(path)
|
local function custom(path)
|
||||||
@@ -103,17 +110,23 @@ end
|
|||||||
--- git_status: reference
|
--- git_status: reference
|
||||||
--- unloaded_bufnr: copy
|
--- unloaded_bufnr: copy
|
||||||
--- bufinfo: empty unless no_buffer set: vim.fn.getbufinfo { buflisted = 1 }
|
--- 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, unloaded_bufnr)
|
||||||
local status = {
|
local status = {
|
||||||
git_status = git_status or {},
|
git_status = git_status or {},
|
||||||
unloaded_bufnr = unloaded_bufnr,
|
unloaded_bufnr = unloaded_bufnr,
|
||||||
bufinfo = {},
|
bufinfo = {},
|
||||||
|
bookmarks = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
if M.config.filter_no_buffer then
|
if M.config.filter_no_buffer then
|
||||||
status.bufinfo = vim.fn.getbufinfo { buflisted = 1 }
|
status.bufinfo = vim.fn.getbufinfo { buflisted = 1 }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
for _, node in pairs(marks.get_marks()) do
|
||||||
|
status.bookmarks[node.absolute_path] = true
|
||||||
|
end
|
||||||
|
|
||||||
return status
|
return status
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -127,7 +140,11 @@ function M.should_filter(path, status)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
return git(path, status.git_status) or buf(path, status.bufinfo, status.unloaded_bufnr) or dotfile(path) or custom(path)
|
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)
|
||||||
end
|
end
|
||||||
|
|
||||||
function M.setup(opts)
|
function M.setup(opts)
|
||||||
@@ -137,6 +154,7 @@ function M.setup(opts)
|
|||||||
filter_git_ignored = opts.filters.git_ignored,
|
filter_git_ignored = opts.filters.git_ignored,
|
||||||
filter_git_clean = opts.filters.git_clean,
|
filter_git_clean = opts.filters.git_clean,
|
||||||
filter_no_buffer = opts.filters.no_buffer,
|
filter_no_buffer = opts.filters.no_buffer,
|
||||||
|
filter_no_bookmark = opts.filters.no_bookmark,
|
||||||
}
|
}
|
||||||
|
|
||||||
M.ignore_list = {}
|
M.ignore_list = {}
|
||||||
|
|||||||
@@ -64,14 +64,15 @@ function M.default_on_attach(bufnr)
|
|||||||
vim.keymap.set('n', 'e', api.fs.rename_basename, opts('Rename: Basename'))
|
vim.keymap.set('n', 'e', api.fs.rename_basename, opts('Rename: Basename'))
|
||||||
vim.keymap.set('n', ']e', api.node.navigate.diagnostics.next, opts('Next Diagnostic'))
|
vim.keymap.set('n', ']e', api.node.navigate.diagnostics.next, opts('Next Diagnostic'))
|
||||||
vim.keymap.set('n', '[e', api.node.navigate.diagnostics.prev, opts('Prev Diagnostic'))
|
vim.keymap.set('n', '[e', api.node.navigate.diagnostics.prev, opts('Prev Diagnostic'))
|
||||||
vim.keymap.set('n', 'F', api.live_filter.clear, opts('Clean Filter'))
|
vim.keymap.set('n', 'F', api.live_filter.clear, opts('Live Filter: Clear'))
|
||||||
vim.keymap.set('n', 'f', api.live_filter.start, opts('Filter'))
|
vim.keymap.set('n', 'f', api.live_filter.start, opts('Live Filter: Start'))
|
||||||
vim.keymap.set('n', 'g?', api.tree.toggle_help, opts('Help'))
|
vim.keymap.set('n', 'g?', api.tree.toggle_help, opts('Help'))
|
||||||
vim.keymap.set('n', 'gy', api.fs.copy.absolute_path, opts('Copy Absolute Path'))
|
vim.keymap.set('n', 'gy', api.fs.copy.absolute_path, opts('Copy Absolute Path'))
|
||||||
vim.keymap.set('n', 'H', api.tree.toggle_hidden_filter, opts('Toggle Filter: Dotfiles'))
|
vim.keymap.set('n', 'H', api.tree.toggle_hidden_filter, opts('Toggle Filter: Dotfiles'))
|
||||||
vim.keymap.set('n', 'I', api.tree.toggle_gitignore_filter, opts('Toggle Filter: Git Ignore'))
|
vim.keymap.set('n', 'I', api.tree.toggle_gitignore_filter, opts('Toggle Filter: Git Ignore'))
|
||||||
vim.keymap.set('n', 'J', api.node.navigate.sibling.last, opts('Last Sibling'))
|
vim.keymap.set('n', 'J', api.node.navigate.sibling.last, opts('Last Sibling'))
|
||||||
vim.keymap.set('n', 'K', api.node.navigate.sibling.first, opts('First Sibling'))
|
vim.keymap.set('n', 'K', api.node.navigate.sibling.first, opts('First Sibling'))
|
||||||
|
vim.keymap.set('n', 'M', api.tree.toggle_no_bookmark_filter, opts('Toggle Filter: No Bookmark'))
|
||||||
vim.keymap.set('n', 'm', api.marks.toggle, opts('Toggle Bookmark'))
|
vim.keymap.set('n', 'm', api.marks.toggle, opts('Toggle Bookmark'))
|
||||||
vim.keymap.set('n', 'o', api.node.open.edit, opts('Open'))
|
vim.keymap.set('n', 'o', api.node.open.edit, opts('Open'))
|
||||||
vim.keymap.set('n', 'O', api.node.open.no_window_picker, opts('Open: No Window Picker'))
|
vim.keymap.set('n', 'O', api.node.open.no_window_picker, opts('Open: No Window Picker'))
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
---@field parent DirNode
|
---@field parent DirNode
|
||||||
---@field type string
|
---@field type string
|
||||||
---@field watcher function|nil
|
---@field watcher function|nil
|
||||||
|
---@field diag_status DiagStatus|nil
|
||||||
|
|
||||||
---@class DirNode: BaseNode
|
---@class DirNode: BaseNode
|
||||||
---@field has_children boolean
|
---@field has_children boolean
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
local HL_POSITION = require("nvim-tree.enum").HL_POSITION
|
local HL_POSITION = require("nvim-tree.enum").HL_POSITION
|
||||||
|
local diagnostics = require "nvim-tree.diagnostics"
|
||||||
|
|
||||||
local M = {
|
local M = {
|
||||||
HS_FILE = {},
|
HS_FILE = {},
|
||||||
@@ -17,10 +18,11 @@ function M.get_highlight(node)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local group
|
local group
|
||||||
|
local diag_status = diagnostics.get_diag_status(node)
|
||||||
if node.nodes then
|
if node.nodes then
|
||||||
group = M.HS_FOLDER[node.diag_status]
|
group = M.HS_FOLDER[diag_status and diag_status.value]
|
||||||
else
|
else
|
||||||
group = M.HS_FILE[node.diag_status]
|
group = M.HS_FILE[diag_status and diag_status.value]
|
||||||
end
|
end
|
||||||
|
|
||||||
if group then
|
if group then
|
||||||
@@ -35,7 +37,8 @@ end
|
|||||||
---@return HighlightedString|nil modified icon
|
---@return HighlightedString|nil modified icon
|
||||||
function M.get_icon(node)
|
function M.get_icon(node)
|
||||||
if node and M.config.diagnostics.enable and M.config.renderer.icons.show.diagnostics then
|
if node and M.config.diagnostics.enable and M.config.renderer.icons.show.diagnostics then
|
||||||
return M.ICON[node.diag_status]
|
local diag_status = diagnostics.get_diag_status(node)
|
||||||
|
return M.ICON[diag_status and diag_status.value]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
|
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
|
||||||
"include-v-in-tag": true,
|
"include-v-in-tag": true,
|
||||||
|
"bootstrap-sha": "34780aca5bac0a58c163ea30719a276fead1bd95",
|
||||||
"packages": {
|
"packages": {
|
||||||
".": {
|
".": {
|
||||||
"package-name": "nvim-tree",
|
"package-name": "nvim-tree",
|
||||||
|
|||||||
Reference in New Issue
Block a user