Merge #35000 docs: lsp, ui events, dev guidance

This commit is contained in:
Justin M. Keyes
2025-07-28 22:23:07 -04:00
committed by GitHub
39 changed files with 330 additions and 322 deletions

View File

@@ -882,6 +882,12 @@ must handle.
clearing the screen (messages sent by other "msg_" events below should clearing the screen (messages sent by other "msg_" events below should
not be affected). 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] ~ ["msg_showmode", content] ~
Shows 'showmode' and |recording| messages. `content` has the same Shows 'showmode' and |recording| messages. `content` has the same
format as in "msg_show". This event is sent with empty `content` to format as in "msg_show". This event is sent with empty `content` to

View File

@@ -1311,6 +1311,9 @@ nvim_replace_termcodes({str}, {from_part}, {do_lt}, {special})
Replaces terminal codes and |keycodes| (<CR>, <Esc>, ...) in a string with Replaces terminal codes and |keycodes| (<CR>, <Esc>, ...) in a string with
the internal representation. the internal representation.
Note: ~
• Lua can use |vim.keycode()| instead.
Attributes: ~ Attributes: ~
Since: 0.1.0 Since: 0.1.0

View File

@@ -353,7 +353,7 @@ Where possible, these patterns apply to _both_ Lua and the API:
- Examples: |vim.lsp.codelens.clear()| |vim.diagnostic.enable()| - Examples: |vim.lsp.codelens.clear()| |vim.diagnostic.enable()|
- Any function signature that accepts a callback (example: |table.foreach()|) - Any function signature that accepts a callback (example: |table.foreach()|)
should place it as the LAST parameter (after opts), if possible (or ALWAYS 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. - Improves readability by placing the less "noisy" arguments near the start.
- Consistent with luv. - Consistent with luv.
- Useful for future async lib which transforms functions of the form - 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 - add: Appends or inserts into a collection
- attach: Listens to something to get events from it (TODO: rename to "on"?) - attach: Listens to something to get events from it (TODO: rename to "on"?)
- call: Calls a function - call: Calls a function
- callback Continuation callback: a single function parameter (not - callback |continuation|: Function parameter (NOT a field) that
a field) that returns the result of an async function. Use returns the result of an async function. Use the "on_…"
"on_…" for all other callbacks and event handlers. naming-convention for all other callbacks and event handlers.
- cancel: Cancels or dismisses an event or interaction, typically - cancel: Cancels or dismisses an event or interaction, typically
user-initiated and without error. (Compare "abort", which user-initiated and without error. (Compare "abort", which
cancels and signals error/failure.) cancels and signals error/failure.)
@@ -499,6 +499,14 @@ Use this format to name API (RPC) events: >
Example: > Example: >
nvim_buf_changedtick_event 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* *dev-api-name*
Use this format to name new RPC |API| functions: > Use this format to name new RPC |API| functions: >
nvim_{topic}_{verb}_{arbitrary-qualifiers} nvim_{topic}_{verb}_{arbitrary-qualifiers}

View File

@@ -1242,10 +1242,10 @@ MULTIPLE WINDOWS AND BUFFERS *window-exit*
*:confirm* *:conf* *:confirm* *:conf*
:conf[irm] {command} Execute {command}, and use a dialog when an :conf[irm] {command} Execute {command}, and use a dialog when an
operation has to be confirmed. Can be used on the operation has to be confirmed. Can be used on the
|:edit|, |:q|, |:qa| and |:w| commands (the latter to |:edit|, |:restart|, |:q|, |:qa| and |:w| commands
override a read-only setting), and any commands that (the latter to override a read-only setting), and any
can fail because of unsaved changes, such as |:only|, commands that can fail because of unsaved changes,
|:buffer|, |:bdelete|, etc. such as |:only|, |:buffer|, |:bdelete|, etc.
Examples: > Examples: >
:confirm w foo :confirm w foo

View File

@@ -112,7 +112,6 @@ API (EXTENSIBILITY/SCRIPTING/PLUGINS)
|channel| Nvim asynchronous IO |channel| Nvim asynchronous IO
|vimscript| Vimscript reference |vimscript| Vimscript reference
|vimscript-functions| Vimscript functions |vimscript-functions| Vimscript functions
|testing.txt| Vimscript testing functions
|remote-plugin| Nvim remote plugins |remote-plugin| Nvim remote plugins
|health| Health checking |health| Health checking

View File

@@ -28,26 +28,19 @@ Follow these steps to get LSP features:
upstream installation instructions. You can find language servers here: upstream installation instructions. You can find language servers here:
https://microsoft.github.io/language-server-protocol/implementors/servers/ https://microsoft.github.io/language-server-protocol/implementors/servers/
2. Use |vim.lsp.config()| to define a configuration for an LSP client 2. Define a new config |lsp-new-config| (or install https://github.com/neovim/nvim-lspconfig).
(see https://github.com/neovim/nvim-lspconfig for examples).
Example: >lua Example: >lua
vim.lsp.config['luals'] = { vim.lsp.config['luals'] = {
-- Command and arguments to start the server. -- Command and arguments to start the server.
cmd = { 'lua-language-server' }, cmd = { 'lua-language-server' },
-- Filetypes to automatically attach to. -- Filetypes to automatically attach to.
filetypes = { 'lua' }, filetypes = { 'lua' },
-- Sets the "workspace" to the directory where any of these files is found.
-- Sets the "root directory" to the parent directory of the file in the -- Files that share a root directory will reuse the LSP server connection.
-- 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.
-- Nested lists indicate equal priority, see |vim.lsp.Config|. -- Nested lists indicate equal priority, see |vim.lsp.Config|.
root_markers = { { '.luarc.json', '.luarc.jsonc' }, '.git' }, root_markers = { { '.luarc.json', '.luarc.jsonc' }, '.git' },
-- Specific settings to send to the server. The schema is server-defined.
-- Specific settings to send to the server. The schema for this is -- Example: https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json
-- 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
settings = { settings = {
Lua = { Lua = {
runtime = { 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 Example: >lua
vim.lsp.enable('luals') vim.lsp.enable('luals')
< <
@@ -130,21 +123,46 @@ CONFIG *lsp-config*
You can configure LSP behavior statically via vim.lsp.config(), and You can configure LSP behavior statically via vim.lsp.config(), and
dynamically via |lsp-attach| or |Client:on_attach()|. dynamically via |lsp-attach| or |Client:on_attach()|.
Use |vim.lsp.config()| to define, and selectively enable, LSP configurations. Use |vim.lsp.config()| to define or modify LSP configurations, and
This is basically a wrapper around |vim.lsp.start()| which allows you to share |vim.lsp.enable()| to auto-activate them. This is basically a wrapper around
and merge configs (which may be provided by Nvim or third-party plugins). |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 *lsp-new-config*
following (in increasing priority): To create a new config you can either use `vim.lsp.config()` or create
a `lsp/<config-name>.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. 1. Configuration defined for the `'*'` name.
2. Configuration from the result of merging all tables returned by 2. Configuration from the result of merging all tables returned by
`lsp/<name>.lua` files in 'runtimepath' for a server of name `name`. `lsp/<name>.lua` files in 'runtimepath' for a server of name `name`.
3. Configurations defined anywhere else. 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 Example: given the following configs... >lua
-- Defined in init.lua -- Defined in init.lua
vim.lsp.config('*', { vim.lsp.config('*', {

View File

@@ -230,6 +230,11 @@ Note:
plugins using shell, which will not work with paths containing semicolons, plugins using shell, which will not work with paths containing semicolons,
it is better to not have them in 'runtimepath' at all. 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* COMMANDS *lua-commands*
@@ -1784,6 +1789,10 @@ SystemObj:write({data}) *SystemObj:write()*
vim.system({cmd}, {opts}, {on_exit}) *vim.system()* vim.system({cmd}, {opts}, {on_exit}) *vim.system()*
Runs a system command or throws an error if {cmd} cannot be run. 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 Examples: >lua
local on_exit = function(obj) local on_exit = function(obj)
print(obj.code) print(obj.code)

View File

@@ -63,10 +63,7 @@ DIAGNOSTICS
EDITOR EDITOR
|vim.secure.read()| now removes the choice "(a)llow" from the prompt reply for todo
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.
EVENTS EVENTS
@@ -174,6 +171,8 @@ EDITOR
commands. commands.
• 'wildchar' now enables completion in search contexts using |/|, |?|, |:g|, |:v| • 'wildchar' now enables completion in search contexts using |/|, |?|, |:g|, |:v|
and |:vimgrep| commands. and |:vimgrep| commands.
• For security, 'exrc' no longer shows an "(a)llow" choice. Instead you must
"(v)iew" then run `:trust`.
EVENTS EVENTS
@@ -277,7 +276,7 @@ TERMINAL
TREESITTER TREESITTER
todo |:EditQuery| command gained tab-completion, works with injected languages.
TUI TUI

View File

@@ -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 Unset 'exrc' to stop further searching of 'exrc' files in parent
directories, similar to |editorconfig.root|. 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|: Compare 'exrc' to |editorconfig|:
- 'exrc' can execute any code; editorconfig only specifies settings. - 'exrc' can execute any code; editorconfig only specifies settings.

View File

@@ -22,8 +22,8 @@ plugins, a package can...
*runtime-search-path* *runtime-search-path*
Nvim searches for |:runtime| files in: Nvim searches for |:runtime| files in:
1. all paths in 'runtimepath' - 1. all paths in 'runtimepath'
2. all "pack/*/start/*" dirs - 2. all "pack/*/start/*" dirs
Note that the "pack/*/start/*" paths are not explicitly included in Note that the "pack/*/start/*" paths are not explicitly included in
'runtimepath', so they will not be reported by ":set rtp" or "echo &rtp". 'runtimepath', so they will not be reported by ":set rtp" or "echo &rtp".
@@ -43,7 +43,7 @@ add a package from a zip archive "/tmp/foopack.zip": >
The directory name "foo" is arbitrary, you can pick anything you like. The directory name "foo" is arbitrary, you can pick anything you like.
You would now have these files under ~/.local/share/nvim/site: You would now have these files under ~/.local/share/nvim/site: >
pack/foo/README.txt pack/foo/README.txt
pack/foo/start/foobar/plugin/foo.vim pack/foo/start/foobar/plugin/foo.vim
pack/foo/start/foobar/syntax/some.vim pack/foo/start/foobar/syntax/some.vim
@@ -90,7 +90,7 @@ directory level: >
% cd ~/.local/share/nvim/site/pack/foo/start/foobar % cd ~/.local/share/nvim/site/pack/foo/start/foobar
% unzip /tmp/someplugin.zip % unzip /tmp/someplugin.zip
You would now have these files: You would now have these files: >
pack/foo/start/foobar/plugin/foo.vim pack/foo/start/foobar/plugin/foo.vim
pack/foo/start/foobar/syntax/some.vim pack/foo/start/foobar/syntax/some.vim
@@ -154,7 +154,7 @@ bit harder to update to a new version. A repository can usually be kept
up-to-date easily, but it requires a program like "git" to be available. up-to-date easily, but it requires a program like "git" to be available.
You can do both, github can automatically create an archive for a release. You can do both, github can automatically create an archive for a release.
Your directory layout would be like this: Your directory layout would be like this: >
start/foobar/plugin/foo.vim " always loaded, defines commands start/foobar/plugin/foo.vim " always loaded, defines commands
start/foobar/plugin/bar.vim " always loaded, defines commands start/foobar/plugin/bar.vim " always loaded, defines commands
start/foobar/autoload/foo.vim " loaded when foo command used start/foobar/autoload/foo.vim " loaded when foo command used
@@ -164,7 +164,7 @@ Your directory layout would be like this:
opt/fooextra/autoload/extra.vim " loaded when extra command used opt/fooextra/autoload/extra.vim " loaded when extra command used
opt/fooextra/doc/extra.txt " help for extra.vim opt/fooextra/doc/extra.txt " help for extra.vim
opt/fooextra/doc/tags " help tags opt/fooextra/doc/tags " help tags
<
This allows for the user to do: > This allows for the user to do: >
mkdir ~/.local/share/nvim/site/pack mkdir ~/.local/share/nvim/site/pack
cd ~/.local/share/nvim/site/pack cd ~/.local/share/nvim/site/pack
@@ -194,11 +194,11 @@ Suppose you have two plugins that depend on the same functionality. You can
put the common functionality in an autoload directory, so that it will be put the common functionality in an autoload directory, so that it will be
found automatically. Your package would have these files: found automatically. Your package would have these files:
pack/foo/start/one/plugin/one.vim > pack/foo/start/one/plugin/one.vim >
call foolib#getit() call foolib#getit()
< pack/foo/start/two/plugin/two.vim > pack/foo/start/two/plugin/two.vim >
call foolib#getit() call foolib#getit()
< pack/foo/start/lib/autoload/foolib.vim > pack/foo/start/lib/autoload/foolib.vim >
func foolib#getit() func foolib#getit()
This works, because start packages will be searched for autoload files, when This works, because start packages will be searched for autoload files, when

View File

@@ -191,7 +191,7 @@ Using Vim scripts *using-scripts*
For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|. 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 :so[urce] {file} Runs |Ex-commands| or Lua code (".lua" files) from
{file}. {file}.
Triggers the |SourcePre| autocommand. Triggers the |SourcePre| autocommand.

View File

@@ -138,35 +138,43 @@ exposes via the |TermRequest| event.
OSC 7: change working directory *terminal-osc7* OSC 7: change working directory *terminal-osc7*
To handle OSC 7 emitted from :terminal processes, this code will :cd to the Shells can emit the "OSC 7" sequence to announce when the current directory
directory indicated in the request. >lua (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' }, { vim.api.nvim_create_autocmd({ 'TermRequest' }, {
desc = 'Handles OSC 7 dir change requests', desc = 'Handles OSC 7 dir change requests',
callback = function(ev) callback = function(ev)
if string.sub(ev.data.sequence, 1, 4) == '\x1b]7;' then local val, n = string.gsub(ev.data.sequence, '\027]7;file://[^/]*', '')
local dir = string.gsub(ev.data.sequence, '\x1b]7;file://[^/]*', '') if n > 0 then
-- OSC 7: dir-change
local dir = val
if vim.fn.isdirectory(dir) == 0 then if vim.fn.isdirectory(dir) == 0 then
vim.notify('invalid dir: '..dir) vim.notify('invalid dir: '..dir)
return return
end end
vim.api.nvim_buf_set_var(ev.buf, 'osc7_dir', dir) vim.b[ev.buf].osc7_dir = dir
if vim.o.autochdir and vim.api.nvim_get_current_buf() == ev.buf then if vim.api.nvim_get_current_buf() == ev.buf then
vim.cmd.cd(dir) vim.cmd.lcd(dir)
end end
end 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 To try it out, select the above code and source it with `:'<,'>lua`, then run
`g==`), then run this command in a :terminal buffer: > this command in a :terminal buffer: >
printf "\033]7;file://./foo/bar\033\\" 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`, starts and ends. The start of a prompt is marked by sequence `OSC 133 ; A ST`,
and the end by `OSC 133 ; B 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 or your terminal may attempt to do it for you (assuming your shell config
doesn't interfere). doesn't interfere).

View File

@@ -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_<feature>.vim (replace <feature> 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:

View File

@@ -1321,10 +1321,8 @@ add_predicate({name}, {handler}, {opts})
edit({lang}) *vim.treesitter.query.edit()* edit({lang}) *vim.treesitter.query.edit()*
Opens a live editor to query the buffer you started from. Opens a live editor to query the buffer you started from.
Can also be shown with `:EditQuery`. *:EditQuery* Can also be shown with the *:EditQuery* command. `:EditQuery <tab>`
completes available parsers.
`:EditQuery <tab>` completes the treesitter parser names in the runtime
path.
If you move the cursor to a capture name ("@foo"), text matching the 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 capture is highlighted in the source buffer. The query editor is a scratch

View File

@@ -31,7 +31,7 @@ script. There are a lot of them, thus this is a long chapter.
Table of contents: |usr_toc.txt| 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 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 it starts up and executes the commands. You can set options to values you

View File

@@ -248,10 +248,15 @@ gx Opens the current filepath or URL (decided by
:sh[ell] Removed. |vim-differences| :sh[ell] Removed. |vim-differences|
*:terminal* *:te* *:terminal* *:te*
:te[rminal][!] [{cmd}] Run {cmd} in a non-interactive 'shell' in a new :te[rminal][!] [cmd] Run [cmd] in a non-interactive 'shell' in a new
|terminal-emulator| buffer. Without {cmd}, start an |terminal-emulator| buffer. Without [cmd], start an
interactive 'shell'. 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 Type |i| to enter |Terminal-mode|, then keys are sent to
the job running in the terminal. Type <C-\><C-N> to the job running in the terminal. Type <C-\><C-N> to
leave Terminal-mode. |CTRL-\_CTRL-N|. Type <C-\><C-O> leave Terminal-mode. |CTRL-\_CTRL-N|. Type <C-\><C-O>
@@ -260,7 +265,7 @@ gx Opens the current filepath or URL (decided by
Fails if changes have been made to the current buffer, Fails if changes have been made to the current buffer,
unless 'hidden' is set. 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 error, the buffer is closed automatically
|default-autocmds|. |default-autocmds|.

View File

@@ -3774,7 +3774,7 @@ This is not allowed when the textlock is active:
- etc. - 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, 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 script authors. Currently, it only includes very few functions, but it may

View File

@@ -2098,35 +2098,35 @@ expand({string} [, {nosuf} [, {list}]]) *expand()*
done like for the |cmdline-special| variables with their done like for the |cmdline-special| variables with their
associated modifiers. Here is a short overview: associated modifiers. Here is a short overview:
% current file name % Current file name
# alternate file name # Alternate file name
#n alternate file name n #n Alternate file name n
<cfile> file name under the cursor <cfile> File name under the cursor
<afile> autocmd file name <afile> Autocmd file name
<abuf> autocmd buffer number (as a String!) <abuf> Autocmd buffer number (as a String!)
<amatch> autocmd matched name <amatch> Autocmd matched name
<cexpr> C expression under the cursor <cexpr> C expression under the cursor
<sfile> deprecated, use <script> or <stack> <sfile> Deprecated, use <script> or <stack>
<slnum> sourced script line number or function <slnum> Sourced script line number or function
line number line number
<sflnum> script file line number, also when in <sflnum> Script file line number, also when in
a function a function
<SID> "<SNR>123_" where "123" is the <SID> "<SNR>123_" where "123" is the
current script ID |<SID>| current script ID |<SID>|
<script> sourced script file, or script file <script> Sourced script file, or script file
where the current function was defined. where the current function was defined.
Use |debug.getinfo()| in Lua scripts. For Lua see |lua-script-location|.
<stack> call stack <stack> Call stack
<cword> word under the cursor <cword> Word under the cursor
<cWORD> WORD under the cursor <cWORD> WORD under the cursor
<client> the {clientid} of the last received <client> The {clientid} of the last received
message message
Modifiers: Modifiers:
:p expand to full path :p Expand to full path
:h head (last path component removed) :h Head (last path component removed)
:t tail (last path component only) :t Tail (last path component only)
:r root (one extension removed) :r Root (one extension removed)
:e extension only :e Extension only
Example: >vim Example: >vim
let &tags = expand("%:p:h") .. "/tags" let &tags = expand("%:p:h") .. "/tags"

View File

@@ -257,8 +257,8 @@ and 'winminwidth' are relevant.
*:hor* *:horizontal* *:hor* *:horizontal*
:hor[izontal] {cmd} :hor[izontal] {cmd}
Execute {cmd}. Currently only makes a difference for Execute {cmd} in a horizontal split window. Supports these
the following commands: commands:
- `:wincmd =`: equalize windows only horizontally. - `:wincmd =`: equalize windows only horizontally.
- |:terminal|: open a |terminal| buffer in a split window. - |:terminal|: open a |terminal| buffer in a split window.
- |:checkhealth|: open a healthcheck buffer in a split window. - |:checkhealth|: open a healthcheck buffer in a split window.

View File

@@ -1,17 +1,18 @@
local M = {} local M = {}
--- Called by builtin serverlist(). Returns all running servers. --- Called by builtin serverlist(). Returns all running servers in stdpath("run").
--- in stdpath("run"). Does not include named pipes or TCP servers. ---
--- - TODO: track TCP servers, somehow.
--- - TODO: support Windows named pipes.
--- ---
--- @param listed string[] Already listed servers --- @param listed string[] Already listed servers
--- @return string[] A list of currently running servers in stdpath("run") --- @return string[] # List of servers found on the current machine in stdpath("run").
function M.serverlist(listed) function M.serverlist(listed)
-- TODO: also get named pipes on Windows
local socket_paths = vim.fs.find(function(name, _) local socket_paths = vim.fs.find(function(name, _)
return name:match('nvim.*') return name:match('nvim.*')
end, { path = vim.fn.stdpath('run'), type = 'socket', limit = math.huge }) end, { path = vim.fn.stdpath('run'), type = 'socket', limit = math.huge })
local running_sockets = {} local found = {} ---@type string[]
for _, socket in ipairs(socket_paths) do for _, socket in ipairs(socket_paths) do
-- Don't list servers twice -- Don't list servers twice
if not vim.list_contains(listed, socket) then if not vim.list_contains(listed, socket) then
@@ -20,14 +21,14 @@ function M.serverlist(listed)
-- Check that the server is responding -- Check that the server is responding
-- TODO: do we need a timeout or error handling here? -- TODO: do we need a timeout or error handling here?
if vim.fn.rpcrequest(chan, 'nvim_get_chan_info', 0).id then if vim.fn.rpcrequest(chan, 'nvim_get_chan_info', 0).id then
table.insert(running_sockets, socket) table.insert(found, socket)
end end
vim.fn.chanclose(chan) vim.fn.chanclose(chan)
end end
end end
end end
return running_sockets return found
end end
return M return M

View File

@@ -2045,6 +2045,10 @@ function vim.api.nvim_put(lines, type, after, follow) end
--- Replaces terminal codes and `keycodes` ([<CR>], [<Esc>], ...) in a string with --- Replaces terminal codes and `keycodes` ([<CR>], [<Esc>], ...) in a string with
--- the internal representation. --- the internal representation.
--- ---
---
--- Note:
--- Lua can use |vim.keycode()| instead.
---
--- @see replace_termcodes --- @see replace_termcodes
--- @see cpoptions --- @see cpoptions
--- @param str string String to be converted. --- @param str string String to be converted.

View File

@@ -2239,7 +2239,8 @@ vim.bo.et = vim.bo.expandtab
--- Unset 'exrc' to stop further searching of 'exrc' files in parent --- Unset 'exrc' to stop further searching of 'exrc' files in parent
--- directories, similar to `editorconfig.root`. --- 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`: --- Compare 'exrc' to `editorconfig`:
--- - 'exrc' can execute any code; editorconfig only specifies settings. --- - 'exrc' can execute any code; editorconfig only specifies settings.

View File

@@ -1855,35 +1855,35 @@ function vim.fn.exp(expr) end
--- done like for the |cmdline-special| variables with their --- done like for the |cmdline-special| variables with their
--- associated modifiers. Here is a short overview: --- associated modifiers. Here is a short overview:
--- ---
--- % current file name --- % Current file name
--- # alternate file name --- # Alternate file name
--- #n alternate file name n --- #n Alternate file name n
--- <cfile> file name under the cursor --- <cfile> File name under the cursor
--- <afile> autocmd file name --- <afile> Autocmd file name
--- <abuf> autocmd buffer number (as a String!) --- <abuf> Autocmd buffer number (as a String!)
--- <amatch> autocmd matched name --- <amatch> Autocmd matched name
--- <cexpr> C expression under the cursor --- <cexpr> C expression under the cursor
--- <sfile> deprecated, use <script> or <stack> --- <sfile> Deprecated, use <script> or <stack>
--- <slnum> sourced script line number or function --- <slnum> Sourced script line number or function
--- line number --- line number
--- <sflnum> script file line number, also when in --- <sflnum> Script file line number, also when in
--- a function --- a function
--- <SID> "<SNR>123_" where "123" is the --- <SID> "<SNR>123_" where "123" is the
--- current script ID |<SID>| --- current script ID |<SID>|
--- <script> sourced script file, or script file --- <script> Sourced script file, or script file
--- where the current function was defined. --- where the current function was defined.
--- Use |debug.getinfo()| in Lua scripts. --- For Lua see |lua-script-location|.
--- <stack> call stack --- <stack> Call stack
--- <cword> word under the cursor --- <cword> Word under the cursor
--- <cWORD> WORD under the cursor --- <cWORD> WORD under the cursor
--- <client> the {clientid} of the last received --- <client> The {clientid} of the last received
--- message --- message
--- Modifiers: --- Modifiers:
--- :p expand to full path --- :p Expand to full path
--- :h head (last path component removed) --- :h Head (last path component removed)
--- :t tail (last path component only) --- :t Tail (last path component only)
--- :r root (one extension removed) --- :r Root (one extension removed)
--- :e extension only --- :e Extension only
--- ---
--- Example: >vim --- Example: >vim
--- let &tags = expand("%:p:h") .. "/tags" --- let &tags = expand("%:p:h") .. "/tags"

View File

@@ -471,6 +471,10 @@ end
--- Runs a system command or throws an error if {cmd} cannot be run. --- 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: --- Examples:
--- ---
--- ```lua --- ```lua

View File

@@ -40,17 +40,11 @@ function M.request(url, opts, on_response)
table.insert(args, url) table.insert(args, url)
local function on_exit(res) local function on_exit(res)
local err_msg = nil local s = 'Request failed with exit code %d'
local response = nil local err_msg = res.code ~= 0
and ((res.stderr ~= '' and res.stderr) or string.format(s, res.code))
if res.code ~= 0 then or nil
err_msg = (res.stderr ~= '' and res.stderr) local response = res.code == 0 and { body = opts.outpath and true or res.stdout } or nil
or string.format('Request failed with exit code %d', res.code)
else
response = {
body = opts.outpath and true or res.stdout,
}
end
if on_response then if on_response then
on_response(err_msg, response) on_response(err_msg, response)

View File

@@ -121,16 +121,20 @@ function M.read(path)
return contents return contents
end end
local dir_msg = ' To enable it, choose (v)iew then run `:trust`.' local msg2 = ' To enable it, choose (v)iew then run `:trust`:'
local choices = '&ignore\n&view\n&deny' local choices = '&ignore\n&view\n&deny'
if hash == 'directory' then if hash == 'directory' then
dir_msg = ' DIRECTORY trust is decided only by its name, not its contents.' msg2 = ' DIRECTORY trust is decided only by name, not contents:'
choices = '&ignore\n&view\n&deny\n&allow' choices = '&ignore\n&view\n&deny\n&allow'
end end
-- File either does not exist in trust database or the hash does not match -- File either does not exist in trust database or the hash does not match
local ok, result = local ok, result = pcall(
pcall(vim.fn.confirm, string.format('%s is not trusted.%s', fullpath, dir_msg), choices, 1) vim.fn.confirm,
string.format('exrc: Found untrusted code.%s\n%s', msg2, fullpath),
choices,
1
)
if not ok and result ~= 'Keyboard interrupt' then if not ok and result ~= 'Keyboard interrupt' then
error(result) error(result)

View File

@@ -1104,7 +1104,7 @@ do
err_msg = is_valid(name, value, validator, msg, false) err_msg = is_valid(name, value, validator, msg, false)
end end
elseif type(name) == 'table' then -- Form 2 elseif type(name) == 'table' then -- Form 2
vim.deprecate('vim.validate', 'vim.validate(name, value, validator, optional_or_msg)', '1.0') vim.deprecate('vim.validate{<table>}', 'vim.validate(<params>)', '1.0')
err_msg = validate_spec(name) err_msg = validate_spec(name)
else else
error('invalid arguments') error('invalid arguments')

View File

@@ -1163,9 +1163,8 @@ end
--- Opens a live editor to query the buffer you started from. --- Opens a live editor to query the buffer you started from.
--- ---
--- Can also be shown with `:EditQuery`. [:EditQuery]() --- Can also be shown with the [:EditQuery]() command. `:EditQuery <tab>` completes available
--- --- parsers.
--- `:EditQuery <tab>` completes the treesitter parser names in the runtime path.
--- ---
--- If you move the cursor to a capture name ("@foo"), text matching the capture is highlighted in --- 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 buffer, use `:write` to save it. You can find --- the source buffer. The query editor is a scratch buffer, use `:write` to save it. You can find

View File

@@ -207,7 +207,7 @@ preprocess_patch() {
2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/\<\%('"${na_rt}"'\)\>@exe "norm! d/\\v(^diff)|%$\r"' +w +q "$file" 2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/\<\%('"${na_rt}"'\)\>@exe "norm! d/\\v(^diff)|%$\r"' +w +q "$file"
# Remove unwanted Vim doc files. # Remove unwanted Vim doc files.
local na_doc='channel\.txt\|if_cscop\.txt\|netbeans\.txt\|os_\w\+\.txt\|print\.txt\|term\.txt\|todo\.txt\|vim9\.txt\|tags' local na_doc='channel\.txt\|if_cscop\.txt\|netbeans\.txt\|os_\w\+\.txt\|print\.txt\|term\.txt\|testing\.txt\|todo\.txt\|vim9\.txt\|tags'
2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/doc/\<\%('"${na_doc}"'\)\>@exe "norm! d/\\v(^diff)|%$\r"' +w +q "$file" 2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/doc/\<\%('"${na_doc}"'\)\>@exe "norm! d/\\v(^diff)|%$\r"' +w +q "$file"
# Remove "Last change ..." changes in doc files. # Remove "Last change ..." changes in doc files.

View File

@@ -79,6 +79,7 @@ local new_layout = {
['news-0.10.txt'] = true, ['news-0.10.txt'] = true,
['news-0.11.txt'] = true, ['news-0.11.txt'] = true,
['nvim.txt'] = true, ['nvim.txt'] = true,
['pack.txt'] = true,
['provider.txt'] = true, ['provider.txt'] = true,
['tui.txt'] = true, ['tui.txt'] = true,
['ui.txt'] = true, ['ui.txt'] = true,

View File

@@ -466,12 +466,14 @@ error:
/// Replaces terminal codes and |keycodes| ([<CR>], [<Esc>], ...) in a string with /// Replaces terminal codes and |keycodes| ([<CR>], [<Esc>], ...) in a string with
/// the internal representation. /// the internal representation.
/// ///
/// @note Lua can use |vim.keycode()| instead.
/// @see replace_termcodes
/// @see cpoptions
///
/// @param str String to be converted. /// @param str String to be converted.
/// @param from_part Legacy Vim parameter. Usually true. /// @param from_part Legacy Vim parameter. Usually true.
/// @param do_lt Also translate [<lt>]. Ignored if `special` is false. /// @param do_lt Also translate [<lt>]. Ignored if `special` is false.
/// @param special Replace |keycodes|, e.g. [<CR>] becomes a "\r" char. /// @param special Replace |keycodes|, e.g. [<CR>] becomes a "\r" char.
/// @see replace_termcodes
/// @see cpoptions
String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, Boolean special) String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, Boolean special)
FUNC_API_SINCE(1) FUNC_API_RET_ALLOC FUNC_API_SINCE(1) FUNC_API_RET_ALLOC
{ {

View File

@@ -2405,35 +2405,35 @@ M.funcs = {
done like for the |cmdline-special| variables with their done like for the |cmdline-special| variables with their
associated modifiers. Here is a short overview: associated modifiers. Here is a short overview:
% current file name % Current file name
# alternate file name # Alternate file name
#n alternate file name n #n Alternate file name n
<cfile> file name under the cursor <cfile> File name under the cursor
<afile> autocmd file name <afile> Autocmd file name
<abuf> autocmd buffer number (as a String!) <abuf> Autocmd buffer number (as a String!)
<amatch> autocmd matched name <amatch> Autocmd matched name
<cexpr> C expression under the cursor <cexpr> C expression under the cursor
<sfile> deprecated, use <script> or <stack> <sfile> Deprecated, use <script> or <stack>
<slnum> sourced script line number or function <slnum> Sourced script line number or function
line number line number
<sflnum> script file line number, also when in <sflnum> Script file line number, also when in
a function a function
<SID> "<SNR>123_" where "123" is the <SID> "<SNR>123_" where "123" is the
current script ID |<SID>| current script ID |<SID>|
<script> sourced script file, or script file <script> Sourced script file, or script file
where the current function was defined. where the current function was defined.
Use |debug.getinfo()| in Lua scripts. For Lua see |lua-script-location|.
<stack> call stack <stack> Call stack
<cword> word under the cursor <cword> Word under the cursor
<cWORD> WORD under the cursor <cWORD> WORD under the cursor
<client> the {clientid} of the last received <client> The {clientid} of the last received
message message
Modifiers: Modifiers:
:p expand to full path :p Expand to full path
:h head (last path component removed) :h Head (last path component removed)
:t tail (last path component only) :t Tail (last path component only)
:r root (one extension removed) :r Root (one extension removed)
:e extension only :e Extension only
Example: >vim Example: >vim
let &tags = expand("%:p:h") .. "/tags" let &tags = expand("%:p:h") .. "/tags"

View File

@@ -421,20 +421,20 @@ EXTERN int sc_col; // column for shown command
// First NO_SCREEN, then NO_BUFFERS, then 0 when startup finished. // First NO_SCREEN, then NO_BUFFERS, then 0 when startup finished.
EXTERN int starting INIT( = NO_SCREEN); EXTERN int starting INIT( = NO_SCREEN);
// true when planning to exit. Might keep running if there is a changed buffer. // Planning to exit. Might keep running if there is a changed buffer.
EXTERN bool exiting INIT( = false); EXTERN bool exiting INIT( = false);
// true when planning to restart. // Planning to restart.
EXTERN bool restarting INIT( = false); EXTERN bool restarting INIT( = false);
// internal value of v:dying // Internal value of v:dying
EXTERN int v_dying INIT( = 0); EXTERN int v_dying INIT( = 0);
// is stdin a terminal? // Is stdin a terminal?
EXTERN bool stdin_isatty INIT( = true); EXTERN bool stdin_isatty INIT( = true);
// is stdout a terminal? // Is stdout a terminal?
EXTERN bool stdout_isatty INIT( = true); EXTERN bool stdout_isatty INIT( = true);
// is stderr a terminal? // Is stderr a terminal?
EXTERN bool stderr_isatty INIT( = true); EXTERN bool stderr_isatty INIT( = true);
/// filedesc set by embedder for reading first buffer like `cmd | nvim -` /// Filedesc set by embedder for reading first buffer like `cmd | nvim -`.
EXTERN int stdin_fd INIT( = -1); EXTERN int stdin_fd INIT( = -1);
// true when doing full-screen output, otherwise only writing some messages. // true when doing full-screen output, otherwise only writing some messages.

View File

@@ -78,11 +78,11 @@ static bool nlua_trust(const char *action, const char *path)
if (msg != NULL) { if (msg != NULL) {
if (success) { if (success) {
if (strcmp(action, "allow") == 0) { if (strcmp(action, "allow") == 0) {
smsg(0, "Allowed \"%s\" in trust database.", msg); smsg(0, "Allowed in trust database: \"%s\"", msg);
} else if (strcmp(action, "deny") == 0) { } else if (strcmp(action, "deny") == 0) {
smsg(0, "Denied \"%s\" in trust database.", msg); smsg(0, "Denied in trust database: \"%s\"", msg);
} else if (strcmp(action, "remove") == 0) { } else if (strcmp(action, "remove") == 0) {
smsg(0, "Removed \"%s\" from trust database.", msg); smsg(0, "Removed from trust database: \"%s\"", msg);
} }
} else { } else {
semsg(e_trustfile, msg); semsg(e_trustfile, msg);

View File

@@ -2847,7 +2847,8 @@ local options = {
Unset 'exrc' to stop further searching of 'exrc' files in parent Unset 'exrc' to stop further searching of 'exrc' files in parent
directories, similar to |editorconfig.root|. 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|: Compare 'exrc' to |editorconfig|:
- 'exrc' can execute any code; editorconfig only specifies settings. - 'exrc' can execute any code; editorconfig only specifies settings.

View File

@@ -187,22 +187,20 @@ describe('server', function()
-- After serverstop() the servers should NOT be in the list. -- After serverstop() the servers should NOT be in the list.
eq(_n, eval('len(serverlist())')) eq(_n, eval('len(serverlist())'))
-- serverlist({ peer = true }) returns servers from other Nvim sessions. -- serverlist({peer=true}) returns servers from other Nvim sessions.
if t.is_os('win') then if t.is_os('win') then
return return
end end
local client_address = n.new_pipename() local peer_addr = n.new_pipename()
local client = n.new_session( local client =
true, n.new_session(true, { args = { '--clean', '--listen', peer_addr, '--embed' }, merge = false })
{ args = { '-u', 'NONE', '--listen', client_address, '--embed' }, merge = false }
)
n.set_session(client) n.set_session(client)
eq(client_address, fn.serverlist()[1]) eq(peer_addr, fn.serverlist()[1])
n.set_session(current_server) n.set_session(current_server)
new_servs = fn.serverlist({ peer = true }) new_servs = fn.serverlist({ peer = true })
eq(true, vim.list_contains(new_servs, client_address)) eq(true, vim.list_contains(new_servs, peer_addr))
client:close() client:close()
end) end)
end) end)

View File

@@ -1262,11 +1262,11 @@ describe('user config init', function()
-- trust .exrc -- trust .exrc
feed(':trust<CR>') feed(':trust<CR>')
screen:expect({ any = 'Allowed ".*' .. pathsep .. '%.exrc" in trust database.' }) screen:expect({ any = 'Allowed in trust database: ".*' .. pathsep .. '%.exrc"' })
feed(':q<CR>') feed(':q<CR>')
-- trust .nvim.lua -- trust .nvim.lua
feed(':trust<CR>') feed(':trust<CR>')
screen:expect({ any = 'Allowed ".*' .. pathsep .. '%.nvim%.lua" in trust database.' }) screen:expect({ any = 'Allowed in trust database: ".*' .. pathsep .. '%.nvim%.lua"' })
feed(':q<CR>') feed(':q<CR>')
-- no exrc file is executed -- no exrc file is executed
feed(':echo g:exrc_count<CR>') feed(':echo g:exrc_count<CR>')

View File

@@ -35,15 +35,15 @@ describe(':trust', function()
local hash = fn.sha256(t.read_file('test_file')) local hash = fn.sha256(t.read_file('test_file'))
command('edit test_file') command('edit test_file')
matches('^Allowed ".*test_file" in trust database%.$', exec_capture('trust')) matches('^Allowed in trust database%: ".*test_file"$', exec_capture('trust'))
local trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust') local trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(string.format('%s %s', hash, cwd .. pathsep .. 'test_file'), vim.trim(trust)) eq(string.format('%s %s', hash, cwd .. pathsep .. 'test_file'), vim.trim(trust))
matches('^Denied ".*test_file" in trust database%.$', exec_capture('trust ++deny')) matches('^Denied in trust database%: ".*test_file"$', exec_capture('trust ++deny'))
trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust') trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(string.format('! %s', cwd .. pathsep .. 'test_file'), vim.trim(trust)) eq(string.format('! %s', cwd .. pathsep .. 'test_file'), vim.trim(trust))
matches('^Removed ".*test_file" from trust database%.$', exec_capture('trust ++remove')) matches('^Removed from trust database%: ".*test_file"$', exec_capture('trust ++remove'))
trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust') trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(string.format(''), vim.trim(trust)) eq(string.format(''), vim.trim(trust))
end) end)
@@ -53,15 +53,15 @@ describe(':trust', function()
local hash = fn.sha256(t.read_file('test_file')) local hash = fn.sha256(t.read_file('test_file'))
command('edit test_file') command('edit test_file')
matches('^Denied ".*test_file" in trust database%.$', exec_capture('trust ++deny')) matches('^Denied in trust database%: ".*test_file"$', exec_capture('trust ++deny'))
local trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust') local trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(string.format('! %s', cwd .. pathsep .. 'test_file'), vim.trim(trust)) eq(string.format('! %s', cwd .. pathsep .. 'test_file'), vim.trim(trust))
matches('^Allowed ".*test_file" in trust database%.$', exec_capture('trust')) matches('^Allowed in trust database%: ".*test_file"$', exec_capture('trust'))
trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust') trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(string.format('%s %s', hash, cwd .. pathsep .. 'test_file'), vim.trim(trust)) eq(string.format('%s %s', hash, cwd .. pathsep .. 'test_file'), vim.trim(trust))
matches('^Removed ".*test_file" from trust database%.$', exec_capture('trust ++remove')) matches('^Removed from trust database%: ".*test_file"$', exec_capture('trust ++remove'))
trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust') trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(string.format(''), vim.trim(trust)) eq(string.format(''), vim.trim(trust))
end) end)
@@ -69,12 +69,12 @@ describe(':trust', function()
it('deny then remove a file using file path', function() it('deny then remove a file using file path', function()
local cwd = fn.getcwd() local cwd = fn.getcwd()
matches('^Denied ".*test_file" in trust database%.$', exec_capture('trust ++deny test_file')) matches('^Denied in trust database%: ".*test_file"$', exec_capture('trust ++deny test_file'))
local trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust') local trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(string.format('! %s', cwd .. pathsep .. 'test_file'), vim.trim(trust)) eq(string.format('! %s', cwd .. pathsep .. 'test_file'), vim.trim(trust))
matches( matches(
'^Removed ".*test_file" from trust database%.$', '^Removed from trust database%: ".*test_file"$',
exec_capture('trust ++remove test_file') exec_capture('trust ++remove test_file')
) )
trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust') trust = t.read_file(fn.stdpath('state') .. pathsep .. 'trust')

View File

@@ -55,22 +55,18 @@ describe('vim.secure', function()
}) })
local cwd = fn.getcwd() local cwd = fn.getcwd()
local msg = cwd local msg = 'exrc: Found untrusted code. To enable it, choose (v)iew then run `:trust`:'
.. pathsep local path = ('%s%sXfile'):format(cwd, pathsep)
.. 'Xfile is not trusted. To enable it, choose (v)iew then run `:trust`.'
if #msg >= screen._width then
pending('path too long')
return
end
-- Need to use feed_command instead of exec_lua because of the confirmation prompt -- Need to use feed_command instead of exec_lua because of the confirmation prompt
feed_command([[lua vim.secure.read('Xfile')]]) feed_command([[lua vim.secure.read('Xfile')]])
screen:expect([[ screen:expect([[
{MATCH: +}| {MATCH: +}|
{1:~{MATCH: +}}|*3 {1:~{MATCH: +}}|*2
{2:{MATCH: +}}| {2:{MATCH: +}}|
:lua vim.secure.read('Xfile'){MATCH: +}| :lua vim.secure.read('Xfile'){MATCH: +}|
{3:]] .. msg .. [[}{MATCH: +}| {3:]] .. msg .. [[}{MATCH: *}|
{3:]] .. path .. [[}{MATCH: *}|
{3:[i]gnore, (v)iew, (d)eny: }^{MATCH: +}| {3:[i]gnore, (v)iew, (d)eny: }^{MATCH: +}|
]]) ]])
feed('d') feed('d')
@@ -89,10 +85,11 @@ describe('vim.secure', function()
feed_command([[lua vim.secure.read('Xfile')]]) feed_command([[lua vim.secure.read('Xfile')]])
screen:expect([[ screen:expect([[
{MATCH: +}| {MATCH: +}|
{1:~{MATCH: +}}|*3 {1:~{MATCH: +}}|*2
{2:{MATCH: +}}| {2:{MATCH: +}}|
:lua vim.secure.read('Xfile'){MATCH: +}| :lua vim.secure.read('Xfile'){MATCH: +}|
{3:]] .. msg .. [[}{MATCH: +}| {3:]] .. msg .. [[}{MATCH: *}|
{3:]] .. path .. [[}{MATCH: *}|
{3:[i]gnore, (v)iew, (d)eny: }^{MATCH: +}| {3:[i]gnore, (v)iew, (d)eny: }^{MATCH: +}|
]]) ]])
feed('v') feed('v')
@@ -104,7 +101,7 @@ describe('vim.secure', function()
{MATCH: +}| {MATCH: +}|
{1:~{MATCH: +}}| {1:~{MATCH: +}}|
{4:[No Name]{MATCH: +}}| {4:[No Name]{MATCH: +}}|
Allowed "]] .. cwd .. pathsep .. [[Xfile" in trust database.{MATCH: +}| Allowed in trust database: "]] .. cwd .. pathsep .. [[Xfile"{MATCH: +}|
]]) ]])
-- close the split for the next test below. -- close the split for the next test below.
feed(':q<CR>') feed(':q<CR>')
@@ -119,10 +116,11 @@ describe('vim.secure', function()
feed_command([[lua vim.secure.read('Xfile')]]) feed_command([[lua vim.secure.read('Xfile')]])
screen:expect([[ screen:expect([[
{MATCH: +}| {MATCH: +}|
{1:~{MATCH: +}}|*3 {1:~{MATCH: +}}|*2
{2:{MATCH: +}}| {2:{MATCH: +}}|
:lua vim.secure.read('Xfile'){MATCH: +}| :lua vim.secure.read('Xfile'){MATCH: +}|
{3:]] .. msg .. [[}{MATCH: +}| {3:]] .. msg .. [[}{MATCH: *}|
{3:]] .. path .. [[}{MATCH: *}|
{3:[i]gnore, (v)iew, (d)eny: }^{MATCH: +}| {3:[i]gnore, (v)iew, (d)eny: }^{MATCH: +}|
]]) ]])
feed('i') feed('i')
@@ -138,10 +136,11 @@ describe('vim.secure', function()
feed_command([[lua vim.secure.read('Xfile')]]) feed_command([[lua vim.secure.read('Xfile')]])
screen:expect([[ screen:expect([[
{MATCH: +}| {MATCH: +}|
{1:~{MATCH: +}}|*3 {1:~{MATCH: +}}|*2
{2:{MATCH: +}}| {2:{MATCH: +}}|
:lua vim.secure.read('Xfile'){MATCH: +}| :lua vim.secure.read('Xfile'){MATCH: +}|
{3:]] .. msg .. [[}{MATCH: +}| {3:]] .. msg .. [[}{MATCH: +}|
{3:]] .. path .. [[}{MATCH: *}|
{3:[i]gnore, (v)iew, (d)eny: }^{MATCH: +}| {3:[i]gnore, (v)iew, (d)eny: }^{MATCH: +}|
]]) ]])
feed('v') feed('v')
@@ -172,22 +171,19 @@ describe('vim.secure', function()
}) })
local cwd = fn.getcwd() local cwd = fn.getcwd()
local msg = cwd local msg =
.. pathsep 'exrc: Found untrusted code. DIRECTORY trust is decided only by name, not contents:'
.. 'Xdir is not trusted. DIRECTORY trust is decided only by its name, not its contents.' local path = ('%s%sXdir'):format(cwd, pathsep)
if #msg >= screen._width then
pending('path too long')
return
end
-- Need to use feed_command instead of exec_lua because of the confirmation prompt -- Need to use feed_command instead of exec_lua because of the confirmation prompt
feed_command([[lua vim.secure.read('Xdir')]]) feed_command([[lua vim.secure.read('Xdir')]])
screen:expect([[ screen:expect([[
{MATCH: +}| {MATCH: +}|
{1:~{MATCH: +}}|*3 {1:~{MATCH: +}}|*2
{2:{MATCH: +}}| {2:{MATCH: +}}|
:lua vim.secure.read('Xdir'){MATCH: +}| :lua vim.secure.read('Xdir'){MATCH: +}|
{3:]] .. msg .. [[}{MATCH: +}| {3:]] .. msg .. [[}{MATCH: +}|
{3:]] .. path .. [[}{MATCH: +}|
{3:[i]gnore, (v)iew, (d)eny, (a)llow: }^{MATCH: +}| {3:[i]gnore, (v)iew, (d)eny, (a)llow: }^{MATCH: +}|
]]) ]])
feed('d') feed('d')
@@ -206,10 +202,11 @@ describe('vim.secure', function()
feed_command([[lua vim.secure.read('Xdir')]]) feed_command([[lua vim.secure.read('Xdir')]])
screen:expect([[ screen:expect([[
{MATCH: +}| {MATCH: +}|
{1:~{MATCH: +}}|*3 {1:~{MATCH: +}}|*2
{2:{MATCH: +}}| {2:{MATCH: +}}|
:lua vim.secure.read('Xdir'){MATCH: +}| :lua vim.secure.read('Xdir'){MATCH: +}|
{3:]] .. msg .. [[}{MATCH: +}| {3:]] .. msg .. [[}{MATCH: +}|
{3:]] .. path .. [[}{MATCH: +}|
{3:[i]gnore, (v)iew, (d)eny, (a)llow: }^{MATCH: +}| {3:[i]gnore, (v)iew, (d)eny, (a)llow: }^{MATCH: +}|
]]) ]])
feed('a') feed('a')
@@ -231,10 +228,11 @@ describe('vim.secure', function()
feed_command([[lua vim.secure.read('Xdir')]]) feed_command([[lua vim.secure.read('Xdir')]])
screen:expect([[ screen:expect([[
{MATCH: +}| {MATCH: +}|
{1:~{MATCH: +}}|*3 {1:~{MATCH: +}}|*2
{2:{MATCH: +}}| {2:{MATCH: +}}|
:lua vim.secure.read('Xdir'){MATCH: +}| :lua vim.secure.read('Xdir'){MATCH: +}|
{3:]] .. msg .. [[}{MATCH: +}| {3:]] .. msg .. [[}{MATCH: +}|
{3:]] .. path .. [[}{MATCH: +}|
{3:[i]gnore, (v)iew, (d)eny, (a)llow: }^{MATCH: +}| {3:[i]gnore, (v)iew, (d)eny, (a)llow: }^{MATCH: +}|
]]) ]])
feed('i') feed('i')
@@ -250,10 +248,11 @@ describe('vim.secure', function()
feed_command([[lua vim.secure.read('Xdir')]]) feed_command([[lua vim.secure.read('Xdir')]])
screen:expect([[ screen:expect([[
{MATCH: +}| {MATCH: +}|
{1:~{MATCH: +}}|*3 {1:~{MATCH: +}}|*2
{2:{MATCH: +}}| {2:{MATCH: +}}|
:lua vim.secure.read('Xdir'){MATCH: +}| :lua vim.secure.read('Xdir'){MATCH: +}|
{3:]] .. msg .. [[}{MATCH: +}| {3:]] .. msg .. [[}{MATCH: +}|
{3:]] .. path .. [[}{MATCH: +}|
{3:[i]gnore, (v)iew, (d)eny, (a)llow: }^{MATCH: +}| {3:[i]gnore, (v)iew, (d)eny, (a)llow: }^{MATCH: +}|
]]) ]])
feed('v') feed('v')