1 // This is an open source non-commercial project. Dear PVS-Studio, please check
2 // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
3
4 #include <lauxlib.h>
5 #include <lua.h>
6 #include <lualib.h>
7
8 #include "luv/luv.h"
9 #include "nvim/api/private/defs.h"
10 #include "nvim/api/private/helpers.h"
11 #include "nvim/api/vim.h"
12 #include "nvim/ascii.h"
13 #include "nvim/assert.h"
14 #include "nvim/buffer_defs.h"
15 #include "nvim/change.h"
16 #include "nvim/cursor.h"
17 #include "nvim/eval/userfunc.h"
18 #include "nvim/event/loop.h"
19 #include "nvim/event/time.h"
20 #include "nvim/ex_cmds2.h"
21 #include "nvim/ex_getln.h"
22 #include "nvim/extmark.h"
23 #include "nvim/func_attr.h"
24 #include "nvim/garray.h"
25 #include "nvim/getchar.h"
26 #include "nvim/lua/converter.h"
27 #include "nvim/lua/executor.h"
28 #include "nvim/lua/stdlib.h"
29 #include "nvim/lua/treesitter.h"
30 #include "nvim/macros.h"
31 #include "nvim/map.h"
32 #include "nvim/memline.h"
33 #include "nvim/message.h"
34 #include "nvim/misc1.h"
35 #include "nvim/msgpack_rpc/channel.h"
36 #include "nvim/os/os.h"
37 #include "nvim/screen.h"
38 #include "nvim/undo.h"
39 #include "nvim/version.h"
40 #include "nvim/vim.h"
41
42 static int in_fast_callback = 0;
43
44 // Initialized in nlua_init().
45 static lua_State *global_lstate = NULL;
46
47 typedef struct {
48 Error err;
49 String lua_err_str;
50 } LuaError;
51
52 #ifdef INCLUDE_GENERATED_DECLARATIONS
53 # include "lua/executor.c.generated.h"
54 # include "lua/vim_module.generated.h"
55 #endif
56
57 #define PUSH_ALL_TYPVALS(lstate, args, argcount, special) \
58 for (int i = 0; i < argcount; i++) { \
59 if (args[i].v_type == VAR_UNKNOWN) { \
60 lua_pushnil(lstate); \
61 } else { \
62 nlua_push_typval(lstate, &args[i], special); \
63 } \
64 }
65
66 #if __has_feature(address_sanitizer)
67 static PMap(handle_T) nlua_ref_markers = MAP_INIT;
68 static bool nlua_track_refs = false;
69 # define NLUA_TRACK_REFS
70 #endif
71
72 /// Convert lua error into a Vim error message
73 ///
74 /// @param lstate Lua interpreter state.
75 /// @param[in] msg Message base, must contain one `%s`.
nlua_error(lua_State * const lstate,const char * const msg)76 static void nlua_error(lua_State *const lstate, const char *const msg)
77 FUNC_ATTR_NONNULL_ALL
78 {
79 size_t len;
80 const char *const str = lua_tolstring(lstate, -1, &len);
81
82 msg_ext_set_kind("lua_error");
83 semsg_multiline(msg, (int)len, str);
84
85 lua_pop(lstate, 1);
86 }
87
88 /// Like lua_pcall, but use debug.traceback as errfunc.
89 ///
90 /// @param lstate Lua interpreter state
91 /// @param[in] nargs Number of arguments expected by the function being called.
92 /// @param[in] nresults Number of results the function returns.
nlua_pcall(lua_State * lstate,int nargs,int nresults)93 static int nlua_pcall(lua_State *lstate, int nargs, int nresults)
94 {
95 lua_getglobal(lstate, "debug");
96 lua_getfield(lstate, -1, "traceback");
97 lua_remove(lstate, -2);
98 lua_insert(lstate, -2 - nargs);
99 int status = lua_pcall(lstate, nargs, nresults, -2 - nargs);
100 if (status) {
101 lua_remove(lstate, -2);
102 } else {
103 lua_remove(lstate, -1 - nresults);
104 }
105 return status;
106 }
107
108
109 /// Gets the version of the current Nvim build.
110 ///
111 /// @param lstate Lua interpreter state.
nlua_nvim_version(lua_State * const lstate)112 static int nlua_nvim_version(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
113 {
114 Dictionary version = version_dict();
115 nlua_push_Dictionary(lstate, version, true);
116 api_free_dictionary(version);
117 return 1;
118 }
119
120
nlua_luv_error_event(void ** argv)121 static void nlua_luv_error_event(void **argv)
122 {
123 char *error = (char *)argv[0];
124 msg_ext_set_kind("lua_error");
125 semsg_multiline("Error executing luv callback:\n%s", error);
126 xfree(error);
127 }
128
nlua_luv_cfpcall(lua_State * lstate,int nargs,int nresult,int flags)129 static int nlua_luv_cfpcall(lua_State *lstate, int nargs, int nresult, int flags)
130 FUNC_ATTR_NONNULL_ALL
131 {
132 int retval;
133
134 // luv callbacks might be executed at any os_breakcheck/line_breakcheck
135 // call, so using the API directly here is not safe.
136 in_fast_callback++;
137
138 int top = lua_gettop(lstate);
139 int status = nlua_pcall(lstate, nargs, nresult);
140 if (status) {
141 if (status == LUA_ERRMEM && !(flags & LUVF_CALLBACK_NOEXIT)) {
142 // consider out of memory errors unrecoverable, just like xmalloc()
143 mch_errmsg(e_outofmem);
144 mch_errmsg("\n");
145 preserve_exit();
146 }
147 const char *error = lua_tostring(lstate, -1);
148
149 multiqueue_put(main_loop.events, nlua_luv_error_event,
150 1, xstrdup(error));
151 lua_pop(lstate, 1); // error message
152 retval = -status;
153 } else { // LUA_OK
154 if (nresult == LUA_MULTRET) {
155 nresult = lua_gettop(lstate) - top + nargs + 1;
156 }
157 retval = nresult;
158 }
159
160 in_fast_callback--;
161 return retval;
162 }
163
nlua_schedule_event(void ** argv)164 static void nlua_schedule_event(void **argv)
165 {
166 LuaRef cb = (LuaRef)(ptrdiff_t)argv[0];
167 lua_State *const lstate = global_lstate;
168 nlua_pushref(lstate, cb);
169 nlua_unref(lstate, cb);
170 if (nlua_pcall(lstate, 0, 0)) {
171 nlua_error(lstate, _("Error executing vim.schedule lua callback: %.*s"));
172 }
173 }
174
175 /// Schedule Lua callback on main loop's event queue
176 ///
177 /// @param lstate Lua interpreter state.
nlua_schedule(lua_State * const lstate)178 static int nlua_schedule(lua_State *const lstate)
179 FUNC_ATTR_NONNULL_ALL
180 {
181 if (lua_type(lstate, 1) != LUA_TFUNCTION) {
182 lua_pushliteral(lstate, "vim.schedule: expected function");
183 return lua_error(lstate);
184 }
185
186 LuaRef cb = nlua_ref(lstate, 1);
187
188 multiqueue_put(main_loop.events, nlua_schedule_event,
189 1, (void *)(ptrdiff_t)cb);
190 return 0;
191 }
192
193 // Dummy timer callback. Used by f_wait().
dummy_timer_due_cb(TimeWatcher * tw,void * data)194 static void dummy_timer_due_cb(TimeWatcher *tw, void *data)
195 {
196 }
197
198 // Dummy timer close callback. Used by f_wait().
dummy_timer_close_cb(TimeWatcher * tw,void * data)199 static void dummy_timer_close_cb(TimeWatcher *tw, void *data)
200 {
201 xfree(tw);
202 }
203
nlua_wait_condition(lua_State * lstate,int * status,bool * callback_result)204 static bool nlua_wait_condition(lua_State *lstate, int *status, bool *callback_result)
205 {
206 lua_pushvalue(lstate, 2);
207 *status = nlua_pcall(lstate, 0, 1);
208 if (*status) {
209 return true; // break on error, but keep error on stack
210 }
211 *callback_result = lua_toboolean(lstate, -1);
212 lua_pop(lstate, 1);
213 return *callback_result; // break if true
214 }
215
216 /// "vim.wait(timeout, condition[, interval])" function
nlua_wait(lua_State * lstate)217 static int nlua_wait(lua_State *lstate)
218 FUNC_ATTR_NONNULL_ALL
219 {
220 intptr_t timeout = luaL_checkinteger(lstate, 1);
221 if (timeout < 0) {
222 return luaL_error(lstate, "timeout must be > 0");
223 }
224
225 int lua_top = lua_gettop(lstate);
226
227 // Check if condition can be called.
228 bool is_function = false;
229 if (lua_top >= 2 && !lua_isnil(lstate, 2)) {
230 is_function = (lua_type(lstate, 2) == LUA_TFUNCTION);
231
232 // Check if condition is callable table
233 if (!is_function && luaL_getmetafield(lstate, 2, "__call") != 0) {
234 is_function = (lua_type(lstate, -1) == LUA_TFUNCTION);
235 lua_pop(lstate, 1);
236 }
237
238 if (!is_function) {
239 lua_pushliteral(lstate,
240 "vim.wait: if passed, condition must be a function");
241 return lua_error(lstate);
242 }
243 }
244
245 intptr_t interval = 200;
246 if (lua_top >= 3 && !lua_isnil(lstate, 3)) {
247 interval = luaL_checkinteger(lstate, 3);
248 if (interval < 0) {
249 return luaL_error(lstate, "interval must be > 0");
250 }
251 }
252
253 bool fast_only = false;
254 if (lua_top >= 4) {
255 fast_only = lua_toboolean(lstate, 4);
256 }
257
258 MultiQueue *loop_events = fast_only || in_fast_callback > 0
259 ? main_loop.fast_events : main_loop.events;
260
261 TimeWatcher *tw = xmalloc(sizeof(TimeWatcher));
262
263 // Start dummy timer.
264 time_watcher_init(&main_loop, tw, NULL);
265 tw->events = loop_events;
266 tw->blockable = true;
267 time_watcher_start(tw,
268 dummy_timer_due_cb,
269 (uint64_t)interval,
270 (uint64_t)interval);
271
272 int pcall_status = 0;
273 bool callback_result = false;
274
275 LOOP_PROCESS_EVENTS_UNTIL(&main_loop,
276 loop_events,
277 (int)timeout,
278 is_function ? nlua_wait_condition(lstate,
279 &pcall_status,
280 &callback_result) : false || got_int);
281
282 // Stop dummy timer
283 time_watcher_stop(tw);
284 time_watcher_close(tw, dummy_timer_close_cb);
285
286 if (pcall_status) {
287 return lua_error(lstate);
288 } else if (callback_result) {
289 lua_pushboolean(lstate, 1);
290 lua_pushnil(lstate);
291 } else if (got_int) {
292 got_int = false;
293 vgetc();
294 lua_pushboolean(lstate, 0);
295 lua_pushinteger(lstate, -2);
296 } else {
297 lua_pushboolean(lstate, 0);
298 lua_pushinteger(lstate, -1);
299 }
300
301 return 2;
302 }
303
304 /// Initialize lua interpreter state
305 ///
306 /// Called by lua interpreter itself to initialize state.
nlua_state_init(lua_State * const lstate)307 static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
308 {
309 // print
310 lua_pushcfunction(lstate, &nlua_print);
311 lua_setglobal(lstate, "print");
312
313 // debug.debug
314 lua_getglobal(lstate, "debug");
315 lua_pushcfunction(lstate, &nlua_debug);
316 lua_setfield(lstate, -2, "debug");
317 lua_pop(lstate, 1);
318
319 #ifdef WIN32
320 // os.getenv
321 lua_getglobal(lstate, "os");
322 lua_pushcfunction(lstate, &nlua_getenv);
323 lua_setfield(lstate, -2, "getenv");
324 lua_pop(lstate, 1);
325 #endif
326
327 // vim
328 lua_newtable(lstate);
329
330 // vim.api
331 nlua_add_api_functions(lstate);
332
333 // vim.types, vim.type_idx, vim.val_idx
334 nlua_init_types(lstate);
335
336 // neovim version
337 lua_pushcfunction(lstate, &nlua_nvim_version);
338 lua_setfield(lstate, -2, "version");
339
340 // schedule
341 lua_pushcfunction(lstate, &nlua_schedule);
342 lua_setfield(lstate, -2, "schedule");
343
344 // in_fast_event
345 lua_pushcfunction(lstate, &nlua_in_fast_event);
346 lua_setfield(lstate, -2, "in_fast_event");
347
348 // call
349 lua_pushcfunction(lstate, &nlua_call);
350 lua_setfield(lstate, -2, "call");
351
352 // rpcrequest
353 lua_pushcfunction(lstate, &nlua_rpcrequest);
354 lua_setfield(lstate, -2, "rpcrequest");
355
356 // rpcnotify
357 lua_pushcfunction(lstate, &nlua_rpcnotify);
358 lua_setfield(lstate, -2, "rpcnotify");
359
360 // wait
361 lua_pushcfunction(lstate, &nlua_wait);
362 lua_setfield(lstate, -2, "wait");
363
364 // vim.NIL
365 lua_newuserdata(lstate, 0);
366 lua_createtable(lstate, 0, 0);
367 lua_pushcfunction(lstate, &nlua_nil_tostring);
368 lua_setfield(lstate, -2, "__tostring");
369 lua_setmetatable(lstate, -2);
370 nlua_nil_ref = nlua_ref(lstate, -1);
371 lua_pushvalue(lstate, -1);
372 lua_setfield(lstate, LUA_REGISTRYINDEX, "mpack.NIL");
373 lua_setfield(lstate, -2, "NIL");
374
375 // vim._empty_dict_mt
376 lua_createtable(lstate, 0, 0);
377 lua_pushcfunction(lstate, &nlua_empty_dict_tostring);
378 lua_setfield(lstate, -2, "__tostring");
379 nlua_empty_dict_ref = nlua_ref(lstate, -1);
380 lua_pushvalue(lstate, -1);
381 lua_setfield(lstate, LUA_REGISTRYINDEX, "mpack.empty_dict");
382 lua_setfield(lstate, -2, "_empty_dict_mt");
383
384 // internal vim._treesitter... API
385 nlua_add_treesitter(lstate);
386
387 // vim.loop
388 luv_set_loop(lstate, &main_loop.uv);
389 luv_set_callback(lstate, nlua_luv_cfpcall);
390 luaopen_luv(lstate);
391 lua_pushvalue(lstate, -1);
392 lua_setfield(lstate, -3, "loop");
393
394 // package.loaded.luv = vim.loop
395 // otherwise luv will be reinitialized when require'luv'
396 lua_getglobal(lstate, "package");
397 lua_getfield(lstate, -1, "loaded");
398 lua_pushvalue(lstate, -3);
399 lua_setfield(lstate, -2, "luv");
400 lua_pop(lstate, 3);
401
402 nlua_state_add_stdlib(lstate);
403
404 lua_setglobal(lstate, "vim");
405
406 {
407 const char *code = (char *)&shared_module[0];
408 if (luaL_loadbuffer(lstate, code, strlen(code), "@vim/shared.lua")
409 || nlua_pcall(lstate, 0, 0)) {
410 nlua_error(lstate, _("E5106: Error while creating shared module: %.*s"));
411 return 1;
412 }
413 }
414
415 {
416 lua_getglobal(lstate, "package"); // [package]
417 lua_getfield(lstate, -1, "loaded"); // [package, loaded]
418
419 const char *code = (char *)&inspect_module[0];
420 if (luaL_loadbuffer(lstate, code, strlen(code), "@vim/inspect.lua")
421 || nlua_pcall(lstate, 0, 1)) {
422 nlua_error(lstate, _("E5106: Error while creating inspect module: %.*s"));
423 return 1;
424 }
425 // [package, loaded, inspect]
426 lua_setfield(lstate, -2, "vim.inspect"); // [package, loaded]
427
428 code = (char *)&lua_F_module[0];
429 if (luaL_loadbuffer(lstate, code, strlen(code), "@vim/F.lua")
430 || nlua_pcall(lstate, 0, 1)) {
431 nlua_error(lstate, _("E5106: Error while creating vim.F module: %.*s"));
432 return 1;
433 }
434 // [package, loaded, module]
435 lua_setfield(lstate, -2, "vim.F"); // [package, loaded]
436
437 lua_pop(lstate, 2); // []
438 }
439
440 {
441 const char *code = (char *)&vim_module[0];
442 if (luaL_loadbuffer(lstate, code, strlen(code), "@vim.lua")
443 || nlua_pcall(lstate, 0, 0)) {
444 nlua_error(lstate, _("E5106: Error while creating vim module: %.*s"));
445 return 1;
446 }
447 }
448
449 {
450 lua_getglobal(lstate, "package"); // [package]
451 lua_getfield(lstate, -1, "loaded"); // [package, loaded]
452
453 const char *code = (char *)&lua_meta_module[0];
454 if (luaL_loadbuffer(lstate, code, strlen(code), "@vim/_meta.lua")
455 || nlua_pcall(lstate, 0, 1)) {
456 nlua_error(lstate, _("E5106: Error while creating vim._meta module: %.*s"));
457 return 1;
458 }
459 // [package, loaded, module]
460 lua_setfield(lstate, -2, "vim._meta"); // [package, loaded]
461
462 lua_pop(lstate, 2); // []
463 }
464
465 return 0;
466 }
467
468 /// Initialize global lua interpreter
469 ///
470 /// Crashes Nvim if initialization fails.
nlua_init(void)471 void nlua_init(void)
472 {
473 #ifdef NLUA_TRACK_REFS
474 const char *env = os_getenv("NVIM_LUA_NOTRACK");
475 if (!env || !*env) {
476 nlua_track_refs = true;
477 }
478 #endif
479
480 lua_State *lstate = luaL_newstate();
481 if (lstate == NULL) {
482 emsg(_("E970: Failed to initialize lua interpreter"));
483 preserve_exit();
484 }
485 luaL_openlibs(lstate);
486 nlua_state_init(lstate);
487
488 global_lstate = lstate;
489 }
490
491
nlua_free_all_mem(void)492 void nlua_free_all_mem(void)
493 {
494 if (!global_lstate) {
495 return;
496 }
497 lua_State *lstate = global_lstate;
498
499 nlua_unref(lstate, nlua_nil_ref);
500 nlua_unref(lstate, nlua_empty_dict_ref);
501
502 #ifdef NLUA_TRACK_REFS
503 if (nlua_refcount) {
504 fprintf(stderr, "%d lua references were leaked!", nlua_refcount);
505 }
506
507 if (nlua_track_refs) {
508 // in case there are leaked luarefs, leak the associated memory
509 // to get LeakSanitizer stacktraces on exit
510 pmap_destroy(handle_T)(&nlua_ref_markers);
511 }
512 #endif
513
514 nlua_refcount = 0;
515 lua_close(lstate);
516 }
517
nlua_print_event(void ** argv)518 static void nlua_print_event(void **argv)
519 {
520 char *str = argv[0];
521 const size_t len = (size_t)(intptr_t)argv[1]-1; // exclude final NUL
522
523 for (size_t i = 0; i < len;) {
524 const size_t start = i;
525 while (i < len) {
526 switch (str[i]) {
527 case NUL:
528 str[i] = NL;
529 i++;
530 continue;
531 case NL:
532 // TODO(bfredl): use proper multiline msg? Probably should implement
533 // print() in lua in terms of nvim_message(), when it is available.
534 str[i] = NUL;
535 i++;
536 break;
537 default:
538 i++;
539 continue;
540 }
541 break;
542 }
543 msg(str + start);
544 }
545 if (len && str[len - 1] == NUL) { // Last was newline
546 msg("");
547 }
548 xfree(str);
549 }
550
551 /// Print as a Vim message
552 ///
553 /// @param lstate Lua interpreter state.
nlua_print(lua_State * const lstate)554 static int nlua_print(lua_State *const lstate)
555 FUNC_ATTR_NONNULL_ALL
556 {
557 #define PRINT_ERROR(msg) \
558 do { \
559 errmsg = msg; \
560 errmsg_len = sizeof(msg) - 1; \
561 goto nlua_print_error; \
562 } while (0)
563 const int nargs = lua_gettop(lstate);
564 lua_getglobal(lstate, "tostring");
565 const char *errmsg = NULL;
566 size_t errmsg_len = 0;
567 garray_T msg_ga;
568 ga_init(&msg_ga, 1, 80);
569 int curargidx = 1;
570 for (; curargidx <= nargs; curargidx++) {
571 lua_pushvalue(lstate, -1); // tostring
572 lua_pushvalue(lstate, curargidx); // arg
573 // Do not use nlua_pcall here to avoid duplicate stack trace information
574 if (lua_pcall(lstate, 1, 1, 0)) {
575 errmsg = lua_tolstring(lstate, -1, &errmsg_len);
576 goto nlua_print_error;
577 }
578 size_t len;
579 const char *const s = lua_tolstring(lstate, -1, &len);
580 if (s == NULL) {
581 PRINT_ERROR("<Unknown error: lua_tolstring returned NULL for tostring result>");
582 }
583 ga_concat_len(&msg_ga, s, len);
584 if (curargidx < nargs) {
585 ga_append(&msg_ga, ' ');
586 }
587 lua_pop(lstate, 1);
588 }
589 #undef PRINT_ERROR
590 ga_append(&msg_ga, NUL);
591
592 if (in_fast_callback) {
593 multiqueue_put(main_loop.events, nlua_print_event,
594 2, msg_ga.ga_data, msg_ga.ga_len);
595 } else {
596 nlua_print_event((void *[]){ msg_ga.ga_data,
597 (void *)(intptr_t)msg_ga.ga_len });
598 }
599 return 0;
600
601 nlua_print_error:
602 ga_clear(&msg_ga);
603 const char *fmt = _("E5114: Error while converting print argument #%i: %.*s");
604 size_t len = (size_t)vim_snprintf((char *)IObuff, IOSIZE, fmt, curargidx,
605 (int)errmsg_len, errmsg);
606 lua_pushlstring(lstate, (char *)IObuff, len);
607 return lua_error(lstate);
608 }
609
610 /// debug.debug: interaction with user while debugging.
611 ///
612 /// @param lstate Lua interpreter state.
nlua_debug(lua_State * lstate)613 static int nlua_debug(lua_State *lstate)
614 FUNC_ATTR_NONNULL_ALL
615 {
616 const typval_T input_args[] = {
617 {
618 .v_lock = VAR_FIXED,
619 .v_type = VAR_STRING,
620 .vval.v_string = (char_u *)"lua_debug> ",
621 },
622 {
623 .v_type = VAR_UNKNOWN,
624 },
625 };
626 for (;;) {
627 lua_settop(lstate, 0);
628 typval_T input;
629 get_user_input(input_args, &input, false, false);
630 msg_putchar('\n'); // Avoid outputting on input line.
631 if (input.v_type != VAR_STRING
632 || input.vval.v_string == NULL
633 || *input.vval.v_string == NUL
634 || STRCMP(input.vval.v_string, "cont") == 0) {
635 tv_clear(&input);
636 return 0;
637 }
638 if (luaL_loadbuffer(lstate, (const char *)input.vval.v_string,
639 STRLEN(input.vval.v_string), "=(debug command)")) {
640 nlua_error(lstate, _("E5115: Error while loading debug string: %.*s"));
641 } else if (nlua_pcall(lstate, 0, 0)) {
642 nlua_error(lstate, _("E5116: Error while calling debug string: %.*s"));
643 }
644 tv_clear(&input);
645 }
646 return 0;
647 }
648
nlua_in_fast_event(lua_State * lstate)649 int nlua_in_fast_event(lua_State *lstate)
650 {
651 lua_pushboolean(lstate, in_fast_callback > 0);
652 return 1;
653 }
654
nlua_call(lua_State * lstate)655 int nlua_call(lua_State *lstate)
656 {
657 Error err = ERROR_INIT;
658 size_t name_len;
659 const char_u *name = (const char_u *)luaL_checklstring(lstate, 1, &name_len);
660 if (!nlua_is_deferred_safe()) {
661 return luaL_error(lstate, e_luv_api_disabled, "vimL function");
662 }
663
664 int nargs = lua_gettop(lstate)-1;
665 if (nargs > MAX_FUNC_ARGS) {
666 return luaL_error(lstate, "Function called with too many arguments");
667 }
668
669 typval_T vim_args[MAX_FUNC_ARGS + 1];
670 int i = 0; // also used for freeing the variables
671 for (; i < nargs; i++) {
672 lua_pushvalue(lstate, (int)i+2);
673 if (!nlua_pop_typval(lstate, &vim_args[i])) {
674 api_set_error(&err, kErrorTypeException,
675 "error converting argument %d", i+1);
676 goto free_vim_args;
677 }
678 }
679
680 TRY_WRAP({
681 // TODO(bfredl): this should be simplified in error handling refactor
682 force_abort = false;
683 suppress_errthrow = false;
684 current_exception = NULL;
685 did_emsg = false;
686
687 try_start();
688 typval_T rettv;
689 funcexe_T funcexe = FUNCEXE_INIT;
690 funcexe.firstline = curwin->w_cursor.lnum;
691 funcexe.lastline = curwin->w_cursor.lnum;
692 funcexe.evaluate = true;
693 // call_func() retval is deceptive, ignore it. Instead we set `msg_list`
694 // (TRY_WRAP) to capture abort-causing non-exception errors.
695 (void)call_func(name, (int)name_len, &rettv, nargs, vim_args, &funcexe);
696 if (!try_end(&err)) {
697 nlua_push_typval(lstate, &rettv, false);
698 }
699 tv_clear(&rettv);
700 });
701
702 free_vim_args:
703 while (i > 0) {
704 tv_clear(&vim_args[--i]);
705 }
706 if (ERROR_SET(&err)) {
707 lua_pushstring(lstate, err.msg);
708 api_clear_error(&err);
709 return lua_error(lstate);
710 }
711 return 1;
712 }
713
nlua_rpcrequest(lua_State * lstate)714 static int nlua_rpcrequest(lua_State *lstate)
715 {
716 if (!nlua_is_deferred_safe()) {
717 return luaL_error(lstate, e_luv_api_disabled, "rpcrequest");
718 }
719 return nlua_rpc(lstate, true);
720 }
721
nlua_rpcnotify(lua_State * lstate)722 static int nlua_rpcnotify(lua_State *lstate)
723 {
724 return nlua_rpc(lstate, false);
725 }
726
nlua_rpc(lua_State * lstate,bool request)727 static int nlua_rpc(lua_State *lstate, bool request)
728 {
729 size_t name_len;
730 uint64_t chan_id = (uint64_t)luaL_checkinteger(lstate, 1);
731 const char *name = luaL_checklstring(lstate, 2, &name_len);
732 int nargs = lua_gettop(lstate)-2;
733 Error err = ERROR_INIT;
734 Array args = ARRAY_DICT_INIT;
735
736 for (int i = 0; i < nargs; i++) {
737 lua_pushvalue(lstate, (int)i+3);
738 ADD(args, nlua_pop_Object(lstate, false, &err));
739 if (ERROR_SET(&err)) {
740 api_free_array(args);
741 goto check_err;
742 }
743 }
744
745 if (request) {
746 Object result = rpc_send_call(chan_id, name, args, &err);
747 if (!ERROR_SET(&err)) {
748 nlua_push_Object(lstate, result, false);
749 api_free_object(result);
750 }
751 } else {
752 if (!rpc_send_event(chan_id, name, args)) {
753 api_set_error(&err, kErrorTypeValidation,
754 "Invalid channel: %" PRIu64, chan_id);
755 }
756 }
757
758 check_err:
759 if (ERROR_SET(&err)) {
760 lua_pushstring(lstate, err.msg);
761 api_clear_error(&err);
762 return lua_error(lstate);
763 }
764
765 return request ? 1 : 0;
766 }
767
nlua_nil_tostring(lua_State * lstate)768 static int nlua_nil_tostring(lua_State *lstate)
769 {
770 lua_pushstring(lstate, "vim.NIL");
771 return 1;
772 }
773
nlua_empty_dict_tostring(lua_State * lstate)774 static int nlua_empty_dict_tostring(lua_State *lstate)
775 {
776 lua_pushstring(lstate, "vim.empty_dict()");
777 return 1;
778 }
779
780
781 #ifdef WIN32
782 /// os.getenv: override os.getenv to maintain coherency. #9681
783 ///
784 /// uv_os_setenv uses SetEnvironmentVariableW which does not update _environ.
785 ///
786 /// @param lstate Lua interpreter state.
nlua_getenv(lua_State * lstate)787 static int nlua_getenv(lua_State *lstate)
788 {
789 lua_pushstring(lstate, os_getenv(luaL_checkstring(lstate, 1)));
790 return 1;
791 }
792 #endif
793
794
795 /// add the value to the registry
nlua_ref(lua_State * lstate,int index)796 LuaRef nlua_ref(lua_State *lstate, int index)
797 {
798 lua_pushvalue(lstate, index);
799 LuaRef ref = luaL_ref(lstate, LUA_REGISTRYINDEX);
800 if (ref > 0) {
801 nlua_refcount++;
802 #ifdef NLUA_TRACK_REFS
803 if (nlua_track_refs) {
804 // dummy allocation to make LeakSanitizer track our luarefs
805 pmap_put(handle_T)(&nlua_ref_markers, ref, xmalloc(3));
806 }
807 #endif
808 }
809 return ref;
810 }
811
812 /// remove the value from the registry
nlua_unref(lua_State * lstate,LuaRef ref)813 void nlua_unref(lua_State *lstate, LuaRef ref)
814 {
815 if (ref > 0) {
816 nlua_refcount--;
817 #ifdef NLUA_TRACK_REFS
818 // NB: don't remove entry from map to track double-unref
819 if (nlua_track_refs) {
820 xfree(pmap_get(handle_T)(&nlua_ref_markers, ref));
821 }
822 #endif
823 luaL_unref(lstate, LUA_REGISTRYINDEX, ref);
824 }
825 }
826
api_free_luaref(LuaRef ref)827 void api_free_luaref(LuaRef ref)
828 {
829 nlua_unref(global_lstate, ref);
830 }
831
832 /// push a value referenced in the registry
nlua_pushref(lua_State * lstate,LuaRef ref)833 void nlua_pushref(lua_State *lstate, LuaRef ref)
834 {
835 lua_rawgeti(lstate, LUA_REGISTRYINDEX, ref);
836 }
837
838
839 /// Gets a new reference to an object stored at original_ref
840 ///
841 /// NOTE: It does not copy the value, it creates a new ref to the lua object.
842 /// Leaves the stack unchanged.
api_new_luaref(LuaRef original_ref)843 LuaRef api_new_luaref(LuaRef original_ref)
844 {
845 if (original_ref == LUA_NOREF) {
846 return LUA_NOREF;
847 }
848
849 lua_State *const lstate = global_lstate;
850 nlua_pushref(lstate, original_ref);
851 LuaRef new_ref = nlua_ref(lstate, -1);
852 lua_pop(lstate, 1);
853 return new_ref;
854 }
855
856
857 /// Evaluate lua string
858 ///
859 /// Used for luaeval().
860 ///
861 /// @param[in] str String to execute.
862 /// @param[in] arg Second argument to `luaeval()`.
863 /// @param[out] ret_tv Location where result will be saved.
864 ///
865 /// @return Result of the execution.
nlua_typval_eval(const String str,typval_T * const arg,typval_T * const ret_tv)866 void nlua_typval_eval(const String str, typval_T *const arg, typval_T *const ret_tv)
867 FUNC_ATTR_NONNULL_ALL
868 {
869 #define EVALHEADER "local _A=select(1,...) return ("
870 const size_t lcmd_len = sizeof(EVALHEADER) - 1 + str.size + 1;
871 char *lcmd;
872 if (lcmd_len < IOSIZE) {
873 lcmd = (char *)IObuff;
874 } else {
875 lcmd = xmalloc(lcmd_len);
876 }
877 memcpy(lcmd, EVALHEADER, sizeof(EVALHEADER) - 1);
878 memcpy(lcmd + sizeof(EVALHEADER) - 1, str.data, str.size);
879 lcmd[lcmd_len - 1] = ')';
880 #undef EVALHEADER
881 nlua_typval_exec(lcmd, lcmd_len, "luaeval()", arg, 1, true, ret_tv);
882
883 if (lcmd != (char *)IObuff) {
884 xfree(lcmd);
885 }
886 }
887
nlua_typval_call(const char * str,size_t len,typval_T * const args,int argcount,typval_T * ret_tv)888 void nlua_typval_call(const char *str, size_t len, typval_T *const args, int argcount,
889 typval_T *ret_tv)
890 FUNC_ATTR_NONNULL_ALL
891 {
892 #define CALLHEADER "return "
893 #define CALLSUFFIX "(...)"
894 const size_t lcmd_len = sizeof(CALLHEADER) - 1 + len + sizeof(CALLSUFFIX) - 1;
895 char *lcmd;
896 if (lcmd_len < IOSIZE) {
897 lcmd = (char *)IObuff;
898 } else {
899 lcmd = xmalloc(lcmd_len);
900 }
901 memcpy(lcmd, CALLHEADER, sizeof(CALLHEADER) - 1);
902 memcpy(lcmd + sizeof(CALLHEADER) - 1, str, len);
903 memcpy(lcmd + sizeof(CALLHEADER) - 1 + len, CALLSUFFIX,
904 sizeof(CALLSUFFIX) - 1);
905 #undef CALLHEADER
906 #undef CALLSUFFIX
907
908 nlua_typval_exec(lcmd, lcmd_len, "v:lua", args, argcount, false, ret_tv);
909
910 if (lcmd != (char *)IObuff) {
911 xfree(lcmd);
912 }
913 }
914
nlua_typval_exec(const char * lcmd,size_t lcmd_len,const char * name,typval_T * const args,int argcount,bool special,typval_T * ret_tv)915 static void nlua_typval_exec(const char *lcmd, size_t lcmd_len, const char *name,
916 typval_T *const args, int argcount, bool special, typval_T *ret_tv)
917 {
918 if (check_secure()) {
919 if (ret_tv) {
920 ret_tv->v_type = VAR_NUMBER;
921 ret_tv->vval.v_number = 0;
922 }
923 return;
924 }
925
926 lua_State *const lstate = global_lstate;
927 if (luaL_loadbuffer(lstate, lcmd, lcmd_len, name)) {
928 nlua_error(lstate, _("E5107: Error loading lua %.*s"));
929 return;
930 }
931
932 PUSH_ALL_TYPVALS(lstate, args, argcount, special);
933
934 if (nlua_pcall(lstate, argcount, ret_tv ? 1 : 0)) {
935 nlua_error(lstate, _("E5108: Error executing lua %.*s"));
936 return;
937 }
938
939 if (ret_tv) {
940 nlua_pop_typval(lstate, ret_tv);
941 }
942 }
943
nlua_source_using_linegetter(LineGetter fgetline,void * cookie,char * name)944 int nlua_source_using_linegetter(LineGetter fgetline, void *cookie, char *name)
945 {
946 const linenr_T save_sourcing_lnum = sourcing_lnum;
947 const sctx_T save_current_sctx = current_sctx;
948 current_sctx.sc_sid = SID_STR;
949 current_sctx.sc_seq = 0;
950 current_sctx.sc_lnum = 0;
951 sourcing_lnum = 0;
952
953 garray_T ga;
954 char_u *line = NULL;
955
956 ga_init(&ga, (int)sizeof(char_u *), 10);
957 while ((line = fgetline(0, cookie, 0, false)) != NULL) {
958 GA_APPEND(char_u *, &ga, line);
959 }
960 char *code = ga_concat_strings_sep(&ga, "\n");
961 size_t len = strlen(code);
962 nlua_typval_exec(code, len, name, NULL, 0, false, NULL);
963
964 sourcing_lnum = save_sourcing_lnum;
965 current_sctx = save_current_sctx;
966 ga_clear_strings(&ga);
967 xfree(code);
968 return OK;
969 }
970
971 /// Call a LuaCallable given some typvals
972 ///
973 /// Used to call any lua callable passed from Lua into VimL
974 ///
975 /// @param[in] lstate Lua State
976 /// @param[in] lua_cb Lua Callable
977 /// @param[in] argcount Count of typval arguments
978 /// @param[in] argvars Typval Arguments
979 /// @param[out] rettv The return value from the called function.
typval_exec_lua_callable(lua_State * lstate,LuaCallable lua_cb,int argcount,typval_T * argvars,typval_T * rettv)980 int typval_exec_lua_callable(lua_State *lstate, LuaCallable lua_cb, int argcount, typval_T *argvars,
981 typval_T *rettv)
982 {
983 LuaRef cb = lua_cb.func_ref;
984
985 nlua_pushref(lstate, cb);
986
987 PUSH_ALL_TYPVALS(lstate, argvars, argcount, false);
988
989 if (nlua_pcall(lstate, argcount, 1)) {
990 nlua_print(lstate);
991 return ERROR_OTHER;
992 }
993
994 nlua_pop_typval(lstate, rettv);
995
996 return ERROR_NONE;
997 }
998
999 /// Execute Lua string
1000 ///
1001 /// Used for nvim_exec_lua() and internally to execute a lua string.
1002 ///
1003 /// @param[in] str String to execute.
1004 /// @param[in] args array of ... args
1005 /// @param[out] err Location where error will be saved.
1006 ///
1007 /// @return Return value of the execution.
nlua_exec(const String str,const Array args,Error * err)1008 Object nlua_exec(const String str, const Array args, Error *err)
1009 {
1010 lua_State *const lstate = global_lstate;
1011
1012 if (luaL_loadbuffer(lstate, str.data, str.size, "<nvim>")) {
1013 size_t len;
1014 const char *errstr = lua_tolstring(lstate, -1, &len);
1015 api_set_error(err, kErrorTypeValidation,
1016 "Error loading lua: %.*s", (int)len, errstr);
1017 return NIL;
1018 }
1019
1020 for (size_t i = 0; i < args.size; i++) {
1021 nlua_push_Object(lstate, args.items[i], false);
1022 }
1023
1024 if (nlua_pcall(lstate, (int)args.size, 1)) {
1025 size_t len;
1026 const char *errstr = lua_tolstring(lstate, -1, &len);
1027 api_set_error(err, kErrorTypeException,
1028 "Error executing lua: %.*s", (int)len, errstr);
1029 return NIL;
1030 }
1031
1032 return nlua_pop_Object(lstate, false, err);
1033 }
1034
1035 /// call a LuaRef as a function (or table with __call metamethod)
1036 ///
1037 /// @param ref the reference to call (not consumed)
1038 /// @param name if non-NULL, sent to callback as first arg
1039 /// if NULL, only args are used
1040 /// @param retval if true, convert return value to Object
1041 /// if false, discard return value
1042 /// @param err Error details, if any (if NULL, errors are echoed)
1043 /// @return Return value of function, if retval was set. Otherwise NIL.
nlua_call_ref(LuaRef ref,const char * name,Array args,bool retval,Error * err)1044 Object nlua_call_ref(LuaRef ref, const char *name, Array args, bool retval, Error *err)
1045 {
1046 lua_State *const lstate = global_lstate;
1047 nlua_pushref(lstate, ref);
1048 int nargs = (int)args.size;
1049 if (name != NULL) {
1050 lua_pushstring(lstate, name);
1051 nargs++;
1052 }
1053 for (size_t i = 0; i < args.size; i++) {
1054 nlua_push_Object(lstate, args.items[i], false);
1055 }
1056
1057 if (nlua_pcall(lstate, nargs, retval ? 1 : 0)) {
1058 // if err is passed, the caller will deal with the error.
1059 if (err) {
1060 size_t len;
1061 const char *errstr = lua_tolstring(lstate, -1, &len);
1062 api_set_error(err, kErrorTypeException,
1063 "Error executing lua: %.*s", (int)len, errstr);
1064 } else {
1065 nlua_error(lstate, _("Error executing lua callback: %.*s"));
1066 }
1067 return NIL;
1068 }
1069
1070 if (retval) {
1071 Error dummy = ERROR_INIT;
1072 if (err == NULL) {
1073 err = &dummy;
1074 }
1075 return nlua_pop_Object(lstate, false, err);
1076 } else {
1077 return NIL;
1078 }
1079 }
1080
1081 /// check if the current execution context is safe for calling deferred API
1082 /// methods. Luv callbacks are unsafe as they are called inside the uv loop.
nlua_is_deferred_safe(void)1083 bool nlua_is_deferred_safe(void)
1084 {
1085 return in_fast_callback == 0;
1086 }
1087
1088 /// Run lua string
1089 ///
1090 /// Used for :lua.
1091 ///
1092 /// @param eap VimL command being run.
ex_lua(exarg_T * const eap)1093 void ex_lua(exarg_T *const eap)
1094 FUNC_ATTR_NONNULL_ALL
1095 {
1096 size_t len;
1097 char *const code = script_get(eap, &len);
1098 if (eap->skip) {
1099 xfree(code);
1100 return;
1101 }
1102 nlua_typval_exec(code, len, ":lua", NULL, 0, false, NULL);
1103
1104 xfree(code);
1105 }
1106
1107 /// Run lua string for each line in range
1108 ///
1109 /// Used for :luado.
1110 ///
1111 /// @param eap VimL command being run.
ex_luado(exarg_T * const eap)1112 void ex_luado(exarg_T *const eap)
1113 FUNC_ATTR_NONNULL_ALL
1114 {
1115 if (u_save(eap->line1 - 1, eap->line2 + 1) == FAIL) {
1116 emsg(_("cannot save undo information"));
1117 return;
1118 }
1119 const char *const cmd = (const char *)eap->arg;
1120 const size_t cmd_len = strlen(cmd);
1121
1122 lua_State *const lstate = global_lstate;
1123
1124 #define DOSTART "return function(line, linenr) "
1125 #define DOEND " end"
1126 const size_t lcmd_len = (cmd_len
1127 + (sizeof(DOSTART) - 1)
1128 + (sizeof(DOEND) - 1));
1129 char *lcmd;
1130 if (lcmd_len < IOSIZE) {
1131 lcmd = (char *)IObuff;
1132 } else {
1133 lcmd = xmalloc(lcmd_len + 1);
1134 }
1135 memcpy(lcmd, DOSTART, sizeof(DOSTART) - 1);
1136 memcpy(lcmd + sizeof(DOSTART) - 1, cmd, cmd_len);
1137 memcpy(lcmd + sizeof(DOSTART) - 1 + cmd_len, DOEND, sizeof(DOEND) - 1);
1138 #undef DOSTART
1139 #undef DOEND
1140
1141 if (luaL_loadbuffer(lstate, lcmd, lcmd_len, ":luado")) {
1142 nlua_error(lstate, _("E5109: Error loading lua: %.*s"));
1143 if (lcmd_len >= IOSIZE) {
1144 xfree(lcmd);
1145 }
1146 return;
1147 }
1148 if (lcmd_len >= IOSIZE) {
1149 xfree(lcmd);
1150 }
1151 if (nlua_pcall(lstate, 0, 1)) {
1152 nlua_error(lstate, _("E5110: Error executing lua: %.*s"));
1153 return;
1154 }
1155 for (linenr_T l = eap->line1; l <= eap->line2; l++) {
1156 if (l > curbuf->b_ml.ml_line_count) {
1157 break;
1158 }
1159 lua_pushvalue(lstate, -1);
1160 const char *old_line = (const char *)ml_get_buf(curbuf, l, false);
1161 lua_pushstring(lstate, old_line);
1162 lua_pushnumber(lstate, (lua_Number)l);
1163 if (nlua_pcall(lstate, 2, 1)) {
1164 nlua_error(lstate, _("E5111: Error calling lua: %.*s"));
1165 break;
1166 }
1167 if (lua_isstring(lstate, -1)) {
1168 size_t old_line_len = STRLEN(old_line);
1169
1170 size_t new_line_len;
1171 const char *const new_line = lua_tolstring(lstate, -1, &new_line_len);
1172 char *const new_line_transformed = xmemdupz(new_line, new_line_len);
1173 for (size_t i = 0; i < new_line_len; i++) {
1174 if (new_line_transformed[i] == NUL) {
1175 new_line_transformed[i] = '\n';
1176 }
1177 }
1178 ml_replace(l, (char_u *)new_line_transformed, false);
1179 inserted_bytes(l, 0, (int)old_line_len, (int)new_line_len);
1180 }
1181 lua_pop(lstate, 1);
1182 }
1183 lua_pop(lstate, 1);
1184 check_cursor();
1185 update_screen(NOT_VALID);
1186 }
1187
1188 /// Run lua file
1189 ///
1190 /// Used for :luafile.
1191 ///
1192 /// @param eap VimL command being run.
ex_luafile(exarg_T * const eap)1193 void ex_luafile(exarg_T *const eap)
1194 FUNC_ATTR_NONNULL_ALL
1195 {
1196 nlua_exec_file((const char *)eap->arg);
1197 }
1198
1199 /// execute lua code from a file.
1200 ///
1201 /// @param path path of the file
1202 ///
1203 /// @return true if everything ok, false if there was an error (echoed)
nlua_exec_file(const char * path)1204 bool nlua_exec_file(const char *path)
1205 FUNC_ATTR_NONNULL_ALL
1206 {
1207 lua_State *const lstate = global_lstate;
1208
1209 if (luaL_loadfile(lstate, path)) {
1210 nlua_error(lstate, _("E5112: Error while creating lua chunk: %.*s"));
1211 return false;
1212 }
1213
1214 if (nlua_pcall(lstate, 0, 0)) {
1215 nlua_error(lstate, _("E5113: Error while calling lua chunk: %.*s"));
1216 return false;
1217 }
1218
1219 return true;
1220 }
1221
tslua_get_language_version(lua_State * L)1222 int tslua_get_language_version(lua_State *L)
1223 {
1224 lua_pushnumber(L, TREE_SITTER_LANGUAGE_VERSION);
1225 return 1;
1226 }
1227
nlua_add_treesitter(lua_State * const lstate)1228 static void nlua_add_treesitter(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
1229 {
1230 tslua_init(lstate);
1231
1232 lua_pushcfunction(lstate, tslua_push_parser);
1233 lua_setfield(lstate, -2, "_create_ts_parser");
1234
1235 lua_pushcfunction(lstate, tslua_add_language);
1236 lua_setfield(lstate, -2, "_ts_add_language");
1237
1238 lua_pushcfunction(lstate, tslua_has_language);
1239 lua_setfield(lstate, -2, "_ts_has_language");
1240
1241 lua_pushcfunction(lstate, tslua_inspect_lang);
1242 lua_setfield(lstate, -2, "_ts_inspect_language");
1243
1244 lua_pushcfunction(lstate, tslua_parse_query);
1245 lua_setfield(lstate, -2, "_ts_parse_query");
1246
1247 lua_pushcfunction(lstate, tslua_get_language_version);
1248 lua_setfield(lstate, -2, "_ts_get_language_version");
1249 }
1250
nlua_expand_pat(expand_T * xp,char_u * pat,int * num_results,char_u *** results)1251 int nlua_expand_pat(expand_T *xp, char_u *pat, int *num_results, char_u ***results)
1252 {
1253 lua_State *const lstate = global_lstate;
1254 int ret = OK;
1255
1256 // [ vim ]
1257 lua_getglobal(lstate, "vim");
1258
1259 // [ vim, vim._expand_pat ]
1260 lua_getfield(lstate, -1, "_expand_pat");
1261 luaL_checktype(lstate, -1, LUA_TFUNCTION);
1262
1263 // [ vim, vim._on_key, buf ]
1264 lua_pushlstring(lstate, (const char *)pat, STRLEN(pat));
1265
1266 if (nlua_pcall(lstate, 1, 2) != 0) {
1267 nlua_error(lstate,
1268 _("Error executing vim._expand_pat: %.*s"));
1269 return FAIL;
1270 }
1271
1272 Error err = ERROR_INIT;
1273
1274 *num_results = 0;
1275 *results = NULL;
1276
1277 int prefix_len = (int)nlua_pop_Integer(lstate, &err);
1278 if (ERROR_SET(&err)) {
1279 ret = FAIL;
1280 goto cleanup;
1281 }
1282
1283 Array completions = nlua_pop_Array(lstate, &err);
1284 if (ERROR_SET(&err)) {
1285 ret = FAIL;
1286 goto cleanup_array;
1287 }
1288
1289 garray_T result_array;
1290 ga_init(&result_array, (int)sizeof(char *), 80);
1291 for (size_t i = 0; i < completions.size; i++) {
1292 Object v = completions.items[i];
1293
1294 if (v.type != kObjectTypeString) {
1295 ret = FAIL;
1296 goto cleanup_array;
1297 }
1298
1299 GA_APPEND(char_u *,
1300 &result_array,
1301 vim_strsave((char_u *)v.data.string.data));
1302 }
1303
1304 xp->xp_pattern += prefix_len;
1305 *results = result_array.ga_data;
1306 *num_results = result_array.ga_len;
1307
1308 cleanup_array:
1309 api_free_array(completions);
1310
1311 cleanup:
1312
1313 if (ret == FAIL) {
1314 ga_clear(&result_array);
1315 }
1316
1317 return ret;
1318 }
1319
1320 // Required functions for lua c functions as VimL callbacks
1321
nlua_CFunction_func_call(int argcount,typval_T * argvars,typval_T * rettv,void * state)1322 int nlua_CFunction_func_call(int argcount, typval_T *argvars, typval_T *rettv, void *state)
1323 {
1324 lua_State *const lstate = global_lstate;
1325 LuaCFunctionState *funcstate = (LuaCFunctionState *)state;
1326
1327 return typval_exec_lua_callable(lstate, funcstate->lua_callable,
1328 argcount, argvars, rettv);
1329 }
1330
nlua_CFunction_func_free(void * state)1331 void nlua_CFunction_func_free(void *state)
1332 {
1333 lua_State *const lstate = global_lstate;
1334 LuaCFunctionState *funcstate = (LuaCFunctionState *)state;
1335
1336 nlua_unref(lstate, funcstate->lua_callable.func_ref);
1337 xfree(funcstate);
1338 }
1339
nlua_is_table_from_lua(typval_T * const arg)1340 bool nlua_is_table_from_lua(typval_T *const arg)
1341 {
1342 if (arg->v_type == VAR_DICT) {
1343 return arg->vval.v_dict->lua_table_ref != LUA_NOREF;
1344 } else if (arg->v_type == VAR_LIST) {
1345 return arg->vval.v_list->lua_table_ref != LUA_NOREF;
1346 } else {
1347 return false;
1348 }
1349 }
1350
nlua_register_table_as_callable(typval_T * const arg)1351 char_u *nlua_register_table_as_callable(typval_T *const arg)
1352 {
1353 LuaRef table_ref = LUA_NOREF;
1354 if (arg->v_type == VAR_DICT) {
1355 table_ref = arg->vval.v_dict->lua_table_ref;
1356 } else if (arg->v_type == VAR_LIST) {
1357 table_ref = arg->vval.v_list->lua_table_ref;
1358 }
1359
1360 if (table_ref == LUA_NOREF) {
1361 return NULL;
1362 }
1363
1364 lua_State *const lstate = global_lstate;
1365
1366 #ifndef NDEBUG
1367 int top = lua_gettop(lstate);
1368 #endif
1369
1370 nlua_pushref(lstate, table_ref); // [table]
1371 if (!lua_getmetatable(lstate, -1)) {
1372 lua_pop(lstate, 1);
1373 assert(top == lua_gettop(lstate));
1374 return NULL;
1375 } // [table, mt]
1376
1377 lua_getfield(lstate, -1, "__call"); // [table, mt, mt.__call]
1378 if (!lua_isfunction(lstate, -1)) {
1379 lua_pop(lstate, 3);
1380 assert(top == lua_gettop(lstate));
1381 return NULL;
1382 }
1383 lua_pop(lstate, 2); // [table]
1384
1385 LuaCFunctionState *state = xmalloc(sizeof(LuaCFunctionState));
1386 state->lua_callable.func_ref = nlua_ref(lstate, -1);
1387
1388 char_u *name = register_cfunc(&nlua_CFunction_func_call,
1389 &nlua_CFunction_func_free, state);
1390
1391
1392 lua_pop(lstate, 1); // []
1393 assert(top == lua_gettop(lstate));
1394
1395 return name;
1396 }
1397
nlua_execute_on_key(int c)1398 void nlua_execute_on_key(int c)
1399 {
1400 char_u buf[NUMBUFLEN];
1401 size_t buf_len = special_to_buf(c, mod_mask, false, buf);
1402
1403 lua_State *const lstate = global_lstate;
1404
1405 #ifndef NDEBUG
1406 int top = lua_gettop(lstate);
1407 #endif
1408
1409 // [ vim ]
1410 lua_getglobal(lstate, "vim");
1411
1412 // [ vim, vim._on_key]
1413 lua_getfield(lstate, -1, "_on_key");
1414 luaL_checktype(lstate, -1, LUA_TFUNCTION);
1415
1416 // [ vim, vim._on_key, buf ]
1417 lua_pushlstring(lstate, (const char *)buf, buf_len);
1418
1419 if (nlua_pcall(lstate, 1, 0)) {
1420 nlua_error(lstate,
1421 _("Error executing vim.on_key Lua callback: %.*s"));
1422 }
1423
1424 // [ vim ]
1425 lua_pop(lstate, 1);
1426
1427 #ifndef NDEBUG
1428 // [ ]
1429 assert(top == lua_gettop(lstate));
1430 #endif
1431 }
1432
1433