aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api/extmark.c
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2025-02-05 23:09:29 +0000
committerJosh Rahm <joshuarahm@gmail.com>2025-02-05 23:09:29 +0000
commitd5f194ce780c95821a855aca3c19426576d28ae0 (patch)
treed45f461b19f9118ad2bb1f440a7a08973ad18832 /src/nvim/api/extmark.c
parentc5d770d311841ea5230426cc4c868e8db27300a8 (diff)
parent44740e561fc93afe3ebecfd3618bda2d2abeafb0 (diff)
downloadrneovim-d5f194ce780c95821a855aca3c19426576d28ae0.tar.gz
rneovim-d5f194ce780c95821a855aca3c19426576d28ae0.tar.bz2
rneovim-d5f194ce780c95821a855aca3c19426576d28ae0.zip
Merge remote-tracking branch 'upstream/master' into mix_20240309HEADrahm
Diffstat (limited to 'src/nvim/api/extmark.c')
-rw-r--r--src/nvim/api/extmark.c157
1 files changed, 62 insertions, 95 deletions
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c
index c94b8df9ea..8b31196eef 100644
--- a/src/nvim/api/extmark.c
+++ b/src/nvim/api/extmark.c
@@ -27,6 +27,7 @@
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
+#include "nvim/memory_defs.h"
#include "nvim/move.h"
#include "nvim/pos_defs.h"
#include "nvim/sign.h"
@@ -48,7 +49,7 @@ void api_extmark_free_all_mem(void)
/// Creates a new namespace or gets an existing one. [namespace]()
///
/// Namespaces are used for buffer highlights and virtual text, see
-/// |nvim_buf_add_highlight()| and |nvim_buf_set_extmark()|.
+/// |nvim_buf_set_extmark()|.
///
/// Namespaces can be named or anonymous. If `name` matches an existing
/// namespace, the associated id is returned. If `name` is an empty string
@@ -61,7 +62,7 @@ Integer nvim_create_namespace(String name)
{
handle_T id = map_get(String, int)(&namespace_ids, name);
if (id > 0) {
- return id;
+ return (Integer)id;
}
id = next_namespace_id++;
if (name.size > 0) {
@@ -384,6 +385,9 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
/// - hl_group : highlight group used for the text range. This and below
/// highlight groups can be supplied either as a string or as an integer,
/// the latter of which can be obtained using |nvim_get_hl_id_by_name()|.
+///
+/// Multiple highlight groups can be stacked by passing an array (highest
+/// priority last).
/// - 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
@@ -396,6 +400,15 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
/// (highest priority last).
/// - virt_text_pos : position of virtual text. Possible values:
/// - "eol": right after eol character (default).
+/// - "eol_right_align": display right aligned in the window
+/// unless the virtual text is longer than
+/// the space available. If the virtual
+/// text is too long, it is truncated to
+/// fit in the window after the EOL
+/// character. If the line is wrapped, the
+/// virtual text is shown after the end of
+/// the line rather than the previous
+/// screen line.
/// - "overlay": display over the specified column, without
/// shifting the underlying text.
/// - "right_align": display right aligned in the window.
@@ -498,6 +511,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
DecorVirtText virt_lines = DECOR_VIRT_LINES_INIT;
char *url = NULL;
bool has_hl = false;
+ bool has_hl_multiple = false;
buf_T *buf = find_buffer_by_handle(buffer, err);
if (!buf) {
@@ -550,8 +564,33 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
col2 = (int)val;
}
- hl.hl_id = (int)opts->hl_group;
- has_hl = hl.hl_id > 0;
+ if (HAS_KEY(opts, set_extmark, hl_group)) {
+ if (opts->hl_group.type == kObjectTypeArray) {
+ Array arr = opts->hl_group.data.array;
+ if (arr.size >= 1) {
+ hl.hl_id = object_to_hl_id(arr.items[0], "hl_group item", err);
+ if (ERROR_SET(err)) {
+ goto error;
+ }
+ }
+ for (size_t i = 1; i < arr.size; i++) {
+ int hl_id = object_to_hl_id(arr.items[i], "hl_group item", err);
+ if (ERROR_SET(err)) {
+ goto error;
+ }
+ if (hl_id) {
+ has_hl_multiple = true;
+ }
+ }
+ } else {
+ hl.hl_id = object_to_hl_id(opts->hl_group, "hl_group", err);
+ if (ERROR_SET(err)) {
+ goto error;
+ }
+ }
+ has_hl = hl.hl_id > 0;
+ }
+
sign.hl_id = (int)opts->sign_hl_group;
sign.cursorline_hl_id = (int)opts->cursorline_hl_group;
sign.number_hl_id = (int)opts->number_hl_group;
@@ -590,6 +629,8 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
virt_text.pos = kVPosOverlay;
} else if (strequal("right_align", str.data)) {
virt_text.pos = kVPosRightAlign;
+ } else if (strequal("eol_right_align", str.data)) {
+ virt_text.pos = kVPosEndOfLineRightAlign;
} else if (strequal("inline", str.data)) {
virt_text.pos = kVPosInline;
} else {
@@ -793,6 +834,21 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
}
}
+ if (has_hl_multiple) {
+ Array arr = opts->hl_group.data.array;
+ for (size_t i = arr.size - 1; i > 0; i--) { // skip hl_group[0], handled as hl.hl_id below
+ int hl_id = object_to_hl_id(arr.items[i], "hl_group item", err);
+ if (hl_id > 0) {
+ DecorSignHighlight sh = DECOR_SIGN_HIGHLIGHT_INIT;
+ sh.hl_id = hl_id;
+ sh.flags = opts->hl_eol ? kSHHlEol : 0;
+ sh.next = decor_indexed;
+ decor_indexed = decor_put_sh(sh);
+ decor_flags |= MT_FLAG_DECOR_HL;
+ }
+ }
+ }
+
DecorInline decor = DECOR_INLINE_INIT;
if (decor_alloc || decor_indexed != DECOR_ID_INVALID || url != NULL
|| schar_high(hl.conceal_char)) {
@@ -856,95 +912,6 @@ Boolean nvim_buf_del_extmark(Buffer buffer, Integer ns_id, Integer id, Error *er
return extmark_del_id(buf, (uint32_t)ns_id, (uint32_t)id);
}
-uint32_t src2ns(Integer *src_id)
-{
- if (*src_id == 0) {
- *src_id = nvim_create_namespace((String)STRING_INIT);
- }
- if (*src_id < 0) {
- return (((uint32_t)1) << 31) - 1;
- }
- return (uint32_t)(*src_id);
-}
-
-/// Adds a highlight to buffer.
-///
-/// Useful for plugins that dynamically generate highlights to a buffer
-/// (like a semantic highlighter or linter). The function adds a single
-/// highlight to a buffer. Unlike |matchaddpos()| highlights follow changes to
-/// line numbering (as lines are inserted/removed above the highlighted line),
-/// like signs and marks do.
-///
-/// Namespaces are used for batch deletion/updating of a set of highlights. To
-/// create a namespace, use |nvim_create_namespace()| which returns a namespace
-/// id. Pass it in to this function as `ns_id` to add highlights to the
-/// namespace. All highlights in the same namespace can then be cleared with
-/// single call to |nvim_buf_clear_namespace()|. If the highlight never will be
-/// deleted by an API call, pass `ns_id = -1`.
-///
-/// As a shorthand, `ns_id = 0` can be used to create a new namespace for the
-/// highlight, the allocated id is then returned. If `hl_group` is the empty
-/// string no highlight is added, but a new `ns_id` is still returned. This is
-/// supported for backwards compatibility, new code should use
-/// |nvim_create_namespace()| to create a new empty namespace.
-///
-/// @param buffer Buffer handle, or 0 for current buffer
-/// @param ns_id namespace to use or -1 for ungrouped highlight
-/// @param hl_group Name of the highlight group to use
-/// @param line Line to highlight (zero-indexed)
-/// @param col_start Start of (byte-indexed) column range to highlight
-/// @param col_end End of (byte-indexed) column range to highlight,
-/// or -1 to highlight to end of line
-/// @param[out] err Error details, if any
-/// @return The ns_id that was used
-Integer nvim_buf_add_highlight(Buffer buffer, Integer ns_id, String hl_group, Integer line,
- Integer col_start, Integer col_end, Error *err)
- FUNC_API_SINCE(1)
-{
- buf_T *buf = find_buffer_by_handle(buffer, err);
- if (!buf) {
- return 0;
- }
-
- VALIDATE_RANGE((line >= 0 && line < MAXLNUM), "line number", {
- return 0;
- });
- VALIDATE_RANGE((col_start >= 0 && col_start <= MAXCOL), "column", {
- return 0;
- });
-
- if (col_end < 0 || col_end > MAXCOL) {
- col_end = MAXCOL;
- }
-
- uint32_t ns = src2ns(&ns_id);
-
- if (!(line < buf->b_ml.ml_line_count)) {
- // safety check, we can't add marks outside the range
- return ns_id;
- }
-
- int hl_id = 0;
- if (hl_group.size > 0) {
- hl_id = syn_check_group(hl_group.data, hl_group.size);
- } else {
- return ns_id;
- }
-
- int end_line = (int)line;
- if (col_end == MAXCOL) {
- col_end = 0;
- end_line++;
- }
-
- DecorInline decor = DECOR_INLINE_INIT;
- decor.data.hl.hl_id = hl_id;
-
- extmark_set(buf, ns, NULL, (int)line, (colnr_T)col_start, end_line, (colnr_T)col_end,
- decor, MT_FLAG_DECOR_HL, true, false, false, false, NULL);
- return ns_id;
-}
-
/// Clears |namespace|d objects (highlights, |extmarks|, virtual text) from
/// a region.
///
@@ -1012,8 +979,8 @@ void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start,
/// ```
/// ["start", tick]
/// ```
-/// - on_buf: called for each buffer being redrawn (before
-/// window callbacks)
+/// - on_buf: called for each buffer being redrawn (once per edit,
+/// before window callbacks)
/// ```
/// ["buf", bufnr, tick]
/// ```