stdlib.c (20634B)
1 #include <assert.h> 2 #include <lauxlib.h> 3 #include <lua.h> 4 #include <stdarg.h> 5 #include <stdbool.h> 6 #include <stddef.h> 7 #include <stdint.h> 8 #include <string.h> 9 #include <uv.h> 10 11 #ifdef NVIM_VENDOR_BIT 12 # include "bit.h" 13 #endif 14 15 #include "cjson/lua_cjson.h" 16 #include "mpack/lmpack.h" 17 #include "nvim/api/private/defs.h" 18 #include "nvim/api/private/helpers.h" 19 #include "nvim/ascii_defs.h" 20 #include "nvim/autocmd.h" 21 #include "nvim/autocmd_defs.h" 22 #include "nvim/buffer_defs.h" 23 #include "nvim/eval/typval.h" 24 #include "nvim/eval/typval_defs.h" 25 #include "nvim/eval/vars.h" 26 #include "nvim/eval/window.h" 27 #include "nvim/ex_cmds_defs.h" 28 #include "nvim/ex_docmd.h" 29 #include "nvim/ex_eval.h" 30 #include "nvim/fold.h" 31 #include "nvim/globals.h" 32 #include "nvim/lua/base64.h" 33 #include "nvim/lua/converter.h" 34 #include "nvim/lua/spell.h" 35 #include "nvim/lua/stdlib.h" 36 #include "nvim/lua/xdiff.h" 37 #include "nvim/map_defs.h" 38 #include "nvim/mbyte.h" 39 #include "nvim/mbyte_defs.h" 40 #include "nvim/memline.h" 41 #include "nvim/memory.h" 42 #include "nvim/pos_defs.h" 43 #include "nvim/regexp.h" 44 #include "nvim/regexp_defs.h" 45 #include "nvim/runtime.h" 46 #include "nvim/strings.h" 47 #include "nvim/types_defs.h" 48 #include "nvim/window.h" 49 50 #include "lua/stdlib.c.generated.h" 51 52 static int regex_match(lua_State *lstate, regprog_T **prog, char *str) 53 { 54 regmatch_T rm; 55 rm.regprog = *prog; 56 rm.rm_ic = false; 57 bool match = vim_regexec(&rm, str, 0); 58 *prog = rm.regprog; 59 60 if (match) { 61 lua_pushinteger(lstate, (lua_Integer)(rm.startp[0] - str)); 62 lua_pushinteger(lstate, (lua_Integer)(rm.endp[0] - str)); 63 return 2; 64 } 65 return 0; 66 } 67 68 static int regex_match_str(lua_State *lstate) 69 { 70 regprog_T **prog = regex_check(lstate); 71 const char *str = luaL_checkstring(lstate, 2); 72 int nret = regex_match(lstate, prog, (char *)str); 73 74 if (!*prog) { 75 return luaL_error(lstate, "regex: internal error"); 76 } 77 78 return nret; 79 } 80 81 static int regex_match_line(lua_State *lstate) 82 { 83 regprog_T **prog = regex_check(lstate); 84 85 int narg = lua_gettop(lstate); 86 if (narg < 3) { 87 return luaL_error(lstate, "not enough args"); 88 } 89 90 handle_T bufnr = (handle_T)luaL_checkinteger(lstate, 2); 91 linenr_T rownr = (linenr_T)luaL_checkinteger(lstate, 3); 92 int start = 0; 93 int end = -1; 94 if (narg >= 4) { 95 start = (int)luaL_checkinteger(lstate, 4); 96 } 97 if (narg >= 5) { 98 end = (int)luaL_checkinteger(lstate, 5); 99 if (end < 0) { 100 return luaL_error(lstate, "invalid end"); 101 } 102 } 103 104 buf_T *buf = bufnr ? handle_get_buffer(bufnr) : curbuf; 105 if (!buf || buf->b_ml.ml_mfp == NULL) { 106 return luaL_error(lstate, "invalid buffer"); 107 } 108 109 if (rownr >= buf->b_ml.ml_line_count) { 110 return luaL_error(lstate, "invalid row"); 111 } 112 113 char *line = ml_get_buf(buf, rownr + 1); 114 colnr_T len = ml_get_buf_len(buf, rownr + 1); 115 116 if (start < 0 || start > len) { 117 return luaL_error(lstate, "invalid start"); 118 } 119 120 char save = NUL; 121 if (end >= 0) { 122 if (end > len || end < start) { 123 return luaL_error(lstate, "invalid end"); 124 } 125 save = line[end]; 126 line[end] = NUL; 127 } 128 129 int nret = regex_match(lstate, prog, line + start); 130 131 if (end >= 0) { 132 line[end] = save; 133 } 134 135 if (!*prog) { 136 return luaL_error(lstate, "regex: internal error"); 137 } 138 139 return nret; 140 } 141 142 static regprog_T **regex_check(lua_State *L) 143 { 144 return luaL_checkudata(L, 1, "nvim_regex"); 145 } 146 147 static int regex_gc(lua_State *lstate) 148 { 149 regprog_T **prog = regex_check(lstate); 150 vim_regfree(*prog); 151 return 0; 152 } 153 154 static int regex_tostring(lua_State *lstate) 155 { 156 lua_pushstring(lstate, "<regex>"); 157 return 1; 158 } 159 160 static struct luaL_Reg regex_meta[] = { 161 { "__gc", regex_gc }, 162 { "__tostring", regex_tostring }, 163 { "match_str", regex_match_str }, 164 { "match_line", regex_match_line }, 165 { NULL, NULL } 166 }; 167 168 /// convert byte index to UTF-32 and UTF-16 indices 169 /// 170 /// Expects a string and an optional index. If no index is supplied, the length 171 /// of the string is returned. 172 /// 173 /// Returns two values: the UTF-32 and UTF-16 indices. 174 int nlua_str_utfindex(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL 175 { 176 size_t s1_len; 177 const char *s1 = luaL_checklstring(lstate, 1, &s1_len); 178 intptr_t idx; 179 if (lua_isnoneornil(lstate, 2)) { 180 idx = (intptr_t)s1_len; 181 } else { 182 idx = luaL_checkinteger(lstate, 2); 183 if (idx < 0 || idx > (intptr_t)s1_len) { 184 lua_pushnil(lstate); 185 lua_pushnil(lstate); 186 return 2; 187 } 188 } 189 190 size_t codepoints = 0; 191 size_t codeunits = 0; 192 mb_utflen(s1, (size_t)idx, &codepoints, &codeunits); 193 194 lua_pushinteger(lstate, (lua_Integer)codepoints); 195 lua_pushinteger(lstate, (lua_Integer)codeunits); 196 197 return 2; 198 } 199 200 /// return byte indices of codepoints in a string (only supports utf-8 currently). 201 /// 202 /// Expects a string. 203 /// 204 /// Returns a list of codepoints. 205 static int nlua_str_utf_pos(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL 206 { 207 size_t s1_len; 208 const char *s1 = luaL_checklstring(lstate, 1, &s1_len); 209 lua_newtable(lstate); 210 211 size_t idx = 1; 212 size_t clen; 213 for (size_t i = 0; i < s1_len && s1[i] != NUL; i += clen) { 214 clen = (size_t)utf_ptr2len_len(s1 + i, (int)(s1_len - i)); 215 lua_pushinteger(lstate, (lua_Integer)i + 1); 216 lua_rawseti(lstate, -2, (int)idx); 217 idx++; 218 } 219 220 return 1; 221 } 222 223 /// Return the offset from the 1-indexed byte position to the first byte of the 224 /// current character. 225 /// 226 /// Expects a string and an int. 227 /// 228 /// Returns the byte offset to the first byte of the current character 229 /// pointed into by the offset. 230 static int nlua_str_utf_start(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL 231 { 232 size_t s1_len; 233 const char *s1 = luaL_checklstring(lstate, 1, &s1_len); 234 ptrdiff_t offset = luaL_checkinteger(lstate, 2); 235 if (offset <= 0 || offset > (intptr_t)s1_len) { 236 return luaL_error(lstate, "index out of range"); 237 } 238 size_t const off = (size_t)(offset - 1); 239 int head_off = -utf_cp_bounds_len(s1, s1 + off, (int)(s1_len - off)).begin_off; 240 lua_pushinteger(lstate, head_off); 241 return 1; 242 } 243 244 /// Return the offset from the 1-indexed byte position to the last 245 /// byte of the current character. 246 /// 247 /// Expects a string and an int. 248 /// 249 /// Returns the byte offset to the last byte of the current character 250 /// pointed into by the offset. 251 static int nlua_str_utf_end(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL 252 { 253 size_t s1_len; 254 const char *s1 = luaL_checklstring(lstate, 1, &s1_len); 255 ptrdiff_t offset = luaL_checkinteger(lstate, 2); 256 if (offset <= 0 || offset > (intptr_t)s1_len) { 257 return luaL_error(lstate, "index out of range"); 258 } 259 size_t const off = (size_t)(offset - 1); 260 int tail_off = utf_cp_bounds_len(s1, s1 + off, (int)(s1_len - off)).end_off - 1; 261 lua_pushinteger(lstate, tail_off); 262 return 1; 263 } 264 265 /// convert UTF-32 or UTF-16 indices to byte index. 266 /// 267 /// Expects up to three args: string, index and use_utf16. 268 /// If use_utf16 is not supplied it defaults to false (use UTF-32) 269 /// 270 /// Returns the byte index. 271 int nlua_str_byteindex(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL 272 { 273 size_t s1_len; 274 const char *s1 = luaL_checklstring(lstate, 1, &s1_len); 275 intptr_t idx = luaL_checkinteger(lstate, 2); 276 if (idx < 0) { 277 lua_pushnil(lstate); 278 return 1; 279 } 280 bool use_utf16 = false; 281 if (lua_gettop(lstate) >= 3) { 282 use_utf16 = lua_toboolean(lstate, 3); 283 } 284 285 ssize_t byteidx = mb_utf_index_to_bytes(s1, s1_len, (size_t)idx, use_utf16); 286 if (byteidx == -1) { 287 lua_pushnil(lstate); 288 return 1; 289 } 290 291 lua_pushinteger(lstate, (lua_Integer)byteidx); 292 293 return 1; 294 } 295 296 int nlua_regex(lua_State *lstate) 297 { 298 Error err = ERROR_INIT; 299 const char *text = luaL_checkstring(lstate, 1); 300 regprog_T *prog = NULL; 301 302 TRY_WRAP(&err, { 303 prog = vim_regcomp(text, RE_AUTO | RE_MAGIC | RE_STRICT); 304 }); 305 306 if (ERROR_SET(&err)) { 307 nlua_push_errstr(lstate, "couldn't parse regex: %s", err.msg); 308 api_clear_error(&err); 309 return lua_error(lstate); 310 } else if (prog == NULL) { 311 nlua_push_errstr(lstate, "couldn't parse regex"); 312 return lua_error(lstate); 313 } 314 315 regprog_T **p = lua_newuserdata(lstate, sizeof(regprog_T *)); 316 *p = prog; 317 318 lua_getfield(lstate, LUA_REGISTRYINDEX, "nvim_regex"); // [udata, meta] 319 lua_setmetatable(lstate, -2); // [udata] 320 return 1; 321 } 322 323 static dict_T *nlua_get_var_scope(lua_State *lstate) 324 { 325 const char *scope = luaL_checkstring(lstate, 1); 326 handle_T handle = (handle_T)luaL_checkinteger(lstate, 2); 327 dict_T *dict = NULL; 328 Error err = ERROR_INIT; 329 if (strequal(scope, "g")) { 330 dict = get_globvar_dict(); 331 } else if (strequal(scope, "v")) { 332 dict = get_vimvar_dict(); 333 } else if (strequal(scope, "b")) { 334 buf_T *buf = find_buffer_by_handle(handle, &err); 335 if (buf) { 336 dict = buf->b_vars; 337 } 338 } else if (strequal(scope, "w")) { 339 win_T *win = find_window_by_handle(handle, &err); 340 if (win) { 341 dict = win->w_vars; 342 } 343 } else if (strequal(scope, "t")) { 344 tabpage_T *tabpage = find_tab_by_handle(handle, &err); 345 if (tabpage) { 346 dict = tabpage->tp_vars; 347 } 348 } else { 349 luaL_error(lstate, "invalid scope"); 350 return NULL; 351 } 352 353 if (ERROR_SET(&err)) { 354 nlua_push_errstr(lstate, "scoped variable: %s", err.msg); 355 api_clear_error(&err); 356 lua_error(lstate); 357 return NULL; 358 } 359 return dict; 360 } 361 362 int nlua_setvar(lua_State *lstate) 363 { 364 // non-local return if not found 365 dict_T *dict = nlua_get_var_scope(lstate); 366 String key; 367 key.data = (char *)luaL_checklstring(lstate, 3, &key.size); 368 369 bool del = (lua_gettop(lstate) < 4) || lua_isnil(lstate, 4); 370 371 Error err = ERROR_INIT; 372 dictitem_T *di = dict_check_writable(dict, key, del, &err); 373 if (ERROR_SET(&err)) { 374 nlua_push_errstr(lstate, "%s", err.msg); 375 api_clear_error(&err); 376 lua_error(lstate); 377 return 0; 378 } 379 380 bool watched = tv_dict_is_watched(dict); 381 382 if (del) { 383 // Delete the key 384 if (di == NULL) { 385 // Doesn't exist, nothing to do 386 return 0; 387 } 388 // Notify watchers 389 if (watched) { 390 tv_dict_watcher_notify(dict, key.data, NULL, &di->di_tv); 391 } 392 393 // Delete the entry 394 tv_dict_item_remove(dict, di); 395 } else { 396 // Update the key 397 typval_T tv; 398 399 // Convert the lua value to a vimscript type in the temporary variable 400 lua_pushvalue(lstate, 4); 401 if (!nlua_pop_typval(lstate, &tv)) { 402 return luaL_error(lstate, "Couldn't convert lua value"); 403 } 404 405 typval_T oldtv = TV_INITIAL_VALUE; 406 407 if (di == NULL) { 408 // Need to create an entry 409 di = tv_dict_item_alloc_len(key.data, key.size); 410 tv_dict_add(dict, di); 411 } else { 412 bool type_error = false; 413 if (dict == get_vimvar_dict() 414 && !before_set_vvar(key.data, di, &tv, true, watched, &type_error)) { 415 tv_clear(&tv); 416 if (type_error) { 417 return luaL_error(lstate, "Setting v:%s to value with wrong type", key.data); 418 } 419 return 0; 420 } 421 if (watched) { 422 tv_copy(&di->di_tv, &oldtv); 423 } 424 // Clear the old value 425 tv_clear(&di->di_tv); 426 } 427 428 // Update the value 429 tv_copy(&tv, &di->di_tv); 430 431 // Notify watchers 432 if (watched) { 433 tv_dict_watcher_notify(dict, key.data, &tv, &oldtv); 434 tv_clear(&oldtv); 435 } 436 437 // Clear the temporary variable 438 tv_clear(&tv); 439 } 440 return 0; 441 } 442 443 int nlua_getvar(lua_State *lstate) 444 { 445 // non-local return if not found 446 dict_T *dict = nlua_get_var_scope(lstate); 447 size_t len; 448 const char *name = luaL_checklstring(lstate, 3, &len); 449 450 dictitem_T *di = tv_dict_find(dict, name, (ptrdiff_t)len); 451 if (di == NULL && dict == get_globvar_dict()) { // try to autoload script 452 if (!script_autoload(name, len, false) || aborting()) { 453 return 0; // nil 454 } 455 di = tv_dict_find(dict, name, (ptrdiff_t)len); 456 } 457 if (di == NULL) { 458 return 0; // nil 459 } 460 nlua_push_typval(lstate, &di->di_tv, 0); 461 return 1; 462 } 463 464 /// Compare two strings, ignoring case 465 /// 466 /// Expects two values on the stack: compared strings. Returns one of the 467 /// following numbers: 0, -1 or 1. 468 /// 469 /// Does no error handling: never call it with non-string or with some arguments 470 /// omitted. 471 static int nlua_stricmp(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL 472 { 473 size_t s1_len; 474 size_t s2_len; 475 const char *s1 = luaL_checklstring(lstate, 1, &s1_len); 476 const char *s2 = luaL_checklstring(lstate, 2, &s2_len); 477 char *nul1; 478 char *nul2; 479 int ret = 0; 480 assert(s1[s1_len] == NUL); 481 assert(s2[s2_len] == NUL); 482 while (true) { 483 nul1 = memchr(s1, NUL, s1_len); 484 nul2 = memchr(s2, NUL, s2_len); 485 ret = STRICMP(s1, s2); 486 if (ret == 0) { 487 // Compare "a\0" greater then "a". 488 if ((nul1 == NULL) != (nul2 == NULL)) { 489 ret = ((nul1 != NULL) - (nul2 != NULL)); 490 break; 491 } 492 if (nul1 != NULL) { 493 assert(nul2 != NULL); 494 // Can't shift both strings by the same amount of bytes: lowercase 495 // letter may have different byte-length than uppercase. 496 s1_len -= (size_t)(nul1 - s1) + 1; 497 s2_len -= (size_t)(nul2 - s2) + 1; 498 s1 = nul1 + 1; 499 s2 = nul2 + 1; 500 } else { 501 break; 502 } 503 } else { 504 break; 505 } 506 } 507 lua_pop(lstate, 2); 508 lua_pushnumber(lstate, (lua_Number)((ret > 0) - (ret < 0))); 509 return 1; 510 } 511 512 /// Convert string from one encoding to another 513 static int nlua_iconv(lua_State *lstate) 514 { 515 int narg = lua_gettop(lstate); 516 517 if (narg < 3) { 518 return luaL_error(lstate, "Expected at least 3 arguments"); 519 } 520 521 for (int i = 1; i <= 3; i++) { 522 if (lua_type(lstate, i) != LUA_TSTRING) { 523 return luaL_argerror(lstate, i, "expected string"); 524 } 525 } 526 527 size_t str_len = 0; 528 const char *str = lua_tolstring(lstate, 1, &str_len); 529 530 char *from = enc_canonize(enc_skip((char *)lua_tolstring(lstate, 2, NULL))); 531 char *to = enc_canonize(enc_skip((char *)lua_tolstring(lstate, 3, NULL))); 532 533 vimconv_T vimconv; 534 vimconv.vc_type = CONV_NONE; 535 convert_setup_ext(&vimconv, from, false, to, false); 536 537 char *ret = string_convert(&vimconv, (char *)str, &str_len); 538 539 convert_setup(&vimconv, NULL, NULL); 540 541 xfree(from); 542 xfree(to); 543 544 if (ret == NULL) { 545 lua_pushnil(lstate); 546 } else { 547 lua_pushlstring(lstate, ret, str_len); 548 xfree(ret); 549 } 550 551 return 1; 552 } 553 554 // Update foldlevels (e.g., by evaluating 'foldexpr') for the given line range in the given window, 555 // without invoking other side effects. Unlike `zx`, it does not close manually opened folds and 556 // does not open folds under the cursor. 557 static int nlua_foldupdate(lua_State *lstate) 558 { 559 handle_T window = (handle_T)luaL_checkinteger(lstate, 1); 560 win_T *win = handle_get_window(window); 561 if (!win) { 562 return luaL_error(lstate, "invalid window"); 563 } 564 // input is zero-based end-exclusive range 565 linenr_T top = (linenr_T)luaL_checkinteger(lstate, 2) + 1; 566 if (top < 1) { 567 return luaL_error(lstate, "invalid top"); 568 } 569 linenr_T bot = (linenr_T)luaL_checkinteger(lstate, 3); 570 if (top > bot) { 571 return luaL_error(lstate, "invalid bot"); 572 } 573 574 foldUpdate(win, top, bot); 575 576 return 0; 577 } 578 579 static int nlua_with(lua_State *L) 580 { 581 int flags = 0; 582 buf_T *buf = NULL; 583 win_T *win = NULL; 584 585 #define APPLY_FLAG(key, flag) \ 586 if (strequal((key), k) && (v)) { \ 587 flags |= (flag); \ 588 } 589 590 luaL_argcheck(L, lua_istable(L, 1), 1, "table expected"); 591 lua_pushnil(L); // [dict, ..., nil] 592 while (lua_next(L, 1)) { 593 // [dict, ..., key, value] 594 if (lua_type(L, -2) == LUA_TSTRING) { 595 const char *k = lua_tostring(L, -2); 596 bool v = lua_toboolean(L, -1); 597 if (strequal("buf", k)) { \ 598 buf = handle_get_buffer((int)luaL_checkinteger(L, -1)); 599 } else if (strequal("win", k)) { \ 600 win = handle_get_window((int)luaL_checkinteger(L, -1)); 601 } else { 602 APPLY_FLAG("sandbox", CMOD_SANDBOX); 603 APPLY_FLAG("silent", CMOD_SILENT); 604 APPLY_FLAG("emsg_silent", CMOD_ERRSILENT); 605 APPLY_FLAG("unsilent", CMOD_UNSILENT); 606 APPLY_FLAG("noautocmd", CMOD_NOAUTOCMD); 607 APPLY_FLAG("hide", CMOD_HIDE); 608 APPLY_FLAG("keepalt", CMOD_KEEPALT); 609 APPLY_FLAG("keepmarks", CMOD_KEEPMARKS); 610 APPLY_FLAG("keepjumps", CMOD_KEEPJUMPS); 611 APPLY_FLAG("lockmarks", CMOD_LOCKMARKS); 612 APPLY_FLAG("keeppatterns", CMOD_KEEPPATTERNS); 613 } 614 } 615 // pop the value; lua_next will pop the key. 616 lua_pop(L, 1); // [dict, ..., key] 617 } 618 int status = 0; 619 int rets = 0; 620 621 cmdmod_T save_cmdmod = cmdmod; 622 CLEAR_FIELD(cmdmod); 623 cmdmod.cmod_flags = flags; 624 apply_cmdmod(&cmdmod); 625 626 Error err = ERROR_INIT; 627 TRY_WRAP(&err, { 628 aco_save_T aco; 629 win_execute_T win_execute_args; 630 631 if (win) { 632 tabpage_T *tabpage = win_find_tabpage(win); 633 if (!win_execute_before(&win_execute_args, win, tabpage)) { 634 goto end; 635 } 636 } else if (buf) { 637 aucmd_prepbuf(&aco, buf); 638 } 639 640 int s = lua_gettop(L); 641 lua_pushvalue(L, 2); 642 status = lua_pcall(L, 0, LUA_MULTRET, 0); 643 rets = lua_gettop(L) - s; 644 645 if (win) { 646 win_execute_after(&win_execute_args); 647 } else if (buf) { 648 aucmd_restbuf(&aco); 649 } 650 end:; 651 }); 652 653 undo_cmdmod(&cmdmod); 654 cmdmod = save_cmdmod; 655 656 if (status) { 657 return lua_error(L); 658 } else if (ERROR_SET(&err)) { 659 nlua_push_errstr(L, "%s", err.msg); 660 api_clear_error(&err); 661 return lua_error(L); 662 } 663 664 return rets; 665 } 666 667 // Access to internal functions. For use in runtime/ 668 static void nlua_state_add_internal(lua_State *const lstate) 669 { 670 // _getvar 671 lua_pushcfunction(lstate, &nlua_getvar); 672 lua_setfield(lstate, -2, "_getvar"); 673 674 // _setvar 675 lua_pushcfunction(lstate, &nlua_setvar); 676 lua_setfield(lstate, -2, "_setvar"); 677 678 // _updatefolds 679 lua_pushcfunction(lstate, &nlua_foldupdate); 680 lua_setfield(lstate, -2, "_foldupdate"); 681 682 lua_pushcfunction(lstate, &nlua_with); 683 lua_setfield(lstate, -2, "_with_c"); 684 } 685 686 void nlua_state_add_stdlib(lua_State *const lstate, bool is_thread) 687 { 688 if (!is_thread) { 689 // TODO(bfredl): some of basic string functions should already be 690 // (or be easy to make) threadsafe 691 692 // stricmp 693 lua_pushcfunction(lstate, &nlua_stricmp); 694 lua_setfield(lstate, -2, "stricmp"); 695 // str_utfindex 696 lua_pushcfunction(lstate, &nlua_str_utfindex); 697 lua_setfield(lstate, -2, "_str_utfindex"); 698 // str_byteindex 699 lua_pushcfunction(lstate, &nlua_str_byteindex); 700 lua_setfield(lstate, -2, "_str_byteindex"); 701 // str_utf_pos 702 lua_pushcfunction(lstate, &nlua_str_utf_pos); 703 lua_setfield(lstate, -2, "str_utf_pos"); 704 // str_utf_start 705 lua_pushcfunction(lstate, &nlua_str_utf_start); 706 lua_setfield(lstate, -2, "str_utf_start"); 707 // str_utf_end 708 lua_pushcfunction(lstate, &nlua_str_utf_end); 709 lua_setfield(lstate, -2, "str_utf_end"); 710 // regex 711 lua_pushcfunction(lstate, &nlua_regex); 712 lua_setfield(lstate, -2, "regex"); 713 luaL_newmetatable(lstate, "nvim_regex"); 714 luaL_register(lstate, NULL, regex_meta); 715 716 lua_pushvalue(lstate, -1); // [meta, meta] 717 lua_setfield(lstate, -2, "__index"); // [meta] 718 lua_pop(lstate, 1); // don't use metatable now 719 720 // vim.spell 721 luaopen_spell(lstate); 722 lua_setfield(lstate, -2, "spell"); 723 724 // vim.iconv 725 // depends on p_ambw, p_emoji 726 lua_pushcfunction(lstate, &nlua_iconv); 727 lua_setfield(lstate, -2, "iconv"); 728 729 // vim.base64 730 luaopen_base64(lstate); 731 lua_setfield(lstate, -2, "base64"); 732 733 nlua_state_add_internal(lstate); 734 } 735 736 // vim.mpack 737 luaopen_mpack(lstate); 738 lua_pushvalue(lstate, -1); 739 lua_setfield(lstate, -3, "mpack"); 740 741 // package.loaded.mpack = vim.mpack 742 // otherwise luv will be reinitialized when require'mpack' 743 lua_getglobal(lstate, "package"); 744 lua_getfield(lstate, -1, "loaded"); 745 lua_pushvalue(lstate, -3); 746 lua_setfield(lstate, -2, "mpack"); 747 lua_pop(lstate, 3); 748 749 // vim.lpeg 750 int luaopen_lpeg(lua_State *); 751 luaopen_lpeg(lstate); 752 lua_pushvalue(lstate, -1); 753 lua_setfield(lstate, -4, "lpeg"); 754 755 // package.loaded.lpeg = vim.lpeg 756 lua_getglobal(lstate, "package"); 757 lua_getfield(lstate, -1, "loaded"); 758 lua_pushvalue(lstate, -3); 759 lua_setfield(lstate, -2, "lpeg"); 760 lua_pop(lstate, 4); 761 762 // vim.text.diff 763 lua_pushcfunction(lstate, &nlua_xdl_diff); 764 // TODO(justinmk): set vim.text.diff here, or rename this to "_diff". goddamnit. 765 lua_setfield(lstate, -2, "diff"); 766 767 // vim.json 768 lua_cjson_new(lstate); 769 lua_setfield(lstate, -2, "json"); 770 771 #ifdef NVIM_VENDOR_BIT 772 // if building with puc lua, use internal fallback for require'bit' 773 int top = lua_gettop(lstate); 774 luaopen_bit(lstate); 775 lua_settop(lstate, top); 776 #endif 777 } 778 779 /// like luaL_error, but allow cleanup 780 void nlua_push_errstr(lua_State *L, const char *fmt, ...) 781 { 782 va_list argp; 783 va_start(argp, fmt); 784 luaL_where(L, 1); 785 lua_pushvfstring(L, fmt, argp); 786 va_end(argp); 787 lua_concat(L, 2); 788 }