mirror of
https://github.com/folke/snacks.nvim
synced 2025-08-04 18:58:12 +00:00
docs: better docgen using treesitter
This commit is contained in:
parent
7f9f691a12
commit
7e6ea65f5f
31 changed files with 233 additions and 80 deletions
|
@ -1,4 +1,4 @@
|
|||
*snacks-bigfile.txt* For Neovim Last change: 2024 November 08
|
||||
*snacks-bigfile.txt* snacks.nvim
|
||||
|
||||
==============================================================================
|
||||
Table of Contents *snacks-bigfile-table-of-contents*
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
*snacks-bufdelete.txt* For Neovim Last change: 2024 November 08
|
||||
*snacks-bufdelete.txt* snacks.nvim
|
||||
|
||||
==============================================================================
|
||||
Table of Contents *snacks-bufdelete-table-of-contents*
|
||||
|
||||
1. Module |snacks-bufdelete-module|
|
||||
1. Config |snacks-bufdelete-config|
|
||||
2. Module |snacks-bufdelete-module|
|
||||
- Snacks.bufdelete() |snacks-bufdelete-module-snacks.bufdelete()|
|
||||
- Snacks.bufdelete.all() |snacks-bufdelete-module-snacks.bufdelete.all()|
|
||||
- Snacks.bufdelete.delete()|snacks-bufdelete-module-snacks.bufdelete.delete()|
|
||||
|
@ -15,7 +16,20 @@ discard.
|
|||
|
||||
|
||||
==============================================================================
|
||||
1. Module *snacks-bufdelete-module*
|
||||
1. Config *snacks-bufdelete-config*
|
||||
|
||||
>lua
|
||||
---@class snacks.bufdelete.Opts
|
||||
---@field buf? number Buffer to delete. If not provided, the current buffer is deleted
|
||||
---@field force? boolean Delete the buffer even if it is modified
|
||||
---@field filter? fun(buf: number): boolean Filter buffers to delete
|
||||
---@field wipe? boolean Wipe the buffer instead of deleting it (see `:h :bwipeout`)
|
||||
{}
|
||||
<
|
||||
|
||||
|
||||
==============================================================================
|
||||
2. Module *snacks-bufdelete-module*
|
||||
|
||||
|
||||
SNACKS.BUFDELETE() *snacks-bufdelete-module-snacks.bufdelete()*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
*snacks-debug.txt* For Neovim Last change: 2024 November 08
|
||||
*snacks-debug.txt* snacks.nvim
|
||||
|
||||
==============================================================================
|
||||
Table of Contents *snacks-debug-table-of-contents*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
*snacks-git.txt* For Neovim Last change: 2024 November 08
|
||||
*snacks-git.txt* snacks.nvim
|
||||
|
||||
==============================================================================
|
||||
Table of Contents *snacks-git-table-of-contents*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
*snacks-gitbrowse.txt* For Neovim Last change: 2024 November 08
|
||||
*snacks-gitbrowse.txt* snacks.nvim
|
||||
|
||||
==============================================================================
|
||||
Table of Contents *snacks-gitbrowse-table-of-contents*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
*snacks-init.txt* For Neovim Last change: 2024 November 08
|
||||
*snacks-init.txt* snacks.nvim
|
||||
|
||||
==============================================================================
|
||||
Table of Contents *snacks-init-table-of-contents*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
*snacks-lazygit.txt* For Neovim Last change: 2024 November 08
|
||||
*snacks-lazygit.txt* snacks.nvim
|
||||
|
||||
==============================================================================
|
||||
Table of Contents *snacks-lazygit-table-of-contents*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
*snacks-notifier.txt* For Neovim Last change: 2024 November 08
|
||||
*snacks-notifier.txt* snacks.nvim
|
||||
|
||||
==============================================================================
|
||||
Table of Contents *snacks-notifier-table-of-contents*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
*snacks-notify.txt* For Neovim Last change: 2024 November 08
|
||||
*snacks-notify.txt* snacks.nvim
|
||||
|
||||
==============================================================================
|
||||
Table of Contents *snacks-notify-table-of-contents*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
*snacks-quickfile.txt* For Neovim Last change: 2024 November 08
|
||||
*snacks-quickfile.txt* snacks.nvim
|
||||
|
||||
==============================================================================
|
||||
Table of Contents *snacks-quickfile-table-of-contents*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
*snacks-rename.txt* For Neovim Last change: 2024 November 08
|
||||
*snacks-rename.txt* snacks.nvim
|
||||
|
||||
==============================================================================
|
||||
Table of Contents *snacks-rename-table-of-contents*
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
*snacks-statuscolumn.txt* For Neovim Last change: 2024 November 08
|
||||
*snacks-statuscolumn.txt* snacks.nvim
|
||||
|
||||
==============================================================================
|
||||
Table of Contents *snacks-statuscolumn-table-of-contents*
|
||||
|
||||
1. Config |snacks-statuscolumn-config|
|
||||
2. Module |snacks-statuscolumn-module|
|
||||
- Snacks.statuscolumn() |snacks-statuscolumn-module-snacks.statuscolumn()|
|
||||
- Snacks.statuscolumn.get()|snacks-statuscolumn-module-snacks.statuscolumn.get()|
|
||||
|
||||
==============================================================================
|
||||
1. Config *snacks-statuscolumn-config*
|
||||
|
@ -25,6 +28,26 @@ Table of Contents *snacks-statuscolumn-table-of-contents*
|
|||
}
|
||||
<
|
||||
|
||||
|
||||
==============================================================================
|
||||
2. Module *snacks-statuscolumn-module*
|
||||
|
||||
|
||||
SNACKS.STATUSCOLUMN() *snacks-statuscolumn-module-snacks.statuscolumn()*
|
||||
|
||||
>lua
|
||||
---@type fun(): string
|
||||
Snacks.statuscolumn()
|
||||
<
|
||||
|
||||
|
||||
SNACKS.STATUSCOLUMN.GET()*snacks-statuscolumn-module-snacks.statuscolumn.get()*
|
||||
|
||||
>lua
|
||||
---@return string
|
||||
Snacks.statuscolumn.get()
|
||||
<
|
||||
|
||||
Generated by panvimdoc <https://github.com/kdheepak/panvimdoc>
|
||||
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
*snacks-terminal.txt* For Neovim Last change: 2024 November 08
|
||||
*snacks-terminal.txt* snacks.nvim
|
||||
|
||||
==============================================================================
|
||||
Table of Contents *snacks-terminal-table-of-contents*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
*snacks-toggle.txt* For Neovim Last change: 2024 November 08
|
||||
*snacks-toggle.txt* snacks.nvim
|
||||
|
||||
==============================================================================
|
||||
Table of Contents *snacks-toggle-table-of-contents*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
*snacks-win.txt* For Neovim Last change: 2024 November 08
|
||||
*snacks-win.txt* snacks.nvim
|
||||
|
||||
==============================================================================
|
||||
Table of Contents *snacks-win-table-of-contents*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
*snacks-words.txt* For Neovim Last change: 2024 November 08
|
||||
*snacks-words.txt* snacks.nvim
|
||||
|
||||
==============================================================================
|
||||
Table of Contents *snacks-words-table-of-contents*
|
||||
|
@ -21,6 +21,8 @@ Auto-show LSP references and quickly navigate between them
|
|||
debounce = 200, -- time in ms to wait before updating
|
||||
notify_jump = false, -- show a notification when jumping
|
||||
notify_end = true, -- show a notification when reaching the end
|
||||
foldopen = true, -- open folds after jumping
|
||||
jumplist = true, -- set jump point before jumping
|
||||
modes = { "n", "i", "c" }, -- modes to show references
|
||||
}
|
||||
<
|
||||
|
|
|
@ -20,3 +20,19 @@
|
|||
refresh = 50, -- refresh at most every 50ms
|
||||
}
|
||||
```
|
||||
|
||||
## 📦 Module
|
||||
|
||||
### `Snacks.statuscolumn()`
|
||||
|
||||
```lua
|
||||
---@type fun(): string
|
||||
Snacks.statuscolumn()
|
||||
```
|
||||
|
||||
### `Snacks.statuscolumn.get()`
|
||||
|
||||
```lua
|
||||
---@return string
|
||||
Snacks.statuscolumn.get()
|
||||
```
|
||||
|
|
|
@ -16,6 +16,7 @@ local defaults = {
|
|||
end,
|
||||
}
|
||||
|
||||
---@private
|
||||
function M.setup()
|
||||
local opts = Snacks.config.get("bigfile", defaults)
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
---@class snacks.bufdelete
|
||||
---@hide
|
||||
---@overload fun(buf?: number)
|
||||
local M = setmetatable({}, {
|
||||
__call = function(t, ...)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
---@class snacks.debug
|
||||
---@hide
|
||||
---@overload fun(...)
|
||||
local M = setmetatable({}, {
|
||||
__call = function(t, ...)
|
||||
|
|
|
@ -1,63 +1,154 @@
|
|||
local M = {}
|
||||
|
||||
local query = vim.treesitter.query.parse(
|
||||
"lua",
|
||||
[[
|
||||
;; top-level locals
|
||||
((variable_declaration (
|
||||
assignment_statement
|
||||
(variable_list name: (identifier) @local_name)
|
||||
(expression_list value: (_) @local_value)
|
||||
(#match? @local_value "(setmetatable|\\{)")
|
||||
)) @local
|
||||
(#any-of? @local_name "M" "defaults" "config")
|
||||
(#has-parent? @local chunk))
|
||||
|
||||
;; top-level functions/methods
|
||||
(function_declaration
|
||||
name: (_) @fun_name (#match? @fun_name "^M")
|
||||
parameters: (_) @fun_params
|
||||
) @fun
|
||||
|
||||
;; styles
|
||||
(function_call
|
||||
name: (dot_index_expression) @_sf (#eq? @_sf "Snacks.config.style")
|
||||
arguments: (arguments
|
||||
(string content: (string_content) @style_name)
|
||||
(table_constructor) @style_config)
|
||||
) @style
|
||||
]]
|
||||
)
|
||||
|
||||
---@class snacks.docs.Capture
|
||||
---@field name string
|
||||
---@field line number
|
||||
---@field node TSNode
|
||||
---@field text string
|
||||
---@field comment string
|
||||
---@field fields table<string, string>
|
||||
|
||||
---@class snacks.docs.Parse
|
||||
---@field captures snacks.docs.Capture[]
|
||||
---@field comments string[]
|
||||
|
||||
---@class snacks.docs.Info
|
||||
---@field config? string
|
||||
---@field mod? string
|
||||
---@field methods {name: string, args: string, comment?: string, types?: string, type: "method"|"function"}[]
|
||||
---@field types string[]
|
||||
---@field styles {name:string, opts:string}[]
|
||||
|
||||
---@param lines string[]
|
||||
function M.extract(lines)
|
||||
local code = table.concat(lines, "\n")
|
||||
local config = code:match("\n(%-%-%- ?@class snacks%.%w+%.Config.-\n})")
|
||||
config = config or code:match("\n(%-%-%- ?@class snacks%.Config.-\n})")
|
||||
local mod ---@type string
|
||||
function M.parse(lines)
|
||||
local source = table.concat(lines, "\n")
|
||||
local parser = vim.treesitter.get_string_parser(source, "lua")
|
||||
parser:parse()
|
||||
|
||||
local comments = {} ---@type string[]
|
||||
local types = {} ---@type string[]
|
||||
local styles = {} ---@type {name:string, opts:string}[]
|
||||
|
||||
local style_pattern = 'Snacks%.config%.style%("([^"]+)"%s*,%s*({.-}%s*)%)'
|
||||
|
||||
for style_name, style in code:gmatch(style_pattern) do
|
||||
table.insert(styles, { name = style_name, opts = style })
|
||||
end
|
||||
|
||||
---@type {name: string, args: string, comment?: string, types?: string, type: "method"|"function"}[]
|
||||
local methods = {}
|
||||
|
||||
for _, line in ipairs(lines) do
|
||||
if line:match("^%-%-") then
|
||||
table.insert(comments, line)
|
||||
else
|
||||
local comment = table.concat(comments, "\n")
|
||||
if line:find("^local M =") then
|
||||
mod = comment
|
||||
elseif comment:find("@private") then
|
||||
else
|
||||
local t, name, args = line:match("^function M([:%.])([%w_%.]+)%((.-)%)")
|
||||
if name and args then
|
||||
if not name:find("^_") then
|
||||
table.insert(methods, {
|
||||
name = name,
|
||||
args = args,
|
||||
type = t,
|
||||
comment = comment,
|
||||
})
|
||||
end
|
||||
elseif #comments > 0 and line == "" then
|
||||
table.insert(types, table.concat(comments, "\n"))
|
||||
end
|
||||
for l, line in ipairs(lines) do
|
||||
if line:find("^%-%-") then
|
||||
comments[l] = line
|
||||
if comments[l - 1] then
|
||||
comments[l] = comments[l - 1] .. "\n" .. comments[l]
|
||||
comments[l - 1] = nil
|
||||
end
|
||||
comments = {}
|
||||
end
|
||||
end
|
||||
|
||||
local private = mod and mod:find("@private")
|
||||
config = config and config:gsub("local defaults = ", ""):gsub("local config = ", "") or nil
|
||||
---@type snacks.docs.Parse
|
||||
local ret = { captures = {}, comments = {} }
|
||||
|
||||
---@class snacks.docs.Info
|
||||
for id, node in query:iter_captures(parser:trees()[1]:root(), source) do
|
||||
local name = query.captures[id]
|
||||
if not name:find("_") then
|
||||
-- add fields
|
||||
local fields = {}
|
||||
for id2, node2 in query:iter_captures(node, source) do
|
||||
local c = query.captures[id2]
|
||||
if c:find(".+_") then
|
||||
fields[c:gsub("^.*_", "")] = vim.treesitter.get_node_text(node2, source)
|
||||
end
|
||||
end
|
||||
|
||||
-- add comments
|
||||
local comment = "" ---@type string
|
||||
if comments[node:start()] then
|
||||
comment = comments[node:start()]
|
||||
comments[node:start()] = nil
|
||||
end
|
||||
|
||||
table.insert(ret.captures, {
|
||||
text = vim.treesitter.get_node_text(node, source),
|
||||
name = name,
|
||||
comment = comment,
|
||||
line = node:start() + 1,
|
||||
node = node,
|
||||
fields = fields,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
-- remove comments that are followed by code
|
||||
for l in pairs(comments) do
|
||||
if lines[l + 1] and lines[l + 1]:find("^.+$") then
|
||||
comments[l] = nil
|
||||
end
|
||||
end
|
||||
for l in ipairs(lines) do
|
||||
if comments[l] then
|
||||
table.insert(ret.comments, comments[l])
|
||||
end
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
---@param lines string[]
|
||||
function M.extract(lines)
|
||||
local parse = M.parse(lines)
|
||||
---@type snacks.docs.Info
|
||||
local ret = {
|
||||
config = config,
|
||||
mod = mod,
|
||||
methods = methods,
|
||||
types = types,
|
||||
styles = styles,
|
||||
methods = {},
|
||||
types = vim.tbl_filter(function(c)
|
||||
return not c:find("@private")
|
||||
end, parse.comments),
|
||||
styles = {},
|
||||
}
|
||||
return private and { config = config, methods = {}, types = {}, styles = styles } or ret
|
||||
|
||||
for _, c in ipairs(parse.captures) do
|
||||
if c.comment:find("@private") then
|
||||
-- skip private
|
||||
elseif c.name == "local" then
|
||||
if vim.tbl_contains({ "defaults", "config" }, c.fields.name) then
|
||||
ret.config = vim.trim(c.comment .. "\n" .. c.fields.value)
|
||||
elseif c.fields.name == "M" then
|
||||
ret.mod = c.comment
|
||||
end
|
||||
elseif c.name == "fun" then
|
||||
local name = c.fields.name:sub(2)
|
||||
local args = (c.fields.params or ""):sub(2, -2)
|
||||
local comment = c.comment
|
||||
local type = name:sub(1, 1)
|
||||
name = name:sub(2)
|
||||
if not name:find("^_") then
|
||||
table.insert(ret.methods, { name = name, args = args, comment = comment, type = type })
|
||||
end
|
||||
elseif c.name == "style" then
|
||||
table.insert(ret.styles, { name = c.fields.name, opts = c.fields.config })
|
||||
end
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
---@param tag string
|
||||
|
@ -75,6 +166,7 @@ end
|
|||
---@param str string
|
||||
---@param opts? {extract_comment: boolean} -- default true
|
||||
function M.md(str, opts)
|
||||
str = str or ""
|
||||
opts = opts or {}
|
||||
if opts.extract_comment == nil then
|
||||
opts.extract_comment = true
|
||||
|
@ -161,7 +253,8 @@ function M.render(name, info)
|
|||
end
|
||||
return true
|
||||
end, mod_lines)
|
||||
if not info.mod:find("@hide") then
|
||||
local hide = #mod_lines == 1 and mod_lines[1]:find("@class")
|
||||
if not hide then
|
||||
table.insert(mod_lines, prefix .. " = {}")
|
||||
add(M.md(table.concat(mod_lines, "\n")))
|
||||
end
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
---@class snacks.git
|
||||
---@hide
|
||||
local M = {}
|
||||
|
||||
Snacks.config.style("blame_line", {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
---@class snacks.gitbrowse
|
||||
---@hide
|
||||
---@overload fun(opts?: snacks.gitbrowse.Config)
|
||||
local M = setmetatable({}, {
|
||||
__call = function(t, ...)
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
---@hide
|
||||
---@class snacks.lazygit
|
||||
---@overload fun(opts?: snacks.lazygit.Config): snacks.win
|
||||
local M = setmetatable({}, {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
---@hide
|
||||
---@class snacks.notifier
|
||||
---@overload fun(msg: string, level?: snacks.notifier.level|number, opts?: snacks.notifier.Notif.opts): number|string
|
||||
local M = setmetatable({}, {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
---@hide
|
||||
---@class snacks.notify
|
||||
---@overload fun(msg: string|string[], opts?: snacks.notify.Opts)
|
||||
local M = setmetatable({}, {
|
||||
|
|
|
@ -8,6 +8,7 @@ local defaults = {
|
|||
exclude = { "latex" },
|
||||
}
|
||||
|
||||
---@private
|
||||
function M.setup()
|
||||
local opts = Snacks.config.get("quickfile", defaults)
|
||||
-- Skip if we already entered vim
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
---@hide
|
||||
---@class snacks.rename
|
||||
local M = {}
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
---@private
|
||||
---@class snacks.statuscolumn
|
||||
---@overload fun(): string
|
||||
local M = setmetatable({}, {
|
||||
|
@ -24,6 +23,7 @@ local defaults = {
|
|||
|
||||
local config = Snacks.config.get("statuscolumn", defaults)
|
||||
|
||||
---@private
|
||||
---@alias snacks.statuscolumn.Sign.type "mark"|"sign"|"fold"|"git"
|
||||
---@alias snacks.statuscolumn.Sign {name:string, text:string, texthl:string, priority:number, type:snacks.statuscolumn.Sign.type}
|
||||
|
||||
|
@ -33,6 +33,7 @@ local cache = {}
|
|||
|
||||
local did_setup = false
|
||||
|
||||
---@private
|
||||
function M.setup()
|
||||
if did_setup then
|
||||
return
|
||||
|
@ -44,6 +45,7 @@ function M.setup()
|
|||
end)
|
||||
end
|
||||
|
||||
---@private
|
||||
---@param name string
|
||||
function M.is_git_sign(name)
|
||||
for _, pattern in ipairs(config.git.patterns) do
|
||||
|
@ -54,6 +56,7 @@ function M.is_git_sign(name)
|
|||
end
|
||||
|
||||
-- Returns a list of regular and extmark signs sorted by priority (low to high)
|
||||
---@private
|
||||
---@return table<number, snacks.statuscolumn.Sign[]>
|
||||
---@param buf number
|
||||
function M.buf_signs(buf)
|
||||
|
@ -110,10 +113,11 @@ function M.buf_signs(buf)
|
|||
end
|
||||
|
||||
-- Returns a list of regular and extmark signs sorted by priority (high to low)
|
||||
---@return snacks.statuscolumn.Sign[]
|
||||
---@private
|
||||
---@param win number
|
||||
---@param buf number
|
||||
---@param lnum number
|
||||
---@return snacks.statuscolumn.Sign[]
|
||||
function M.line_signs(win, buf, lnum)
|
||||
local signs = M.buf_signs(buf)[lnum] or {}
|
||||
|
||||
|
@ -133,6 +137,7 @@ function M.line_signs(win, buf, lnum)
|
|||
return signs
|
||||
end
|
||||
|
||||
---@private
|
||||
---@param sign? snacks.statuscolumn.Sign
|
||||
---@param len? number
|
||||
function M.icon(sign, len)
|
||||
|
@ -143,6 +148,7 @@ function M.icon(sign, len)
|
|||
return sign.texthl and ("%#" .. sign.texthl .. "#" .. text .. "%*") or text
|
||||
end
|
||||
|
||||
---@return string
|
||||
function M.get()
|
||||
M.setup()
|
||||
local win = vim.g.statusline_winid
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
---@hide
|
||||
---@class snacks.words
|
||||
local M = {}
|
||||
|
||||
|
|
|
@ -13,5 +13,11 @@ fi
|
|||
PANVIMDOC=~/projects/panvimdoc
|
||||
|
||||
for f in docs/*.md; do
|
||||
$PANVIMDOC/panvimdoc.sh --project-name "snacks-$(basename "$f" .md)" --input-file "$f" --vim-version "Neovim" --demojify "true" --shift-heading-level-by -1
|
||||
$PANVIMDOC/panvimdoc.sh \
|
||||
--project-name "snacks-$(basename "$f" .md)" \
|
||||
--description "snacks.nvim" \
|
||||
--input-file "$f" \
|
||||
--vim-version "Neovim" \
|
||||
--demojify "true" \
|
||||
--shift-heading-level-by -1
|
||||
done
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue