neovim

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

spell.c (2476B)


      1 #include <assert.h>
      2 #include <lauxlib.h>
      3 #include <limits.h>
      4 #include <lua.h>
      5 #include <stdbool.h>
      6 #include <stddef.h>
      7 
      8 #include "nvim/ascii_defs.h"
      9 #include "nvim/buffer_defs.h"
     10 #include "nvim/errors.h"
     11 #include "nvim/gettext_defs.h"
     12 #include "nvim/globals.h"
     13 #include "nvim/highlight_defs.h"
     14 #include "nvim/lua/spell.h"
     15 #include "nvim/message.h"
     16 #include "nvim/spell.h"
     17 
     18 #include "lua/spell.c.generated.h"  // IWYU pragma: keep
     19 
     20 int nlua_spell_check(lua_State *lstate)
     21  FUNC_ATTR_NONNULL_ALL
     22 {
     23  if (lua_gettop(lstate) < 1) {
     24    return luaL_error(lstate, "Expected 1 argument");
     25  }
     26 
     27  if (lua_type(lstate, 1) != LUA_TSTRING) {
     28    luaL_argerror(lstate, 1, "expected string");
     29  }
     30 
     31  const char *str = lua_tolstring(lstate, 1, NULL);
     32 
     33  // spell.c requires that 'spell' is enabled, so we need to temporarily enable
     34  // it before we can call spell functions.
     35  const int wo_spell_save = curwin->w_p_spell;
     36 
     37  if (!curwin->w_p_spell) {
     38    parse_spelllang(curwin);
     39    curwin->w_p_spell = true;
     40  }
     41 
     42  // Check 'spelllang'
     43  if (*curwin->w_s->b_p_spl == NUL) {
     44    emsg(_(e_no_spell));
     45    curwin->w_p_spell = wo_spell_save;
     46    return 0;
     47  }
     48 
     49  hlf_T attr = HLF_COUNT;
     50  size_t pos = 0;
     51  int capcol = -1;
     52  int no_res = 0;
     53  const char *result;
     54 
     55  lua_createtable(lstate, 0, 0);
     56 
     57  while (*str != NUL) {
     58    attr = HLF_COUNT;
     59    size_t len = spell_check(curwin, (char *)str, &attr, &capcol, false);
     60    assert(len <= INT_MAX);
     61 
     62    if (attr != HLF_COUNT) {
     63      lua_createtable(lstate, 3, 0);
     64 
     65      lua_pushlstring(lstate, str, len);
     66      lua_rawseti(lstate, -2, 1);
     67 
     68      result = attr == HLF_SPB
     69               ? "bad" : (attr == HLF_SPR
     70                          ? "rare" : (attr == HLF_SPL
     71                                      ? "local" : (attr == HLF_SPC
     72                                                   ? "caps" : NULL)));
     73 
     74      assert(result != NULL);
     75 
     76      lua_pushstring(lstate, result);
     77      lua_rawseti(lstate, -2, 2);
     78 
     79      // +1 for 1-indexing
     80      lua_pushinteger(lstate, (lua_Integer)pos + 1);
     81      lua_rawseti(lstate, -2, 3);
     82 
     83      lua_rawseti(lstate, -2, ++no_res);
     84    }
     85 
     86    str += len;
     87    pos += len;
     88    capcol -= (int)len;
     89  }
     90 
     91  // Restore 'spell'
     92  curwin->w_p_spell = wo_spell_save;
     93  return 1;
     94 }
     95 
     96 static const luaL_Reg spell_functions[] = {
     97  { "check", nlua_spell_check },
     98  { NULL, NULL }
     99 };
    100 
    101 int luaopen_spell(lua_State *L)
    102  FUNC_ATTR_NONNULL_ALL
    103 {
    104  lua_newtable(L);
    105  luaL_register(L, NULL, spell_functions);
    106  return 1;
    107 }