aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/lua/tree_sitter.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/lua/tree_sitter.c')
-rw-r--r--src/nvim/lua/tree_sitter.c54
1 files changed, 53 insertions, 1 deletions
diff --git a/src/nvim/lua/tree_sitter.c b/src/nvim/lua/tree_sitter.c
index 1ecb2bcac4..f992639955 100644
--- a/src/nvim/lua/tree_sitter.c
+++ b/src/nvim/lua/tree_sitter.c
@@ -65,6 +65,8 @@ static struct luaL_Reg node_meta[] = {
{NULL, NULL}
};
+PMap(cstr_t) *langs;
+
void build_meta(lua_State *L, const luaL_Reg *meta)
{
// [env, target]
@@ -86,6 +88,9 @@ void build_meta(lua_State *L, const luaL_Reg *meta)
/// all global state is stored in the regirstry of the lua_State
void tslua_init(lua_State *L)
{
+
+ langs = pmap_new(cstr_t)();
+
lua_createtable(L, 0, 0);
// type metatables
@@ -114,9 +119,55 @@ static int tslua_debug(lua_State *L)
return 2;
}
-void tslua_push_parser(lua_State *L, TSLanguage *lang)
+
+int ts_lua_register_lang(lua_State *L)
+{
+ if (lua_gettop(L) < 2 || !lua_isstring(L, 1) || !lua_isstring(L, 2)) {
+ return luaL_error(L, "string expected");
+ }
+
+ const char *path = lua_tostring(L,1);
+ const char *lang_name = lua_tostring(L,2);
+
+ if (pmap_has(cstr_t)(langs, lang_name)) {
+ return 0;
+ }
+
+ // TODO: unsafe!
+ char symbol_buf[128] = "tree_sitter_";
+ STRCAT(symbol_buf, lang_name);
+
+ // TODO: we should maybe keep the uv_lib_t around, and close them
+ // at exit, to keep LeakSanitizer happy.
+ uv_lib_t lib;
+ if (uv_dlopen(path, &lib)) {
+ return luaL_error(L, "Failed to load parser: uv_dlopen: %s", uv_dlerror(&lib));
+ }
+
+ TSLanguage *(*lang_parser)(void);
+ if (uv_dlsym(&lib, symbol_buf, (void **)&lang_parser)) {
+ return luaL_error(L, "Failed to load parser: uv_dlsym: %s", uv_dlerror(&lib));
+ }
+
+ TSLanguage *lang = lang_parser();
+ if (lang == NULL) {
+ return luaL_error(L, "Failed to load parser: internal error");
+ }
+
+ pmap_put(cstr_t)(langs, xstrdup(lang_name), lang);
+
+ lua_pushboolean(L, true);
+ return 1;
+}
+
+int tslua_push_parser(lua_State *L, const char *lang_name)
{
TSParser *parser = ts_parser_new();
+ TSLanguage *lang = pmap_get(cstr_t)(langs, lang_name);
+ if (!lang) {
+ return luaL_error(L, "no such language: %s", lang_name);
+ }
+
ts_parser_set_language(parser, lang);
Tslua_parser *p = lua_newuserdata(L, sizeof(Tslua_parser)); // [udata]
p->parser = parser;
@@ -126,6 +177,7 @@ void tslua_push_parser(lua_State *L, TSLanguage *lang)
lua_getfield(L, -1, "parser-meta"); // [udata, env, meta]
lua_setmetatable(L, -3); // [udata, env]
lua_pop(L, 1); // [udata]
+ return 1;
}
static Tslua_parser *parser_check(lua_State *L)