From 56a4ef3c213d87bfba5f361376bd23eefdf6c6ec Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Fri, 11 Jul 2025 08:33:29 -0400 Subject: [PATCH 1/3] docs: lsp, ui events, dev guidance, osc7 fix #34981 --- runtime/doc/api-ui-events.txt | 6 +++ runtime/doc/api.txt | 3 ++ runtime/doc/develop.txt | 16 ++++++-- runtime/doc/editing.txt | 8 ++-- runtime/doc/help.txt | 1 - runtime/doc/lsp.txt | 60 ++++++++++++++++++---------- runtime/doc/lua.txt | 11 ++++- runtime/doc/news.txt | 9 ++--- runtime/doc/options.txt | 5 ++- runtime/doc/repeat.txt | 2 +- runtime/doc/terminal.txt | 42 +++++++++++-------- runtime/doc/testing.txt | 54 ------------------------- runtime/doc/treesitter.txt | 6 +-- runtime/doc/usr_41.txt | 2 +- runtime/doc/various.txt | 11 +++-- runtime/doc/vimeval.txt | 2 +- runtime/doc/vimfn.txt | 40 +++++++++---------- runtime/doc/windows.txt | 4 +- runtime/lua/vim/_core/server.lua | 15 +++---- runtime/lua/vim/_meta/api.lua | 4 ++ runtime/lua/vim/_meta/options.lua | 5 ++- runtime/lua/vim/_meta/vimfn.lua | 40 +++++++++---------- runtime/lua/vim/_system.lua | 4 ++ runtime/lua/vim/net.lua | 16 +++----- runtime/lua/vim/shared.lua | 2 +- runtime/lua/vim/treesitter/query.lua | 5 +-- scripts/vim-patch.sh | 2 +- src/nvim/api/vim.c | 6 ++- src/nvim/eval.lua | 40 +++++++++---------- src/nvim/globals.h | 14 +++---- src/nvim/options.lua | 5 ++- test/functional/core/server_spec.lua | 10 ++--- 32 files changed, 228 insertions(+), 222 deletions(-) delete mode 100644 runtime/doc/testing.txt diff --git a/runtime/doc/api-ui-events.txt b/runtime/doc/api-ui-events.txt index c221521af8..05c4bb181b 100644 --- a/runtime/doc/api-ui-events.txt +++ b/runtime/doc/api-ui-events.txt @@ -882,6 +882,12 @@ must handle. clearing the screen (messages sent by other "msg_" events below should not be affected). + Guidance: The "clear messages" behavior is UI-specific. If the UI + presents messages in a new window, it may choose to clear messages + after a few seconds. If the UI presents messages in a persistent area + (e.g. cmdline), it should clear messages at the start of the next + batch (typically, the next event-loop cycle). + ["msg_showmode", content] ~ Shows 'showmode' and |recording| messages. `content` has the same format as in "msg_show". This event is sent with empty `content` to diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 701e869379..7734cab633 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -1311,6 +1311,9 @@ nvim_replace_termcodes({str}, {from_part}, {do_lt}, {special}) Replaces terminal codes and |keycodes| (, , ...) in a string with the internal representation. + Note: ~ + • Lua can use |vim.keycode()| instead. + Attributes: ~ Since: 0.1.0 diff --git a/runtime/doc/develop.txt b/runtime/doc/develop.txt index 358c615261..a632a7a261 100644 --- a/runtime/doc/develop.txt +++ b/runtime/doc/develop.txt @@ -353,7 +353,7 @@ Where possible, these patterns apply to _both_ Lua and the API: - Examples: |vim.lsp.codelens.clear()| |vim.diagnostic.enable()| - 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). + for |continuation|s——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 @@ -426,9 +426,9 @@ Use existing common {verb} names (actions) if possible: - add: Appends or inserts into a collection - attach: Listens to something to get events from it (TODO: rename to "on"?) - call: Calls a function - - callback Continuation callback: a single function parameter (not - a field) that returns the result of an async function. Use - "on_…" for all other callbacks and event handlers. + - callback |continuation|: Function parameter (NOT a field) that + returns the result of an async function. Use the "on_…" + naming-convention for all other callbacks and event handlers. - cancel: Cancels or dismisses an event or interaction, typically user-initiated and without error. (Compare "abort", which cancels and signals error/failure.) @@ -499,6 +499,14 @@ Use this format to name API (RPC) events: > Example: > nvim_buf_changedtick_event < + *continuation* +A "continuation" is implemented as a callback function that returns the result +of an async function and is called exactly once. Often accepts `err` as the +first parameter, to avoid erroring on the main thread. Example: > + foo(…, callback: fun(err, …)) +Use the name `callback` only for a continuation. All other callbacks and event +handlers should be named with the |dev-name-events| "on_…" convention. + *dev-api-name* Use this format to name new RPC |API| functions: > nvim_{topic}_{verb}_{arbitrary-qualifiers} diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt index d02e82e415..3f9fc4e12a 100644 --- a/runtime/doc/editing.txt +++ b/runtime/doc/editing.txt @@ -1242,10 +1242,10 @@ MULTIPLE WINDOWS AND BUFFERS *window-exit* *:confirm* *:conf* :conf[irm] {command} Execute {command}, and use a dialog when an operation has to be confirmed. Can be used on the - |:edit|, |:q|, |:qa| and |:w| commands (the latter to - override a read-only setting), and any commands that - can fail because of unsaved changes, such as |:only|, - |:buffer|, |:bdelete|, etc. + |:edit|, |:restart|, |:q|, |:qa| and |:w| commands + (the latter to override a read-only setting), and any + commands that can fail because of unsaved changes, + such as |:only|, |:buffer|, |:bdelete|, etc. Examples: > :confirm w foo diff --git a/runtime/doc/help.txt b/runtime/doc/help.txt index 991b3d02c8..3ece28b672 100644 --- a/runtime/doc/help.txt +++ b/runtime/doc/help.txt @@ -112,7 +112,6 @@ API (EXTENSIBILITY/SCRIPTING/PLUGINS) |channel| Nvim asynchronous IO |vimscript| Vimscript reference |vimscript-functions| Vimscript functions -|testing.txt| Vimscript testing functions |remote-plugin| Nvim remote plugins |health| Health checking diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index 0414631204..f2af0330a9 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -28,26 +28,19 @@ Follow these steps to get LSP features: upstream installation instructions. You can find language servers here: https://microsoft.github.io/language-server-protocol/implementors/servers/ -2. Use |vim.lsp.config()| to define a configuration for an LSP client - (see https://github.com/neovim/nvim-lspconfig for examples). +2. Define a new config |lsp-new-config| (or install https://github.com/neovim/nvim-lspconfig). Example: >lua vim.lsp.config['luals'] = { -- Command and arguments to start the server. cmd = { 'lua-language-server' }, - -- Filetypes to automatically attach to. filetypes = { 'lua' }, - - -- Sets the "root directory" to the parent directory of the file in the - -- current buffer that contains either a ".luarc.json" or a - -- ".luarc.jsonc" file. Files that share a root directory will reuse - -- the connection to the same LSP server. + -- Sets the "workspace" to the directory where any of these files is found. + -- Files that share a root directory will reuse the LSP server connection. -- Nested lists indicate equal priority, see |vim.lsp.Config|. root_markers = { { '.luarc.json', '.luarc.jsonc' }, '.git' }, - - -- Specific settings to send to the server. The schema for this is - -- defined by the server. For example the schema for lua-language-server - -- can be found here https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json + -- Specific settings to send to the server. The schema is server-defined. + -- Example: https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json settings = { Lua = { runtime = { @@ -57,7 +50,7 @@ Follow these steps to get LSP features: } } -3. Use |vim.lsp.enable()| to enable a configuration. +3. Use |vim.lsp.enable()| to enable the config. Example: >lua vim.lsp.enable('luals') < @@ -130,21 +123,46 @@ CONFIG *lsp-config* You can configure LSP behavior statically via vim.lsp.config(), and dynamically via |lsp-attach| or |Client:on_attach()|. -Use |vim.lsp.config()| to define, and selectively enable, LSP configurations. -This is basically a wrapper around |vim.lsp.start()| which allows you to share -and merge configs (which may be provided by Nvim or third-party plugins). +Use |vim.lsp.config()| to define or modify LSP configurations, and +|vim.lsp.enable()| to auto-activate them. This is basically a wrapper around +|vim.lsp.start()| which allows you to share and merge configs (provided by +Nvim, plugins, and your local config). -When an LSP client starts, it resolves its configuration by merging from the -following (in increasing priority): + *lsp-new-config* +To create a new config you can either use `vim.lsp.config()` or create +a `lsp/.lua` file. + +EXAMPLE: DEFINE A CONFIG AS CODE ~ + +1. Run `:lua vim.lsp.config('foo', {cmd={'true'}})` +2. Run `:lua vim.lsp.enable('foo')` +3. Run `:checkhealth vim.lsp`, check "Enabled Configurations". 😎 + +EXAMPLE: DEFINE A CONFIG AS A FILE ~ + +1. Create a file `lsp/foo.lua` somewhere on your 'runtimepath'. > + :exe 'edit' stdpath('config') .. '/lsp/foo.lua' +2. Add this code to the file (or copy an example from + https://github.com/neovim/nvim-lspconfig): > + return { + cmd = { 'true' }, + } +3. Save the file (with `++p` to ensure its parent directory is created). > + :write ++p +4. Enable the config. > + :lua vim.lsp.enable('foo') +5. Run `:checkhealth vim.lsp`, check "Enabled Configurations". 🌈 + + *lsp-config-merge* +When an LSP client starts, it resolves its configuration by merging the +following sources (merge semantics defined by |vim.tbl_deep_extend()|), in +order of increasing priority: 1. Configuration defined for the `'*'` name. 2. Configuration from the result of merging all tables returned by `lsp/.lua` files in 'runtimepath' for a server of name `name`. 3. Configurations defined anywhere else. -Note: The merge semantics of configurations follow the behaviour of -|vim.tbl_deep_extend()|. - Example: given the following configs... >lua -- Defined in init.lua vim.lsp.config('*', { diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 2e5b25f89a..b8635b2e43 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -191,7 +191,7 @@ IMPORTING LUA MODULES *lua-module-load* Modules are searched for under the directories specified in 'runtimepath' and |packages-runtimepath|, in the order they appear in the output of this command >vim - :echo nvim_list_runtime_paths() + :echo nvim_list_runtime_paths() < Any "." in the module name is treated as a directory separator when searching. For a module `foo.bar`, each directory is searched for `lua/foo/bar.lua`, then @@ -230,6 +230,11 @@ Note: plugins using shell, which will not work with paths containing semicolons, it is better to not have them in 'runtimepath' at all. + *lua-script-location* +To get its own location, Lua scripts/modules can use |debug.getinfo()|: > + debug.getinfo(1, 'S').source:sub(2) +< + ============================================================================== COMMANDS *lua-commands* @@ -1784,6 +1789,10 @@ SystemObj:write({data}) *SystemObj:write()* vim.system({cmd}, {opts}, {on_exit}) *vim.system()* Runs a system command or throws an error if {cmd} cannot be run. + The command runs directly (not in 'shell') so shell builtins such as + "echo" in cmd.exe, cmdlets in powershell, or "help" in bash, will not work + unless you actually invoke a shell: `vim.system({'bash', '-c', 'help'})`. + Examples: >lua local on_exit = function(obj) print(obj.code) diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index a07682c97d..109a92c920 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -63,10 +63,7 @@ DIAGNOSTICS EDITOR -• |vim.secure.read()| now removes the choice "(a)llow" from the prompt reply for - files unlisted in the user's trust database, and thus requires the user to - choose (v)iew then run `:trust`. Previously the user would be able to press - the single key 'a' to execute the arbitrary execution immediately. +• todo EVENTS @@ -174,6 +171,8 @@ EDITOR commands. • 'wildchar' now enables completion in search contexts using |/|, |?|, |:g|, |:v| and |:vimgrep| commands. +• For security, 'exrc' no longer shows an "(a)llow" choice. Instead you must + "(v)iew" then run `:trust`. EVENTS @@ -277,7 +276,7 @@ TERMINAL TREESITTER -• todo +• |:EditQuery| command gained tab-completion, works with injected languages. TUI diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 9f4f8e7274..a7820fda6c 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -2566,7 +2566,8 @@ A jump table for the options with a short description can be found at |Q_op|. Unset 'exrc' to stop further searching of 'exrc' files in parent directories, similar to |editorconfig.root|. - To get its own location, Lua exrc files can use |debug.getinfo()|. + To get its own location, a Lua exrc file can use |debug.getinfo()|. + See |lua-script-location|. Compare 'exrc' to |editorconfig|: - 'exrc' can execute any code; editorconfig only specifies settings. @@ -2576,7 +2577,7 @@ A jump table for the options with a short description can be found at |Q_op|. 1. Enable 'exrc'. 2. Place LSP configs at ".nvim/lsp/*.lua" in your project root. 3. Create ".nvim.lua" in your project root directory with this line: >lua - vim.cmd[[set runtimepath+=.nvim]] + vim.cmd[[set runtimepath+=.nvim]] < This option cannot be set from a |modeline| or in the |sandbox|, for security reasons. diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt index fe6a8be443..5d2fd87865 100644 --- a/runtime/doc/repeat.txt +++ b/runtime/doc/repeat.txt @@ -191,7 +191,7 @@ Using Vim scripts *using-scripts* For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|. - *:so* *:source* *load-vim-script* + *:so* *:source* :so[urce] {file} Runs |Ex-commands| or Lua code (".lua" files) from {file}. Triggers the |SourcePre| autocommand. diff --git a/runtime/doc/terminal.txt b/runtime/doc/terminal.txt index a620091748..25ba08d579 100644 --- a/runtime/doc/terminal.txt +++ b/runtime/doc/terminal.txt @@ -138,35 +138,43 @@ exposes via the |TermRequest| event. OSC 7: change working directory *terminal-osc7* -To handle OSC 7 emitted from :terminal processes, this code will :cd to the -directory indicated in the request. >lua +Shells can emit the "OSC 7" sequence to announce when the current directory +(CWD) changed. + +You can configure your shell init (e.g. ~/.bashrc) to emit OSC 7, or your +terminal may attempt to do it for you. + +To configure bash to emit OSC 7: >bash + function print_osc7() { + printf '\033]7;file://%s\033\\' "$PWD" + } + PROMPT_COMMAND='print_osc7' + +Having ensured that your shell emits OSC 7, you can now handle it in Nvim. The +following code will run :lcd whenever your shell CWD changes in a :terminal +buffer: >lua vim.api.nvim_create_autocmd({ 'TermRequest' }, { desc = 'Handles OSC 7 dir change requests', callback = function(ev) - if string.sub(ev.data.sequence, 1, 4) == '\x1b]7;' then - local dir = string.gsub(ev.data.sequence, '\x1b]7;file://[^/]*', '') + local val, n = string.gsub(ev.data.sequence, '\027]7;file://[^/]*', '') + if n > 0 then + -- OSC 7: dir-change + local dir = val if vim.fn.isdirectory(dir) == 0 then vim.notify('invalid dir: '..dir) return end - vim.api.nvim_buf_set_var(ev.buf, 'osc7_dir', dir) - if vim.o.autochdir and vim.api.nvim_get_current_buf() == ev.buf then - vim.cmd.cd(dir) + vim.b[ev.buf].osc7_dir = dir + if vim.api.nvim_get_current_buf() == ev.buf then + vim.cmd.lcd(dir) end end end }) - vim.api.nvim_create_autocmd({ 'BufEnter', 'WinEnter', 'DirChanged' }, { - callback = function(ev) - if vim.b.osc7_dir and vim.fn.isdirectory(vim.b.osc7_dir) == 1 then - vim.cmd.cd(vim.b.osc7_dir) - end - end - }) -To try it out, select the above code and source it with `:'<,'>lua` (or -`g==`), then run this command in a :terminal buffer: > +To try it out, select the above code and source it with `:'<,'>lua`, then run +this command in a :terminal buffer: > printf "\033]7;file://./foo/bar\033\\" @@ -191,7 +199,7 @@ Shells can emit semantic escape sequences (OSC 133) to mark where each prompt starts and ends. The start of a prompt is marked by sequence `OSC 133 ; A ST`, and the end by `OSC 133 ; B ST`. -You can configure your shell "rc" (e.g. ~/.bashrc) to emit OSC 133 sequences, +You can configure your shell init (e.g. ~/.bashrc) to emit OSC 133 sequences, or your terminal may attempt to do it for you (assuming your shell config doesn't interfere). diff --git a/runtime/doc/testing.txt b/runtime/doc/testing.txt deleted file mode 100644 index 941c440b6c..0000000000 --- a/runtime/doc/testing.txt +++ /dev/null @@ -1,54 +0,0 @@ -*testing.txt* Nvim - - - VIM REFERENCE MANUAL by Bram Moolenaar - - -Testing Vim and Vim script *testing-support* - -Expression evaluation is explained in |eval.txt|. This file goes into details -about writing tests in Vim script. This can be used for testing Vim itself -and for testing plugins. - -1. Testing Vim |testing| -2. Test functions |test-functions-details| -3. Assert functions |assert-functions-details| - -============================================================================== -1. Testing Vim *testing* - -Vim can be tested after building it, usually with "make test". -The tests are located in the directory "src/testdir". - - *new-style-testing* -New tests should be added as new style tests. The test scripts are named -test_.vim (replace with the feature under test). These use -functions such as |assert_equal()| to keep the test commands and the expected -result in one place. - -Find more information in the file src/testdir/README.txt. - -============================================================================== -2. Test functions *test-functions-details* - -See |test_garbagecollect_now()|. - -============================================================================== -3. Assert functions *assert-functions-details* - -See: - - |assert_beeps()| - - |assert_equal()| - - |assert_equalfile()| - - |assert_exception()| - - |assert_fails()| - - |assert_false()| - - |assert_inrange()| - - |assert_match()| - - |assert_nobeep()| - - |assert_notequal()| - - |assert_notmatch()| - - |assert_report()| - - |assert_true()| - - vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index ba74a6c616..c029b4921e 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -1321,10 +1321,8 @@ add_predicate({name}, {handler}, {opts}) edit({lang}) *vim.treesitter.query.edit()* Opens a live editor to query the buffer you started from. - Can also be shown with `:EditQuery`. *:EditQuery* - - `:EditQuery ` completes the treesitter parser names in the runtime - path. + Can also be shown with the *:EditQuery* command. `:EditQuery ` + completes available parsers. If you move the cursor to a capture name ("@foo"), text matching the capture is highlighted in the source buffer. The query editor is a scratch diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index 0657b5fefe..cb0b8a1e1b 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -31,7 +31,7 @@ script. There are a lot of them, thus this is a long chapter. Table of contents: |usr_toc.txt| ============================================================================== -*41.1* Introduction *vim-script-intro* *script* +*41.1* Introduction *vimscript-intro* Your first experience with Vim scripts is the vimrc file. Vim reads it when it starts up and executes the commands. You can set options to values you diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt index 686c573403..95e1f7489c 100644 --- a/runtime/doc/various.txt +++ b/runtime/doc/various.txt @@ -248,10 +248,15 @@ gx Opens the current filepath or URL (decided by :sh[ell] Removed. |vim-differences| *:terminal* *:te* -:te[rminal][!] [{cmd}] Run {cmd} in a non-interactive 'shell' in a new - |terminal-emulator| buffer. Without {cmd}, start an +:te[rminal][!] [cmd] Run [cmd] in a non-interactive 'shell' in a new + |terminal-emulator| buffer. Without [cmd], start an interactive 'shell'. + By default the current window is used. To open in + a split window, use |:horizontal| or |:vertical|: > + :hor te + :vert te +< Type |i| to enter |Terminal-mode|, then keys are sent to the job running in the terminal. Type to leave Terminal-mode. |CTRL-\_CTRL-N|. Type @@ -260,7 +265,7 @@ gx Opens the current filepath or URL (decided by Fails if changes have been made to the current buffer, unless 'hidden' is set. - If {cmd} is omitted, and the 'shell' job exits with no + If [cmd] is omitted, and the 'shell' job exits with no error, the buffer is closed automatically |default-autocmds|. diff --git a/runtime/doc/vimeval.txt b/runtime/doc/vimeval.txt index 1815e439fd..70262a1e74 100644 --- a/runtime/doc/vimeval.txt +++ b/runtime/doc/vimeval.txt @@ -3774,7 +3774,7 @@ This is not allowed when the textlock is active: - etc. ============================================================================== -Vim script library *vim-script-library* +Vim script library *vimscript-library* Vim comes bundled with a Vim script library, that can be used by runtime, script authors. Currently, it only includes very few functions, but it may diff --git a/runtime/doc/vimfn.txt b/runtime/doc/vimfn.txt index 9cd2464f4e..754d1a7e94 100644 --- a/runtime/doc/vimfn.txt +++ b/runtime/doc/vimfn.txt @@ -2098,35 +2098,35 @@ expand({string} [, {nosuf} [, {list}]]) *expand()* done like for the |cmdline-special| variables with their associated modifiers. Here is a short overview: - % current file name - # alternate file name - #n alternate file name n - file name under the cursor - autocmd file name - autocmd buffer number (as a String!) - autocmd matched name + % Current file name + # Alternate file name + #n Alternate file name n + File name under the cursor + Autocmd file name + Autocmd buffer number (as a String!) + Autocmd matched name C expression under the cursor - deprecated, use