aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api/buffer.c
diff options
context:
space:
mode:
authorBjörn Linse <bjorn.linse@gmail.com>2021-08-08 17:36:54 +0200
committerBjörn Linse <bjorn.linse@gmail.com>2021-09-26 12:19:54 +0200
commit392c658d4d0f9457f143748adf98ecd4cdc8dc85 (patch)
tree187943b860e19c66dbdd898661d67274c55e983f /src/nvim/api/buffer.c
parentb3b02eb52943fdc8ba74af3b485e9d11655bc9c9 (diff)
downloadrneovim-392c658d4d0f9457f143748adf98ecd4cdc8dc85.tar.gz
rneovim-392c658d4d0f9457f143748adf98ecd4cdc8dc85.tar.bz2
rneovim-392c658d4d0f9457f143748adf98ecd4cdc8dc85.zip
feat(decorations): support virtual lines (for now: only one block at a time)
Diffstat (limited to 'src/nvim/api/buffer.c')
-rw-r--r--src/nvim/api/buffer.c86
1 files changed, 78 insertions, 8 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 8973f8fef6..0ef2776263 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -1415,6 +1415,10 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
/// - end_col : ending col of the mark, 0-based exclusive.
/// - hl_group : name of the highlight group used to highlight
/// this mark.
+/// - hl_eol : when true, for a multiline highlight covering the
+/// EOL of a line, continue the highlight for the rest
+/// of the screen line (just like for diff and
+/// cursorline highlight).
/// - virt_text : virtual text to link to this mark.
/// A list of [text, highlight] tuples, each representing a
/// text chunk with specified highlight. `highlight` element
@@ -1442,10 +1446,28 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
/// default
/// - "combine": combine with background text color
/// - "blend": blend with background text color.
-/// - hl_eol : when true, for a multiline highlight covering the
-/// EOL of a line, continue the highlight for the rest
-/// of the screen line (just like for diff and
-/// cursorline highlight).
+///
+/// - virt_lines : virtual lines to add next to this mark
+/// This should be an array over lines, where each line in
+/// turn is an array over [text, highlight] tuples. In
+/// general, buffer and window options do not affect the
+/// display of the text. In particular 'wrap'
+/// and 'linebreak' options do not take effect, so
+/// the number of extra screen lines will always match
+/// the size of the array. However the 'tabstop' buffer
+/// option is still used for hard tabs. By default lines are
+/// placed below the buffer line containing the mark.
+///
+/// Note: currently virtual lines are limited to one block
+/// per buffer. Thus setting a new mark disables any previous
+/// `virt_lines` decoration. However plugins should not rely
+/// on this behaviour, as this limitation is planned to be
+/// removed.
+///
+/// - virt_lines_above: place virtual lines above instead.
+/// - virt_lines_leftcol: Place extmarks in the leftmost
+/// column of the window, bypassing
+/// sign and number columns.
///
/// - ephemeral : for use with |nvim_set_decoration_provider|
/// callbacks. The mark will only be used for the current
@@ -1487,6 +1509,10 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
bool end_right_gravity = false;
bool end_gravity_set = false;
+ VirtLines virt_lines = KV_INITIAL_VALUE;
+ bool virt_lines_above = false;
+ bool virt_lines_leftcol = false;
+
for (size_t i = 0; i < opts.size; i++) {
String k = opts.items[i].key;
Object *v = &opts.items[i].value;
@@ -1584,6 +1610,36 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
if (ERROR_SET(err)) {
goto error;
}
+ } else if (strequal("virt_lines", k.data)) {
+ if (v->type != kObjectTypeArray) {
+ api_set_error(err, kErrorTypeValidation,
+ "virt_lines is not an Array");
+ goto error;
+ }
+ Array a = v->data.array;
+ for (size_t j = 0; j < a.size; j++) {
+ if (a.items[j].type != kObjectTypeArray) {
+ api_set_error(err, kErrorTypeValidation,
+ "virt_text_line item is not an Array");
+ goto error;
+ }
+ int dummig;
+ VirtText jtem = parse_virt_text(a.items[j].data.array, err, &dummig);
+ kv_push(virt_lines, jtem);
+ if (ERROR_SET(err)) {
+ goto error;
+ }
+ }
+ } else if (strequal("virt_lines_above", k.data)) {
+ virt_lines_above = api_object_to_bool(*v, "virt_lines_above", false, err);
+ if (ERROR_SET(err)) {
+ goto error;
+ }
+ } else if (strequal("virt_lines_leftcol", k.data)) {
+ virt_lines_leftcol = api_object_to_bool(*v, "virt_lines_leftcol", false, err);
+ if (ERROR_SET(err)) {
+ goto error;
+ }
} else if (strequal("hl_eol", k.data)) {
decor.hl_eol = api_object_to_bool(*v, "hl_eol", false, err);
if (ERROR_SET(err)) {
@@ -1721,9 +1777,23 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
goto error;
}
- id = extmark_set(buf, (uint64_t)ns_id, id, (int)line, (colnr_T)col,
- line2, col2, d, right_gravity,
- end_right_gravity, kExtmarkNoUndo);
+ if (kv_size(virt_lines) && buf->b_virt_line_mark) {
+ mtpos_t pos = marktree_lookup(buf->b_marktree, buf->b_virt_line_mark, NULL);
+ clear_virt_lines(buf, pos.row); // handles pos.row == -1
+ }
+
+ uint64_t mark = extmark_set(buf, (uint64_t)ns_id, &id, (int)line, (colnr_T)col,
+ line2, col2, d, right_gravity,
+ end_right_gravity, kExtmarkNoUndo);
+
+ if (kv_size(virt_lines)) {
+ buf->b_virt_lines = virt_lines;
+ buf->b_virt_line_mark = mark;
+ buf->b_virt_line_pos = -1;
+ buf->b_virt_line_above = virt_lines_above;
+ buf->b_virt_line_leftcol = virt_lines_leftcol;
+ redraw_buf_line_later(buf, MIN(buf->b_ml.ml_line_count, line+1+(virt_lines_above?0:1)));
+ }
}
return (Integer)id;
@@ -1827,7 +1897,7 @@ Integer nvim_buf_add_highlight(Buffer buffer, Integer ns_id, String hl_group, In
end_line++;
}
- extmark_set(buf, ns, 0,
+ extmark_set(buf, ns, NULL,
(int)line, (colnr_T)col_start,
end_line, (colnr_T)col_end,
decor_hl(hl_id), true, false, kExtmarkNoUndo);