diff options
author | Björn Linse <bjorn.linse@gmail.com> | 2020-09-12 10:29:30 +0200 |
---|---|---|
committer | Björn Linse <bjorn.linse@gmail.com> | 2020-09-13 07:46:39 +0200 |
commit | 4042975df42152a64f4d390ed677013d1c8609c5 (patch) | |
tree | d512c959d96451357f152c5c8f3beb12f0c029d6 | |
parent | 05c68922d35af8db38df594a46c87270b5cac0c8 (diff) | |
download | rneovim-4042975df42152a64f4d390ed677013d1c8609c5.tar.gz rneovim-4042975df42152a64f4d390ed677013d1c8609c5.tar.bz2 rneovim-4042975df42152a64f4d390ed677013d1c8609c5.zip |
luahl: global the luahl
-rw-r--r-- | runtime/lua/vim/treesitter/highlighter.lua | 60 | ||||
-rw-r--r-- | src/nvim/api/buffer.c | 72 | ||||
-rw-r--r-- | src/nvim/api/private/helpers.c | 12 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 65 | ||||
-rw-r--r-- | src/nvim/buffer_defs.h | 6 | ||||
-rw-r--r-- | src/nvim/extmark.c | 2 | ||||
-rw-r--r-- | src/nvim/globals.h | 6 | ||||
-rw-r--r-- | src/nvim/main.c | 2 | ||||
-rw-r--r-- | src/nvim/screen.c | 23 |
9 files changed, 144 insertions, 104 deletions
diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index 772016ee57..5b964a6020 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -4,6 +4,8 @@ local a = vim.api local TSHighlighter = rawget(vim.treesitter, 'TSHighlighter') or {} TSHighlighter.__index = TSHighlighter +TSHighlighter.active = TSHighlighter.active or {} + -- These are conventions defined by tree-sitter, though it -- needs to be user extensible also. TSHighlighter.hl_map = { @@ -53,13 +55,16 @@ TSHighlighter.hl_map = { } function TSHighlighter.new(query, bufnr, ft) + if bufnr == nil or bufnr == 0 then + bufnr = a.nvim_get_current_buf() + end + local self = setmetatable({}, TSHighlighter) self.parser = vim.treesitter.get_parser( bufnr, ft, { on_changedtree = function(...) self:on_changedtree(...) end, - on_bytes = function() self.parser:parse() end } ) @@ -71,11 +76,8 @@ function TSHighlighter.new(query, bufnr, ft) self.root = self.parser:parse():root() a.nvim_buf_set_option(self.buf, "syntax", "") - a.nvim__buf_set_luahl(self.buf, { - on_start=function(...) return self:on_start(...) end, - on_window=function(...) return self:on_window(...) end, - on_line=function(...) return self:on_line(...) end, - }) + -- TODO(bfredl): can has multiple highlighters per buffer???? + TSHighlighter.active[bufnr] = self -- Tricky: if syntax hasn't been enabled, we need to reload color scheme -- but use synload.vim rather than syntax.vim to not enable @@ -138,20 +140,13 @@ function TSHighlighter:set_query(query) a.nvim__buf_redraw_range(self.buf, 0, a.nvim_buf_line_count(self.buf)) end -function TSHighlighter:on_window(_, _win, _buf, _topline, botline) - self.iter = nil - self.nextrow = 0 - self.botline = botline - self.redraw_count = self.redraw_count + 1 -end - -function TSHighlighter:on_start(_, _buf, _tick) - local tree = self.parser:parse() - self.root = tree:root() -end - +function TSHighlighter._on_line(_, _win, buf, line) + -- on_line is only called when this is non-nil + local self = TSHighlighter.active[buf] + if self.root == nil then + return -- parser bought the farm already + end -function TSHighlighter:on_line(_, _win, buf, line) if self.iter == nil then self.iter = self.query:iter_captures(self.root,buf,line,self.botline) end @@ -171,4 +166,31 @@ function TSHighlighter:on_line(_, _win, buf, line) end end +function TSHighlighter._on_start(_, buf, _tick) + local self = TSHighlighter.active[buf] + if self then + local tree = self.parser:parse() + self.root = (tree and tree:root()) or nil + end +end + +function TSHighlighter._on_win(_, _win, buf, _topline, botline) + local self = TSHighlighter.active[buf] + if not self then + return false + end + + self.iter = nil + self.nextrow = 0 + self.botline = botline + self.redraw_count = self.redraw_count + 1 + return true +end + +a.nvim__set_luahl { + on_start = TSHighlighter._on_start; + on_win = TSHighlighter._on_win; + on_line = TSHighlighter._on_line; +} + return TSHighlighter diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index e58035b6c7..21f7c8e931 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -244,78 +244,6 @@ Boolean nvim_buf_detach(uint64_t channel_id, return true; } -static void buf_clear_luahl(buf_T *buf, bool force) -{ - if (buf->b_luahl || force) { - api_free_luaref(buf->b_luahl_start); - api_free_luaref(buf->b_luahl_window); - api_free_luaref(buf->b_luahl_line); - api_free_luaref(buf->b_luahl_end); - } - buf->b_luahl_start = LUA_NOREF; - buf->b_luahl_window = LUA_NOREF; - buf->b_luahl_line = LUA_NOREF; - buf->b_luahl_end = LUA_NOREF; -} - -/// Unstabilized interface for defining syntax hl in lua. -/// -/// This is not yet safe for general use, lua callbacks will need to -/// be restricted, like textlock and probably other stuff. -/// -/// The API on_line/nvim__put_attr is quite raw and not intended to be the -/// final shape. Ideally this should operate on chunks larger than a single -/// line to reduce interpreter overhead, and generate annotation objects -/// (bufhl/virttext) on the fly but using the same representation. -void nvim__buf_set_luahl(uint64_t channel_id, Buffer buffer, - DictionaryOf(LuaRef) opts, Error *err) - FUNC_API_LUA_ONLY -{ - buf_T *buf = find_buffer_by_handle(buffer, err); - - if (!buf) { - return; - } - - redraw_buf_later(buf, NOT_VALID); - buf_clear_luahl(buf, false); - - for (size_t i = 0; i < opts.size; i++) { - String k = opts.items[i].key; - Object *v = &opts.items[i].value; - if (strequal("on_start", k.data)) { - if (v->type != kObjectTypeLuaRef) { - api_set_error(err, kErrorTypeValidation, "callback is not a function"); - goto error; - } - buf->b_luahl_start = v->data.luaref; - v->data.luaref = LUA_NOREF; - } else if (strequal("on_window", k.data)) { - if (v->type != kObjectTypeLuaRef) { - api_set_error(err, kErrorTypeValidation, "callback is not a function"); - goto error; - } - buf->b_luahl_window = v->data.luaref; - v->data.luaref = LUA_NOREF; - } else if (strequal("on_line", k.data)) { - if (v->type != kObjectTypeLuaRef) { - api_set_error(err, kErrorTypeValidation, "callback is not a function"); - goto error; - } - buf->b_luahl_line = v->data.luaref; - v->data.luaref = LUA_NOREF; - } else { - api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); - goto error; - } - } - buf->b_luahl = true; - return; -error: - buf_clear_luahl(buf, true); - buf->b_luahl = false; -} - void nvim__buf_redraw_range(Buffer buffer, Integer first, Integer last, Error *err) FUNC_API_LUA_ONLY diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index f1ecd732ee..e0d5862e02 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -1618,3 +1618,15 @@ free_exit: clear_virttext(&virt_text); return virt_text; } + +bool api_is_truthy(Object obj, const char *what, Error *err) +{ + if (obj.type == kObjectTypeBoolean) { + return obj.data.boolean; + } else if (obj.type == kObjectTypeInteger) { + return obj.data.integer; // C semantics: non-zery int is true + } else { + api_set_error(err, kErrorTypeValidation, "%s is not an boolean", what); + return false; + } +} diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index cb5d1e1f77..1de1472fc2 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -2702,3 +2702,68 @@ void nvim__screenshot(String path) { ui_call_screenshot(path); } + +static void clear_luahl(bool force) +{ + if (luahl_active || force) { + api_free_luaref(luahl_start); + api_free_luaref(luahl_win); + api_free_luaref(luahl_line); + api_free_luaref(luahl_end); + } + luahl_start = LUA_NOREF; + luahl_win = LUA_NOREF; + luahl_line = LUA_NOREF; + luahl_end = LUA_NOREF; + luahl_active = false; +} + +/// Unstabilized interface for defining syntax hl in lua. +/// +/// This is not yet safe for general use, lua callbacks will need to +/// be restricted, like textlock and probably other stuff. +/// +/// The API on_line/nvim__put_attr is quite raw and not intended to be the +/// final shape. Ideally this should operate on chunks larger than a single +/// line to reduce interpreter overhead, and generate annotation objects +/// (bufhl/virttext) on the fly but using the same representation. +void nvim__set_luahl(DictionaryOf(LuaRef) opts, Error *err) + FUNC_API_LUA_ONLY +{ + redraw_later(NOT_VALID); + clear_luahl(false); + + for (size_t i = 0; i < opts.size; i++) { + String k = opts.items[i].key; + Object *v = &opts.items[i].value; + if (strequal("on_start", k.data)) { + if (v->type != kObjectTypeLuaRef) { + api_set_error(err, kErrorTypeValidation, "callback is not a function"); + goto error; + } + luahl_start = v->data.luaref; + v->data.luaref = LUA_NOREF; + } else if (strequal("on_win", k.data)) { + if (v->type != kObjectTypeLuaRef) { + api_set_error(err, kErrorTypeValidation, "callback is not a function"); + goto error; + } + luahl_win = v->data.luaref; + v->data.luaref = LUA_NOREF; + } else if (strequal("on_line", k.data)) { + if (v->type != kObjectTypeLuaRef) { + api_set_error(err, kErrorTypeValidation, "callback is not a function"); + goto error; + } + luahl_line = v->data.luaref; + v->data.luaref = LUA_NOREF; + } else { + api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); + goto error; + } + } + luahl_active = true; + return; +error: + clear_luahl(true); +} diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index b3c95f9362..bd9cd2f5ec 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -842,12 +842,6 @@ struct file_buffer { // The number for times the current line has been flushed in the memline. int flush_count; - bool b_luahl; - LuaRef b_luahl_start; - LuaRef b_luahl_window; - LuaRef b_luahl_line; - LuaRef b_luahl_end; - int b_diff_failed; // internal diff failed for this buffer }; diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c index 3a04908ccb..c45714de78 100644 --- a/src/nvim/extmark.c +++ b/src/nvim/extmark.c @@ -845,7 +845,7 @@ bool decorations_redraw_reset(buf_T *buf, DecorationRedrawState *state) { state->row = -1; kv_size(state->active) = 0; - return buf->b_extmark_index || buf->b_luahl; + return buf->b_extmark_index; } diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 205be4b811..ddb69fc567 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -405,6 +405,12 @@ EXTERN int sys_menu INIT(= false); // ('lines' and 'rows') must not be changed. EXTERN int updating_screen INIT(= 0); +EXTERN bool luahl_active INIT(= false); +EXTERN LuaRef luahl_start INIT(= LUA_NOREF); +EXTERN LuaRef luahl_win INIT(= LUA_NOREF); +EXTERN LuaRef luahl_line INIT(= LUA_NOREF); +EXTERN LuaRef luahl_end INIT(= LUA_NOREF); + // All windows are linked in a list. firstwin points to the first entry, // lastwin to the last entry (can be the same as firstwin) and curwin to the // currently active window. diff --git a/src/nvim/main.c b/src/nvim/main.c index 1374c5eb5d..a22df9cc69 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -7,6 +7,8 @@ #include <string.h> #include <stdbool.h> +#include <lua.h> +#include <lauxlib.h> #include <msgpack.h> #include "nvim/ascii.h" diff --git a/src/nvim/screen.c b/src/nvim/screen.c index ca1c4589f8..7d020432d9 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -158,6 +158,8 @@ static bool msg_grid_invalid = false; static bool resizing = false; +static bool do_luahl_line = false; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "screen.c.generated.h" #endif @@ -508,12 +510,12 @@ int update_screen(int type) } buf_T *buf = wp->w_buffer; - if (buf->b_luahl && buf->b_luahl_window != LUA_NOREF) { + if (luahl_active && luahl_start != LUA_NOREF) { Error err = ERROR_INIT; FIXED_TEMP_ARRAY(args, 2); args.items[0] = BUFFER_OBJ(buf->handle); args.items[1] = INTEGER_OBJ(display_tick); - nlua_call_ref(buf->b_luahl_start, "start", args, false, &err); + nlua_call_ref(luahl_start, "start", args, false, &err); if (ERROR_SET(&err)) { ELOG("error in luahl start: %s", err.msg); api_clear_error(&err); @@ -1239,7 +1241,9 @@ static void win_update(win_T *wp) decorations_active = decorations_redraw_reset(buf, &decorations); - if (buf->b_luahl && buf->b_luahl_window != LUA_NOREF) { + do_luahl_line = false; + + if (luahl_win != LUA_NOREF) { Error err = ERROR_INIT; FIXED_TEMP_ARRAY(args, 4); linenr_T knownmax = ((wp->w_valid & VALID_BOTLINE) @@ -1252,7 +1256,13 @@ static void win_update(win_T *wp) args.items[3] = INTEGER_OBJ(knownmax); // TODO(bfredl): we could allow this callback to change mod_top, mod_bot. // For now the "start" callback is expected to use nvim__buf_redraw_range. - nlua_call_ref(buf->b_luahl_window, "window", args, false, &err); + Object ret = nlua_call_ref(luahl_win, "win", args, true, &err); + + if (!ERROR_SET(&err) && api_is_truthy(ret, "luahl_window retval", &err)) { + do_luahl_line = true; + decorations_active = true; + } + if (ERROR_SET(&err)) { ELOG("error in luahl window: %s", err.msg); api_clear_error(&err); @@ -2349,7 +2359,7 @@ win_line ( } if (decorations_active) { - if (buf->b_luahl && buf->b_luahl_line != LUA_NOREF) { + if (do_luahl_line && luahl_line != LUA_NOREF) { Error err = ERROR_INIT; FIXED_TEMP_ARRAY(args, 3); args.items[0] = WINDOW_OBJ(wp->handle); @@ -2357,8 +2367,9 @@ win_line ( args.items[2] = INTEGER_OBJ(lnum-1); lua_attr_active = true; extra_check = true; - nlua_call_ref(buf->b_luahl_line, "line", args, false, &err); + nlua_call_ref(luahl_line, "line", args, false, &err); lua_attr_active = false; + if (ERROR_SET(&err)) { ELOG("error in luahl line: %s", err.msg); luatext = err.msg; |