aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api/vim.c
diff options
context:
space:
mode:
authorBjörn Linse <bjorn.linse@gmail.com>2020-09-13 08:29:49 +0200
committerGitHub <noreply@github.com>2020-09-13 08:29:49 +0200
commit542022aae4ed8d1c0352042858f06da1ee077bf8 (patch)
treeefdbc77ce8d0607f3bdfbd644022985a5d525058 /src/nvim/api/vim.c
parent4d3ef578e91cb23586979ed50fa0dfddd45ded1d (diff)
parent2c15f695a812c8b6ad1484912acbecb978f8727b (diff)
downloadrneovim-542022aae4ed8d1c0352042858f06da1ee077bf8.tar.gz
rneovim-542022aae4ed8d1c0352042858f06da1ee077bf8.tar.bz2
rneovim-542022aae4ed8d1c0352042858f06da1ee077bf8.zip
Merge pull request #12851 from bfredl/luahl
luahl: still WIP but better
Diffstat (limited to 'src/nvim/api/vim.c')
-rw-r--r--src/nvim/api/vim.c150
1 files changed, 142 insertions, 8 deletions
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 9155ffcfb8..1de1472fc2 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -2610,22 +2610,91 @@ Array nvim__inspect_cell(Integer grid, Integer row, Integer col, Error *err)
/// interface should probably be derived from a reformed
/// bufhl/virttext interface with full support for multi-line
/// ranges etc
-void nvim__put_attr(Integer id, Integer start_row, Integer start_col,
- Integer end_row, Integer end_col)
+void nvim__put_attr(Integer line, Integer col, Dictionary opts, Error *err)
FUNC_API_LUA_ONLY
{
if (!lua_attr_active) {
return;
}
- if (id == 0 || syn_get_final_id((int)id) == 0) {
- return;
+ int line2 = -1, hl_id = 0;
+ colnr_T col2 = 0;
+ VirtText virt_text = KV_INITIAL_VALUE;
+ for (size_t i = 0; i < opts.size; i++) {
+ String k = opts.items[i].key;
+ Object *v = &opts.items[i].value;
+ if (strequal("end_line", k.data)) {
+ if (v->type != kObjectTypeInteger) {
+ api_set_error(err, kErrorTypeValidation,
+ "end_line is not an integer");
+ goto error;
+ }
+ if (v->data.integer < 0) {
+ api_set_error(err, kErrorTypeValidation,
+ "end_line value outside range");
+ goto error;
+ }
+
+ line2 = (int)v->data.integer;
+ } else if (strequal("end_col", k.data)) {
+ if (v->type != kObjectTypeInteger) {
+ api_set_error(err, kErrorTypeValidation,
+ "end_col is not an integer");
+ goto error;
+ }
+ if (v->data.integer < 0 || v->data.integer > MAXCOL) {
+ api_set_error(err, kErrorTypeValidation,
+ "end_col value outside range");
+ goto error;
+ }
+
+ col2 = (colnr_T)v->data.integer;
+ } else if (strequal("hl_group", k.data)) {
+ String hl_group;
+ switch (v->type) {
+ case kObjectTypeString:
+ hl_group = v->data.string;
+ hl_id = syn_check_group(
+ (char_u *)(hl_group.data),
+ (int)hl_group.size);
+ break;
+ case kObjectTypeInteger:
+ hl_id = (int)v->data.integer;
+ break;
+ default:
+ api_set_error(err, kErrorTypeValidation,
+ "hl_group is not valid.");
+ goto error;
+ }
+ } else if (strequal("virt_text", k.data)) {
+ if (v->type != kObjectTypeArray) {
+ api_set_error(err, kErrorTypeValidation,
+ "virt_text is not an Array");
+ goto error;
+ }
+ virt_text = parse_virt_text(v->data.array, err);
+ if (ERROR_SET(err)) {
+ goto error;
+ }
+ } else {
+ api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data);
+ goto error;
+ }
+ }
+ if (col2 && line2 < 0) {
+ line2 = (int)line;
}
- int attr = syn_id2attr((int)id);
- if (attr == 0) {
+
+ int attr = hl_id ? syn_id2attr((int)hl_id) : 0;
+ if (attr == 0 && !kv_size(virt_text)) {
return;
}
- decorations_add_luahl_attr(attr, (int)start_row, (colnr_T)start_col,
- (int)end_row, (colnr_T)end_col);
+
+ VirtText *v = xmalloc(sizeof(*v));
+ *v = virt_text; // LeakSanitizer be sad
+ decorations_add_luahl_attr(attr, (int)line, (colnr_T)col,
+ (int)line2, (colnr_T)col2, v);
+error:
+ return;
}
void nvim__screenshot(String path)
@@ -2633,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);
+}