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 }