diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index fcf0ef1bf3e..5e327ae72cf 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -487,7 +487,7 @@ for files and and directories. Highlighting is additive, with higher precedence overriding lower. |nvim_tree.config.renderer| {decorators} controls which highlighting is -applied and its precedence. See |nvim-tree-decorators| for information on +applied and its precedence. See |nvim-tree-api-decorator| for information on creating custom decorators. < `ICON` @@ -890,34 +890,34 @@ Require and register it during |nvim-tree-setup|: < Contents of `my-decorator.lua`: >lua - ---@class (exact) MyDecorator: nvim_tree.api.decorator.UserDecorator - ---@field private my_icon1 nvim_tree.api.HighlightedString - ---@field private my_icon2 nvim_tree.api.HighlightedString - ---@field private my_icon_node nvim_tree.api.HighlightedString + ---@class (exact) MyDecorator: nvim_tree.api.Decorator + ---@field private my_icon1 nvim_tree.api.decorator.highlighted_string + ---@field private my_icon2 nvim_tree.api.decorator.highlighted_string + ---@field private my_icon_node nvim_tree.api.decorator.highlighted_string ---@field private my_highlight_group string - local MyDecorator = require("nvim-tree.api").decorator.UserDecorator:extend() - + local MyDecorator = require("nvim-tree.api").Decorator:extend() + ---Mandatory constructor :new() will be called once per tree render, with no arguments. function MyDecorator:new() self.enabled = true self.highlight_range = "name" self.icon_placement = "after" - + -- create your icons and highlights once, applied to every node self.my_icon1 = { str = "1", hl = { "DiffAdd" } } self.my_icon2 = { str = "2", hl = { "DiffText" } } self.my_icon_node = { str = "N", hl = { "Error" } } self.my_highlight_group = "IncSearch" - + -- Define the icon signs only once -- Only needed if you are using icon_placement = "signcolumn" -- self:define_sign(self.my_icon1) -- self:define_sign(self.my_icon2) end - + ---Override node icon ---@param node nvim_tree.api.Node - ---@return nvim_tree.api.HighlightedString? icon_node + ---@return nvim_tree.api.decorator.highlighted_string? icon_node function MyDecorator:icon_node(node) if node.name == "example" then return self.my_icon_node @@ -925,10 +925,10 @@ Contents of `my-decorator.lua`: return nil end end - + ---Return two icons for DecoratorIconPlacement "after" ---@param node nvim_tree.api.Node - ---@return nvim_tree.api.HighlightedString[]? icons + ---@return nvim_tree.api.decorator.highlighted_string[]? icons function MyDecorator:icons(node) if node.name == "example" then return { self.my_icon1, self.my_icon2, } @@ -936,7 +936,7 @@ Contents of `my-decorator.lua`: return nil end end - + ---Exactly one highlight group for DecoratorHighlightRange "name" ---@param node nvim_tree.api.Node ---@return string? highlight_group @@ -947,7 +947,7 @@ Contents of `my-decorator.lua`: return nil end end - + return MyDecorator < ============================================================================== @@ -1366,9 +1366,10 @@ Config: renderer *nvim-tree-config-renderer* • {symlink_destination}? (`boolean`, default: `true`) Appends an arrow followed by the target of the symlink. - • {decorators}? (`(string|nvim_tree.api.decorator.UserDecorator)[]`) - (default: - `{ "Git", "Open", "Hidden", "Modified", "Bookmark", "Diagnostics", "Copied", "Cut", }`) + • {decorators}? (`(string|nvim_tree.api.Decorator)[]`, default: `{ "Git", "Open", "Hidden", "Modified", "Bookmark", "Diagnostics", "Copied", "Cut", }`) + Ordered list of builtin and user decorators + to enable, see |nvim-tree-api-decorator| + and |nvim-tree-icons-highlighting| • {highlight_git}? (`nvim_tree.config.renderer.highlight`) (default: `"none"`) • {highlight_opened_files}? (`nvim_tree.config.renderer.highlight`) @@ -3200,4 +3201,152 @@ winid({opts}) *nvim_tree.api.tree.winid()* (`integer?`) |window-ID|, nil if tree is not visible. +============================================================================== +API: Decorator *nvim-tree-api-decorator* + +Highlighting and icons for nodes are provided by Decorators, see +|nvim-tree-icons-highlighting|. You may provide your own in addition to the +builtin decorators. + +Decorators may: +• Add icons +• Set highlight group for the name or icons +• Override node icon + +To register your decorator: +• Create a class that extends |nvim_tree.api.Decorator| +• Register it by adding the class to |nvim_tree.config.renderer| {decorators} + +Your class must: +• |nvim_tree.Class:extend()| the interface |nvim_tree.api.Decorator| +• Provide a no-arguments constructor |nvim_tree.Class:new()| that sets the + mandatory fields: + • {enabled} + • {highlight_range} + • {icon_placement} + +Your class may: +• Implement methods to provide decorations: + • |nvim_tree.api.Decorator:highlight_group()| + • |nvim_tree.api.Decorator:icon_node()| + • |nvim_tree.api.Decorator:icons()| + +Your class must: +• Call |nvim_tree.api.Decorator:define_sign()| in your constructor if using + `"signcolumn"` {icon_placement} + + +*nvim_tree.api.Decorator* + Extends: |nvim_tree.Class| + + Abstract Decorator interface + + Fields: ~ + • {enabled} (`boolean`) + • {highlight_range} (`nvim_tree.api.decorator.highlight_range`) + • {icon_placement} (`nvim_tree.api.decorator.icon_placement`) + • {icon_node} (`fun(self: nvim_tree.api.Decorator, node: nvim_tree.api.Node): nvim_tree.api.decorator.highlighted_string?`) + See |nvim_tree.api.Decorator:icon_node()|. + • {icons} (`fun(self: nvim_tree.api.Decorator, node: nvim_tree.api.Node): nvim_tree.api.decorator.highlighted_string[]?`) + See |nvim_tree.api.Decorator:icons()|. + • {highlight_group} (`fun(self: nvim_tree.api.Decorator, node: nvim_tree.api.Node): string?`) + See |nvim_tree.api.Decorator:highlight_group()|. + • {define_sign} (`fun(self: nvim_tree.api.Decorator, icon: nvim_tree.api.decorator.highlighted_string?)`) + See |nvim_tree.api.Decorator:define_sign()|. + + +Decorator:define_sign({icon}) *nvim_tree.api.Decorator:define_sign()* + Defines a sign. This should be called in the constructor. + + Parameters: ~ + • {icon} (`nvim_tree.api.decorator.highlighted_string?`) + + *nvim_tree.api.Decorator:highlight_group()* +Decorator:highlight_group({node}) + Abstract: optionally implement to provide one highlight group to apply to + your highlight_range. + + Parameters: ~ + • {node} (`nvim_tree.api.Node`) + + Return: ~ + (`string?`) highlight_group + +Decorator:icon_node({node}) *nvim_tree.api.Decorator:icon_node()* + Abstract: optionally implement to set the node's icon + + Parameters: ~ + • {node} (`nvim_tree.api.Node`) + + Return: ~ + (`nvim_tree.api.decorator.highlighted_string?`) icon_node + +Decorator:icons({node}) *nvim_tree.api.Decorator:icons()* + Abstract: optionally implement to provide icons and the highlight groups + for your icon_placement. + + Parameters: ~ + • {node} (`nvim_tree.api.Node`) + + Return: ~ + (`nvim_tree.api.decorator.highlighted_string[]?`) icons + + +============================================================================== +API: Class *nvim-tree-api-class* + +*nvim_tree.Class* + + Fields: ~ + • {super} (`Class`) + • {new} (`fun(self: nvim_tree.Class)`) See + |nvim_tree.Class:new()|. + • {extend} (`fun(self: nvim_tree.Class)`) See + |nvim_tree.Class:extend()|. + • {implement} (`fun(self: nvim_tree.Class, mixin: Class)`) See + |nvim_tree.Class:implement()|. + • {is} (`fun(self: nvim_tree.Class, class: T): boolean`) See + |nvim_tree.Class:is()|. + • {as} (`fun(self: nvim_tree.Class, class: T): T?`) See + |nvim_tree.Class:as()|. + • {nop} (`fun(self: nvim_tree.Class, ...: any)`) See + |nvim_tree.Class:nop()|. + + +Class:as({class}) *nvim_tree.Class:as()* + Return object if |nvim_tree.Class:is()| otherwise nil + + Parameters: ~ + • {class} (`any`) + + Return: ~ + (`T?`) + +Class:extend() *nvim_tree.Class:extend()* + Extend a class, setting .super + +Class:implement({mixin}) *nvim_tree.Class:implement()* + Implement the functions of a mixin Add the mixin to .implements + + Parameters: ~ + • {mixin} (`Class`) + +Class:is({class}) *nvim_tree.Class:is()* + Object is an instance of class or implements a mixin + + Parameters: ~ + • {class} (`any`) + + Return: ~ + (`boolean`) + +Class:new() *nvim_tree.Class:new()* + Default constructor + +Class:nop({...}) *nvim_tree.Class:nop()* + + Parameters: ~ + • {...} (`any`) + + vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl: diff --git a/lua/nvim-tree.lua b/lua/nvim-tree.lua index 4d4dad7b1f3..7d3a79b46de 100644 --- a/lua/nvim-tree.lua +++ b/lua/nvim-tree.lua @@ -813,7 +813,7 @@ function M.setup(conf) vim.g.NvimTreeSetup = 1 vim.api.nvim_exec_autocmds("User", { pattern = "NvimTreeSetup" }) - require("nvim-tree.api.impl.post")(api) + require("nvim-tree.api.impl.post").hydrate(api) end vim.g.NvimTreeRequired = 1 diff --git a/lua/nvim-tree/_meta/api/decorator.lua b/lua/nvim-tree/_meta/api/decorator.lua new file mode 100644 index 00000000000..c4643325572 --- /dev/null +++ b/lua/nvim-tree/_meta/api/decorator.lua @@ -0,0 +1,93 @@ +---@meta + +---@brief +---Highlighting and icons for nodes are provided by Decorators, see [nvim-tree-icons-highlighting]. You may provide your own in addition to the builtin decorators. +--- +---Decorators may: +---- Add icons +---- Set highlight group for the name or icons +---- Override node icon +--- +---To register your decorator: +---- Create a class that extends [nvim_tree.api.Decorator] +---- Register it by adding the class to [nvim_tree.config.renderer] {decorators} +--- +---Your class must: +---- [nvim_tree.Class:extend()] the interface [nvim_tree.api.Decorator] +---- Provide a no-arguments constructor [nvim_tree.Class:new()] that sets the mandatory fields: +--- - {enabled} +--- - {highlight_range} +--- - {icon_placement} +--- +---Your class may: +---- Implement methods to provide decorations: +--- - [nvim_tree.api.Decorator:highlight_group()] +--- - [nvim_tree.api.Decorator:icon_node()] +--- - [nvim_tree.api.Decorator:icons()] +--- +---Your class must: +---- Call [nvim_tree.api.Decorator:define_sign()] in your constructor if using `"signcolumn"` {icon_placement} + +local nvim_tree = { api = {} } + +local Class = require("nvim-tree.classic") + +--- +---Highlight group range as per nvim-tree.renderer.highlight_* +--- +---@alias nvim_tree.api.decorator.highlight_range nvim_tree.config.renderer.highlight + +---Icon position as per renderer.icons.*_placement +--- +---@alias nvim_tree.api.decorator.icon_placement "none"|nvim_tree.config.renderer.icons.placement + +--- +---Names of builtin decorators or your decorator classes. Builtins are ordered lowest to highest priority. +--- +---@alias nvim_tree.api.decorator.types nvim_tree.api.Decorator|"Git"|"Opened"|"Hidden"|"Modified"|"Bookmarks"|"Diagnostics"|"Copied"|"Cut" + +--- +---A string for rendering, with optional highlight groups to apply to it +--- +---@class (exact) nvim_tree.api.decorator.highlighted_string +---@field str string +---@field hl string[] + +--- +---Abstract Decorator interface +--- +---@class nvim_tree.api.Decorator: nvim_tree.Class +---@field enabled boolean +---@field highlight_range nvim_tree.api.decorator.highlight_range +---@field icon_placement nvim_tree.api.decorator.icon_placement +local Decorator = Class:extend() +nvim_tree.api.Decorator = Decorator + +--- +---Abstract: optionally implement to set the node's icon +--- +---@param node nvim_tree.api.Node +---@return nvim_tree.api.decorator.highlighted_string? icon_node +function Decorator:icon_node(node) end + +--- +---Abstract: optionally implement to provide icons and the highlight groups for your icon_placement. +--- +---@param node nvim_tree.api.Node +---@return nvim_tree.api.decorator.highlighted_string[]? icons +function Decorator:icons(node) end + +--- +---Abstract: optionally implement to provide one highlight group to apply to your highlight_range. +--- +---@param node nvim_tree.api.Node +---@return string? highlight_group +function Decorator:highlight_group(node) end + +--- +---Defines a sign. This should be called in the constructor. +--- +---@param icon nvim_tree.api.decorator.highlighted_string? +function Decorator:define_sign(icon) end + +return nvim_tree.api.Decorator diff --git a/lua/nvim-tree/_meta/api/deprecated.lua b/lua/nvim-tree/_meta/api/deprecated.lua index fdd4b88e85a..f9f37852225 100644 --- a/lua/nvim-tree/_meta/api/deprecated.lua +++ b/lua/nvim-tree/_meta/api/deprecated.lua @@ -30,4 +30,10 @@ nvim_tree.api.diagnostics = {} ---@deprecated use `nvim_tree.api.health.hi_test()` function nvim_tree.api.diagnostics.hi_test() end +nvim_tree.api.decorator = {} + +---@class nvim_tree.api.decorator.UserDecorator: nvim_tree.api.Decorator +---@deprecated use `nvim_tree.api.Decorator` +nvim_tree.api.decorator.UserDecorator = nvim_tree.api.Decorator + return nvim_tree.api diff --git a/lua/nvim-tree/_meta/api_decorator.lua b/lua/nvim-tree/_meta/api_decorator.lua deleted file mode 100644 index 4acca3a9acf..00000000000 --- a/lua/nvim-tree/_meta/api_decorator.lua +++ /dev/null @@ -1,59 +0,0 @@ ----@meta -error("Cannot require a meta file") - -local nvim_tree = { api = { decorator = {} } } - ----Highlight group range as per nvim-tree.renderer.highlight_* ----@alias nvim_tree.api.decorator.HighlightRange "none" | "icon" | "name" | "all" - ----Icon position as per renderer.icons.*_placement ----@alias nvim_tree.api.decorator.IconPlacement "none" | "before" | "after" | "signcolumn" | "right_align" - ----Names of builtin decorators or your decorator classes. Builtins are ordered lowest to highest priority. ----@alias nvim_tree.api.decorator.Name "Git" | "Opened" | "Hidden" | "Modified" | "Bookmarks" | "Diagnostics" | "Copied" | "Cut" | nvim_tree.api.decorator.UserDecorator - ----A string for rendering, with optional highlight groups to apply to it ----@class (exact) nvim_tree.api.HighlightedString ----@field str string ----@field hl string[] - ----Custom decorator, see :help nvim-tree-decorators ---- ----@class (exact) nvim_tree.api.decorator.UserDecorator ----@field protected enabled boolean ----@field protected highlight_range nvim_tree.api.decorator.HighlightRange ----@field protected icon_placement nvim_tree.api.decorator.IconPlacement -nvim_tree.api.decorator.UserDecorator = {} - ----Create your decorator class ---- -function nvim_tree.api.decorator.UserDecorator:extend() end - ----Abstract: no-args constructor must be implemented and will be called once per tree render. ----Must set all fields. ---- -function nvim_tree.api.decorator.UserDecorator:new() end - ----Abstract: optionally implement to set the node's icon ---- ----@param node nvim_tree.api.Node ----@return nvim_tree.api.HighlightedString? icon_node -function nvim_tree.api.decorator.UserDecorator:icon_node(node) end - ----Abstract: optionally implement to provide icons and the highlight groups for your icon_placement. ---- ----@param node nvim_tree.api.Node ----@return nvim_tree.api.HighlightedString[]? icons -function nvim_tree.api.decorator.UserDecorator:icons(node) end - ----Abstract: optionally implement to provide one highlight group to apply to your highlight_range. ---- ----@param node nvim_tree.api.Node ----@return string? highlight_group -function nvim_tree.api.decorator.UserDecorator:highlight_group(node) end - ----Define a sign. This should be called in the constructor. ---- ----@protected ----@param icon nvim_tree.api.HighlightedString? -function nvim_tree.api.decorator.UserDecorator:define_sign(icon) end diff --git a/lua/nvim-tree/_meta/config/default.lua b/lua/nvim-tree/_meta/config/default.lua index 1f1252f7483..6566a1ed4ab 100644 --- a/lua/nvim-tree/_meta/config/default.lua +++ b/lua/nvim-tree/_meta/config/default.lua @@ -8,4 +8,3 @@ ---default-config-injection-placeholder ---} ---``` ---- diff --git a/lua/nvim-tree/_meta/config/renderer.lua b/lua/nvim-tree/_meta/config/renderer.lua index e1ba26cbb91..b18c0b0d319 100644 --- a/lua/nvim-tree/_meta/config/renderer.lua +++ b/lua/nvim-tree/_meta/config/renderer.lua @@ -61,8 +61,9 @@ error("Cannot require a meta file") ---(default: `true`) ---@field symlink_destination? boolean --- +---Ordered list of builtin and user decorators to enable, see [nvim-tree-api-decorator] and [nvim-tree-icons-highlighting] ---(default: `{ "Git", "Open", "Hidden", "Modified", "Bookmark", "Diagnostics", "Copied", "Cut", }`) ----@field decorators? (string|nvim_tree.api.decorator.UserDecorator)[] +---@field decorators? (string|nvim_tree.api.Decorator)[] --- ---(default: `"none"`) ---@field highlight_git? nvim_tree.config.renderer.highlight diff --git a/lua/nvim-tree/api.lua b/lua/nvim-tree/api.lua index e88b19d1f0a..81250fe5fca 100644 --- a/lua/nvim-tree/api.lua +++ b/lua/nvim-tree/api.lua @@ -69,12 +69,9 @@ --- --- Load the (empty) meta definitions --- -local deprecated = require("nvim-tree._meta.api.deprecated") - +--- ---nvim-tree Public API +--- ---@class nvim_tree.api ---@nodoc local api = { @@ -89,17 +86,14 @@ local api = { node = require("nvim-tree._meta.api.node"), tree = require("nvim-tree._meta.api.tree"), - config = deprecated.config, ---@deprecated - diagnostics = deprecated.diagnostics, ---@deprecated - live_filter = deprecated.live_filter, ---@deprecated -} - - --- --- Map before-setup implementations, most throw an error notification "nvim-tree setup not called". --- -require("nvim-tree.api.impl.pre")(api) + Decorator = require("nvim-tree._meta.api.decorator"), + config = require("nvim-tree._meta.api.deprecated").config, ---@deprecated + decorator = require("nvim-tree._meta.api.deprecated").decorator, ---@deprecated + diagnostics = require("nvim-tree._meta.api.deprecated").diagnostics, ---@deprecated + live_filter = require("nvim-tree._meta.api.deprecated").live_filter, ---@deprecated +} +require("nvim-tree.api.impl.pre").hydrate(api) return api diff --git a/lua/nvim-tree/api/impl/legacy.lua b/lua/nvim-tree/api/impl/legacy.lua index 51924b4f365..66f817f6669 100644 --- a/lua/nvim-tree/api/impl/legacy.lua +++ b/lua/nvim-tree/api/impl/legacy.lua @@ -1,6 +1,8 @@ +local M = {} + ---Silently create new api entries pointing legacy functions to current ---@param api table not properly typed to prevent LSP from referencing implementations -return function(api) +function M.hydrate(api) api.config = api.config or {} api.config.mappings = api.config.mappings or {} api.config.mappings.get_keymap = api.map.keymap.current @@ -22,4 +24,8 @@ return function(api) api.diagnostics = api.diagnostics or {} api.diagnostics.hi_test = api.health.hi_test + + api.decorator.UserDecorator = api.Decorator end + +return M diff --git a/lua/nvim-tree/api/impl/post.lua b/lua/nvim-tree/api/impl/post.lua index 2aa5a3caec3..181753a34ce 100644 --- a/lua/nvim-tree/api/impl/post.lua +++ b/lua/nvim-tree/api/impl/post.lua @@ -16,6 +16,8 @@ local DirectoryNode = require("nvim-tree.node.directory") local FileLinkNode = require("nvim-tree.node.file-link") local RootNode = require("nvim-tree.node.root") +local M = {} + ---Invoke a method on the singleton explorer. ---Print error when setup not called. ---@param explorer_method string explorer method name @@ -133,9 +135,9 @@ local function open_or_expand_or_dir_up(mode, toggle_group) end end ----Hydrate all implementations barring those that were called during hydrate_pre +---Re-Hydrate api functions and classes post-setup ---@param api table not properly typed to prevent LSP from referencing implementations -local function hydrate_post(api) +function M.hydrate(api) api.tree.open = actions.tree.open.fn api.tree.focus = api.tree.open @@ -252,14 +254,9 @@ local function hydrate_post(api) api.marks.navigate.select = wrap_explorer_member("marks", "navigate_select") api.map.keymap.current = keymap.get_keymap -end ----Re-hydrate api ----@param api table not properly typed to prevent LSP from referencing implementations -return function(api) - -- All concrete implementations - hydrate_post(api) - - -- (Re)hydrate any legacy by mapping to function set above - require("nvim-tree.api.impl.legacy")(api) + -- (Re)hydrate any legacy by mapping to concrete set above + require("nvim-tree.api.impl.legacy").hydrate(api) end + +return M diff --git a/lua/nvim-tree/api/impl/pre.lua b/lua/nvim-tree/api/impl/pre.lua index 7ad25ecb41f..5ce5f67ac05 100644 --- a/lua/nvim-tree/api/impl/pre.lua +++ b/lua/nvim-tree/api/impl/pre.lua @@ -1,6 +1,7 @@ ---Hydrates meta api empty definition functions with a new function: --- - Default: error notification "nvim-tree setup not called". --- - Exceptions: concrete implementation for API that can be called before setup. +--Hydrates meta api empty definitions pre-setup: +-- - Pre-setup functions will be hydrated with their concrete implementation. +-- - Post-setup functions will notify error: "nvim-tree setup not called" +-- - All classes will be hydrated with their implementations. -- --Call it once when api is first required -- @@ -15,65 +16,44 @@ local notify = require("nvim-tree.notify") -- already required by events and local UserDecorator = require("nvim-tree.renderer.decorator.user") ----Walk the api, hydrating all functions with the error notification ----@param t table api root or sub-module +local M = {} + +---Walk the api, hydrating all functions with the error notification. +---Do not hydrate classes: anything with a metatable. +---@param t table local function hydrate_error(t) for k, v in pairs(t) do if type(v) == "function" then t[k] = function() notify.error("nvim-tree setup not called") end - elseif type(v) == "table" then + elseif type(v) == "table" and not getmetatable(v) then hydrate_error(v) end end end ----Hydrate implementations that may be called pre setup +---Hydrate api functions and classes pre-setup ---@param api table not properly typed to prevent LSP from referencing implementations -local function hydrate_pre(api) - -- - -- Essential - -- +function M.hydrate(api) + -- default to the error message + hydrate_error(api) + + -- eager functions api.events.Event = events.Event api.events.subscribe = events.subscribe - api.map.on_attach.default = keymap.on_attach_default - - - -- - -- May be lazily requried on execution - -- - api.health.hi_test = function() require("nvim-tree.appearance.hi-test")() end - - - -- - -- Already required elsewhere - -- api.commands.get = commands.get - api.map.keymap.default = keymap.get_keymap_default + -- lazy functions + api.health.hi_test = function() require("nvim-tree.appearance.hi-test")() end - -- - -- TODO #3241 - -- - api.decorator = {} - ---Create a decorator class by calling :extend() - ---See :help nvim-tree-decorators - ---@type nvim_tree.api.decorator.UserDecorator - api.decorator.UserDecorator = UserDecorator --[[@as nvim_tree.api.decorator.UserDecorator]] -end - ----Hydrate api ----@param api table not properly typed to prevent LSP from referencing implementations -return function(api) - -- Default: error - hydrate_error(api) - - -- Exceptions: may be called - hydrate_pre(api) + -- classes + api.Decorator = UserDecorator:extend() - -- Hydrate any legacy by mapping to function set above - require("nvim-tree.api.impl.legacy")(api) + -- Hydrate any legacy by mapping to concrete set above + require("nvim-tree.api.impl.legacy").hydrate(api) end + +return M diff --git a/lua/nvim-tree/classic.lua b/lua/nvim-tree/classic.lua index 6e856bc90c0..d7a072c10da 100644 --- a/lua/nvim-tree/classic.lua +++ b/lua/nvim-tree/classic.lua @@ -9,14 +9,17 @@ -- https://github.com/rxi/classic -- ----@class (exact) Class +---TODO #3241 document and rename +---@class Class: nvim_tree.Class +---@nodoc + +---@class nvim_tree.Class ---@field super Class ---@field private implements table local Class = {} Class.__index = Class ---@diagnostic disable-line: inject-field ---Default constructor ----@protected function Class:new(...) --luacheck: ignore 212 end @@ -68,7 +71,7 @@ function Class:is(class) return false end ----Return object if :is otherwise nil +---Return object if [nvim_tree.Class:is()] otherwise nil ---@generic T ---@param class T ---@return T|nil @@ -76,7 +79,7 @@ function Class:as(class) return self:is(class) and self or nil end ----Constructor to create instance, call :new and return +---Constructor to create instance, call [nvim_tree.Class:new()] and return function Class:__call(...) local obj = setmetatable({}, self) obj:new(...) diff --git a/lua/nvim-tree/node/directory-link.lua b/lua/nvim-tree/node/directory-link.lua index 6d503ad6d40..b1c19f54172 100644 --- a/lua/nvim-tree/node/directory-link.lua +++ b/lua/nvim-tree/node/directory-link.lua @@ -38,7 +38,7 @@ function DirectoryLinkNode:update_git_status(parent_ignored, project) self.git_status = git_utils.git_status_dir(parent_ignored, project, self.link_to, self.absolute_path) end ----@return HighlightedString name +---@return nvim_tree.api.decorator.highlighted_string name function DirectoryLinkNode:highlighted_icon() if not self.explorer.opts.renderer.icons.show.folder then return self:highlighted_icon_empty() @@ -58,7 +58,7 @@ function DirectoryLinkNode:highlighted_icon() end ---Maybe override name with arrow ----@return HighlightedString name +---@return nvim_tree.api.decorator.highlighted_string name function DirectoryLinkNode:highlighted_name() local name = DirectoryNode.highlighted_name(self) diff --git a/lua/nvim-tree/node/directory.lua b/lua/nvim-tree/node/directory.lua index d53718085f9..9b376e7b6f6 100644 --- a/lua/nvim-tree/node/directory.lua +++ b/lua/nvim-tree/node/directory.lua @@ -198,7 +198,7 @@ function DirectoryNode:expand_or_collapse(toggle_group) self.explorer.renderer:draw() end ----@return HighlightedString icon +---@return nvim_tree.api.decorator.highlighted_string icon function DirectoryNode:highlighted_icon() if not self.explorer.opts.renderer.icons.show.folder then return self:highlighted_icon_empty() @@ -243,7 +243,7 @@ function DirectoryNode:highlighted_icon() return { str = str, hl = { hl } } end ----@return HighlightedString icon +---@return nvim_tree.api.decorator.highlighted_string icon function DirectoryNode:highlighted_name() local str, hl diff --git a/lua/nvim-tree/node/file-link.lua b/lua/nvim-tree/node/file-link.lua index 6cb83e0343a..7130897ddec 100644 --- a/lua/nvim-tree/node/file-link.lua +++ b/lua/nvim-tree/node/file-link.lua @@ -31,7 +31,7 @@ function FileLinkNode:update_git_status(parent_ignored, project) self.git_status = git_utils.git_status_file(parent_ignored, project, self.link_to, self.absolute_path) end ----@return HighlightedString icon +---@return nvim_tree.api.decorator.highlighted_string icon function FileLinkNode:highlighted_icon() if not self.explorer.opts.renderer.icons.show.file then return self:highlighted_icon_empty() @@ -46,7 +46,7 @@ function FileLinkNode:highlighted_icon() return { str = str, hl = { hl } } end ----@return HighlightedString name +---@return nvim_tree.api.decorator.highlighted_string name function FileLinkNode:highlighted_name() local str = self.name if self.explorer.opts.renderer.symlink_destination then diff --git a/lua/nvim-tree/node/file.lua b/lua/nvim-tree/node/file.lua index bba1621e21b..2b0ea0362c9 100644 --- a/lua/nvim-tree/node/file.lua +++ b/lua/nvim-tree/node/file.lua @@ -50,7 +50,7 @@ function FileNode:get_git_xy() return self.git_status.file and { self.git_status.file } end ----@return HighlightedString icon +---@return nvim_tree.api.decorator.highlighted_string icon function FileNode:highlighted_icon() if not self.explorer.opts.renderer.icons.show.file then return self:highlighted_icon_empty() @@ -79,7 +79,7 @@ function FileNode:highlighted_icon() return { str = str, hl = { hl } } end ----@return HighlightedString name +---@return nvim_tree.api.decorator.highlighted_string name function FileNode:highlighted_name() local hl if vim.tbl_contains(self.explorer.opts.renderer.special_files, self.absolute_path) or vim.tbl_contains(self.explorer.opts.renderer.special_files, self.name) then diff --git a/lua/nvim-tree/node/init.lua b/lua/nvim-tree/node/init.lua index 5aaf4fb094a..4c8d5c81daa 100644 --- a/lua/nvim-tree/node/init.lua +++ b/lua/nvim-tree/node/init.lua @@ -93,28 +93,28 @@ end ---Empty highlighted icon ---@protected ----@return HighlightedString icon +---@return nvim_tree.api.decorator.highlighted_string icon function Node:highlighted_icon_empty() return { str = "", hl = {} } end ---Highlighted icon for the node ---Empty for base Node ----@return HighlightedString icon +---@return nvim_tree.api.decorator.highlighted_string icon function Node:highlighted_icon() return self:highlighted_icon_empty() end ---Empty highlighted name ---@protected ----@return HighlightedString name +---@return nvim_tree.api.decorator.highlighted_string name function Node:highlighted_name_empty() return { str = "", hl = {} } end ---Highlighted name for the node ---Empty for base Node ----@return HighlightedString name +---@return nvim_tree.api.decorator.highlighted_string name function Node:highlighted_name() return self:highlighted_name_empty() end diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 819660e5306..0c76ab515f5 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -18,10 +18,10 @@ local UserDecorator = require("nvim-tree.renderer.decorator.user") local pad = require("nvim-tree.renderer.components.padding") ----@alias HighlightedString nvim_tree.api.HighlightedString +---TODO #3241 add an alias for builtins or document the enum -- Builtin Decorators ----@type table +---@type table local BUILTIN_DECORATORS = { Git = GitDecorator, Open = OpenDecorator, @@ -106,7 +106,7 @@ function Builder:insert_highlight(groups, start, end_) end ---@private ----@param highlighted_strings HighlightedString[] +---@param highlighted_strings nvim_tree.api.decorator.highlighted_string[] ---@return string function Builder:unwrap_highlighted_strings(highlighted_strings) if not highlighted_strings then @@ -126,12 +126,12 @@ function Builder:unwrap_highlighted_strings(highlighted_strings) end ---@private ----@param indent_markers HighlightedString[] ----@param arrows HighlightedString[]|nil ----@param icon HighlightedString ----@param name HighlightedString +---@param indent_markers nvim_tree.api.decorator.highlighted_string[] +---@param arrows? nvim_tree.api.decorator.highlighted_string[] +---@param icon nvim_tree.api.decorator.highlighted_string +---@param name nvim_tree.api.decorator.highlighted_string ---@param node table ----@return HighlightedString[] +---@return nvim_tree.api.decorator.highlighted_string[] function Builder:format_line(indent_markers, arrows, icon, name, node) local added_len = 0 local function add_to_end(t1, t2) @@ -155,23 +155,39 @@ function Builder:format_line(indent_markers, arrows, icon, name, node) -- use the api node for user decorators local api_node = self.api_nodes and self.api_nodes[node.uid_node] --[[@as Node]] + local u local line = { indent_markers, arrows } add_to_end(line, { icon }) for _, d in ipairs(self.decorators) do - add_to_end(line, d:icons_before(not d:is(UserDecorator) and node or api_node)) + u = d:as(UserDecorator) + if not u then + add_to_end(line, d:icons_before(node)) + elseif api_node then + add_to_end(line, u:icons_before(api_node)) + end end add_to_end(line, { name }) for _, d in ipairs(self.decorators) do - add_to_end(line, d:icons_after(not d:is(UserDecorator) and node or api_node)) + u = d:as(UserDecorator) + if not u then + add_to_end(line, d:icons_after(node)) + elseif api_node then + add_to_end(line, u:icons_after(api_node)) + end end local rights = {} for _, d in ipairs(self.decorators) do - add_to_end(rights, d:icons_right_align(not d:is(UserDecorator) and node or api_node)) + u = d:as(UserDecorator) + if not u then + add_to_end(line, d:icons_right_align(node)) + elseif api_node then + add_to_end(line, u:icons_right_align(api_node)) + end end if #rights > 0 then self.extmarks[self.index] = rights @@ -187,10 +203,17 @@ function Builder:build_signs(node) local api_node = self.api_nodes and self.api_nodes[node.uid_node] --[[@as Node]] -- first in priority order - local d, sign_name + local d, u, sign_name for i = #self.decorators, 1, -1 do d = self.decorators[i] - sign_name = d:sign_name(not d:is(UserDecorator) and node or api_node) + + u = d:as(UserDecorator) + if not u then + sign_name = d:sign_name(node) + elseif api_node then + sign_name = u:sign_name(api_node) + end + if sign_name then self.signs[self.index] = sign_name break @@ -231,8 +254,8 @@ end ---A highlight group is always calculated and upserted for the case of highlights changing. ---@private ---@param node Node ----@return HighlightedString icon ----@return HighlightedString name +---@return nvim_tree.api.decorator.highlighted_string icon +---@return nvim_tree.api.decorator.highlighted_string name function Builder:icon_name_decorated(node) -- use the api node for user decorators local api_node = self.api_nodes and self.api_nodes[node.uid_node] --[[@as Node]] @@ -245,11 +268,17 @@ function Builder:icon_name_decorated(node) local icon_groups = {} local name_groups = {} local hl_icon, hl_name + local u for _, d in ipairs(self.decorators) do - -- maybe overridde icon - icon = d:icon_node((not d:is(UserDecorator) and node or api_node)) or icon - - hl_icon, hl_name = d:highlight_group_icon_name((not d:is(UserDecorator) and node or api_node)) + -- maybe override icon + u = d:as(UserDecorator) + if not u then + icon = d:icon_node(node) or icon + hl_icon, hl_name = d:highlight_group_icon_name(node) + elseif api_node then + icon = u:icon_node(api_node) or icon + hl_icon, hl_name = u:highlight_group_icon_name(api_node) + end table.insert(icon_groups, hl_icon) table.insert(name_groups, hl_name) diff --git a/lua/nvim-tree/renderer/components/padding.lua b/lua/nvim-tree/renderer/components/padding.lua index a33525cc437..a8289b4d4e1 100644 --- a/lua/nvim-tree/renderer/components/padding.lua +++ b/lua/nvim-tree/renderer/components/padding.lua @@ -64,7 +64,7 @@ end ---@param node Node ---@param markers table ---@param early_stop integer? ----@return HighlightedString +---@return nvim_tree.api.decorator.highlighted_string function M.get_indent_markers(depth, idx, nodes_number, node, markers, early_stop) local str = "" @@ -83,7 +83,7 @@ function M.get_indent_markers(depth, idx, nodes_number, node, markers, early_sto end ---@param node Node ----@return HighlightedString[]|nil +---@return nvim_tree.api.decorator.highlighted_string[]? function M.get_arrows(node) if not M.config.icons.show.folder_arrow then return diff --git a/lua/nvim-tree/renderer/decorator/bookmarks.lua b/lua/nvim-tree/renderer/decorator/bookmarks.lua index c661748ef21..5c6bff438e2 100644 --- a/lua/nvim-tree/renderer/decorator/bookmarks.lua +++ b/lua/nvim-tree/renderer/decorator/bookmarks.lua @@ -2,7 +2,7 @@ local Decorator = require("nvim-tree.renderer.decorator") ---@class (exact) BookmarkDecorator: Decorator ---@field private explorer Explorer ----@field private icon HighlightedString? +---@field private icon nvim_tree.api.decorator.highlighted_string? local BookmarkDecorator = Decorator:extend() ---@class BookmarkDecorator @@ -28,7 +28,7 @@ end ---Bookmark icon: renderer.icons.show.bookmarks and node is marked ---@param node Node ----@return HighlightedString[]? icons +---@return nvim_tree.api.decorator.highlighted_string[]? icons function BookmarkDecorator:icons(node) if self.explorer.marks:get(node) then return { self.icon } diff --git a/lua/nvim-tree/renderer/decorator/diagnostics.lua b/lua/nvim-tree/renderer/decorator/diagnostics.lua index 56598ef9418..fd7ceba6446 100644 --- a/lua/nvim-tree/renderer/decorator/diagnostics.lua +++ b/lua/nvim-tree/renderer/decorator/diagnostics.lua @@ -32,7 +32,7 @@ local ICON_KEYS = { ---@class (exact) DiagnosticsDecorator: Decorator ---@field private explorer Explorer ----@field private diag_icons HighlightedString[]? +---@field private diag_icons nvim_tree.api.decorator.highlighted_string[]? local DiagnosticsDecorator = Decorator:extend() ---@class DiagnosticsDecorator @@ -73,7 +73,7 @@ end ---Diagnostic icon: diagnostics.enable, renderer.icons.show.diagnostics and node has status ---@param node Node ----@return HighlightedString[]? icons +---@return nvim_tree.api.decorator.highlighted_string[]? icons function DiagnosticsDecorator:icons(node) if node and self.diag_icons then local diag_status = diagnostics.get_diag_status(node) diff --git a/lua/nvim-tree/renderer/decorator/git.lua b/lua/nvim-tree/renderer/decorator/git.lua index c117b16959d..bcd83df99a2 100644 --- a/lua/nvim-tree/renderer/decorator/git.lua +++ b/lua/nvim-tree/renderer/decorator/git.lua @@ -3,7 +3,7 @@ local notify = require("nvim-tree.notify") local Decorator = require("nvim-tree.renderer.decorator") local DirectoryNode = require("nvim-tree.node.directory") ----@class (exact) GitHighlightedString: nvim_tree.api.HighlightedString +---@class (exact) GitHighlightedString: nvim_tree.api.decorator.highlighted_string ---@field ord number decreasing priority ---@alias GitStatusStrings "deleted" | "ignored" | "renamed" | "staged" | "unmerged" | "unstaged" | "untracked" @@ -142,7 +142,7 @@ end ---Git icons: git.enable, renderer.icons.show.git and node has status ---@param node Node ----@return HighlightedString[]? icons +---@return nvim_tree.api.decorator.highlighted_string[]? icons function GitDecorator:icons(node) if not self.icons_by_xy then return nil diff --git a/lua/nvim-tree/renderer/decorator/hidden.lua b/lua/nvim-tree/renderer/decorator/hidden.lua index 87168ceb82b..bffd82c370b 100644 --- a/lua/nvim-tree/renderer/decorator/hidden.lua +++ b/lua/nvim-tree/renderer/decorator/hidden.lua @@ -3,7 +3,7 @@ local DirectoryNode = require("nvim-tree.node.directory") ---@class (exact) HiddenDecorator: Decorator ---@field private explorer Explorer ----@field private icon HighlightedString? +---@field private icon nvim_tree.api.decorator.highlighted_string? local HiddenDecorator = Decorator:extend() ---@class HiddenDecorator @@ -29,7 +29,7 @@ end ---Hidden icon: renderer.icons.show.hidden and node starts with `.` (dotfile). ---@param node Node ----@return HighlightedString[]? icons +---@return nvim_tree.api.decorator.highlighted_string[]? icons function HiddenDecorator:icons(node) if node:is_dotfile() then return { self.icon } diff --git a/lua/nvim-tree/renderer/decorator/init.lua b/lua/nvim-tree/renderer/decorator/init.lua index cc7ab0ad305..d5d2b1a7931 100644 --- a/lua/nvim-tree/renderer/decorator/init.lua +++ b/lua/nvim-tree/renderer/decorator/init.lua @@ -1,38 +1,14 @@ -local Class = require("nvim-tree.classic") - ----Abstract Decorator +---Abstract Decorator implementation ---@class (exact) Decorator: Class ---@field protected enabled boolean ----@field protected highlight_range nvim_tree.api.decorator.HighlightRange ----@field protected icon_placement nvim_tree.api.decorator.IconPlacement -local Decorator = Class:extend() +---@field protected highlight_range nvim_tree.api.decorator.highlight_range +---@field protected icon_placement nvim_tree.api.decorator.icon_placement +local Decorator = require("nvim-tree._meta.api.decorator"):extend() +---TODO #3241 create an internal decorator class with explorer member and lose the UserDecorator ---@class (exact) DecoratorArgs ---@field explorer Explorer ----Abstract icon override, optionally implemented ----@param node Node ----@return HighlightedString? icon_node -function Decorator:icon_node(node) - return self:nop(node) -end - ----Abstract icons, optionally implemented ----@protected ----@param node Node ----@return HighlightedString[]? icons -function Decorator:icons(node) - self:nop(node) -end - ----Abstract highlight group, optionally implemented ----@protected ----@param node Node ----@return string? highlight_group -function Decorator:highlight_group(node) - self:nop(node) -end - ---Maybe highlight groups for icon and name ---@param node Node ---@return string? icon highlight group @@ -70,7 +46,7 @@ end ---Icons when "before" ---@param node Node ----@return HighlightedString[]? icons +---@return nvim_tree.api.decorator.highlighted_string[]? icons function Decorator:icons_before(node) if not self.enabled or self.icon_placement ~= "before" then return @@ -81,7 +57,7 @@ end ---Icons when "after" ---@param node Node ----@return HighlightedString[]? icons +---@return nvim_tree.api.decorator.highlighted_string[]? icons function Decorator:icons_after(node) if not self.enabled or self.icon_placement ~= "after" then return @@ -92,7 +68,7 @@ end ---Icons when "right_align" ---@param node Node ----@return HighlightedString[]? icons +---@return nvim_tree.api.decorator.highlighted_string[]? icons function Decorator:icons_right_align(node) if not self.enabled or self.icon_placement ~= "right_align" then return @@ -103,7 +79,7 @@ end ---Define a sign ---@protected ----@param icon HighlightedString? +---@param icon nvim_tree.api.decorator.highlighted_string? 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 c182e300afc..ee41d7d90cd 100644 --- a/lua/nvim-tree/renderer/decorator/modified.lua +++ b/lua/nvim-tree/renderer/decorator/modified.lua @@ -5,7 +5,7 @@ local DirectoryNode = require("nvim-tree.node.directory") ---@class (exact) ModifiedDecorator: Decorator ---@field private explorer Explorer ----@field private icon HighlightedString? +---@field private icon nvim_tree.api.decorator.highlighted_string? local ModifiedDecorator = Decorator:extend() ---@class ModifiedDecorator @@ -31,7 +31,7 @@ end ---Modified icon: modified.enable, renderer.icons.show.modified and node is modified ---@param node Node ----@return HighlightedString[]? icons +---@return nvim_tree.api.decorator.highlighted_string[]? icons function ModifiedDecorator:icons(node) if buffers.is_modified(node) then return { self.icon } diff --git a/lua/nvim-tree/renderer/decorator/opened.lua b/lua/nvim-tree/renderer/decorator/opened.lua index 240dce4948a..094a893211c 100644 --- a/lua/nvim-tree/renderer/decorator/opened.lua +++ b/lua/nvim-tree/renderer/decorator/opened.lua @@ -4,7 +4,7 @@ local Decorator = require("nvim-tree.renderer.decorator") ---@class (exact) OpenDecorator: Decorator ---@field private explorer Explorer ----@field private icon HighlightedString|nil +---@field private icon? nvim_tree.api.decorator.highlighted_string local OpenDecorator = Decorator:extend() ---@class OpenDecorator diff --git a/scripts/gen_vimdoc.sh b/scripts/gen_vimdoc.sh index 93d7e171708..8f190a532f3 100755 --- a/scripts/gen_vimdoc.sh +++ b/scripts/gen_vimdoc.sh @@ -65,6 +65,9 @@ export LUA_PATH="${DIR_NVIM_SRC}/src/?.lua;${DIR_NVT}/scripts/?.lua" mkdir -pv "${DIR_WORK}/runtime/lua" ln -sv "${DIR_NVT}/lua/nvim-tree" "${DIR_WORK}/runtime/lua/nvim_tree" +# leave a generic placeholder to bridge between nvim.gen_vimdoc.Config +echo "---@brief placeholder" > "${DIR_WORK}/runtime/lua/placeholder.lua" + # generate cd "${DIR_WORK}" && pwd ./gen_vimdoc.lua diff --git a/scripts/gen_vimdoc_config.lua b/scripts/gen_vimdoc_config.lua index d5d7bf4636f..674b1609aa4 100644 --- a/scripts/gen_vimdoc_config.lua +++ b/scripts/gen_vimdoc_config.lua @@ -40,23 +40,31 @@ local srcs_config = { { helptag = "nvim-tree-config-default", section = "Config: Default", path = pre .. "_meta/config/default.lua", }, - { helptag = "nvim-tree-api", section = "placeholder for next Config", path = pre .. "api.lua", }, + { helptag = "nvim-tree-api", section = "PLACEHOLDER", path = "runtime/lua/placeholder.lua", }, } ---@type Src[] local srcs_api = { - { helptag = "nvim-tree-api", section = "API", path = pre .. "api.lua", }, - - { helptag = "nvim-tree-api-commands", section = "API: commands", path = pre .. "_meta/api/commands.lua", }, - { helptag = "nvim-tree-api-events", section = "API: events", path = pre .. "_meta/api/events.lua", }, - { helptag = "nvim-tree-api-filter", section = "API: filter", path = pre .. "_meta/api/filter.lua", }, - { helptag = "nvim-tree-api-fs", section = "API: fs", path = pre .. "_meta/api/fs.lua", }, - { helptag = "nvim-tree-api-git", section = "API: git", path = pre .. "_meta/api/git.lua", }, - { helptag = "nvim-tree-api-health", section = "API: health", path = pre .. "_meta/api/health.lua", }, - { helptag = "nvim-tree-api-map", section = "API: map", path = pre .. "_meta/api/map.lua", }, - { helptag = "nvim-tree-api-marks", section = "API: marks", path = pre .. "_meta/api/marks.lua", }, - { helptag = "nvim-tree-api-node", section = "API: node", path = pre .. "_meta/api/node.lua", }, - { helptag = "nvim-tree-api-tree", section = "API: tree", path = pre .. "_meta/api/tree.lua", }, + { helptag = "nvim-tree-api", section = "API", path = pre .. "api.lua", }, + + { helptag = "nvim-tree-api-commands", section = "API: commands", path = pre .. "_meta/api/commands.lua", }, + { helptag = "nvim-tree-api-events", section = "API: events", path = pre .. "_meta/api/events.lua", }, + { helptag = "nvim-tree-api-filter", section = "API: filter", path = pre .. "_meta/api/filter.lua", }, + { helptag = "nvim-tree-api-fs", section = "API: fs", path = pre .. "_meta/api/fs.lua", }, + { helptag = "nvim-tree-api-git", section = "API: git", path = pre .. "_meta/api/git.lua", }, + { helptag = "nvim-tree-api-health", section = "API: health", path = pre .. "_meta/api/health.lua", }, + { helptag = "nvim-tree-api-map", section = "API: map", path = pre .. "_meta/api/map.lua", }, + { helptag = "nvim-tree-api-marks", section = "API: marks", path = pre .. "_meta/api/marks.lua", }, + { helptag = "nvim-tree-api-node", section = "API: node", path = pre .. "_meta/api/node.lua", }, + { helptag = "nvim-tree-api-tree", section = "API: tree", path = pre .. "_meta/api/tree.lua", }, + + { helptag = "nvim-tree-api-decorator", section = "PLACEHOLDER", path = "runtime/lua/placeholder.lua", }, +} + +---@type Src[] +local srcs_class = { + { helptag = "nvim-tree-api-decorator", section = "API: Decorator", path = pre .. "_meta/api/decorator.lua", }, + { helptag = "nvim-tree-api-class", section = "API: Class", path = pre .. "classic.lua", }, } ---Map paths to file names @@ -92,6 +100,22 @@ local function src_by_name(name, srcs) error(string.format("\n\nPath for lower, extension stripped file name='%s' not found in\nsrcs=%s\n", name, vim.inspect(srcs))) end +-- generator doesn't strip _meta +local function normalise_module(fun) + fun.module = fun.module and fun.module:gsub("._meta", "", 1) or nil +end + +---HACK +---Problem: +--- Generator generates fields for a class' methods. +--- This is a problem as method fields don't have a module and aren't transformed. +--- Method field fun only contains: classvar, desc, name and (function) type +---Solution: +--- Collect a map of "class:method" to modules when the real method passes through fn_xform +--- This works as the real method function is processed before the field method. +---@type table +local modules_by_method = {} + -- @type nvim.gen_vimdoc.Config[] return { -- Config @@ -110,23 +134,38 @@ return { section_fmt = function(name) return src_by_name(name, srcs_api).section end, helptag_fmt = function(name) return src_by_name(name, srcs_api).helptag end, - -- optional, no default xform to override + -- strip module from the name fn_xform = function(fun) - if (fun.module) then - -- generator doesn't strip meta - -- also cascades into fn_helptag_fmt - local module = fun.module:gsub("._meta", "", 1) - - -- remove the API prefix from the left aligned function name - -- this will cascade into fn_helptag_fmt, which will apply the module prefix anyway - local name, replaced = fun.name:gsub("^" .. module .. "%.", "", 1) - if (replaced ~= 1) then - error(string.format("\n\nfun.name='%s' does not start with _meta stripped module='%s'\nfun=%s", fun.name, module, vim.inspect(fun))) - end - - fun.module = module - fun.name = name - end + normalise_module(fun) + fun.name = fun.name:gsub("^" .. fun.module .. "%.", "", 1) end, - } + }, + -- Classes + { + filename = "nvim-tree-lua.txt", + section_order = section_order(srcs_class), + files = files(srcs_class), + section_fmt = function(name) return src_by_name(name, srcs_class).section end, + helptag_fmt = function(name) return src_by_name(name, srcs_class).helptag end, + + fn_xform = function(fun) + -- strip module from name and record the module for the method + normalise_module(fun) + + -- strip the class file from the module + fun.module = fun.module:gsub("%.[^%.]*$", "", 1) + + -- strip module from name and record the module for the method + modules_by_method[fun.classvar .. ":" .. fun.name] = fun.module + end, + + -- fn_helptag_fmt_common derived + -- module prepended to classes + -- module is fetched from modules_by_method when fun.module unavailable + fn_helptag_fmt = function(fun) + local fn_sfx = fun.table and "" or "()" + local module = fun.module or modules_by_method[fun.classvar .. ":" .. fun.name] + return string.format("%s.%s:%s%s", module, fun.classvar, fun.name, fn_sfx) + end, + }, }