From 1e9e2451bef21ff705e677802d1b0980356f1f86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Linse?= Date: Fri, 7 Jun 2019 18:19:59 +0200 Subject: [PATCH] tree-sitter: objectify API --- runtime/lua/tree_sitter_demo.lua | 2 +- runtime/lua/vim/tree_sitter.lua | 46 +++++++++++++++++++------------- runtime/plugin/ts_test.vim | 3 +-- src/nvim/lua/executor.c | 14 +--------- 4 files changed, 30 insertions(+), 35 deletions(-) diff --git a/runtime/lua/tree_sitter_demo.lua b/runtime/lua/tree_sitter_demo.lua index 24a0f3d622..bbfd69109d 100644 --- a/runtime/lua/tree_sitter_demo.lua +++ b/runtime/lua/tree_sitter_demo.lua @@ -7,7 +7,7 @@ end local my_ns = __treesitter_rt_ns function ts_inspect_pos(row,col) - local tree = parse_tree(theparser) + local tree = theparser:parse_tree() local root = tree:root() local node = root:descendant_for_point_range(row,col,row,col) show_node(node) diff --git a/runtime/lua/vim/tree_sitter.lua b/runtime/lua/vim/tree_sitter.lua index a4cb3f3db6..bbc4db5f29 100644 --- a/runtime/lua/vim/tree_sitter.lua +++ b/runtime/lua/vim/tree_sitter.lua @@ -1,47 +1,55 @@ local a = vim.api -function parse_tree(tsstate, force) - if tsstate.valid and not force then - return tsstate.tree +local Parser = {} +Parser.__index = Parser + +function Parser:parse_tree(force) + if self.valid and not force then + return self.tree end - tsstate.tree = tsstate.parser:parse_buf(tsstate.bufnr) - tsstate.valid = true - return tsstate.tree + self.tree = self._parser:parse_buf(self.bufnr) + self.valid = true + return self.tree end -local function change_cb(tsstate, ev, bufnr, tick, start_row, oldstopline, stop_row) +local function change_cb(self, ev, bufnr, tick, start_row, oldstopline, stop_row) local start_byte = a.nvim_buf_get_offset(bufnr,start_row) -- a bit messy, should we expose edited but not reparsed tree? -- are multiple edits safe in general? - local root = tsstate.parser:tree():root() + local root = self._parser:tree():root() -- TODO: add proper lookup function! local inode = root:descendant_for_point_range(oldstopline+9000,0, oldstopline,0) if inode == nil then local stop_byte = a.nvim_buf_get_offset(bufnr,stop_row) - tsstate.parser:edit(start_byte,stop_byte,stop_byte,start_row,0,stop_row,0,stop_row,0) + self._parser:edit(start_byte,stop_byte,stop_byte,start_row,0,stop_row,0,stop_row,0) else local fakeoldstoprow, fakeoldstopcol, fakebyteoldstop = inode:start() local fake_rows = fakeoldstoprow-oldstopline local fakestop = stop_row+fake_rows local fakebytestop = a.nvim_buf_get_offset(bufnr,fakestop)+fakeoldstopcol - tsstate.parser:edit(start_byte,fakebyteoldstop,fakebytestop,start_row,0,fakeoldstoprow,fakeoldstopcol,fakestop,fakeoldstopcol) + self._parser:edit(start_byte,fakebyteoldstop,fakebytestop,start_row,0,fakeoldstoprow,fakeoldstopcol,fakestop,fakeoldstopcol) end - tsstate.valid = false + self.valid = false end -function create_parser(bufnr) +local function create_parser(bufnr) if bufnr == 0 then bufnr = a.nvim_get_current_buf() end local ft = a.nvim_buf_get_option(bufnr, "filetype") - local tsstate = {} - tsstate.bufnr = bufnr - tsstate.parser = vim.ts_parser(ft.."_parser.so", ft) - parse_tree(tsstate) + local self = setmetatable({bufnr=bufnr, valid=false}, Parser) + self._parser = vim._create_ts_parser(ft.."_parser.so", ft) + self:parse_tree() local function cb(ev, ...) - return change_cb(tsstate, ev, ...) + -- TODO: use weakref to self, so that the parser is free'd is no plugin is + -- using it. + return change_cb(self, ev, ...) end - a.nvim_buf_attach(tsstate.bufnr, false, {on_lines=cb}) - return tsstate + a.nvim_buf_attach(self.bufnr, false, {on_lines=cb}) + return self end +-- TODO: weak table with reusable parser per buffer. + +return {create_parser=create_parser} + diff --git a/runtime/plugin/ts_test.vim b/runtime/plugin/ts_test.vim index d048dbe7c8..76318163f6 100644 --- a/runtime/plugin/ts_test.vim +++ b/runtime/plugin/ts_test.vim @@ -6,9 +6,8 @@ func! TSTest() return end " TODO: module! - lua require'vim.tree_sitter' + lua theparser = require'vim.tree_sitter'.create_parser(0) lua require'tree_sitter_demo' - lua theparser = create_parser(vim.api.nvim_get_current_buf()) let g:has_ts = v:true endfunc diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 1794cee8d8..a6447ebb2b 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -822,16 +822,6 @@ void ex_luafile(exarg_T *const eap) } } -static int unsafe_ptr_to_ts_tree(lua_State *L) -{ - if (!lua_gettop(L)) { - return 0; - } - TSTree *const *ptr = lua_topointer(L,1); - tslua_push_tree(L, *ptr); - return 1; -} - static int create_tslua_parser(lua_State *L) { if (lua_gettop(L) < 2) { @@ -867,9 +857,7 @@ static int create_tslua_parser(lua_State *L) static void nlua_add_treesitter(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL { tslua_init(lstate); - lua_pushcfunction(lstate, unsafe_ptr_to_ts_tree); - lua_setfield(lstate, -2, "unsafe_ts_tree"); lua_pushcfunction(lstate, create_tslua_parser); - lua_setfield(lstate, -2, "ts_parser"); + lua_setfield(lstate, -2, "_create_ts_parser"); }