mirror of
https://github.com/neovim/neovim.git
synced 2025-10-17 07:16:09 +00:00
luahl
This commit is contained in:
@@ -1664,43 +1664,6 @@ void nvim_buf_clear_highlight(Buffer buffer,
|
|||||||
nvim_buf_clear_namespace(buffer, ns_id, line_start, line_end, err);
|
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.
|
/// Set the virtual text (annotation) for a buffer line.
|
||||||
///
|
///
|
||||||
|
@@ -15,6 +15,8 @@
|
|||||||
#include "nvim/lua/executor.h"
|
#include "nvim/lua/executor.h"
|
||||||
#include "nvim/ascii.h"
|
#include "nvim/ascii.h"
|
||||||
#include "nvim/assert.h"
|
#include "nvim/assert.h"
|
||||||
|
#include "nvim/charset.h"
|
||||||
|
#include "nvim/syntax.h"
|
||||||
#include "nvim/vim.h"
|
#include "nvim/vim.h"
|
||||||
#include "nvim/buffer.h"
|
#include "nvim/buffer.h"
|
||||||
#include "nvim/window.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;
|
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
|
/// interface should probably be derived from a reformed
|
||||||
/// bufhl/virttext interface with full support for multi-line
|
/// bufhl/virttext interface with full support for multi-line
|
||||||
/// ranges etc
|
/// ranges etc
|
||||||
void nvim__put_attr(Integer id, Integer start_row, Integer start_col,
|
void nvim__put_attr(Integer line, Integer col, Dictionary opts, Error *err)
|
||||||
Integer end_row, Integer end_col)
|
|
||||||
FUNC_API_LUA_ONLY
|
FUNC_API_LUA_ONLY
|
||||||
{
|
{
|
||||||
if (!lua_attr_active) {
|
if (!lua_attr_active) {
|
||||||
return;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
int attr = syn_id2attr((int)id);
|
|
||||||
if (attr == 0) {
|
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;
|
return;
|
||||||
}
|
|
||||||
decorations_add_luahl_attr(attr, (int)start_row, (colnr_T)start_col,
|
|
||||||
(int)end_row, (colnr_T)end_col);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvim__screenshot(String path)
|
void nvim__screenshot(String path)
|
||||||
|
@@ -639,10 +639,11 @@ bool decorations_active = false;
|
|||||||
|
|
||||||
void decorations_add_luahl_attr(int attr_id,
|
void decorations_add_luahl_attr(int attr_id,
|
||||||
int start_row, int start_col,
|
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,
|
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);
|
args.items[2] = INTEGER_OBJ(lnum-1);
|
||||||
lua_attr_active = true;
|
lua_attr_active = true;
|
||||||
extra_check = 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;
|
lua_attr_active = false;
|
||||||
if (o.type == kObjectTypeString) {
|
if (ERROR_SET(&err)) {
|
||||||
// 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)) {
|
|
||||||
ELOG("error in luahl line: %s", err.msg);
|
ELOG("error in luahl line: %s", err.msg);
|
||||||
luatext = err.msg;
|
luatext = err.msg;
|
||||||
do_virttext = true;
|
do_virttext = true;
|
||||||
|
Reference in New Issue
Block a user