"nvim -es": disable shada #21723

Problem:
`nvim -es` (and `nvim -Es`) is the recommended way to non-interactively
run commands/vimscript. But it enables shada by default, which is
usually not wanted.

Solution:
- Disable shada by default for `nvim -es/-Es`. This can be overridden by
  `-i foo` if needed.
- Do NOT change the 'loadplugins' default.
  - User config + packages _should_ be enabled by default, for both `nvim
    -es` and `nvim -l`. Else any Lua packages you have can't be accessed
    without `-u path/to/config`, which is clumsy.
      - Use-cases:
        ```
        nvim --headless "+Lazy! sync" +qa
            would become: nvim -es "+Lazy! sync"
        nvim --headless +PlugInstall +qall
            would become: nvim -es +PlugInstall
        ```
  - Opt-out (`--clean` or `-u NONE`) is much easier than opt-in (`-u
    path/to/config`).
  -  User config/packages are analogous to pip packages, which are
     expected when doing `python -c ...`.

related: 7c94bcd2d7
related: ddd0eb6f51
This commit is contained in:
Justin M. Keyes
2025-01-05 17:10:16 -08:00
committed by GitHub
parent 570a8da01b
commit 5e02a2c470
7 changed files with 58 additions and 25 deletions

View File

@@ -618,20 +618,20 @@ Example: TCP echo-server *tcp-server*
Multithreading *lua-loop-threading* Multithreading *lua-loop-threading*
Plugins can perform work in separate (os-level) threads using the threading Plugins can perform work in separate (os-level) threads using the threading
APIs in luv, for instance `vim.uv.new_thread`. Note that every thread APIs in luv, for instance `vim.uv.new_thread`. Each thread has its own
gets its own separate Lua interpreter state, with no access to Lua globals separate Lua interpreter state, with no access to Lua globals on the main
in the main thread. Neither can the state of the editor (buffers, windows, thread. Neither can the editor state (buffers, windows, etc) be directly
etc) be directly accessed from threads. accessed from threads.
A subset of the `vim.*` API is available in threads. This includes: A subset of the `vim.*` stdlib is available in threads, including:
- `vim.uv` with a separate event loop per thread. - `vim.uv` with a separate event loop per thread.
- `vim.mpack` and `vim.json` (useful for serializing messages between threads) - `vim.mpack` and `vim.json` (useful for serializing messages between threads)
- `require` in threads can use Lua packages from the global |package.path| - `require` in threads can use Lua packages from the global |package.path|
- `print()` and `vim.inspect` - `print()` and `vim.inspect`
- `vim.diff` - `vim.diff`
- most utility functions in `vim.*` for working with pure Lua values - Most utility functions in `vim.*` that work with pure Lua values, like
like `vim.split`, `vim.tbl_*`, `vim.list_*`, and so on. `vim.split`, `vim.tbl_*`, `vim.list_*`, etc.
- `vim.is_thread()` returns true from a non-main thread. - `vim.is_thread()` returns true from a non-main thread.

View File

@@ -295,6 +295,7 @@ PLUGINS
STARTUP STARTUP
• |-es| ("script mode") disables shada by default.
• Nvim will fail if the |--listen| or |$NVIM_LISTEN_ADDRESS| address is • Nvim will fail if the |--listen| or |$NVIM_LISTEN_ADDRESS| address is
invalid, instead of silently skipping an invalid address. invalid, instead of silently skipping an invalid address.

View File

@@ -207,12 +207,12 @@ argument.
:print :print
:set :set
With |:verbose| or 'verbose', other commands display on stderr: > With |:verbose| or 'verbose', other commands display on stderr: >
nvim -es +":verbose echo 'foo'" nvim -es +"verbose echo 'foo'"
nvim -V1 -es +foo nvim -V1 -es +"echo 'foo'"
<
< User |config| is skipped unless |-u| was given. Skips user |config| unless |-u| was given.
Swap file is skipped (like |-n|). Disables |shada| unless |-i| was given.
User |shada| is loaded (unless "-i NONE" is given). Disables swapfile (like |-n|).
*-l* *-l*
-l {script} [args] -l {script} [args]
@@ -235,6 +235,11 @@ argument.
nvim +q -l foo.lua nvim +q -l foo.lua
< This loads Lua module "bar" before executing "foo.lua": > < This loads Lua module "bar" before executing "foo.lua": >
nvim +"lua require('bar')" -l foo.lua nvim +"lua require('bar')" -l foo.lua
< *lua-shebang*
You can set the "shebang" of the script so that Nvim executes
the script when called with "./" from a shell (remember to
"chmod u+x"): >
#!/usr/bin/env -S nvim -l
< <
Skips user |config| unless |-u| was given. Skips user |config| unless |-u| was given.
Disables plugins unless 'loadplugins' was set. Disables plugins unless 'loadplugins' was set.
@@ -243,7 +248,7 @@ argument.
*-ll* *-ll*
-ll {script} [args] -ll {script} [args]
Execute a Lua script, similarly to |-l|, but the editor is not Executes a Lua script, similarly to |-l|, but the editor is not
initialized. This gives a Lua environment similar to a worker initialized. This gives a Lua environment similar to a worker
thread. See |lua-loop-threading|. thread. See |lua-loop-threading|.

View File

@@ -409,6 +409,8 @@ Startup:
- |-es| and |-Es| have improved behavior: - |-es| and |-Es| have improved behavior:
- Quits automatically, don't need "-c qa!". - Quits automatically, don't need "-c qa!".
- Skips swap-file dialog. - Skips swap-file dialog.
- Optimized for non-interactive scripts: disables swapfile, shada.
- |-l| Executes Lua scripts non-interactively.
- |-s| reads Normal commands from stdin if the script name is "-". - |-s| reads Normal commands from stdin if the script name is "-".
- Reading text (instead of commands) from stdin |--|: - Reading text (instead of commands) from stdin |--|:
- works by default: "-" file is optional - works by default: "-" file is optional

View File

@@ -1228,6 +1228,9 @@ static void command_line_scan(mparm_T *parmp)
if (exmode_active) { // "-es" silent (batch) Ex-mode if (exmode_active) { // "-es" silent (batch) Ex-mode
silent_mode = true; silent_mode = true;
parmp->no_swap_file = true; parmp->no_swap_file = true;
if (p_shadafile == NULL || *p_shadafile == NUL) {
set_option_value_give_err(kOptShadafile, STATIC_CSTR_AS_OPTVAL("NONE"), 0);
}
} else { // "-s {scriptin}" read from script file } else { // "-s {scriptin}" read from script file
want_argument = true; want_argument = true;
} }
@@ -2085,8 +2088,7 @@ static void source_startup_scripts(const mparm_T *const parmp)
{ {
// If -u given, use only the initializations from that file and nothing else. // If -u given, use only the initializations from that file and nothing else.
if (parmp->use_vimrc != NULL) { if (parmp->use_vimrc != NULL) {
if (strequal(parmp->use_vimrc, "NONE") if (strequal(parmp->use_vimrc, "NONE") || strequal(parmp->use_vimrc, "NORC")) {
|| strequal(parmp->use_vimrc, "NORC")) {
// Do nothing. // Do nothing.
} else { } else {
if (do_source(parmp->use_vimrc, false, DOSO_NONE, NULL) != OK) { if (do_source(parmp->use_vimrc, false, DOSO_NONE, NULL) != OK) {

View File

@@ -2719,7 +2719,7 @@ static msgchunk_T *disp_sb_line(int row, msgchunk_T *smp)
} }
/// @return true when messages should be printed to stdout/stderr: /// @return true when messages should be printed to stdout/stderr:
/// - "batch mode" ("silent mode", -es/-Es) /// - "batch mode" ("silent mode", -es/-Es/-l)
/// - no UI and not embedded /// - no UI and not embedded
int msg_use_printf(void) int msg_use_printf(void)
{ {

View File

@@ -136,7 +136,11 @@ describe('startup', function()
vim.list_extend(args, { '-l', (script or 'test/functional/fixtures/startup.lua') }) vim.list_extend(args, { '-l', (script or 'test/functional/fixtures/startup.lua') })
vim.list_extend(args, lua_args or {}) vim.list_extend(args, lua_args or {})
local out = fn.system(args, input):gsub('\r\n', '\n') local out = fn.system(args, input):gsub('\r\n', '\n')
return eq(dedent(expected), out) if type(expected) == 'function' then
return expected(out)
else
return eq(dedent(expected), out)
end
end end
it('failure modes', function() it('failure modes', function()
@@ -172,6 +176,7 @@ describe('startup', function()
it('Lua-error sets Nvim exitcode', function() it('Lua-error sets Nvim exitcode', function()
local proc = n.spawn_wait('-l', 'test/functional/fixtures/startup-fail.lua') local proc = n.spawn_wait('-l', 'test/functional/fixtures/startup-fail.lua')
matches('E5113: .* my pearls!!', proc:output()) matches('E5113: .* my pearls!!', proc:output())
eq(0, proc.signal)
eq(1, proc.status) eq(1, proc.status)
eq(0, eval('v:shell_error')) eq(0, eval('v:shell_error'))
@@ -282,14 +287,30 @@ describe('startup', function()
eq(0, eval('v:shell_error')) eq(0, eval('v:shell_error'))
end) end)
it('disables swapfile/shada/config/plugins', function() it('disables swapfile/shada/config/plugins unless overridden', function()
local script = [[print(('updatecount=%d shadafile=%s loadplugins=%s scripts=%d'):format(
vim.o.updatecount, vim.o.shadafile, tostring(vim.o.loadplugins), math.max(1, #vim.fn.getscriptinfo())))]]
finally(function()
os.remove('Xtest_shada')
end)
assert_l_out( assert_l_out(
'updatecount=0 shadafile=NONE loadplugins=false scripts=1\n', 'updatecount=0 shadafile=NONE loadplugins=false scripts=1\n',
nil, nil,
nil, nil,
'-', '-',
[[print(('updatecount=%d shadafile=%s loadplugins=%s scripts=%d'):format( script
vim.o.updatecount, vim.o.shadafile, tostring(vim.o.loadplugins), math.max(1, #vim.fn.getscriptinfo())))]] )
-- User can override.
assert_l_out(
function(out)
return matches('updatecount=99 shadafile=Xtest_shada loadplugins=true scripts=2%d\n', out)
end,
{ '+set updatecount=99', '-i', 'Xtest_shada', '+set loadplugins', '-u', 'NORC' },
nil,
'-',
script
) )
end) end)
end) end)
@@ -572,19 +593,21 @@ describe('startup', function()
eq(' encoding=utf-8\n', fn.system({ nvim_prog, '-n', '-es' }, { 'set encoding', '' })) eq(' encoding=utf-8\n', fn.system({ nvim_prog, '-n', '-es' }, { 'set encoding', '' }))
end) end)
it('-es/-Es disables swapfile, user config #8540', function() it('-es/-Es disables swapfile/shada/config #8540', function()
for _, arg in ipairs({ '-es', '-Es' }) do for _, arg in ipairs({ '-es', '-Es' }) do
local out = fn.system({ local out = fn.system({
nvim_prog, nvim_prog,
arg, arg,
'+set swapfile? updatecount? shadafile?', '+set updatecount? shadafile? loadplugins?',
'+put =map(getscriptinfo(), {-> v:val.name})', '+put =map(getscriptinfo(), {-> v:val.name})',
'+%print', '+%print',
}) })
local line1 = string.match(out, '^.-\n') local line1 = string.match(out, '^.-\n')
-- updatecount=0 means swapfile was disabled. -- updatecount=0 means swapfile was disabled.
eq(' swapfile updatecount=0 shadafile=\n', line1) eq(' updatecount=0 shadafile=NONE loadplugins\n', line1)
-- Standard plugins were loaded, but not user config. -- Standard plugins were loaded, but not user config. #31878
local nrlines = #vim.split(out, '\n')
ok(nrlines > 20, '>20', nrlines)
ok(string.find(out, 'man.lua') ~= nil) ok(string.find(out, 'man.lua') ~= nil)
ok(string.find(out, 'init.vim') == nil) ok(string.find(out, 'init.vim') == nil)
end end