diff options
Diffstat (limited to 'src/nvim/lua/treesitter.c')
-rw-r--r-- | src/nvim/lua/treesitter.c | 200 |
1 files changed, 120 insertions, 80 deletions
diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c index e3fa48f530..37929093e3 100644 --- a/src/nvim/lua/treesitter.c +++ b/src/nvim/lua/treesitter.c @@ -5,22 +5,20 @@ // NB: this file mostly contains a generic lua interface for tree-sitter // trees and nodes, and could be broken out as a reusable lua package -#include <stdbool.h> -#include <stdlib.h> -#include <string.h> -#include <inttypes.h> #include <assert.h> - +#include <inttypes.h> +#include <lauxlib.h> #include <lua.h> #include <lualib.h> -#include <lauxlib.h> - -#include "tree_sitter/api.h" +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include "nvim/api/private/helpers.h" +#include "nvim/buffer.h" #include "nvim/lua/treesitter.h" -#include "nvim/api/private/handle.h" #include "nvim/memline.h" -#include "nvim/buffer.h" +#include "tree_sitter/api.h" #define TS_META_PARSER "treesitter_parser" #define TS_META_TREE "treesitter_tree" @@ -80,6 +78,10 @@ static struct luaL_Reg node_meta[] = { { "parent", node_parent }, { "iter_children", node_iter_children }, { "_rawquery", node_rawquery }, + { "next_sibling", node_next_sibling }, + { "prev_sibling", node_prev_sibling }, + { "next_named_sibling", node_next_named_sibling }, + { "prev_named_sibling", node_prev_named_sibling }, { NULL, NULL } }; @@ -101,7 +103,7 @@ static struct luaL_Reg treecursor_meta[] = { { NULL, NULL } }; -static PMap(cstr_t) *langs; +static PMap(cstr_t) langs = MAP_INIT; static void build_meta(lua_State *L, const char *tname, const luaL_Reg *meta) { @@ -119,8 +121,6 @@ static void build_meta(lua_State *L, const char *tname, 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)(); - // type metatables build_meta(L, TS_META_PARSER, parser_meta); build_meta(L, TS_META_TREE, tree_meta); @@ -133,7 +133,7 @@ void tslua_init(lua_State *L) int tslua_has_language(lua_State *L) { const char *lang_name = luaL_checkstring(L, 1); - lua_pushboolean(L, pmap_has(cstr_t)(langs, lang_name)); + lua_pushboolean(L, pmap_has(cstr_t)(&langs, lang_name)); return 1; } @@ -142,7 +142,7 @@ int tslua_add_language(lua_State *L) const char *path = luaL_checkstring(L, 1); const char *lang_name = luaL_checkstring(L, 2); - if (pmap_has(cstr_t)(langs, lang_name)) { + if (pmap_has(cstr_t)(&langs, lang_name)) { return 0; } @@ -177,15 +177,14 @@ int tslua_add_language(lua_State *L) uint32_t lang_version = ts_language_version(lang); if (lang_version < TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION || lang_version > TREE_SITTER_LANGUAGE_VERSION) { - return luaL_error( - L, - "ABI version mismatch for %s: supported between %d and %d, found %d", - path, - TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION, - TREE_SITTER_LANGUAGE_VERSION, lang_version); + return luaL_error(L, + "ABI version mismatch for %s: supported between %d and %d, found %d", + path, + TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION, + TREE_SITTER_LANGUAGE_VERSION, lang_version); } - pmap_put(cstr_t)(langs, xstrdup(lang_name), lang); + pmap_put(cstr_t)(&langs, xstrdup(lang_name), lang); lua_pushboolean(L, true); return 1; @@ -195,7 +194,7 @@ int tslua_inspect_lang(lua_State *L) { const char *lang_name = luaL_checkstring(L, 1); - TSLanguage *lang = pmap_get(cstr_t)(langs, lang_name); + TSLanguage *lang = pmap_get(cstr_t)(&langs, lang_name); if (!lang) { return luaL_error(L, "no such language: %s", lang_name); } @@ -243,7 +242,7 @@ int tslua_push_parser(lua_State *L) // Gather language name const char *lang_name = luaL_checkstring(L, 1); - TSLanguage *lang = pmap_get(cstr_t)(langs, lang_name); + TSLanguage *lang = pmap_get(cstr_t)(&langs, lang_name); if (!lang) { return luaL_error(L, "no such language: %s", lang_name); } @@ -261,7 +260,7 @@ int tslua_push_parser(lua_State *L) return 1; } -static TSParser ** parser_check(lua_State *L, uint16_t index) +static TSParser **parser_check(lua_State *L, uint16_t index) { return luaL_checkudata(L, index, TS_META_PARSER); } @@ -283,8 +282,8 @@ static int parser_tostring(lua_State *L) return 1; } -static const char *input_cb(void *payload, uint32_t byte_index, - TSPoint position, uint32_t *bytes_read) +static const char *input_cb(void *payload, uint32_t byte_index, TSPoint position, + uint32_t *bytes_read) { buf_T *bp = payload; #define BUFSIZE 256 @@ -316,9 +315,7 @@ static const char *input_cb(void *payload, uint32_t byte_index, #undef BUFSIZE } -static void push_ranges(lua_State *L, - const TSRange *ranges, - const unsigned int length) +static void push_ranges(lua_State *L, const TSRange *ranges, const unsigned int length) { lua_createtable(L, length, 0); for (size_t i = 0; i < length; i++) { @@ -359,40 +356,39 @@ static int parser_parse(lua_State *L) // This switch is necessary because of the behavior of lua_isstring, that // consider numbers as strings... switch (lua_type(L, 3)) { - case LUA_TSTRING: - str = lua_tolstring(L, 3, &len); - new_tree = ts_parser_parse_string(*p, old_tree, str, len); - break; + case LUA_TSTRING: + str = lua_tolstring(L, 3, &len); + new_tree = ts_parser_parse_string(*p, old_tree, str, len); + break; - case LUA_TNUMBER: - bufnr = lua_tointeger(L, 3); - buf = handle_get_buffer(bufnr); + case LUA_TNUMBER: + bufnr = lua_tointeger(L, 3); + buf = handle_get_buffer(bufnr); - if (!buf) { - return luaL_error(L, "invalid buffer handle: %d", bufnr); - } + if (!buf) { + return luaL_error(L, "invalid buffer handle: %d", bufnr); + } - input = (TSInput){ (void *)buf, input_cb, TSInputEncodingUTF8 }; - new_tree = ts_parser_parse(*p, old_tree, input); + input = (TSInput){ (void *)buf, input_cb, TSInputEncodingUTF8 }; + new_tree = ts_parser_parse(*p, old_tree, input); - break; + break; - default: - return luaL_error(L, "invalid argument to parser:parse()"); + default: + return luaL_error(L, "invalid argument to parser:parse()"); } // Sometimes parsing fails (timeout, or wrong parser ABI) // In those case, just return an error. if (!new_tree) { - return luaL_error(L, "An error occured when parsing."); + return luaL_error(L, "An error occurred when parsing."); } // The new tree will be pushed to the stack, without copy, owwership is now to // the lua GC. // Old tree is still owned by the lua GC. uint32_t n_ranges = 0; - TSRange *changed = old_tree ? ts_tree_get_changed_ranges( - old_tree, new_tree, &n_ranges) : NULL; + TSRange *changed = old_tree ? ts_tree_get_changed_ranges(old_tree, new_tree, &n_ranges) : NULL; push_tree(L, new_tree, false); // [tree] @@ -502,17 +498,15 @@ static void range_from_lua(lua_State *L, TSRange *range) } return; error: - luaL_error( - L, - "Ranges can only be made from 6 element long tables or nodes."); + luaL_error(L, + "Ranges can only be made from 6 element long tables or nodes."); } static int parser_set_ranges(lua_State *L) { if (lua_gettop(L) < 2) { - return luaL_error( - L, - "not enough args to parser:set_included_ranges()"); + return luaL_error(L, + "not enough args to parser:set_included_ranges()"); } TSParser **p = parser_check(L, 1); @@ -521,9 +515,8 @@ static int parser_set_ranges(lua_State *L) } if (!lua_istable(L, 2)) { - return luaL_error( - L, - "argument for parser:set_included_ranges() should be a table."); + return luaL_error(L, + "argument for parser:set_included_ranges() should be a table."); } size_t tbl_len = lua_objlen(L, 2); @@ -888,9 +881,9 @@ static int node_descendant_for_range(lua_State *L) return 0; } TSPoint start = { (uint32_t)lua_tointeger(L, 2), - (uint32_t)lua_tointeger(L, 3) }; + (uint32_t)lua_tointeger(L, 3) }; TSPoint end = { (uint32_t)lua_tointeger(L, 4), - (uint32_t)lua_tointeger(L, 5) }; + (uint32_t)lua_tointeger(L, 5) }; TSNode child = ts_node_descendant_for_point_range(node, start, end); push_node(L, child, 1); @@ -904,9 +897,9 @@ static int node_named_descendant_for_range(lua_State *L) return 0; } TSPoint start = { (uint32_t)lua_tointeger(L, 2), - (uint32_t)lua_tointeger(L, 3) }; + (uint32_t)lua_tointeger(L, 3) }; TSPoint end = { (uint32_t)lua_tointeger(L, 4), - (uint32_t)lua_tointeger(L, 5) }; + (uint32_t)lua_tointeger(L, 5) }; TSNode child = ts_node_named_descendant_for_point_range(node, start, end); push_node(L, child, 1); @@ -915,8 +908,7 @@ static int node_named_descendant_for_range(lua_State *L) static int node_next_child(lua_State *L) { - TSTreeCursor *ud = luaL_checkudata( - L, lua_upvalueindex(1), TS_META_TREECURSOR); + TSTreeCursor *ud = luaL_checkudata(L, lua_upvalueindex(1), TS_META_TREECURSOR); if (!ud) { return 0; } @@ -937,19 +929,18 @@ static int node_next_child(lua_State *L) if (ts_tree_cursor_goto_next_sibling(ud)) { push: - push_node( - L, - ts_tree_cursor_current_node(ud), - lua_upvalueindex(2)); // [node] + push_node(L, + ts_tree_cursor_current_node(ud), + lua_upvalueindex(2)); // [node] - const char * field = ts_tree_cursor_current_field_name(ud); + const char * field = ts_tree_cursor_current_field_name(ud); - if (field != NULL) { - lua_pushstring(L, ts_tree_cursor_current_field_name(ud)); - } else { - lua_pushnil(L); - } // [node, field_name_or_nil] - return 2; + if (field != NULL) { + lua_pushstring(L, ts_tree_cursor_current_field_name(ud)); + } else { + lua_pushnil(L); + } // [node, field_name_or_nil] + return 2; } end: @@ -992,6 +983,50 @@ static int node_parent(lua_State *L) return 1; } +static int node_next_sibling(lua_State *L) +{ + TSNode node; + if (!node_check(L, 1, &node)) { + return 0; + } + TSNode sibling = ts_node_next_sibling(node); + push_node(L, sibling, 1); + return 1; +} + +static int node_prev_sibling(lua_State *L) +{ + TSNode node; + if (!node_check(L, 1, &node)) { + return 0; + } + TSNode sibling = ts_node_prev_sibling(node); + push_node(L, sibling, 1); + return 1; +} + +static int node_next_named_sibling(lua_State *L) +{ + TSNode node; + if (!node_check(L, 1, &node)) { + return 0; + } + TSNode sibling = ts_node_next_named_sibling(node); + push_node(L, sibling, 1); + return 1; +} + +static int node_prev_named_sibling(lua_State *L) +{ + TSNode node; + if (!node_check(L, 1, &node)) { + return 0; + } + TSNode sibling = ts_node_prev_named_sibling(node); + push_node(L, sibling, 1); + return 1; +} + /// assumes the match table being on top of the stack static void set_match(lua_State *L, TSQueryMatch *match, int nodeidx) { @@ -1127,7 +1162,7 @@ int tslua_parse_query(lua_State *L) } const char *lang_name = lua_tostring(L, 1); - TSLanguage *lang = pmap_get(cstr_t)(langs, lang_name); + TSLanguage *lang = pmap_get(cstr_t)(&langs, lang_name); if (!lang) { return luaL_error(L, "no such language: %s", lang_name); } @@ -1154,11 +1189,16 @@ int tslua_parse_query(lua_State *L) static const char *query_err_string(TSQueryError err) { switch (err) { - case TSQueryErrorSyntax: return "invalid syntax"; - case TSQueryErrorNodeType: return "invalid node type"; - case TSQueryErrorField: return "invalid field"; - case TSQueryErrorCapture: return "invalid capture"; - default: return "error"; + case TSQueryErrorSyntax: + return "invalid syntax"; + case TSQueryErrorNodeType: + return "invalid node type"; + case TSQueryErrorField: + return "invalid field"; + case TSQueryErrorCapture: + return "invalid capture"; + default: + return "error"; } } |