aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/api')
-rw-r--r--src/nvim/api/buffer.c45
-rw-r--r--src/nvim/api/private/helpers.c37
-rw-r--r--src/nvim/api/vim.c42
3 files changed, 119 insertions, 5 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 8d82d22040..67f4f92bf6 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -1200,8 +1200,7 @@ static Array extmark_to_array(ExtmarkInfo extmark, bool id, bool add_dict)
/// @param ns_id Namespace id from |nvim_create_namespace()|
/// @param id Extmark id
/// @param opts Optional parameters. Keys:
-/// - limit: Maximum number of marks to return
-/// - details Whether to include the details dict
+/// - details: Whether to include the details dict
/// @param[out] err Error details, if any
/// @return (row, col) tuple or empty list () if extmark id was absent
ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id,
@@ -1400,6 +1399,13 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id,
/// callbacks. The mark will only be used for the current
/// redraw cycle, and not be permantently stored in the
/// buffer.
+/// - right_gravity : boolean that indicates the direction
+/// the extmark will be shifted in when new text is inserted
+/// (true for right, false for left). defaults to true.
+/// - end_right_gravity : boolean that indicates the direction
+/// the extmark end position (if it exists) will be shifted
+/// in when new text is inserted (true for right, false
+/// for left). Defaults to false.
/// @param[out] err Error details, if any
/// @return Id of the created/updated extmark
Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
@@ -1440,6 +1446,10 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
DecorPriority priority = DECOR_PRIORITY_BASE;
colnr_T col2 = 0;
VirtText virt_text = KV_INITIAL_VALUE;
+ bool right_gravity = true;
+ bool end_right_gravity = false;
+ bool end_gravity_set = false;
+
for (size_t i = 0; i < opts.size; i++) {
String k = opts.items[i].key;
Object *v = &opts.items[i].value;
@@ -1522,12 +1532,35 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
goto error;
}
priority = (DecorPriority)v->data.integer;
+ } else if (strequal("right_gravity", k.data)) {
+ if (v->type != kObjectTypeBoolean) {
+ api_set_error(err, kErrorTypeValidation,
+ "right_gravity must be a boolean");
+ goto error;
+ }
+ right_gravity = v->data.boolean;
+ } else if (strequal("end_right_gravity", k.data)) {
+ if (v->type != kObjectTypeBoolean) {
+ api_set_error(err, kErrorTypeValidation,
+ "end_right_gravity must be a boolean");
+ goto error;
+ }
+ end_right_gravity = v->data.boolean;
+ end_gravity_set = true;
} else {
api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data);
goto error;
}
}
+ // Only error out if they try to set end_right_gravity without
+ // setting end_col or end_line
+ if (line2 == -1 && col2 == 0 && end_gravity_set) {
+ api_set_error(err, kErrorTypeValidation,
+ "cannot set end_right_gravity "
+ "without setting end_line or end_col");
+ }
+
if (col2 >= 0) {
if (line2 >= 0 && line2 < buf->b_ml.ml_line_count) {
len = STRLEN(ml_get_buf(buf, (linenr_T)line2 + 1, false));
@@ -1572,7 +1605,8 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
}
id = extmark_set(buf, (uint64_t)ns_id, id, (int)line, (colnr_T)col,
- line2, col2, decor, kExtmarkNoUndo);
+ line2, col2, decor, right_gravity,
+ end_right_gravity, kExtmarkNoUndo);
}
return (Integer)id;
@@ -1687,7 +1721,7 @@ Integer nvim_buf_add_highlight(Buffer buffer,
extmark_set(buf, ns_id, 0,
(int)line, (colnr_T)col_start,
end_line, (colnr_T)col_end,
- decor_hl(hl_id), kExtmarkNoUndo);
+ decor_hl(hl_id), true, false, kExtmarkNoUndo);
return src_id;
}
@@ -1796,7 +1830,8 @@ Integer nvim_buf_set_virtual_text(Buffer buffer,
Decoration *decor = xcalloc(1, sizeof(*decor));
decor->virt_text = virt_text;
- extmark_set(buf, ns_id, 0, (int)line, 0, -1, -1, decor, kExtmarkNoUndo);
+ extmark_set(buf, ns_id, 0, (int)line, 0, -1, -1, decor, true,
+ false, kExtmarkNoUndo);
return src_id;
}
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index 8f224e8c78..7cee569989 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -1645,6 +1645,43 @@ bool api_object_to_bool(Object obj, const char *what,
}
}
+HlMessage parse_hl_msg(Array chunks, Error *err)
+{
+ HlMessage hl_msg = 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 = copy_string(chunk.items[0].data.string);
+
+ int attr = 0;
+ if (chunk.size == 2) {
+ String hl = chunk.items[1].data.string;
+ if (hl.size > 0) {
+ int hl_id = syn_check_group((char_u *)hl.data, (int)hl.size);
+ attr = hl_id > 0 ? syn_id2attr(hl_id) : 0;
+ }
+ }
+ kv_push(hl_msg, ((HlMessageChunk){ .text = str, .attr = attr }));
+ }
+
+ return hl_msg;
+
+free_exit:
+ clear_hl_msg(&hl_msg);
+ return hl_msg;
+}
+
const char *describe_ns(NS ns_id)
{
String name;
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 1e972e01be..09895a2119 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -990,6 +990,48 @@ void nvim_set_option(uint64_t channel_id, String name, Object value, Error *err)
set_option_to(channel_id, NULL, SREQ_GLOBAL, name, value, err);
}
+/// Echo a message.
+///
+/// @param chunks A list of [text, hl_group] arrays, each representing a
+/// text chunk with specified highlight. `hl_group` element
+/// can be omitted for no highlight.
+/// @param history if true, add to |message-history|.
+/// @param opts Optional parameters. Reserved for future use.
+void nvim_echo(Array chunks, Boolean history, Dictionary opts, Error *err)
+ FUNC_API_SINCE(7)
+{
+ HlMessage hl_msg = parse_hl_msg(chunks, err);
+ if (ERROR_SET(err)) {
+ goto error;
+ }
+
+ if (opts.size > 0) {
+ api_set_error(err, kErrorTypeValidation, "opts dict isn't empty");
+ goto error;
+ }
+
+ no_wait_return++;
+ msg_start();
+ msg_clr_eos();
+ bool need_clear = false;
+ for (uint32_t i = 0; i < kv_size(hl_msg); i++) {
+ HlMessageChunk chunk = kv_A(hl_msg, i);
+ msg_multiline_attr((const char *)chunk.text.data, chunk.attr,
+ false, &need_clear);
+ }
+ if (history) {
+ msg_ext_set_kind("echomsg");
+ add_hl_msg_hist(hl_msg);
+ } else {
+ msg_ext_set_kind("echo");
+ }
+ no_wait_return--;
+ msg_end();
+
+error:
+ clear_hl_msg(&hl_msg);
+}
+
/// Writes a message to the Vim output buffer. Does not append "\n", the
/// message is buffered (won't display) until a linefeed is written.
///