diff options
-rw-r--r-- | runtime/doc/builtin.txt | 1 | ||||
-rw-r--r-- | runtime/doc/develop.txt | 37 | ||||
-rw-r--r-- | runtime/doc/health.txt | 6 | ||||
-rw-r--r-- | runtime/doc/lsp.txt | 3 | ||||
-rw-r--r-- | runtime/doc/lua.txt | 22 | ||||
-rw-r--r-- | runtime/doc/news.txt | 5 | ||||
-rw-r--r-- | runtime/doc/provider.txt | 4 | ||||
-rw-r--r-- | runtime/lua/vim/_editor.lua | 26 | ||||
-rw-r--r-- | runtime/lua/vim/_meta/vimfn.lua | 1 | ||||
-rw-r--r-- | runtime/lua/vim/health.lua | 4 | ||||
-rw-r--r-- | runtime/lua/vim/iter.lua | 10 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/completion.lua | 2 | ||||
-rwxr-xr-x | scripts/gen_vimdoc.lua | 4 | ||||
-rw-r--r-- | src/nvim/eval.lua | 1 | ||||
-rw-r--r-- | src/nvim/main.c | 4 | ||||
-rw-r--r-- | src/nvim/os/env.c | 30 | ||||
-rw-r--r-- | src/nvim/os/input.c | 2 | ||||
-rw-r--r-- | test/functional/lua/vim_spec.lua | 10 | ||||
-rw-r--r-- | test/functional/plugin/lsp/completion_spec.lua | 2 |
19 files changed, 91 insertions, 83 deletions
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index f1d8cc8526..cd8abc2351 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -4361,6 +4361,7 @@ maparg({name} [, {mode} [, {abbr} [, {dict}]]]) *maparg()* "lhsrawalt" The {lhs} of the mapping as raw bytes, alternate form, only present when it differs from "lhsraw" "rhs" The {rhs} of the mapping as typed. + "callback" Lua function, if RHS was defined as such. "silent" 1 for a |:map-silent| mapping, else 0. "noremap" 1 if the {rhs} of the mapping is not remappable. "script" 1 if mapping was defined with <script>. diff --git a/runtime/doc/develop.txt b/runtime/doc/develop.txt index d7837dc2fe..41bb90299b 100644 --- a/runtime/doc/develop.txt +++ b/runtime/doc/develop.txt @@ -138,15 +138,15 @@ DOCUMENTATION *dev-doc* - Write docstrings (as opposed to inline comments) with present tense ("Gets"), not imperative ("Get"). This tends to reduce ambiguity and improve clarity by describing "What" instead of "How". > - GOOD: + ✅ OK: /// Gets a highlight definition. - BAD: + ❌ NO: /// Get a highlight definition. - Avoid starting docstrings with "The" or "A" unless needed to avoid ambiguity. This is a visual aid and reduces noise. > - GOOD: + ✅ OK: /// @param dirname Path fragment before `pend` - BAD: + ❌ NO: /// @param dirname The path fragment before `pend` - Vim differences: - Do not prefix help tags with "nvim-". Use |vim_diff.txt| to catalog @@ -329,13 +329,20 @@ Where possible, these patterns apply to _both_ Lua and the API: - When accepting a buffer id, etc., 0 means "current buffer", nil means "all buffers". Likewise for window id, tabpage id, etc. - Examples: |vim.lsp.codelens.clear()| |vim.diagnostic.enable()| -- Any function signature that accepts a callback function should define the - callback as the LAST parameter, if possible. This improves readability of - calls by placing the less "noisy" arguments near the start. > - GOOD: - filter(table, opts, function() … end) - BAD: - filter(function() … end, table, opts) +- Any function signature that accepts a callback (example: |table.foreach()|) + should place it as the LAST parameter (after opts), if possible (or ALWAYS + for "continuation callbacks"—functions called exactly once). + - Improves readability by placing the less "noisy" arguments near the start. + - Consistent with luv. + - Useful for future async lib which transforms functions of the form + `function(<args>, cb(<ret)>))` => `function(<args>) -> <ret>`. + - Example: >lua + -- ✅ OK: + filter(…, opts, function() … end) + -- ❌ NO: + filter(function() … end, …, opts) + -- ❌ NO: + filter(…, function() … end, opts) - "Enable" ("toggle") interface and behavior: - `enable(…, nil)` and `enable(…, {buf=nil})` are synonyms and control the the "global" enablement of a feature. @@ -566,10 +573,10 @@ a good name: it's idiomatic and unambiguous. If the package is named "neovim", it confuses users, and complicates documentation and discussions. Examples of API-client package names: -- GOOD: nvim-racket -- GOOD: pynvim -- BAD: python-client -- BAD: neovim_ +- ✅ OK: nvim-racket +- ✅ OK: pynvim +- ❌ NO: python-client +- ❌ NO: neovim_ API client implementation guidelines ~ diff --git a/runtime/doc/health.txt b/runtime/doc/health.txt index e879f11351..cb70961b55 100644 --- a/runtime/doc/health.txt +++ b/runtime/doc/health.txt @@ -7,10 +7,10 @@ Type |gO| to see the table of contents. ============================================================================== -Checkhealth *health* +Checkhealth *vim.health* *health* -health.vim is a minimal framework to help users troubleshoot configuration and +vim.health is a minimal framework to help users troubleshoot configuration and any other environment conditions that a plugin might care about. Nvim ships with healthchecks for configuration, performance, python support, ruby support, clipboard support, and more. @@ -49,7 +49,7 @@ Commands *health-commands* :checkhealth vim* < -Create a healthcheck *health-dev* *vim.health* +Create a healthcheck *health-dev* Healthchecks are functions that check the user environment, configuration, or any other prerequisites that a plugin cares about. Nvim ships with diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index 7f5ae06030..e820d54a9e 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -1639,8 +1639,7 @@ Lua module: vim.lsp.completion *lsp-completion* Fields: ~ • {autotrigger}? (`boolean`) Whether to trigger completion automatically. Default: false - • {convert}? (`fun(item: lsp.CompletionItem): table`) An optional - function used to customize the transformation of an + • {convert}? (`fun(item: lsp.CompletionItem): table`) Transforms an LSP CompletionItem to |complete-items|. diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index f071d67030..0a7c53a482 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -352,16 +352,14 @@ Example: >vim < *lua-table-ambiguous* Lua tables are used as both dictionaries and lists, so it is impossible to -determine whether empty table is meant to be empty list or empty dictionary. -Additionally Lua does not have integer numbers. To distinguish between these -cases there is the following agreement: +decide whether empty table is a list or a dict. Also Lua does not have integer +numbers. To disambiguate these cases, we define: *lua-list* -0. Empty table is empty list. -1. Table with N consecutive integer indices starting from 1 and ending with - N is considered a list. See also |list-iterator|. +0. Empty table is a list. Use |vim.empty_dict()| to represent empty dict. +1. Table with N consecutive (no `nil` values, aka "holes") integer keys 1…N is + a list. See also |list-iterator|. *lua-dict* -2. Table with string keys, none of which contains NUL byte, is considered to - be a dictionary. +2. Table with string keys, none of which contains NUL byte, is a dict. 3. Table with string keys, at least one of which contains NUL byte, is also considered to be a dictionary, but this time it is converted to a |msgpack-special-map|. @@ -3839,10 +3837,12 @@ argument into an *Iter* object with methods (such as |Iter:filter()| and chained to create iterator "pipelines": the output of each pipeline stage is input to the next stage. The first stage depends on the type passed to `vim.iter()`: -• List tables (arrays, |lua-list|) yield only the value of each element. - • Holes (nil values) are allowed. +• Lists or arrays (|lua-list|) yield only the value of each element. + • Holes (nil values) are allowed (but discarded). + • Use pairs() to treat array/list tables as dicts (preserve holes and + non-contiguous integer keys): `vim.iter(pairs(…))`. • Use |Iter:enumerate()| to also pass the index to the next stage. - • Or initialize with ipairs(): `vim.iter(ipairs(…))`. + • Or initialize with ipairs(): `vim.iter(ipairs(…))`. • Non-list tables (|lua-dict|) yield both the key and value of each element. • Function |iterator|s yield all values returned by the underlying function. • Tables with a |__call()| metamethod are treated as function iterators. diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 21a8d2bd91..3d1ea8548f 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -65,9 +65,8 @@ EVENTS LSP -• Add convert field in |vim.lsp.completion.BufferOpts| of - |vim.lsp.completion.enable()| an optional function used to customize the - transformation of an Lsp CompletionItem to |complete-items|. +• |vim.lsp.completion.enable()| gained the `convert` callback which enables + customizing the transformation of an LSP CompletionItem to |complete-items|. • |vim.lsp.diagnostic.from()| can be used to convert a list of |vim.Diagnostic| objects into their LSP diagnostic representation. diff --git a/runtime/doc/provider.txt b/runtime/doc/provider.txt index a39f4bc5d7..c43110790a 100644 --- a/runtime/doc/provider.txt +++ b/runtime/doc/provider.txt @@ -248,8 +248,8 @@ For Windows WSL, try this g:clipboard definition: \ '*': 'clip.exe', \ }, \ 'paste': { - \ '+': 'powershell.exe -c [Console]::Out.Write($(Get-Clipboard -Raw).tostring().replace("`r", ""))', - \ '*': 'powershell.exe -c [Console]::Out.Write($(Get-Clipboard -Raw).tostring().replace("`r", ""))', + \ '+': 'powershell.exe -NoLogo -NoProfile -c [Console]::Out.Write($(Get-Clipboard -Raw).tostring().replace("`r", ""))', + \ '*': 'powershell.exe -NoLogo -NoProfile -c [Console]::Out.Write($(Get-Clipboard -Raw).tostring().replace("`r", ""))', \ }, \ 'cache_enabled': 0, \ } diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index c7c8362bfb..7b5570cc99 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -1,17 +1,19 @@ -- Nvim-Lua stdlib: the `vim` module (:help lua-stdlib) -- --- Lua code lives in one of three places: --- 1. runtime/lua/vim/ (the runtime): For "nice to have" features, e.g. the --- `inspect` and `lpeg` modules. --- 2. runtime/lua/vim/shared.lua: pure Lua functions which always --- are available. Used in the test runner, as well as worker threads --- and processes launched from Nvim. --- 3. runtime/lua/vim/_editor.lua: Code which directly interacts with --- the Nvim editor state. Only available in the main thread. +-- Lua code lives in one of four places: +-- 1. Plugins! Not everything needs to live on "vim.*". Plugins are the correct model for +-- non-essential features which the user may want to disable or replace with a third-party +-- plugin. Examples: "editorconfig", "comment". +-- - "opt-out": runtime/plugin/*.lua +-- - "opt-in": runtime/pack/dist/opt/ +-- 2. runtime/lua/vim/ (the runtime): Lazy-loaded modules. Examples: `inspect`, `lpeg`. +-- 3. runtime/lua/vim/shared.lua: pure Lua functions which always are available. Used in the test +-- runner, as well as worker threads and processes launched from Nvim. +-- 4. runtime/lua/vim/_editor.lua: Eager-loaded code which directly interacts with the Nvim +-- editor state. Only available in the main thread. -- --- Guideline: "If in doubt, put it in the runtime". --- --- Most functions should live directly in `vim.`, not in submodules. +-- The top level "vim.*" namespace is for fundamental Lua and editor features. Use submodules for +-- everything else (but avoid excessive "nesting"), or plugins (see above). -- -- Compatibility with Vim's `if_lua` is explicitly a non-goal. -- @@ -19,9 +21,7 @@ -- - https://github.com/luafun/luafun -- - https://github.com/rxi/lume -- - http://leafo.net/lapis/reference/utilities.html --- - https://github.com/torch/paths -- - https://github.com/bakpakin/Fennel (pretty print, repl) --- - https://github.com/howl-editor/howl/tree/master/lib/howl/util -- These are for loading runtime modules lazily since they aren't available in -- the nvim binary as specified in executor.c diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index 05b9fc2bbf..10b09333a8 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -5262,6 +5262,7 @@ function vim.fn.map(expr1, expr2) end --- "lhsrawalt" The {lhs} of the mapping as raw bytes, alternate --- form, only present when it differs from "lhsraw" --- "rhs" The {rhs} of the mapping as typed. +--- "callback" Lua function, if RHS was defined as such. --- "silent" 1 for a |:map-silent| mapping, else 0. --- "noremap" 1 if the {rhs} of the mapping is not remappable. --- "script" 1 if mapping was defined with <script>. diff --git a/runtime/lua/vim/health.lua b/runtime/lua/vim/health.lua index 236f9da752..d183c82516 100644 --- a/runtime/lua/vim/health.lua +++ b/runtime/lua/vim/health.lua @@ -1,6 +1,6 @@ --- @brief ---<pre>help ---- health.vim is a minimal framework to help users troubleshoot configuration and +--- vim.health is a minimal framework to help users troubleshoot configuration and --- any other environment conditions that a plugin might care about. Nvim ships --- with healthchecks for configuration, performance, python support, ruby --- support, clipboard support, and more. @@ -39,7 +39,7 @@ --- :checkhealth vim* --- < --- ---- Create a healthcheck *health-dev* *vim.health* +--- Create a healthcheck *health-dev* --- --- Healthchecks are functions that check the user environment, configuration, or --- any other prerequisites that a plugin cares about. Nvim ships with diff --git a/runtime/lua/vim/iter.lua b/runtime/lua/vim/iter.lua index 6bddf0bc5e..4bbcaf16db 100644 --- a/runtime/lua/vim/iter.lua +++ b/runtime/lua/vim/iter.lua @@ -6,10 +6,12 @@ --- of each pipeline stage is input to the next stage. The first stage depends on the type passed to --- `vim.iter()`: --- ---- - List tables (arrays, |lua-list|) yield only the value of each element. ---- - Holes (nil values) are allowed. +--- - Lists or arrays (|lua-list|) yield only the value of each element. +--- - Holes (nil values) are allowed (but discarded). +--- - Use pairs() to treat array/list tables as dicts (preserve holes and non-contiguous integer +--- keys): `vim.iter(pairs(…))`. --- - Use |Iter:enumerate()| to also pass the index to the next stage. ---- - Or initialize with ipairs(): `vim.iter(ipairs(…))`. +--- - Or initialize with ipairs(): `vim.iter(ipairs(…))`. --- - Non-list tables (|lua-dict|) yield both the key and value of each element. --- - Function |iterator|s yield all values returned by the underlying function. --- - Tables with a |__call()| metamethod are treated as function iterators. @@ -1034,7 +1036,7 @@ function Iter.new(src, ...) if type(k) ~= 'number' or k <= 0 or math.floor(k) ~= k then return Iter.new(pairs(src)) end - t[#t + 1] = v + t[#t + 1] = v -- Coerce to list-like table. end return ArrayIter.new(t) end diff --git a/runtime/lua/vim/lsp/completion.lua b/runtime/lua/vim/lsp/completion.lua index 89d6d0e8b9..71ea2df100 100644 --- a/runtime/lua/vim/lsp/completion.lua +++ b/runtime/lua/vim/lsp/completion.lua @@ -597,7 +597,7 @@ end --- @class vim.lsp.completion.BufferOpts --- @field autotrigger? boolean Whether to trigger completion automatically. Default: false ---- @field convert? fun(item: lsp.CompletionItem): table An optional function used to customize the transformation of an LSP CompletionItem to |complete-items|. +--- @field convert? fun(item: lsp.CompletionItem): table Transforms an LSP CompletionItem to |complete-items|. ---@param client_id integer ---@param bufnr integer diff --git a/scripts/gen_vimdoc.lua b/scripts/gen_vimdoc.lua index dc384c12f5..aa09bc7dc7 100755 --- a/scripts/gen_vimdoc.lua +++ b/scripts/gen_vimdoc.lua @@ -373,8 +373,8 @@ local config = { section_fmt = function(_name) return 'Checkhealth' end, - helptag_fmt = function(name) - return name:lower() + helptag_fmt = function() + return 'vim.health* *health' -- HACK end, }, } diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 5087c2d36d..cbab735489 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -6442,6 +6442,7 @@ M.funcs = { "lhsrawalt" The {lhs} of the mapping as raw bytes, alternate form, only present when it differs from "lhsraw" "rhs" The {rhs} of the mapping as typed. + "callback" Lua function, if RHS was defined as such. "silent" 1 for a |:map-silent| mapping, else 0. "noremap" 1 if the {rhs} of the mapping is not remappable. "script" 1 if mapping was defined with <script>. diff --git a/src/nvim/main.c b/src/nvim/main.c index c507a201b0..6b90a13e1e 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -1434,9 +1434,9 @@ scripterror: // On Windows expand "~\" or "~/" prefix in file names to profile directory. #ifdef MSWIN if (*p == '~' && (p[1] == '\\' || p[1] == '/')) { - size_t size = strlen(os_get_homedir()) + strlen(p); + size_t size = strlen(os_homedir()) + strlen(p); char *tilde_expanded = xmalloc(size); - snprintf(tilde_expanded, size, "%s%s", os_get_homedir(), p + 1); + snprintf(tilde_expanded, size, "%s%s", os_homedir(), p + 1); xfree(p); p = tilde_expanded; } diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c index a4d5c02b5b..8dfedd073e 100644 --- a/src/nvim/os/env.c +++ b/src/nvim/os/env.c @@ -395,7 +395,21 @@ void os_get_hostname(char *hostname, size_t size) #endif } -/// To get the "real" home directory: +/// The "real" home directory as determined by `init_homedir`. +static char *homedir = NULL; +static char *os_uv_homedir(void); + +/// Gets the "real", resolved user home directory as determined by `init_homedir`. +const char *os_homedir(void) +{ + if (!homedir) { + emsg("os_homedir failed: homedir not initialized"); + return NULL; + } + return homedir; +} + +/// Sets `homedir` to the "real", resolved user home directory, as follows: /// 1. get value of $HOME /// 2. if $HOME is not set, try the following /// For Windows: @@ -409,20 +423,6 @@ void os_get_hostname(char *hostname, size_t size) /// This also works with mounts and links. /// Don't do this for Windows, it will change the "current dir" for a drive. /// 3. fall back to current working directory as a last resort -static char *homedir = NULL; -static char *os_uv_homedir(void); - -/// Public accessor for the cached "real", resolved user home directory. See -/// comment on `homedir`. -const char *os_get_homedir(void) -{ - if (!homedir) { - emsg("os_get_homedir failed: homedir not initialized"); - return NULL; - } - return homedir; -} - void init_homedir(void) { // In case we are called a second time. diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c index c4eb2803f6..8affc58591 100644 --- a/src/nvim/os/input.c +++ b/src/nvim/os/input.c @@ -514,7 +514,7 @@ static void process_ctrl_c(void) size_t available = input_available(); ssize_t i; - for (i = (ssize_t)available - 1; i >= 0; i--) { + for (i = (ssize_t)available - 1; i >= 0; i--) { // Reverse-search input for Ctrl_C. uint8_t c = (uint8_t)input_read_pos[i]; if (c == Ctrl_C || (c == 'C' && i >= 3 diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index a70f35e8e3..df68020d8e 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -145,10 +145,9 @@ describe('lua stdlib', function() -- "0.10" or "0.10-dev+xxx" local curstr = ('%s.%s%s'):format(curver.major, curver.minor, prerel or '') eq( - dedent( - [[ - foo.bar() is deprecated. Run ":checkhealth vim.deprecated" for more information]] - ):format(curstr), + ([[foo.bar() is deprecated. Run ":checkhealth vim.deprecated" for more information]]):format( + curstr + ), exec_lua('return vim.deprecate(...)', 'foo.bar()', 'zub.wooo{ok=yay}', curstr) ) -- Same message as above; skipped this time. @@ -178,8 +177,7 @@ describe('lua stdlib', function() it('plugin=nil, to be deleted in the next major version (1.0)', function() eq( - dedent [[ - foo.baz() is deprecated. Run ":checkhealth vim.deprecated" for more information]], + [[foo.baz() is deprecated. Run ":checkhealth vim.deprecated" for more information]], exec_lua [[ return vim.deprecate('foo.baz()', nil, '1.0') ]] ) end) diff --git a/test/functional/plugin/lsp/completion_spec.lua b/test/functional/plugin/lsp/completion_spec.lua index 16d64fc95d..d3796082fb 100644 --- a/test/functional/plugin/lsp/completion_spec.lua +++ b/test/functional/plugin/lsp/completion_spec.lua @@ -724,7 +724,7 @@ describe('vim.lsp.completion: protocol', function() end) end) - it('custom word/abbar format', function() + it('enable(…,{convert=fn}) custom word/abbr format', function() create_server({ isIncomplete = false, items = { |