mirror of
https://github.com/neovim/neovim.git
synced 2024-12-20 11:15:14 -07:00
luahl
This commit is contained in:
parent
4d3ef578e9
commit
18a3a89822
@ -1664,43 +1664,6 @@ void nvim_buf_clear_highlight(Buffer buffer,
|
||||
nvim_buf_clear_namespace(buffer, ns_id, line_start, line_end, err);
|
||||
}
|
||||
|
||||
static VirtText parse_virt_text(Array chunks, Error *err)
|
||||
{
|
||||
VirtText virt_text = KV_INITIAL_VALUE;
|
||||
for (size_t i = 0; i < chunks.size; i++) {
|
||||
if (chunks.items[i].type != kObjectTypeArray) {
|
||||
api_set_error(err, kErrorTypeValidation, "Chunk is not an array");
|
||||
goto free_exit;
|
||||
}
|
||||
Array chunk = chunks.items[i].data.array;
|
||||
if (chunk.size == 0 || chunk.size > 2
|
||||
|| chunk.items[0].type != kObjectTypeString
|
||||
|| (chunk.size == 2 && chunk.items[1].type != kObjectTypeString)) {
|
||||
api_set_error(err, kErrorTypeValidation,
|
||||
"Chunk is not an array with one or two strings");
|
||||
goto free_exit;
|
||||
}
|
||||
|
||||
String str = chunk.items[0].data.string;
|
||||
char *text = transstr(str.size > 0 ? str.data : ""); // allocates
|
||||
|
||||
int hl_id = 0;
|
||||
if (chunk.size == 2) {
|
||||
String hl = chunk.items[1].data.string;
|
||||
if (hl.size > 0) {
|
||||
hl_id = syn_check_group((char_u *)hl.data, (int)hl.size);
|
||||
}
|
||||
}
|
||||
kv_push(virt_text, ((VirtTextChunk){ .text = text, .hl_id = hl_id }));
|
||||
}
|
||||
|
||||
return virt_text;
|
||||
|
||||
free_exit:
|
||||
clear_virttext(&virt_text);
|
||||
return virt_text;
|
||||
}
|
||||
|
||||
|
||||
/// Set the virtual text (annotation) for a buffer line.
|
||||
///
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include "nvim/lua/executor.h"
|
||||
#include "nvim/ascii.h"
|
||||
#include "nvim/assert.h"
|
||||
#include "nvim/charset.h"
|
||||
#include "nvim/syntax.h"
|
||||
#include "nvim/vim.h"
|
||||
#include "nvim/buffer.h"
|
||||
#include "nvim/window.h"
|
||||
@ -1579,3 +1581,40 @@ bool extmark_get_index_from_obj(buf_T *buf, Integer ns_id, Object obj, int
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
VirtText parse_virt_text(Array chunks, Error *err)
|
||||
{
|
||||
VirtText virt_text = KV_INITIAL_VALUE;
|
||||
for (size_t i = 0; i < chunks.size; i++) {
|
||||
if (chunks.items[i].type != kObjectTypeArray) {
|
||||
api_set_error(err, kErrorTypeValidation, "Chunk is not an array");
|
||||
goto free_exit;
|
||||
}
|
||||
Array chunk = chunks.items[i].data.array;
|
||||
if (chunk.size == 0 || chunk.size > 2
|
||||
|| chunk.items[0].type != kObjectTypeString
|
||||
|| (chunk.size == 2 && chunk.items[1].type != kObjectTypeString)) {
|
||||
api_set_error(err, kErrorTypeValidation,
|
||||
"Chunk is not an array with one or two strings");
|
||||
goto free_exit;
|
||||
}
|
||||
|
||||
String str = chunk.items[0].data.string;
|
||||
char *text = transstr(str.size > 0 ? str.data : ""); // allocates
|
||||
|
||||
int hl_id = 0;
|
||||
if (chunk.size == 2) {
|
||||
String hl = chunk.items[1].data.string;
|
||||
if (hl.size > 0) {
|
||||
hl_id = syn_check_group((char_u *)hl.data, (int)hl.size);
|
||||
}
|
||||
}
|
||||
kv_push(virt_text, ((VirtTextChunk){ .text = text, .hl_id = hl_id }));
|
||||
}
|
||||
|
||||
return virt_text;
|
||||
|
||||
free_exit:
|
||||
clear_virttext(&virt_text);
|
||||
return virt_text;
|
||||
}
|
||||
|
@ -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) {
|
||||
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 = hl_id ? syn_id2attr((int)hl_id) : 0;
|
||||
if (attr == 0 && !kv_size(virt_text)) {
|
||||
return;
|
||||
}
|
||||
int attr = syn_id2attr((int)id);
|
||||
if (attr == 0) {
|
||||
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)
|
||||
|
@ -639,10 +639,11 @@ bool decorations_active = false;
|
||||
|
||||
void decorations_add_luahl_attr(int attr_id,
|
||||
int start_row, int start_col,
|
||||
int end_row, int end_col)
|
||||
int end_row, int end_col, VirtText *virt_text)
|
||||
{
|
||||
kv_push(decorations.active,
|
||||
((HlRange){ start_row, start_col, end_row, end_col, attr_id, NULL }));
|
||||
((HlRange){ start_row, start_col,
|
||||
end_row, end_col, attr_id, virt_text }));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2356,14 +2357,9 @@ win_line (
|
||||
args.items[2] = INTEGER_OBJ(lnum-1);
|
||||
lua_attr_active = true;
|
||||
extra_check = true;
|
||||
Object o = nlua_call_ref(buf->b_luahl_line, "line", args, true, &err);
|
||||
nlua_call_ref(buf->b_luahl_line, "line", args, false, &err);
|
||||
lua_attr_active = false;
|
||||
if (o.type == kObjectTypeString) {
|
||||
// TODO(bfredl): this is a bit of a hack. A final API should use an
|
||||
// "unified" interface where luahl can add both bufhl and virttext
|
||||
luatext = o.data.string.data;
|
||||
do_virttext = true;
|
||||
} else if (ERROR_SET(&err)) {
|
||||
if (ERROR_SET(&err)) {
|
||||
ELOG("error in luahl line: %s", err.msg);
|
||||
luatext = err.msg;
|
||||
do_virttext = true;
|
||||
|
Loading…
Reference in New Issue
Block a user