neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

nlua0.zig (3922B)


      1 //! "nlua" is an abbreviation for nvim flavored lua, i e lua with the
      2 //! extended standard library functionality added by nvim such as json, mpack
      3 //! and libuv and a range of vim.* utility functions.
      4 //!
      5 //! nlua0 is an interpreter for the "bootstrap" lua code we need to run before
      6 //! nvim can be built, in order to run lua scripts which process and generate
      7 //! more .c code, which still need these extensions.
      8 const std = @import("std");
      9 const ziglua = @import("ziglua");
     10 const options = @import("options");
     11 
     12 const embedded_data = @import("embedded_data");
     13 
     14 // these are common dependencies used by many generators
     15 const hashy = @embedFile("gen/hashy.lua");
     16 const c_grammar = @embedFile("gen/c_grammar.lua");
     17 
     18 const Lua = ziglua.Lua;
     19 
     20 extern "c" fn luaopen_mpack(ptr: *anyopaque) c_int;
     21 extern "c" fn luaopen_lpeg(ptr: *anyopaque) c_int;
     22 extern "c" fn luaopen_bit(ptr: *anyopaque) c_int;
     23 extern "c" fn luaopen_luv(ptr: *anyopaque) c_int;
     24 
     25 fn init() !*Lua {
     26    // Initialize the Lua vm
     27    var lua = try Lua.init(std.heap.c_allocator);
     28    lua.openLibs();
     29 
     30    // this sets _G.vim by itself, so we don't need to
     31    try lua.loadBuffer(embedded_data.shared_module, "shared.lua");
     32    lua.call(.{ .results = 1 });
     33 
     34    try lua.loadBuffer(embedded_data.inspect_module, "inspect.lua");
     35    lua.call(.{ .results = 1 });
     36    lua.setField(-2, "inspect");
     37 
     38    try lua.loadBuffer(embedded_data.iter_module, "iter.lua");
     39    lua.call(.{ .results = 1 });
     40    lua.setField(-2, "iter");
     41 
     42    _ = try lua.getGlobal("package");
     43    _ = lua.getField(-1, "preload");
     44    try lua.loadBuffer(hashy, "hashy.lua"); // [package, preload, hashy]
     45    lua.setField(-2, "gen.hashy");
     46    try lua.loadBuffer(c_grammar, "c_grammar.lua"); // [package, preload, c_grammar]
     47    lua.setField(-2, "gen.c_grammar");
     48    lua.pop(2);
     49 
     50    const retval = luaopen_mpack(lua);
     51    if (retval != 1) return error.LoadError;
     52    _ = lua.getField(-1, "NIL"); // [vim, mpack, NIL]
     53    lua.setField(-3, "NIL"); // vim.NIL = mpack.NIL (wow BOB wow)
     54    lua.setField(-2, "mpack");
     55 
     56    const retval2 = luaopen_lpeg(lua);
     57    if (retval2 != 1) return error.LoadError;
     58    lua.setField(-3, "lpeg");
     59 
     60    const retval3 = luaopen_luv(lua);
     61    if (retval3 != 1) return error.LoadError;
     62    lua.setField(-3, "uv");
     63 
     64    lua.pop(2);
     65 
     66    if (!options.use_luajit) {
     67        lua.pop(luaopen_bit(lua));
     68    }
     69    return lua;
     70 }
     71 
     72 pub fn main() !void {
     73    const argv = std.os.argv;
     74 
     75    const lua = try init();
     76    defer lua.deinit();
     77 
     78    if (argv.len < 2) {
     79        std.debug.print("USAGE: nlua0 script.lua args...\n\n", .{});
     80        return;
     81    }
     82    lua.createTable(@intCast(argv.len - 2), 1);
     83    for (0.., argv[1..]) |i, arg| {
     84        _ = lua.pushString(std.mem.span(arg));
     85        lua.rawSetIndex(-2, @intCast(i));
     86    }
     87    lua.setGlobal("arg");
     88 
     89    _ = try lua.getGlobal("debug");
     90    _ = lua.getField(-1, "traceback");
     91    try lua.loadFile(std.mem.span(argv[1]));
     92    lua.protectedCall(.{ .msg_handler = -2 }) catch |e| {
     93        if (e == error.LuaRuntime) {
     94            const msg = try lua.toString(-1);
     95            std.debug.print("{s}\n", .{msg});
     96        }
     97        return e;
     98    };
     99 }
    100 
    101 fn do_ret1(lua: *Lua, str: [:0]const u8) !void {
    102    try lua.loadString(str);
    103    try lua.protectedCall(.{ .results = 1 });
    104 }
    105 
    106 test "simple test" {
    107    const lua = try init();
    108    defer lua.deinit();
    109 
    110    try do_ret1(lua, "return vim.isarray({2,3})");
    111    try std.testing.expectEqual(true, lua.toBoolean(-1));
    112    lua.pop(1);
    113 
    114    try do_ret1(lua, "return vim.isarray({a=2,b=3})");
    115    try std.testing.expectEqual(false, lua.toBoolean(-1));
    116    lua.pop(1);
    117 
    118    try do_ret1(lua, "return vim.inspect(vim.mpack.decode('\\146\\42\\69'))");
    119    try std.testing.expectEqualStrings("{ 42, 69 }", try lua.toString(-1));
    120    lua.pop(1);
    121 
    122    try do_ret1(lua, "return require'bit'.band(7,12)");
    123    try std.testing.expectEqualStrings("4", try lua.toString(-1));
    124    lua.pop(1);
    125 }