build: ship "_core/*" as bytecode (built-into Nvim binary)

Problem:
We want to encourage implementing core features in Lua instead of C, but
it's clumsy because:
- Core Lua code (built into `nvim` so it is available even if VIMRUNTIME
  is missing/invalid) requires manually updating CMakeLists.txt, or
  stuffing it into `_editor.lua`.
- Core Lua modules are not organized similar to C modules, `_editor.lua`
  is getting too big.

Solution:
- Introduce `_core/` where core Lua code can live. All Lua modules added
  there will automatically be included as bytecode in the `nvim` binary.
- Move these core modules into `_core/*`:
  ```
  _defaults.lua
  _editor.lua
  _options.lua
  _system.lua
  shared.lua
  ```

TODO:
- Move `_extui/ => _core/ui2/`
This commit is contained in:
Justin M. Keyes
2025-08-28 23:43:10 -04:00
parent 03377b9552
commit 20e77c5d88
32 changed files with 237 additions and 140 deletions

View File

@@ -24,7 +24,7 @@ comment:
defaults:
- changed-files:
- any-glob-to-any-file: [ runtime/lua/vim/_defaults.lua ]
- any-glob-to-any-file: [ runtime/lua/vim/_core/defaults.lua ]
diagnostic:
- changed-files:

View File

@@ -232,10 +232,10 @@ See [#549][549] for more details.
### Lua runtime files
Most of the Lua core [`runtime/`](./runtime) modules are precompiled to
bytecode, so changes to those files won't get used unless you rebuild Nvim or
by passing `--luamod-dev` and `$VIMRUNTIME`. For example, try adding a function
to `runtime/lua/vim/_editor.lua` then:
The Lua [`runtime/lua/vim/_core/`](./runtime/lua/vim/_core/) modules are
precompiled to bytecode, so changes won't be usable unless you (1) rebuild Nvim
or (2) start Nvim with `--luamod-dev` and `$VIMRUNTIME`. For example try adding
a function to `runtime/lua/vim/editor.lua`, then:
```bash
VIMRUNTIME=./runtime ./build/bin/nvim --luamod-dev

View File

@@ -69,7 +69,7 @@ endif()
execute_process(
# Note: because of "-ll" (low-level interpreter mode), some modules like
# _editor.lua are not loaded.
# _core/editor.lua are not loaded.
COMMAND ${NVIM_PRG} -ll ${WORKING_DIR}/test/lua_runner.lua ${DEPS_INSTALL_DIR}/share/lua/5.1/ busted -v -o test.busted.outputHandlers.nvim
--lazy --helper=${TEST_DIR}/${TEST_TYPE}/preload.lua
--lpath=${BUILD_DIR}/?.lua

View File

@@ -277,7 +277,7 @@ Docstring format:
- Files declared as `@meta` are only used for typing and documentation (similar to "*.d.ts" typescript files).
Example: the help for |vim.paste()| is generated from a docstring decorating
vim.paste in runtime/lua/vim/_editor.lua like this: >
vim.paste in runtime/lua/vim/_core/editor.lua like this: >
--- Paste handler, invoked by |nvim_paste()| when a conforming UI
--- (such as the |TUI|) pastes text into the editor.

View File

@@ -20,17 +20,64 @@ The purpose of this document is to give:
Type |gO| to see the table of contents.
==============================================================================
Filename conventions
Project layout: where things go
The source filenames use extensions to hint about their purpose.
C CODE
- Nvim C code lives in `src/nvim/`.
- This includes third-party components which we have forked and fully
"own", meaning we no longer track the upstream. In particular: `vterm/`
and `tui/termkey/`.
- Vendored third-party components live in `src/*`.
- `src/tee/` and `src/xxd/` have their own build files. They are shipped
with the Windows artifact to ensure those tools exists there.
- Other components like `src/cjson/` and `src/mpack/` are included with
Nvim itself. These vendored sources are synced from upstream, we do not
"own" them.
See also "MAINTAIN.md".
Generated C files use these filename conventions to hint their purpose:
- `*.c`, `*.generated.c` - full C files, with all includes, etc.
- `*.c.h` - parametrized C files, contain all necessary includes, but require
defining macros before actually using. Example: `typval_encode.c.h`
- `*.h` - full headers, with all includes. Does *not* apply to `*.generated.h`.
- `*.h` - full headers, with all includes. Does not apply to `*.generated.h`.
- `*.h.generated.h` - exported functions declarations.
- `*.c.generated.h` - static functions declarations.
LUA CODE
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 disable or replace with
a third-party plugin, and which do not have a formal API. Examples:
"editorconfig", "comment".
- "opt-out": `runtime/plugin/`
- "opt-in": `runtime/pack/dist/opt/`
2. `runtime/lua/vim/` (the runtime): Lazy-loaded modules. Examples: `treesitter`, `lpeg`.
3. `runtime/lua/vim/_core/shared.lua`: pure Lua functions which always are available.
Used in the test runner, and worker threads/processes launched from Nvim.
4. `runtime/lua/vim/_core/`: Eager-loaded code which directly interacts with the Nvim
editor state. Only available in the main thread. See |dev-lua-builtin|
below.
The top-level `vim.` namespace is for fundamental Lua and editor features. Use
submodules (`vim.foo`) for everything else (but avoid excessive "nesting"), or
plugins (see above).
Compatibility with Vim's `if_lua` is explicitly a non-goal.
*dev-lua-builtin*
Lua modules that are necessary even if VIMRUNTIME is invalid (generally, data
structures and essential utilties), must be compiled into the `nvim` binary.
There are two ways to do that:
- if they are private, put the code file in `runtime/lua/vim/_core/`
- if they are public, choose a new filepath in `runtime/lua/vim/`
and add it to VIM_MODULE_FILE in src/nvim/CMakeLists.txt.
==============================================================================
Data structures

View File

@@ -270,8 +270,8 @@ Limitations:
require("lldebugger").start()
end
< This is a [local-lua-debugger limitation](https://github.com/tomblind/local-lua-debugger-vscode?tab=readme-ov-file#busted)
- You cannot step into code of files which get baked into the nvim binary like
the `shared.lua`.
- You cannot step into code of files which get baked into the nvim binary
(such as `_core/*.lua` and `inspect.lua`).
------------------------------------------------------------------------------

View File

@@ -1,3 +1,3 @@
pub const inspect_module = @embedFile("./lua/vim/inspect.lua");
pub const shared_module = @embedFile("./lua/vim/shared.lua");
pub const shared_module = @embedFile("./lua/vim/_core/shared.lua");
pub const iter_module = @embedFile("./lua/vim/iter.lua");

View File

@@ -1,23 +0,0 @@
local M = {}
--- Adds one or more blank lines above or below the cursor.
-- TODO: move to _defaults.lua once it is possible to assign a Lua function to options #25672
--- @param above? boolean Place blank line(s) above the cursor
local function add_blank(above)
local offset = above and 1 or 0
local repeated = vim.fn['repeat']({ '' }, vim.v.count1)
local linenr = vim.api.nvim_win_get_cursor(0)[1]
vim.api.nvim_buf_set_lines(0, linenr - offset, linenr - offset, true, repeated)
end
-- TODO: move to _defaults.lua once it is possible to assign a Lua function to options #25672
function M.space_above()
add_blank(true)
end
-- TODO: move to _defaults.lua once it is possible to assign a Lua function to options #25672
function M.space_below()
add_blank()
end
return M

View File

@@ -1,3 +1,5 @@
-- Default user-commands, autocmds, mappings, menus.
--- Default user commands
do
vim.api.nvim_create_user_command('Inspect', function(cmd)
@@ -440,13 +442,13 @@ do
-- Add empty lines
vim.keymap.set('n', '[<Space>', function()
-- TODO: update once it is possible to assign a Lua function to options #25672
vim.go.operatorfunc = "v:lua.require'vim._buf'.space_above"
vim.go.operatorfunc = "v:lua.require'vim._core.util'.space_above"
return 'g@l'
end, { expr = true, desc = 'Add empty line above cursor' })
vim.keymap.set('n', ']<Space>', function()
-- TODO: update once it is possible to assign a Lua function to options #25672
vim.go.operatorfunc = "v:lua.require'vim._buf'.space_below"
vim.go.operatorfunc = "v:lua.require'vim._core.util'.space_below"
return 'g@l'
end, { expr = true, desc = 'Add empty line below cursor' })
end

View File

@@ -1,27 +1,5 @@
-- Nvim-Lua stdlib: the `vim` module (:help lua-stdlib)
--
-- 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, and worker threads/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.
--
-- 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.
--
-- Reference (#6580):
-- - https://github.com/luafun/luafun
-- - https://github.com/rxi/lume
-- - http://leafo.net/lapis/reference/utilities.html
-- - https://github.com/bakpakin/Fennel (pretty print, repl)
-- These are for loading runtime modules lazily since they aren't available in
-- the nvim binary as specified in executor.c
@@ -1321,7 +1299,7 @@ function vim.deprecate(name, alternative, version, plugin, backtrace)
end
end
require('vim._options')
require('vim._core.options')
--- Remove at Nvim 1.0
---@deprecated

View File

@@ -1,3 +1,5 @@
-- For 'exrc' and related functionality.
local files = vim.fs.find({ '.nvim.lua', '.nvimrc', '.exrc' }, {
type = 'file',
upward = true,

View File

@@ -1,3 +1,5 @@
-- For "--listen" and related functionality.
local M = {}
--- Called by builtin serverlist(). Returns all running servers in stdpath("run").

View File

@@ -13,7 +13,7 @@ if has_strbuffer then
-- Lua 5.1 does not have __len metamethod so we need to provide a len()
-- function to use instead.
--- @param buf vim._stringbuffer
--- @param buf vim._core.stringbuffer
--- @return integer
function M.len(buf)
return #buf
@@ -22,7 +22,7 @@ if has_strbuffer then
return M
end
--- @class vim._stringbuffer
--- @class vim._core.stringbuffer
--- @field private buf string[]
--- @field package len integer absolute length of the `buf`
--- @field package skip_ptr integer
@@ -103,7 +103,7 @@ function M.new()
return setmetatable({}, StrBuffer):reset()
end
--- @param buf vim._stringbuffer
--- @param buf vim._core.stringbuffer
function M.len(buf)
return buf.len - buf.skip_ptr
end

View File

@@ -1,5 +1,27 @@
-- Nursery for random things that may later find their way into stdlib if they mature.
local M = {}
--- Adds one or more blank lines above or below the cursor.
-- TODO: move to _core/defaults.lua once it is possible to assign a Lua function to options #25672
--- @param above? boolean Place blank line(s) above the cursor
local function add_blank(above)
local offset = above and 1 or 0
local repeated = vim.fn['repeat']({ '' }, vim.v.count1)
local linenr = vim.api.nvim_win_get_cursor(0)[1]
vim.api.nvim_buf_set_lines(0, linenr - offset, linenr - offset, true, repeated)
end
-- TODO: move to _core/defaults.lua once it is possible to assign a Lua function to options #25672
function M.space_above()
add_blank(true)
end
-- TODO: move to _core/defaults.lua once it is possible to assign a Lua function to options #25672
function M.space_below()
add_blank()
end
--- Edit a file in a specific window
--- @param winnr number
--- @param file string

View File

@@ -95,6 +95,6 @@ end
-- only on main thread: functions for interacting with editor state
if vim.api and not vim.is_thread() then
require('vim._editor')
require('vim._system')
require('vim._core.editor')
require('vim._core.system')
end

View File

@@ -1,7 +1,7 @@
local log = require('vim.lsp.log')
local protocol = require('vim.lsp.protocol')
local lsp_transport = require('vim.lsp._transport')
local strbuffer = require('vim._stringbuffer')
local strbuffer = require('vim._core.stringbuffer')
local validate, schedule_wrap = vim.validate, vim.schedule_wrap
--- Embeds the given string into a table and correctly computes `Content-Length`.

View File

@@ -72,21 +72,47 @@ pub fn nvim_gen_sources(
const names = [_][]const u8{
"_init_packages",
"inspect",
"_editor",
"_system",
"filetype",
"fs",
"F",
"keymap",
"loader",
"_defaults",
"_options",
"shared",
"text",
};
for (names) |n| {
gen_step.addFileArg(b.path(b.fmt("runtime/lua/vim/{s}.lua", .{n})));
gen_step.addArg(b.fmt("vim.{s}", .{n}));
}
// Dynamically add all Lua _core/ modules (like CMakeLists.txt does)
if (b.build_root.handle.openDir("runtime/lua/vim/_core", .{ .iterate = true })) |core_dir_handle| {
var core_dir = core_dir_handle;
defer core_dir.close();
var iter = core_dir.iterate();
var core_files = try std.ArrayList([]const u8).initCapacity(b.allocator, 0);
defer core_files.deinit(b.allocator);
while (try iter.next()) |entry| {
if (entry.kind == .file and std.mem.endsWith(u8, entry.name, ".lua")) {
const module_name = try b.allocator.dupe(u8, entry.name[0 .. entry.name.len - 4]);
try core_files.append(b.allocator, module_name);
}
}
std.mem.sort([]const u8, core_files.items, {}, struct {
fn lessThan(_: void, a: []const u8, c: []const u8) bool {
return std.mem.lessThan(u8, a, c);
}
}.lessThan);
for (core_files.items) |n| {
gen_step.addFileArg(b.path(b.fmt("runtime/lua/vim/_core/{s}.lua", .{n})));
gen_step.addArg(b.fmt("vim._core.{s}", .{n}));
}
} else |err| {
std.debug.print("Warning: Could not open _core directory: {}\n", .{err});
}
}
const ui_metadata = ui_step: {

View File

@@ -152,8 +152,8 @@ local config = {
section_order = {
-- Sections at the top, in a specific order:
'builtin.lua',
'_options.lua',
'_editor.lua',
'options.lua',
'editor.lua',
'_inspector.lua',
'shared.lua',
@@ -177,7 +177,7 @@ local config = {
'secure.lua',
'snippet.lua',
'spell.lua',
'_system.lua',
'system.lua',
'text.lua',
'ui.lua',
'uri.lua',
@@ -187,7 +187,9 @@ local config = {
'_extui.lua',
},
files = {
'runtime/lua/vim/_editor.lua',
'runtime/lua/vim/_core/editor.lua',
'runtime/lua/vim/_core/options.lua',
'runtime/lua/vim/_core/system.lua',
'runtime/lua/vim/_extui.lua',
'runtime/lua/vim/_inspector.lua',
'runtime/lua/vim/_meta/base64.lua',
@@ -198,8 +200,6 @@ local config = {
'runtime/lua/vim/_meta/re.lua',
'runtime/lua/vim/_meta/regex.lua',
'runtime/lua/vim/_meta/spell.lua',
'runtime/lua/vim/_options.lua',
'runtime/lua/vim/_system.lua',
'runtime/lua/vim/filetype.lua',
'runtime/lua/vim/fs.lua',
'runtime/lua/vim/glob.lua',
@@ -219,7 +219,7 @@ local config = {
'runtime/lua/vim/version.lua',
},
fn_xform = function(fun)
if contains(fun.module, { 'vim.uri', 'vim.shared', 'vim._editor' }) then
if contains(fun.module, { 'vim.uri', 'vim.shared', 'vim._core.editor' }) then
fun.module = 'vim'
end
@@ -238,11 +238,11 @@ local config = {
},
section_fmt = function(name)
name = name:lower()
if name == '_editor' then
if name == 'editor' then
return 'Lua module: vim'
elseif name == '_system' then
elseif name == 'system' then
return 'Lua module: vim.system'
elseif name == '_options' then
elseif name == 'options' then
return 'LUA-VIMSCRIPT BRIDGE'
elseif name == 'builtin' then
return 'VIM'
@@ -250,11 +250,11 @@ local config = {
return 'Lua module: vim.' .. name
end,
helptag_fmt = function(name)
if name == '_editor' then
if name == 'Editor' then
return 'lua-vim'
elseif name == '_system' then
elseif name == 'System' then
return 'lua-vim-system'
elseif name == '_options' then
elseif name == 'Options' then
return 'lua-vimscript'
end
return 'vim.' .. name:lower()

View File

@@ -340,20 +340,26 @@ set(LUA_API_C_BINDINGS ${GENERATED_DIR}/lua_api_c_bindings.generated.h)
set(VIM_MODULE_FILE ${GENERATED_DIR}/lua/vim_module.generated.h)
# NVIM_RUNTIME_DIR
set(LUA_DEFAULTS_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/_defaults.lua)
set(LUA_EDITOR_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/_editor.lua)
set(LUA_SYSTEM_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/_system.lua)
set(LUA_FILETYPE_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/filetype.lua)
set(LUA_FS_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/fs.lua)
set(LUA_F_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/F.lua)
# Must be item 1 in `builtin_modules`, for `--luamod-dev`.
set(LUA_INIT_PACKAGES_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/_init_packages.lua)
# Must be item 2 in `builtin_modules`, for `--luamod-dev`.
set(LUA_INSPECT_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/inspect.lua)
set(LUA_KEYMAP_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/keymap.lua)
set(LUA_LOADER_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/loader.lua)
set(LUA_OPTIONS_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/_options.lua)
set(LUA_SHARED_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/shared.lua)
set(LUA_TEXT_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/text.lua)
# Find all Lua modules in the _core/ directory.
file(GLOB LUA_CORE_MODULE_SOURCES ${NVIM_RUNTIME_DIR}/lua/vim/_core/*.lua)
set(LUA_CORE_COMMAND_ARGS)
foreach(core_source ${LUA_CORE_MODULE_SOURCES})
get_filename_component(core_filename ${core_source} NAME_WE)
list(APPEND LUA_CORE_COMMAND_ARGS ${core_source} "vim._core.${core_filename}")
endforeach()
file(GLOB API_HEADERS CONFIGURE_DEPENDS api/*.h)
list(REMOVE_ITEM API_HEADERS ${CMAKE_CURRENT_LIST_DIR}/api/ui_events.in.h)
file(GLOB MSGPACK_RPC_HEADERS CONFIGURE_DEPENDS msgpack_rpc/*.h)
@@ -630,32 +636,26 @@ add_custom_command(
# respectively, otherwise --luamod-dev won't work properly.
${LUA_INIT_PACKAGES_MODULE_SOURCE} "vim._init_packages"
${LUA_INSPECT_MODULE_SOURCE} "vim.inspect"
${LUA_EDITOR_MODULE_SOURCE} "vim._editor"
${LUA_SYSTEM_MODULE_SOURCE} "vim._system"
${LUA_FILETYPE_MODULE_SOURCE} "vim.filetype"
${LUA_FS_MODULE_SOURCE} "vim.fs"
${LUA_F_MODULE_SOURCE} "vim.F"
${LUA_KEYMAP_MODULE_SOURCE} "vim.keymap"
${LUA_LOADER_MODULE_SOURCE} "vim.loader"
${LUA_DEFAULTS_MODULE_SOURCE} "vim._defaults"
${LUA_OPTIONS_MODULE_SOURCE} "vim._options"
${LUA_SHARED_MODULE_SOURCE} "vim.shared"
${LUA_TEXT_MODULE_SOURCE} "vim.text"
${LUA_CORE_COMMAND_ARGS}
DEPENDS
${CHAR_BLOB_GENERATOR}
${LUA_INIT_PACKAGES_MODULE_SOURCE}
${LUA_INSPECT_MODULE_SOURCE}
${LUA_EDITOR_MODULE_SOURCE}
${LUA_SYSTEM_MODULE_SOURCE}
${LUA_FILETYPE_MODULE_SOURCE}
${LUA_FS_MODULE_SOURCE}
${LUA_F_MODULE_SOURCE}
${LUA_KEYMAP_MODULE_SOURCE}
${LUA_LOADER_MODULE_SOURCE}
${LUA_DEFAULTS_MODULE_SOURCE}
${LUA_OPTIONS_MODULE_SOURCE}
${LUA_SHARED_MODULE_SOURCE}
${LUA_TEXT_MODULE_SOURCE}
${LUA_CORE_MODULE_SOURCES}
VERBATIM
)

View File

@@ -2875,7 +2875,7 @@ static char *get_lsp_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx)
ADD_C(args, CSTR_AS_OBJ(xp->xp_line));
// Build the current command line as a Lua string argument
Object res = NLUA_EXEC_STATIC("return require'vim._core.ex_cmd.lsp'.lsp_complete(...)", args,
Object res = NLUA_EXEC_STATIC("return require'vim._core.ex_cmd'.lsp_complete(...)", args,
kRetObject, NULL,
&err);
api_clear_error(&err);

View File

@@ -8061,7 +8061,7 @@ static void ex_lsp(exarg_T *eap)
ADD_C(args, CSTR_AS_OBJ(eap->arg));
NLUA_EXEC_STATIC("require'vim._core.ex_cmd.lsp'.ex_lsp(...)", args, kRetNilBool, NULL, &err);
NLUA_EXEC_STATIC("require'vim._core.ex_cmd'.ex_lsp(...)", args, kRetNilBool, NULL, &err);
if (ERROR_SET(&err)) {
emsg_multiline(err.msg, "lua_error", HLF_E, true);
}

View File

@@ -2137,8 +2137,8 @@ void nlua_set_sctx(sctx_T *current)
// Files where internal wrappers are defined so we can ignore them
// like vim.o/opt etc are defined in _options.lua
char *ignorelist[] = {
"vim/_editor.lua",
"vim/_options.lua",
"vim/_core/editor.lua",
"vim/_core/options.lua",
"vim/keymap.lua",
};
int ignorelist_size = sizeof(ignorelist) / sizeof(ignorelist[0]);
@@ -2404,14 +2404,14 @@ plain: {}
return arena_printf(arena, "<Lua %d>", ref).data;
}
/// Execute the vim._defaults module to set up default mappings and autocommands
/// Execute the vim._core.defaults module to set up default mappings and autocommands
void nlua_init_defaults(void)
{
lua_State *const L = global_lstate;
assert(L);
lua_getglobal(L, "require");
lua_pushstring(L, "vim._defaults");
lua_pushstring(L, "vim._core.defaults");
if (nlua_pcall(L, 1, 0)) {
fprintf(stderr, "%s\n", lua_tostring(L, -1));
}

View File

@@ -740,7 +740,7 @@ static void handle_unknown_csi(TermInput *input, const TermKeyKey *key)
// The second argument tells us whether the OS theme is set to light
// mode or dark mode, but all we care about is the background color of
// the terminal emulator. We query for that with OSC 11 and the response
// is handled by the autocommand created in _defaults.lua. The terminal
// is handled by the autocommand created in _core/defaults.lua. The terminal
// may send us multiple notifications all at once so we use a timer to
// coalesce the queries.
if (uv_timer_get_due_in(&input->bg_query_timer) > 0) {

View File

@@ -337,11 +337,9 @@ static void tui_reset_key_encoding(TUIData *tui)
}
}
/// Write the OSC 11 sequence to the terminal emulator to query the current
/// background color.
/// Write the OSC 11 sequence to the terminal emulator to query the current background color.
///
/// The response will be handled by the TermResponse autocommand created in
/// _defaults.lua.
/// Response will be handled by the TermResponse handler in _core/defaults.lua.
void tui_query_bg_color(TUIData *tui)
FUNC_ATTR_NONNULL_ALL
{
@@ -1984,7 +1982,7 @@ static void terminfo_set_str(TUIData *tui, TerminfoDef str, const char *val)
/// Determine if the terminal supports truecolor or not.
///
/// note: We get another chance at detecting these in the nvim server process, see
/// the use of vim.termcap in runtime/lua/vim/_defaults.lua
/// the use of vim.termcap in runtime/lua/vim/_core/defaults.lua
///
/// If terminfo contains Tc, RGB, or both setrgbf and setrgbb capabilities, return true.
static bool term_has_truecolor(TUIData *tui, const char *colorterm)

View File

@@ -202,3 +202,50 @@ describe('command-line option', function()
end
end
end)
describe('vim._core', function()
it('works with "-u NONE" and no VIMRUNTIME', function()
clear {
args_rm = { '-u' },
args = { '-u', 'NONE' },
env = { VIMRUNTIME = 'non-existent' },
}
-- `vim.hl` is NOT a builtin module.
t.matches("^module 'vim%.hl' not found:", t.pcall_err(n.exec_lua, [[require('vim.hl')]]))
-- All `vim._core.*` modules are builtin.
t.eq({ 'serverlist' }, n.exec_lua([[return vim.tbl_keys(require('vim._core.server'))]]))
local expected = {
'vim.F',
'vim._core.defaults',
'vim._core.editor',
'vim._core.ex_cmd',
'vim._core.exrc',
'vim._core.options',
'vim._core.server',
'vim._core.stringbuffer',
'vim._core.system',
'vim._core.util',
'vim._init_packages',
'vim.filetype',
'vim.fs',
'vim.inspect',
'vim.keymap',
'vim.loader',
'vim.shared',
'vim.text',
}
if n.exec_lua [[return not not _G.jit]] then
expected = vim.list_extend({
'ffi',
'jit.profile',
'jit.util',
'string.buffer',
'table.clear',
'table.new',
}, expected)
end
t.eq(expected, n.exec_lua([[local t = vim.tbl_keys(package.preload); table.sort(t); return t]]))
end)
end)

View File

@@ -72,7 +72,7 @@ describe('startup', function()
clear({ args = { '--startuptime', testfile } })
assert_log('Embedded', testfile, 100)
assert_log('sourcing', testfile, 100)
assert_log("require%('vim%._editor'%)", testfile, 100)
assert_log("require%('vim%._core.editor'%)", testfile, 100)
end)
it('--startuptime does not crash on error #31125', function()
@@ -1208,12 +1208,7 @@ describe('user config init', function()
mkdir_p(xconfig .. pathsep .. 'nvim')
mkdir_p(xdata)
write_file(
init_lua_path,
[[
vim.g.lua_rc = 1
]]
)
write_file(init_lua_path, [[vim.g.lua_rc = 1]])
end)
after_each(function()
@@ -1240,10 +1235,10 @@ describe('user config init', function()
exrc_path,
string.format(
[[
vim.g.exrc_file = "%s"
vim.g.exrc_path = debug.getinfo(1, 'S').source:gsub('^@', '')
vim.g.exrc_count = (vim.g.exrc_count or 0) + 1
]],
vim.g.exrc_file = "%s"
vim.g.exrc_path = debug.getinfo(1, 'S').source:gsub('^@', '')
vim.g.exrc_count = (vim.g.exrc_count or 0) + 1
]],
exrc_path
)
)
@@ -1252,10 +1247,10 @@ describe('user config init', function()
exrc_path,
string.format(
[[
let g:exrc_file = "%s"
" let g:exrc_path = ??
let g:exrc_count = get(g:, 'exrc_count', 0) + 1
]],
let g:exrc_file = "%s"
" let g:exrc_path = ??
let g:exrc_count = get(g:, 'exrc_count', 0) + 1
]],
exrc_path
)
)
@@ -1270,9 +1265,9 @@ describe('user config init', function()
write_file(
init_lua_path,
[[
vim.o.exrc = true
vim.g.exrc_file = '---'
]]
vim.o.exrc = true
vim.g.exrc_file = '---'
]]
)
mkdir_p(xstate .. pathsep .. (is_os('win') and 'nvim-data' or 'nvim'))
end)
@@ -1395,8 +1390,8 @@ describe('user config init', function()
write_file(
custom_lua_path,
[[
vim.g.custom_lua_rc = 1
]]
vim.g.custom_lua_rc = 1
]]
)
end)
@@ -1523,16 +1518,16 @@ describe('runtime:', function()
write_file(
table.concat({ plugin_folder_path, 'plugin.vim' }, pathsep),
[[
let &runtimepath = &runtimepath
let g:vim_plugin = 1
]]
let &runtimepath = &runtimepath
let g:vim_plugin = 1
]]
)
write_file(
table.concat({ plugin_folder_path, 'plugin.lua' }, pathsep),
[[
vim.o.runtimepath = vim.o.runtimepath
vim.g.lua_plugin = 1
]]
vim.o.runtimepath = vim.o.runtimepath
vim.g.lua_plugin = 1
]]
)
clear { args_rm = { '-u' }, args = { '--cmd', 'packloadall' }, env = xenv }
@@ -1610,8 +1605,8 @@ describe('user session', function()
write_file(
session_file,
[[
vim.g.lua_session = 1
]]
vim.g.lua_session = 1
]]
)
end)

View File

@@ -28,8 +28,8 @@ describe(':lsp', function()
args = { '-u', 'NONE' },
env = { VIMRUNTIME = 'non-existent' },
}
eq(
[[Vim(lsp):Lua: [string "<nvim>"]:0: module 'vim._core.ex_cmd.lsp' not found:]],
t.matches(
[[Vim%(lsp%):Lua: .*module 'vim%.lsp' not found:]],
vim.split(t.pcall_err(n.command, 'lsp enable dummy'), '\n')[1]
)
end)

View File

@@ -2053,6 +2053,7 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim
end)
it('no wait return before delayed exception error message', function()
screen:try_resize(70, 7)
feed('ia<esc>:lua vim.cmd.quit()<CR>')
screen:expect({
any = {

View File

@@ -73,7 +73,7 @@ aunmenu *
tlunmenu *
autocmd! nvim.popupmenu
" Undo the 'grepprg' and 'grepformat' setting in _defaults.lua.
" Undo the 'grepprg' and 'grepformat' setting in _core/defaults.lua.
set grepprg& grepformat&
" Prevent Nvim log from writing to stderr.