neovim

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

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 }