docs(editorconfig): move to source

This commit is contained in:
Lewis Russell
2024-03-09 12:21:01 +00:00
committed by Lewis Russell
parent 09a919f313
commit a09ddd7ce5
7 changed files with 243 additions and 153 deletions

View File

@@ -3,7 +3,7 @@
NVIM REFERENCE MANUAL NVIM REFERENCE MANUAL
==============================================================================
EditorConfig integration *editorconfig* EditorConfig integration *editorconfig*
Nvim supports EditorConfig. When a file is opened, Nvim searches all parent Nvim supports EditorConfig. When a file is opened, Nvim searches all parent
@@ -13,69 +13,23 @@ entire (recursive) directory. For more information see
https://editorconfig.org/. https://editorconfig.org/.
*g:editorconfig* *b:editorconfig* *g:editorconfig* *b:editorconfig*
EditorConfig is enabled by default. To disable it, add to your config: >lua
EditorConfig is enabled by default. To disable it, add to your config: >lua
vim.g.editorconfig = false vim.g.editorconfig = false
< <
(Vimscript: `let g:editorconfig = v:false`). It can also be disabled (Vimscript: `let g:editorconfig = v:false`). It can also be disabled
per-buffer by setting the |b:editorconfig| buffer-local variable to `false`. per-buffer by setting the |b:editorconfig| buffer-local variable to `false`.
Nvim stores the applied properties in |b:editorconfig| if it is not `false`. Nvim stores the applied properties in |b:editorconfig| if it is not `false`.
*editorconfig-properties*
The following properties are supported by default:
*editorconfig_root*
root If "true", then stop searching for .editorconfig files
in parent directories. This property must be at the
top-level of the .editorconfig file (i.e. it must not
be within a glob section).
*editorconfig_charset*
charset One of "utf-8", "utf-8-bom", "latin1", "utf-16be", or
"utf-16le". Sets the 'fileencoding' and 'bomb'
options.
*editorconfig_end_of_line*
end_of_line One of "lf", "crlf", or "cr". These correspond to
setting 'fileformat' to "unix", "dos", or "mac",
respectively.
*editorconfig_indent_style*
indent_style One of "tab" or "space". Sets the 'expandtab' option.
*editorconfig_indent_size*
indent_size A number indicating the size of a single indent.
Alternatively, use the value "tab" to use the value of
the tab_width property. Sets the 'shiftwidth' and
'softtabstop' options.
If this value is not "tab" and the tab_width property
is not set, 'tabstop' is also set to this value.
*editorconfig_insert_final_newline*
insert_final_newline "true" or "false" to ensure the file always has a
trailing newline as its last byte. Sets the
'fixendofline' and 'endofline' options.
*editorconfig_max_line_length*
max_line_length A number indicating the maximum length of a single
line. Sets the 'textwidth' option.
*editorconfig_tab_width*
tab_width The display size of a single tab character. Sets the
'tabstop' option.
*editorconfig_trim_trailing_whitespace*
trim_trailing_whitespace
When "true", trailing whitespace is automatically
removed when the buffer is written.
*editorconfig-custom-properties* *editorconfig-custom-properties*
New properties can be added by adding a new entry to the "properties" table. New properties can be added by adding a new entry to the "properties" table.
The table key is a property name and the value is a callback function which The table key is a property name and the value is a callback function which
accepts the number of the buffer to be modified, the value of the property accepts the number of the buffer to be modified, the value of the property in
in the .editorconfig file, and (optionally) a table containing all of the the `.editorconfig` file, and (optionally) a table containing all of the other
other properties and their values (useful for properties which depend on other properties and their values (useful for properties which depend on other
properties). The value is always a string and must be coerced if necessary. properties). The value is always a string and must be coerced if necessary.
Example: >lua Example: >lua
@@ -86,4 +40,48 @@ Example: >lua
vim.b[bufnr].foo = val vim.b[bufnr].foo = val
end end
< <
vim:tw=78:ts=8:et:sw=4:ft=help:norl:
*editorconfig-properties*
The following properties are supported by default:
charset *editorconfig.charset*
One of `"utf-8"`, `"utf-8-bom"`, `"latin1"`, `"utf-16be"`, or
`"utf-16le"`. Sets the 'fileencoding' and 'bomb' options.
end_of_line *editorconfig.end_of_line*
One of `"lf"`, `"crlf"`, or `"cr"`. These correspond to setting
'fileformat' to "unix", "dos", or "mac", respectively.
indent_size *editorconfig.indent_size*
A number indicating the size of a single indent. Alternatively, use the
value "tab" to use the value of the tab_width property. Sets the
'shiftwidth' and 'softtabstop' options. If this value is not "tab" and the
tab_width property is not set, 'tabstop' is also set to this value.
indent_style *editorconfig.indent_style*
One of `"tab"` or `"space"`. Sets the 'expandtab' option.
insert_final_newline *editorconfig.insert_final_newline*
`"true"` or `"false"` to ensure the file always has a trailing newline as
its last byte. Sets the 'fixendofline' and 'endofline' options.
max_line_length *editorconfig.max_line_length*
A number indicating the maximum length of a single line. Sets the
'textwidth' option.
root *editorconfig.root*
If "true", then stop searching for `.editorconfig` files in parent
directories. This property must be at the top-level of the `.editorconfig`
file (i.e. it must not be within a glob section).
tab_width *editorconfig.tab_width*
The display size of a single tab character. Sets the 'tabstop' option.
trim_trailing_whitespace *editorconfig.trim_trailing_whitespace*
When `"true"`, trailing whitespace is automatically removed when the
buffer is written.
vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:

View File

@@ -1161,6 +1161,7 @@ Lua list copies the list object to Vimscript and does NOT modify the Lua list: >
vim.print(list) --> "{ 1, 2, 3 }" vim.print(list) --> "{ 1, 2, 3 }"
< <
vim.call({func}, {...}) *vim.call()* vim.call({func}, {...}) *vim.call()*
Invokes |vim-function| or |user-function| {func} with arguments {...}. Invokes |vim-function| or |user-function| {func} with arguments {...}.
See also |vim.fn|. See also |vim.fn|.
@@ -1239,6 +1240,7 @@ vim.v *vim.v*
|v:| variables. |v:| variables.
Invalid or unset key returns `nil`. Invalid or unset key returns `nil`.
*lua-options* *lua-options*
*lua-vim-options* *lua-vim-options*
*lua-vim-set* *lua-vim-set*
@@ -1262,6 +1264,7 @@ window-scoped options. Note that this must NOT be confused with
|local-options| and |:setlocal|. There is also |vim.go| that only accesses the |local-options| and |:setlocal|. There is also |vim.go| that only accesses the
global value of a |global-local| option, see |:setglobal|. global value of a |global-local| option, see |:setglobal|.
*vim.opt_local* *vim.opt_local*
*vim.opt_global* *vim.opt_global*
*vim.opt* *vim.opt*
@@ -3897,6 +3900,7 @@ Iter:enumerate() *Iter:enumerate()*
< <
Example: >lua Example: >lua
local it = vim.iter(vim.gsplit('abc', '')):enumerate() local it = vim.iter(vim.gsplit('abc', '')):enumerate()
it:next() it:next()
-- 1 'a' -- 1 'a'
@@ -3931,6 +3935,7 @@ Iter:find({f}) *Iter:find()*
found. found.
Examples: >lua Examples: >lua
local it = vim.iter({ 3, 6, 9, 12 }) local it = vim.iter({ 3, 6, 9, 12 })
it:find(12) it:find(12)
-- 12 -- 12
@@ -4011,6 +4016,7 @@ Iter:last() *Iter:last()*
Drains the iterator and returns the last item. Drains the iterator and returns the last item.
Example: >lua Example: >lua
local it = vim.iter(vim.gsplit('abcdefg', '')) local it = vim.iter(vim.gsplit('abcdefg', ''))
it:last() it:last()
-- 'g' -- 'g'
@@ -4051,6 +4057,7 @@ Iter:next() *Iter:next()*
Gets the next value from the iterator. Gets the next value from the iterator.
Example: >lua Example: >lua
local it = vim.iter(string.gmatch('1 2 3', '%d+')):map(tonumber) local it = vim.iter(string.gmatch('1 2 3', '%d+')):map(tonumber)
it:next() it:next()
-- 1 -- 1
@@ -4082,6 +4089,7 @@ Iter:nth({n}) *Iter:nth()*
Gets the nth value of an iterator (and advances to it). Gets the nth value of an iterator (and advances to it).
Example: >lua Example: >lua
local it = vim.iter({ 3, 6, 9, 12 }) local it = vim.iter({ 3, 6, 9, 12 })
it:nth(2) it:nth(2)
-- 6 -- 6
@@ -4099,6 +4107,7 @@ Iter:nthback({n}) *Iter:nthback()*
Gets the nth value from the end of a |list-iterator| (and advances to it). Gets the nth value from the end of a |list-iterator| (and advances to it).
Example: >lua Example: >lua
local it = vim.iter({ 3, 6, 9, 12 }) local it = vim.iter({ 3, 6, 9, 12 })
it:nthback(2) it:nthback(2)
-- 9 -- 9
@@ -4116,6 +4125,7 @@ Iter:peek() *Iter:peek()*
Gets the next value in a |list-iterator| without consuming it. Gets the next value in a |list-iterator| without consuming it.
Example: >lua Example: >lua
local it = vim.iter({ 3, 6, 9, 12 }) local it = vim.iter({ 3, 6, 9, 12 })
it:peek() it:peek()
-- 3 -- 3
@@ -4150,6 +4160,7 @@ Iter:rev() *Iter:rev()*
Reverses a |list-iterator| pipeline. Reverses a |list-iterator| pipeline.
Example: >lua Example: >lua
local it = vim.iter({ 3, 6, 9, 12 }):rev() local it = vim.iter({ 3, 6, 9, 12 }):rev()
it:totable() it:totable()
-- { 12, 9, 6, 3 } -- { 12, 9, 6, 3 }
@@ -4166,6 +4177,7 @@ Iter:rfind({f}) *Iter:rfind()*
found. found.
Examples: >lua Examples: >lua
local it = vim.iter({ 1, 2, 3, 2, 1 }):enumerate() local it = vim.iter({ 1, 2, 3, 2, 1 }):enumerate()
it:rfind(1) it:rfind(1)
-- 5 1 -- 5 1
@@ -4186,6 +4198,7 @@ Iter:skip({n}) *Iter:skip()*
Skips `n` values of an iterator pipeline. Skips `n` values of an iterator pipeline.
Example: >lua Example: >lua
local it = vim.iter({ 3, 6, 9, 12 }):skip(2) local it = vim.iter({ 3, 6, 9, 12 }):skip(2)
it:next() it:next()
-- 9 -- 9

View File

@@ -1,31 +1,80 @@
local M = {} --- @brief
--- Nvim supports EditorConfig. When a file is opened, Nvim searches all parent
--- directories of that file for ".editorconfig" files, parses them, and applies
--- any properties that match the opened file. Think of it like 'modeline' for an
--- entire (recursive) directory. For more information see
--- https://editorconfig.org/.
---
--- @brief [g:editorconfig]() [b:editorconfig]()
---
--- EditorConfig is enabled by default. To disable it, add to your config:
--- ```lua
--- vim.g.editorconfig = false
--- ```
---
--- (Vimscript: `let g:editorconfig = v:false`). It can also be disabled
--- per-buffer by setting the [b:editorconfig] buffer-local variable to `false`.
---
--- Nvim stores the applied properties in [b:editorconfig] if it is not `false`.
--- @brief [editorconfig-custom-properties]()
---
--- New properties can be added by adding a new entry to the "properties" table.
--- The table key is a property name and the value is a callback function which
--- accepts the number of the buffer to be modified, the value of the property
--- in the `.editorconfig` file, and (optionally) a table containing all of the
--- other properties and their values (useful for properties which depend on other
--- properties). The value is always a string and must be coerced if necessary.
--- Example:
---
--- ```lua
---
--- require('editorconfig').properties.foo = function(bufnr, val, opts)
--- if opts.charset and opts.charset ~= "utf-8" then
--- error("foo can only be set when charset is utf-8", 0)
--- end
--- vim.b[bufnr].foo = val
--- end
---
--- ```
--- @brief [editorconfig-properties]()
---
--- The following properties are supported by default:
--- @type table<string,fun(bufnr: integer, val: string, opts?: table)> --- @type table<string,fun(bufnr: integer, val: string, opts?: table)>
M.properties = {} local properties = {}
--- @private
--- Modified version of the builtin assert that does not include error position information --- Modified version of the builtin assert that does not include error position information
--- ---
--- @param v any Condition --- @param v any Condition
--- @param message string Error message to display if condition is false or nil --- @param message string Error message to display if condition is false or nil
--- @return any v if not false or nil, otherwise an error is displayed --- @return any v if not false or nil, otherwise an error is displayed
---
---@private
local function assert(v, message) local function assert(v, message)
return v or error(message, 0) return v or error(message, 0)
end end
--- Show a warning message
---
---@param msg string Message to show
---
--- @private --- @private
--- Show a warning message
--- @param msg string Message to show
local function warn(msg, ...) local function warn(msg, ...)
vim.notify_once(string.format(msg, ...), vim.log.levels.WARN, { vim.notify_once(msg:format(...), vim.log.levels.WARN, {
title = 'editorconfig', title = 'editorconfig',
}) })
end end
function M.properties.charset(bufnr, val) --- If "true", then stop searching for `.editorconfig` files in parent
--- directories. This property must be at the top-level of the
--- `.editorconfig` file (i.e. it must not be within a glob section).
function properties.root()
-- Unused
end
--- One of `"utf-8"`, `"utf-8-bom"`, `"latin1"`, `"utf-16be"`, or `"utf-16le"`.
--- Sets the 'fileencoding' and 'bomb' options.
function properties.charset(bufnr, val)
assert( assert(
vim.list_contains({ 'utf-8', 'utf-8-bom', 'latin1', 'utf-16be', 'utf-16le' }, val), vim.list_contains({ 'utf-8', 'utf-8-bom', 'latin1', 'utf-16be', 'utf-16le' }, val),
'charset must be one of "utf-8", "utf-8-bom", "latin1", "utf-16be", or "utf-16le"' 'charset must be one of "utf-8", "utf-8-bom", "latin1", "utf-16be", or "utf-16le"'
@@ -40,14 +89,18 @@ function M.properties.charset(bufnr, val)
end end
end end
function M.properties.end_of_line(bufnr, val) --- One of `"lf"`, `"crlf"`, or `"cr"`.
--- These correspond to setting 'fileformat' to "unix", "dos", or "mac",
--- respectively.
function properties.end_of_line(bufnr, val)
vim.bo[bufnr].fileformat = assert( vim.bo[bufnr].fileformat = assert(
({ lf = 'unix', crlf = 'dos', cr = 'mac' })[val], ({ lf = 'unix', crlf = 'dos', cr = 'mac' })[val],
'end_of_line must be one of "lf", "crlf", or "cr"' 'end_of_line must be one of "lf", "crlf", or "cr"'
) )
end end
function M.properties.indent_style(bufnr, val, opts) --- One of `"tab"` or `"space"`. Sets the 'expandtab' option.
function properties.indent_style(bufnr, val, opts)
assert(val == 'tab' or val == 'space', 'indent_style must be either "tab" or "space"') assert(val == 'tab' or val == 'space', 'indent_style must be either "tab" or "space"')
vim.bo[bufnr].expandtab = val == 'space' vim.bo[bufnr].expandtab = val == 'space'
if val == 'tab' and not opts.indent_size then if val == 'tab' and not opts.indent_size then
@@ -56,7 +109,11 @@ function M.properties.indent_style(bufnr, val, opts)
end end
end end
function M.properties.indent_size(bufnr, val, opts) --- A number indicating the size of a single indent. Alternatively, use the
--- value "tab" to use the value of the tab_width property. Sets the
--- 'shiftwidth' and 'softtabstop' options. If this value is not "tab" and
--- the tab_width property is not set, 'tabstop' is also set to this value.
function properties.indent_size(bufnr, val, opts)
if val == 'tab' then if val == 'tab' then
vim.bo[bufnr].shiftwidth = 0 vim.bo[bufnr].shiftwidth = 0
vim.bo[bufnr].softtabstop = 0 vim.bo[bufnr].softtabstop = 0
@@ -70,11 +127,14 @@ function M.properties.indent_size(bufnr, val, opts)
end end
end end
function M.properties.tab_width(bufnr, val) --- The display size of a single tab character. Sets the 'tabstop' option.
function properties.tab_width(bufnr, val)
vim.bo[bufnr].tabstop = assert(tonumber(val), 'tab_width must be a number') vim.bo[bufnr].tabstop = assert(tonumber(val), 'tab_width must be a number')
end end
function M.properties.max_line_length(bufnr, val) --- A number indicating the maximum length of a single
--- line. Sets the 'textwidth' option.
function properties.max_line_length(bufnr, val)
local n = tonumber(val) local n = tonumber(val)
if n then if n then
vim.bo[bufnr].textwidth = n vim.bo[bufnr].textwidth = n
@@ -84,7 +144,8 @@ function M.properties.max_line_length(bufnr, val)
end end
end end
function M.properties.trim_trailing_whitespace(bufnr, val) --- When `"true"`, trailing whitespace is automatically removed when the buffer is written.
function properties.trim_trailing_whitespace(bufnr, val)
assert( assert(
val == 'true' or val == 'false', val == 'true' or val == 'false',
'trim_trailing_whitespace must be either "true" or "false"' 'trim_trailing_whitespace must be either "true" or "false"'
@@ -109,7 +170,9 @@ function M.properties.trim_trailing_whitespace(bufnr, val)
end end
end end
function M.properties.insert_final_newline(bufnr, val) --- `"true"` or `"false"` to ensure the file always has a trailing newline as its last byte.
--- Sets the 'fixendofline' and 'endofline' options.
function properties.insert_final_newline(bufnr, val)
assert(val == 'true' or val == 'false', 'insert_final_newline must be either "true" or "false"') assert(val == 'true' or val == 'false', 'insert_final_newline must be either "true" or "false"')
vim.bo[bufnr].fixendofline = val == 'true' vim.bo[bufnr].fixendofline = val == 'true'
@@ -128,47 +191,43 @@ function M.properties.insert_final_newline(bufnr, val)
end end
end end
--- Modified version of |glob2regpat()| that does not match path separators on *. --- @private
--- Modified version of [glob2regpat()] that does not match path separators on `*`.
--- ---
--- This function replaces single instances of * with the regex pattern [^/]*. However, the star in --- This function replaces single instances of `*` with the regex pattern `[^/]*`.
--- the replacement pattern also gets interpreted by glob2regpat, so we insert a placeholder, pass --- However, the star in the replacement pattern also gets interpreted by glob2regpat,
--- it through glob2regpat, then replace the placeholder with the actual regex pattern. --- so we insert a placeholder, pass it through glob2regpat, then replace the
--- placeholder with the actual regex pattern.
--- ---
--- @param glob string Glob to convert into a regular expression --- @param glob string Glob to convert into a regular expression
---@return string Regular expression --- @return string regex Regular expression
---
---@private
local function glob2regpat(glob) local function glob2regpat(glob)
local placeholder = '@@PLACEHOLDER@@' local placeholder = '@@PLACEHOLDER@@'
return ( local glob1 = vim.fn.substitute(
string.gsub( glob:gsub('{(%d+)%.%.(%d+)}', '[%1-%2]'),
vim.fn.glob2regpat(
vim.fn.substitute(
string.gsub(glob, '{(%d+)%.%.(%d+)}', '[%1-%2]'),
'\\*\\@<!\\*\\*\\@!', '\\*\\@<!\\*\\*\\@!',
placeholder, placeholder,
'g' 'g'
) )
), local regpat = vim.fn.glob2regpat(glob1)
placeholder, return (regpat:gsub(placeholder, '[^/]*'))
'[^/]*'
)
)
end end
--- Parse a single line in an EditorConfig file
---
---@param line string Line
---@return string|nil If the line contains a pattern, the glob pattern
---@return string|nil If the line contains a key-value pair, the key
---@return string|nil If the line contains a key-value pair, the value
---
--- @private --- @private
--- Parse a single line in an EditorConfig file
--- @param line string Line
--- @return string? glob pattern if the line contains a pattern
--- @return string? key if the line contains a key-value pair
--- @return string? value if the line contains a key-value pair
local function parse_line(line) local function parse_line(line)
if line:find('^%s*[^ #;]') then if not line:find('^%s*[^ #;]') then
return
end
--- @type string?
local glob = (line:match('%b[]') or ''):match('^%s*%[(.*)%]%s*$') local glob = (line:match('%b[]') or ''):match('^%s*%[(.*)%]%s*$')
if glob then if glob then
return glob, nil, nil return glob
end end
local key, val = line:match('^%s*([^:= ][^:=]-)%s*[:=]%s*(.-)%s*$') local key, val = line:match('^%s*([^:= ][^:=]-)%s*[:=]%s*(.-)%s*$')
@@ -176,15 +235,12 @@ local function parse_line(line)
return nil, key:lower(), val:lower() return nil, key:lower(), val:lower()
end end
end end
end
--- Parse options from an .editorconfig file --- @private
--- --- Parse options from an `.editorconfig` file
--- @param filepath string File path of the file to apply EditorConfig settings to --- @param filepath string File path of the file to apply EditorConfig settings to
--- @param dir string Current directory --- @param dir string Current directory
--- @return table<string,string|boolean> Table of options to apply to the given file --- @return table<string,string|boolean> Table of options to apply to the given file
---
---@private
local function parse(filepath, dir) local function parse(filepath, dir)
local pat --- @type vim.regex? local pat --- @type vim.regex?
local opts = {} --- @type table<string,string|boolean> local opts = {} --- @type table<string,string|boolean>
@@ -215,11 +271,11 @@ local function parse(filepath, dir)
return opts return opts
end end
--- Configure the given buffer with options from an .editorconfig file local M = {}
---
---@param bufnr integer Buffer number to configure
---
--- @private --- @private
--- Configure the given buffer with options from an `.editorconfig` file
--- @param bufnr integer Buffer number to configure
function M.config(bufnr) function M.config(bufnr)
bufnr = bufnr or vim.api.nvim_get_current_buf() bufnr = bufnr or vim.api.nvim_get_current_buf()
if not vim.api.nvim_buf_is_valid(bufnr) then if not vim.api.nvim_buf_is_valid(bufnr) then
@@ -247,8 +303,9 @@ function M.config(bufnr)
local applied = {} --- @type table<string,string|boolean> local applied = {} --- @type table<string,string|boolean>
for opt, val in pairs(opts) do for opt, val in pairs(opts) do
if val ~= 'unset' then if val ~= 'unset' then
local func = M.properties[opt] local func = properties[opt]
if func then if func then
--- @type boolean, string?
local ok, err = pcall(func, bufnr, val, opts) local ok, err = pcall(func, bufnr, val, opts)
if ok then if ok then
applied[opt] = val applied[opt] = val

View File

@@ -74,7 +74,6 @@ vim.log = {
--- Examples: --- Examples:
--- ---
--- ```lua --- ```lua
---
--- local on_exit = function(obj) --- local on_exit = function(obj)
--- print(obj.code) --- print(obj.code)
--- print(obj.signal) --- print(obj.signal)

View File

@@ -215,7 +215,6 @@ function vim.schedule(fn) end
--- Examples: --- Examples:
--- ---
--- ```lua --- ```lua
---
--- --- --- ---
--- -- Wait for 100 ms, allowing other events to process --- -- Wait for 100 ms, allowing other events to process
--- vim.wait(100, function() end) --- vim.wait(100, function() end)

View File

@@ -94,12 +94,12 @@ end
local function fn_helptag_fmt_common(fun) local function fn_helptag_fmt_common(fun)
local fn_sfx = fun.table and '' or '()' local fn_sfx = fun.table and '' or '()'
if fun.classvar then if fun.classvar then
return fmt('*%s:%s%s*', fun.classvar, fun.name, fn_sfx) return fmt('%s:%s%s', fun.classvar, fun.name, fn_sfx)
end end
if fun.module then if fun.module then
return fmt('*%s.%s%s*', fun.module, fun.name, fn_sfx) return fmt('%s.%s%s', fun.module, fun.name, fn_sfx)
end end
return fmt('*%s%s*', fun.name, fn_sfx) return fun.name .. fn_sfx
end end
--- @type table<string,nvim.gen_vimdoc.Config> --- @type table<string,nvim.gen_vimdoc.Config>
@@ -129,7 +129,7 @@ local config = {
return name .. ' Functions' return name .. ' Functions'
end, end,
helptag_fmt = function(name) helptag_fmt = function(name)
return fmt('*api-%s*', name:lower()) return fmt('api-%s', name:lower())
end, end,
}, },
lua = { lua = {
@@ -241,22 +241,22 @@ local config = {
end, end,
helptag_fmt = function(name) helptag_fmt = function(name)
if name == '_editor' then if name == '_editor' then
return '*lua-vim*' return 'lua-vim'
elseif name == '_options' then elseif name == '_options' then
return '*lua-vimscript*' return 'lua-vimscript'
elseif name == 'tohtml' then elseif name == 'tohtml' then
return '*tohtml*' return 'tohtml'
end end
return '*vim.' .. name:lower() .. '*' return 'vim.' .. name:lower()
end, end,
fn_helptag_fmt = function(fun) fn_helptag_fmt = function(fun)
local name = fun.name local name = fun.name
if vim.startswith(name, 'vim.') then if vim.startswith(name, 'vim.') then
local fn_sfx = fun.table and '' or '()' local fn_sfx = fun.table and '' or '()'
return fmt('*%s%s*', name, fn_sfx) return name .. fn_sfx
elseif fun.classvar == 'Option' then elseif fun.classvar == 'Option' then
return fmt('*vim.opt:%s()*', name) return fmt('vim.opt:%s()', name)
end end
return fn_helptag_fmt_common(fun) return fn_helptag_fmt_common(fun)
@@ -297,9 +297,9 @@ local config = {
end, end,
helptag_fmt = function(name) helptag_fmt = function(name)
if name:lower() == 'lsp' then if name:lower() == 'lsp' then
return '*lsp-core*' return 'lsp-core'
end end
return fmt('*lsp-%s*', name:lower()) return fmt('lsp-%s', name:lower())
end, end,
}, },
diagnostic = { diagnostic = {
@@ -312,7 +312,7 @@ local config = {
return 'Lua module: vim.diagnostic' return 'Lua module: vim.diagnostic'
end, end,
helptag_fmt = function() helptag_fmt = function()
return '*diagnostic-api*' return 'diagnostic-api'
end, end,
}, },
treesitter = { treesitter = {
@@ -337,9 +337,28 @@ local config = {
end, end,
helptag_fmt = function(name) helptag_fmt = function(name)
if name:lower() == 'treesitter' then if name:lower() == 'treesitter' then
return '*lua-treesitter-core*' return 'lua-treesitter-core'
end end
return '*lua-treesitter-' .. name:lower() .. '*' return 'lua-treesitter-' .. name:lower()
end,
},
editorconfig = {
filename = 'editorconfig.txt',
files = {
'runtime/lua/editorconfig.lua',
},
section_order = {
'editorconfig.lua',
},
section_fmt = function(_name)
return 'EditorConfig integration'
end,
helptag_fmt = function(name)
return name:lower()
end,
fn_xform = function(fun)
fun.table = true
fun.name = vim.split(fun.name, '.', { plain = true })[2]
end, end,
}, },
} }
@@ -600,7 +619,7 @@ local function render_fun_header(fun, cfg)
cfg.fn_helptag_fmt = fn_helptag_fmt_common cfg.fn_helptag_fmt = fn_helptag_fmt_common
end end
local tag = cfg.fn_helptag_fmt(fun) local tag = '*' .. cfg.fn_helptag_fmt(fun) .. '*'
if #proto + #tag > TEXT_WIDTH - 8 then if #proto + #tag > TEXT_WIDTH - 8 then
table.insert(ret, fmt('%78s\n', tag)) table.insert(ret, fmt('%78s\n', tag))
@@ -816,7 +835,7 @@ local function make_section(filename, cfg, section_docs, funs_txt)
local sectname = cfg.section_name and cfg.section_name[filename] or mktitle(name) local sectname = cfg.section_name and cfg.section_name[filename] or mktitle(name)
-- section tag: e.g., "*api-autocmd*" -- section tag: e.g., "*api-autocmd*"
local help_tag = cfg.helptag_fmt(sectname) local help_tag = '*' .. cfg.helptag_fmt(sectname) .. '*'
if funs_txt == '' and #section_docs == 0 then if funs_txt == '' and #section_docs == 0 then
return return
@@ -845,9 +864,9 @@ local function render_section(section, add_header)
}) })
end end
if section.doc and #section.doc > 0 then local sdoc = '\n\n' .. table.concat(section.doc or {}, '\n')
table.insert(doc, '\n\n') if sdoc:find('[^%s]') then
vim.list_extend(doc, section.doc) doc[#doc + 1] = sdoc
end end
if section.funs_txt then if section.funs_txt then
@@ -880,6 +899,7 @@ end
--- @param cfg nvim.gen_vimdoc.Config --- @param cfg nvim.gen_vimdoc.Config
local function gen_target(cfg) local function gen_target(cfg)
print('Target:', cfg.filename)
local sections = {} --- @type table<string,nvim.gen_vimdoc.Section> local sections = {} --- @type table<string,nvim.gen_vimdoc.Section>
expand_files(cfg.files) expand_files(cfg.files)
@@ -891,7 +911,7 @@ local function gen_target(cfg)
local all_classes = {} local all_classes = {}
--- First pass so we can collect all classes --- First pass so we can collect all classes
for _, f in pairs(cfg.files) do for _, f in vim.spairs(cfg.files) do
local ext = assert(f:match('%.([^.]+)$')) --[[@as 'h'|'c'|'lua']] local ext = assert(f:match('%.([^.]+)$')) --[[@as 'h'|'c'|'lua']]
local parser = assert(parsers[ext]) local parser = assert(parsers[ext])
local classes, funs, briefs = parser(f) local classes, funs, briefs = parser(f)
@@ -899,13 +919,14 @@ local function gen_target(cfg)
all_classes = vim.tbl_extend('error', all_classes, classes) all_classes = vim.tbl_extend('error', all_classes, classes)
end end
for f, r in pairs(file_results) do for f, r in vim.spairs(file_results) do
local classes, funs, briefs = r[1], r[2], r[3] local classes, funs, briefs = r[1], r[2], r[3]
local briefs_txt = {} --- @type string[] local briefs_txt = {} --- @type string[]
for _, b in ipairs(briefs) do for _, b in ipairs(briefs) do
briefs_txt[#briefs_txt + 1] = md_to_vimdoc(b, 0, 0, TEXT_WIDTH) briefs_txt[#briefs_txt + 1] = md_to_vimdoc(b, 0, 0, TEXT_WIDTH)
end end
print(' Processing file:', f)
local funs_txt = render_funs(funs, all_classes, cfg) local funs_txt = render_funs(funs, all_classes, cfg)
if next(classes) then if next(classes) then
local classes_txt = render_classes(classes) local classes_txt = render_classes(classes)
@@ -923,8 +944,9 @@ local function gen_target(cfg)
for _, f in ipairs(cfg.section_order) do for _, f in ipairs(cfg.section_order) do
local section = sections[f] local section = sections[f]
if section then if section then
print(string.format(" Rendering section: '%s'", section.title))
local add_sep_and_header = not vim.tbl_contains(cfg.append_only or {}, f) local add_sep_and_header = not vim.tbl_contains(cfg.append_only or {}, f)
table.insert(docs, render_section(section, add_sep_and_header)) docs[#docs + 1] = render_section(section, add_sep_and_header)
end end
end end
@@ -945,7 +967,7 @@ local function gen_target(cfg)
end end
local function run() local function run()
for _, cfg in pairs(config) do for _, cfg in vim.spairs(config) do
gen_target(cfg) gen_target(cfg)
end end
end end

View File

@@ -318,7 +318,7 @@ local function align_tags(text_width)
--- @param line string --- @param line string
--- @return string --- @return string
return function(line) return function(line)
local tag_pat = '%s+(%*[^ ]+%*)%s*$' local tag_pat = '%s*(%*.+%*)%s*$'
local tags = {} local tags = {}
for m in line:gmatch(tag_pat) do for m in line:gmatch(tag_pat) do
table.insert(tags, m) table.insert(tags, m)
@@ -327,7 +327,9 @@ local function align_tags(text_width)
if #tags > 0 then if #tags > 0 then
line = line:gsub(tag_pat, '') line = line:gsub(tag_pat, '')
local tags_str = ' ' .. table.concat(tags, ' ') local tags_str = ' ' .. table.concat(tags, ' ')
local pad = string.rep(' ', text_width - #line - #tags_str) --- @type integer
local conceal_offset = select(2, tags_str:gsub('%*', '')) - 2
local pad = string.rep(' ', text_width - #line - #tags_str + conceal_offset)
return line .. pad .. tags_str return line .. pad .. tags_str
end end
@@ -352,7 +354,7 @@ function M.md_to_vimdoc(text, start_indent, indent, text_width, is_list)
local s = table.concat(lines, '\n') local s = table.concat(lines, '\n')
-- Reduce whitespace in code-blocks -- Reduce whitespace in code-blocks
s = s:gsub('\n+%s*>([a-z]+)\n?\n', ' >%1\n') s = s:gsub('\n+%s*>([a-z]+)\n', ' >%1\n')
s = s:gsub('\n+%s*>\n?\n', ' >\n') s = s:gsub('\n+%s*>\n?\n', ' >\n')
return s return s