mirror of
https://github.com/neovim/neovim.git
synced 2026-07-31 12:49:11 +00:00
Problem:
Options parsing is still painful for dict-style options.
Solution:
schema-maxxing => better `opt:get()` (will be the basis for `vim.o()`),
unified (and more-detailed) err msgs.
- Drop bespoke structure-builder in `_core/options.lua`.
- Define `schema` for all non-primitive options (except 'guicursor' and
statusline-style options); generate reified keysets `OptKeyDict`).
- Generate 'fillchars' => `fcs_tab`, 'listchars' => `lcs_tab`.
- `nvim_set_option_value`:
- Return the improved structures. Also from `vim.opt.x:get()`.
- Eliminate api <=> lua roundtrip, centralize option structure
handling.
- Improve/unify errors.
- Bump ERR_BUFLEN 80 → 256 so the "one of" list isn't truncated.
- Eliminate old 'diffopt' order-dependence (`iwhiteall` before `iwhite`)
Error samples:
Typed-key path (opt_strings_check → diffopt/mousescroll/breakindentopt):
E474: Unknown item 'foo'
E474: 'context' requires a number
E474: 'ver' number is out of range
E474: 'algorithm' must be one of: myers, minimal, patience, histogram
E474: 'filler' does not take a value
Related:
- #31084
- #34661
- #31820
- #14739
- #20107
- fix #18875
- :get() returns `{ sbr = true, shift = '3' }` (reified-keyset) instead of `{'sbr', 'shift:3'}`
- Setting via table now works too. `object_as_optval_for` `is_map` now recognizes struct options.
- fix #30296
- instead of `E474: Invalid argument`, errors now look like:
```
E474: Invalid value 'x', expected one of: single, double: ambiwidth=x
E474: Unknown item 'foo': diffopt=foo
E474: 'context' requires a number: diffopt=context:x
```
simplify `win_float_parse_option` from #26799.
137 lines
4.3 KiB
Zig
137 lines
4.3 KiB
Zig
//! "nlua" is an abbreviation for nvim flavored lua, i e lua with the
|
|
//! extended standard library functionality added by nvim such as json, mpack
|
|
//! and libuv and a range of vim.* utility functions.
|
|
//!
|
|
//! nlua0 is an interpreter for the "bootstrap" lua code we need to run before
|
|
//! nvim can be built, in order to run lua scripts which process and generate
|
|
//! more .c code, which still need these extensions.
|
|
const std = @import("std");
|
|
const ziglua = @import("ziglua");
|
|
const options = @import("options");
|
|
|
|
const embedded_data = @import("embedded_data");
|
|
|
|
// these are common dependencies used by many generators
|
|
const hashy = @embedFile("gen/hashy.lua");
|
|
const keyset = @embedFile("gen/keyset.lua");
|
|
const c_grammar = @embedFile("gen/c_grammar.lua");
|
|
|
|
const Lua = ziglua.Lua;
|
|
|
|
extern "c" fn luaopen_mpack(ptr: *anyopaque) c_int;
|
|
extern "c" fn luaopen_lpeg(ptr: *anyopaque) c_int;
|
|
extern "c" fn luaopen_bit(ptr: *anyopaque) c_int;
|
|
extern "c" fn luaopen_luv(ptr: *anyopaque) c_int;
|
|
|
|
fn init_lua() !*Lua {
|
|
// Initialize the Lua vm
|
|
var lua = try Lua.init(std.heap.c_allocator);
|
|
lua.openLibs();
|
|
|
|
// this sets _G.vim by itself, so we don't need to
|
|
try lua.loadBuffer(embedded_data.shared_module, "shared.lua");
|
|
lua.call(.{ .results = 1 });
|
|
|
|
try lua.loadBuffer(embedded_data.inspect_module, "inspect.lua");
|
|
lua.call(.{ .results = 1 });
|
|
lua.setField(-2, "inspect");
|
|
|
|
try lua.loadBuffer(embedded_data.iter_module, "iter.lua");
|
|
lua.call(.{ .results = 1 });
|
|
lua.setField(-2, "iter");
|
|
|
|
_ = lua.getGlobal("package");
|
|
_ = lua.getField(-1, "preload");
|
|
try lua.loadBuffer(hashy, "hashy.lua"); // [package, preload, hashy]
|
|
lua.setField(-2, "gen.hashy");
|
|
try lua.loadBuffer(keyset, "keyset.lua"); // [package, preload, keyset]
|
|
lua.setField(-2, "gen.keyset");
|
|
try lua.loadBuffer(c_grammar, "c_grammar.lua"); // [package, preload, c_grammar]
|
|
lua.setField(-2, "gen.c_grammar");
|
|
lua.pop(2);
|
|
|
|
const retval = luaopen_mpack(lua);
|
|
if (retval != 1) return error.LoadError;
|
|
_ = lua.getField(-1, "NIL"); // [vim, mpack, NIL]
|
|
lua.setField(-3, "NIL"); // vim.NIL = mpack.NIL (wow BOB wow)
|
|
lua.setField(-2, "mpack");
|
|
|
|
const retval2 = luaopen_lpeg(lua);
|
|
if (retval2 != 1) return error.LoadError;
|
|
lua.setField(-3, "lpeg");
|
|
|
|
const retval3 = luaopen_luv(lua);
|
|
if (retval3 != 1) return error.LoadError;
|
|
lua.setField(-3, "uv");
|
|
|
|
lua.pop(2);
|
|
|
|
if (!options.use_luajit) {
|
|
lua.pop(luaopen_bit(lua));
|
|
}
|
|
return lua;
|
|
}
|
|
|
|
pub fn main(init: std.process.Init) !void {
|
|
const args = init.minimal.args;
|
|
|
|
const lua = try init_lua();
|
|
defer lua.deinit();
|
|
|
|
if (args.vector.len < 2) {
|
|
std.debug.print("USAGE: nlua0 script.lua args...\n\n", .{});
|
|
return;
|
|
}
|
|
lua.createTable(@intCast(args.vector.len - 2), 1);
|
|
|
|
var iter = try init.minimal.args.iterateAllocator(init.arena.allocator());
|
|
_ = iter.skip();
|
|
var i: u32 = 0;
|
|
var firstarg: [:0]const u8 = undefined;
|
|
while (iter.next()) |val| : (i += 1) {
|
|
_ = lua.pushString(val);
|
|
if (i == 0) {
|
|
firstarg = try lua.toString(-1); // preserved on lua heap..
|
|
}
|
|
lua.setIndexRaw(-2, @intCast(i));
|
|
}
|
|
lua.setGlobal("arg");
|
|
|
|
_ = lua.getGlobal("debug");
|
|
_ = lua.getField(-1, "traceback");
|
|
try lua.loadFile(firstarg);
|
|
lua.protectedCall(.{ .msg_handler = -2 }) catch |e| {
|
|
if (e == error.LuaRuntime) {
|
|
const msg = try lua.toString(-1);
|
|
std.debug.print("{s}\n", .{msg});
|
|
}
|
|
return e;
|
|
};
|
|
}
|
|
|
|
fn do_ret1(lua: *Lua, str: [:0]const u8) !void {
|
|
try lua.loadString(str);
|
|
try lua.protectedCall(.{ .results = 1 });
|
|
}
|
|
|
|
test "simple test" {
|
|
const lua = try init_lua();
|
|
defer lua.deinit();
|
|
|
|
try do_ret1(lua, "return vim.isarray({2,3})");
|
|
try std.testing.expectEqual(true, lua.toBoolean(-1));
|
|
lua.pop(1);
|
|
|
|
try do_ret1(lua, "return vim.isarray({a=2,b=3})");
|
|
try std.testing.expectEqual(false, lua.toBoolean(-1));
|
|
lua.pop(1);
|
|
|
|
try do_ret1(lua, "return vim.inspect(vim.mpack.decode('\\146\\42\\69'))");
|
|
try std.testing.expectEqualStrings("{ 42, 69 }", try lua.toString(-1));
|
|
lua.pop(1);
|
|
|
|
try do_ret1(lua, "return require'bit'.band(7,12)");
|
|
try std.testing.expectEqualStrings("4", try lua.toString(-1));
|
|
lua.pop(1);
|
|
}
|