feat(api): deprecate nvim_buf_add_highlight()

This was kept for a while as it was a useful short hand and initially
matched what highlights what actually properly implemented. But now
|vim.hl.range()| is a better high-level shorthand with full support for
native multi-line ranges.
This commit is contained in:
bfredl 2025-01-19 13:30:11 +01:00
parent 71507281fb
commit 19b25f3fea
7 changed files with 110 additions and 202 deletions

View File

@ -406,18 +406,9 @@ Another use case are plugins that show output in an append-only buffer, and
want to add highlights to the outputs. Highlight data cannot be preserved want to add highlights to the outputs. Highlight data cannot be preserved
on writing and loading a buffer to file, nor in undo/redo cycles. on writing and loading a buffer to file, nor in undo/redo cycles.
Highlights are registered using the |nvim_buf_add_highlight()| function. If an Highlights are registered using the |nvim_buf_set_extmark()| function, which
external highlighter plugin wants to add many highlights in a batch, adds highlights as |extmarks|. If highlights need to be tracked or manipulated
performance can be improved by calling |nvim_buf_add_highlight()| as an after adding them, the returned |extmark| id can be used. >lua
asynchronous notification, after first (synchronously) requesting a source id.
|nvim_buf_add_highlight()| adds highlights as |extmarks|. If highlights need to
be tracked or manipulated after adding them, it is better to use
|nvim_buf_set_extmark()| directly, as this function returns the placed |extmark|
id. Thus, instead of >lua
vim.api.nvim_buf_add_highlight(buf, ns_id, hl_group, line, col_start, col_end)
<
use >lua
-- create the highlight through an extmark -- create the highlight through an extmark
extid = vim.api.nvim_buf_set_extmark(buf, ns_id, line, col_start, {end_col = col_end, hl_group = hl_group}) extid = vim.api.nvim_buf_set_extmark(buf, ns_id, line, col_start, {end_col = col_end, hl_group = hl_group})
@ -428,29 +419,7 @@ use >lua
vim.api.nvim_buf_set_extmark(buf, ns_id, NEW_LINE, col_start, {end_col = col_end, hl_group = NEW_HL_GROUP, id = extid}) vim.api.nvim_buf_set_extmark(buf, ns_id, NEW_LINE, col_start, {end_col = col_end, hl_group = NEW_HL_GROUP, id = extid})
< <
Example using the Python API client (|pynvim|): See also |vim.hl.range()|.
>python
src = vim.new_highlight_source()
buf = vim.current.buffer
for i in range(5):
buf.add_highlight("String",i,0,-1,src_id=src)
# some time later ...
buf.clear_namespace(src)
<
If the highlights don't need to be deleted or updated, just pass -1 as
src_id (this is the default in python). Use |nvim_buf_clear_namespace()| to
clear highlights from a specific source, in a specific line range or the
entire buffer by passing in the line range 0, -1 (the latter is the default in
python as used above).
Example using the API from Vimscript: >vim
call nvim_buf_set_lines(0, 0, 0, v:true, ["test text"])
let src = nvim_buf_add_highlight(0, 0, "String", 1, 0, 4)
call nvim_buf_add_highlight(0, src, "Identifier", 0, 5, -1)
" some time later ...
call nvim_buf_clear_namespace(0, src, 0, -1)
============================================================================== ==============================================================================
Floating windows *api-floatwin* Floating windows *api-floatwin*
@ -2491,42 +2460,6 @@ nvim_buf_set_var({buffer}, {name}, {value}) *nvim_buf_set_var()*
============================================================================== ==============================================================================
Extmark Functions *api-extmark* Extmark Functions *api-extmark*
*nvim_buf_add_highlight()*
nvim_buf_add_highlight({buffer}, {ns_id}, {hl_group}, {line}, {col_start},
{col_end})
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.
Parameters: ~
• {buffer} Buffer handle, or 0 for current buffer
• {ns_id} namespace to use or -1 for ungrouped highlight
• {hl_group} Name of the highlight group to use
• {line} Line to highlight (zero-indexed)
• {col_start} Start of (byte-indexed) column range to highlight
• {col_end} End of (byte-indexed) column range to highlight, or -1 to
highlight to end of line
Return: ~
The ns_id that was used
*nvim_buf_clear_namespace()* *nvim_buf_clear_namespace()*
nvim_buf_clear_namespace({buffer}, {ns_id}, {line_start}, {line_end}) nvim_buf_clear_namespace({buffer}, {ns_id}, {line_start}, {line_end})
Clears |namespace|d objects (highlights, |extmarks|, virtual text) from a Clears |namespace|d objects (highlights, |extmarks|, virtual text) from a
@ -2764,7 +2697,7 @@ nvim_create_namespace({name}) *nvim_create_namespace()*
Creates a new namespace or gets an existing one. *namespace* Creates a new namespace or gets an existing one. *namespace*
Namespaces are used for buffer highlights and virtual text, see 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 Namespaces can be named or anonymous. If `name` matches an existing
namespace, the associated id is returned. If `name` is an empty string a namespace, the associated id is returned. If `name` is an empty string a

View File

@ -22,6 +22,7 @@ API
• nvim_out_write() Use |nvim_echo()|. • nvim_out_write() Use |nvim_echo()|.
• nvim_err_write() Use |nvim_echo()| with `{err=true}`. • nvim_err_write() Use |nvim_echo()| with `{err=true}`.
• nvim_err_writeln() Use |nvim_echo()| with `{err=true}`. • nvim_err_writeln() Use |nvim_echo()| with `{err=true}`.
• nvim_buf_add_highlight() Use |vim.hl.range()| or |nvim_buf_set_extmark()|
DIAGNOSTICS DIAGNOSTICS
• *vim.diagnostic.goto_next()* Use |vim.diagnostic.jump()| with `{count=1, float=true}` instead. • *vim.diagnostic.goto_next()* Use |vim.diagnostic.jump()| with `{count=1, float=true}` instead.

View File

@ -1545,7 +1545,7 @@ Your command preview routine must implement this protocol:
3. Add required highlights to the target buffers. If preview buffer is 3. Add required highlights to the target buffers. If preview buffer is
provided, add required highlights to the preview buffer as well. All provided, add required highlights to the preview buffer as well. All
highlights must be added to the preview namespace which is provided as an highlights must be added to the preview namespace which is provided as an
argument to the preview callback (see |nvim_buf_add_highlight()| and argument to the preview callback (see |vim.hl.range()| and
|nvim_buf_set_extmark()| for help on how to add highlights to a namespace). |nvim_buf_set_extmark()| for help on how to add highlights to a namespace).
4. Return an integer (0, 1, 2) which controls how Nvim behaves as follows: 4. Return an integer (0, 1, 2) which controls how Nvim behaves as follows:
0: No preview is shown. 0: No preview is shown.
@ -1574,13 +1574,12 @@ supports incremental command preview:
if start_idx then if start_idx then
-- Highlight the match -- Highlight the match
vim.api.nvim_buf_add_highlight( vim.hl.range(
buf, buf,
preview_ns, preview_ns,
'Substitute', 'Substitute',
line1 + i - 2, {line1 + i - 2, start_idx - 1},
start_idx - 1, {line1 + i - 2, end_idx},
end_idx
) )
-- Add lines and set highlights in the preview buffer -- Add lines and set highlights in the preview buffer
@ -1595,13 +1594,12 @@ supports incremental command preview:
false, false,
{ prefix .. line } { prefix .. line }
) )
vim.api.nvim_buf_add_highlight( vim.hl.range(
preview_buf, preview_buf,
preview_ns, preview_ns,
'Substitute', 'Substitute',
preview_buf_line, {preview_buf_line, #prefix + start_idx - 1},
#prefix + start_idx - 1, {preview_buf_line, #prefix + end_idx},
#prefix + end_idx
) )
preview_buf_line = preview_buf_line + 1 preview_buf_line = preview_buf_line + 1
end end

View File

@ -562,7 +562,7 @@ with the following possible keys:
"ui": Builtin UI highlight. |highlight-groups| "ui": Builtin UI highlight. |highlight-groups|
"syntax": Highlight applied to a buffer by a syntax declaration or "syntax": Highlight applied to a buffer by a syntax declaration or
other runtime/plugin functionality such as other runtime/plugin functionality such as
|nvim_buf_add_highlight()| |nvim_buf_set_extmark()|
"terminal": highlight from a process running in a |terminal-emulator|. "terminal": highlight from a process running in a |terminal-emulator|.
Contains no further semantic information. Contains no further semantic information.
`ui_name`: Highlight name from |highlight-groups|. Only for "ui" kind. `ui_name`: Highlight name from |highlight-groups|. Only for "ui" kind.

View File

@ -163,35 +163,14 @@ function vim.api.nvim__stats() end
--- @return any --- @return any
function vim.api.nvim__unpack(str) end function vim.api.nvim__unpack(str) end
--- Adds a highlight to buffer. --- @deprecated
--- --- @param buffer integer
--- Useful for plugins that dynamically generate highlights to a buffer --- @param ns_id integer
--- (like a semantic highlighter or linter). The function adds a single --- @param hl_group string
--- highlight to a buffer. Unlike `matchaddpos()` highlights follow changes to --- @param line integer
--- line numbering (as lines are inserted/removed above the highlighted line), --- @param col_start integer
--- like signs and marks do. --- @param col_end integer
--- --- @return integer
--- 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 integer Buffer handle, or 0 for current buffer
--- @param ns_id integer namespace to use or -1 for ungrouped highlight
--- @param hl_group string Name of the highlight group to use
--- @param line integer Line to highlight (zero-indexed)
--- @param col_start integer Start of (byte-indexed) column range to highlight
--- @param col_end integer End of (byte-indexed) column range to highlight,
--- or -1 to highlight to end of line
--- @return integer # The ns_id that was used
function vim.api.nvim_buf_add_highlight(buffer, ns_id, hl_group, line, col_start, col_end) end function vim.api.nvim_buf_add_highlight(buffer, ns_id, hl_group, line, col_start, col_end) end
--- Activates buffer-update events on a channel, or as Lua callbacks. --- Activates buffer-update events on a channel, or as Lua callbacks.
@ -987,7 +966,7 @@ function vim.api.nvim_create_buf(listed, scratch) end
--- Creates a new namespace or gets an existing one. [namespace]() --- Creates a new namespace or gets an existing one. [namespace]()
--- ---
--- Namespaces are used for buffer highlights and virtual text, see --- 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 --- Namespaces can be named or anonymous. If `name` matches an existing
--- namespace, the associated id is returned. If `name` is an empty string --- namespace, the associated id is returned. If `name` is an empty string

View File

@ -21,6 +21,7 @@
#include "nvim/highlight.h" #include "nvim/highlight.h"
#include "nvim/highlight_group.h" #include "nvim/highlight_group.h"
#include "nvim/lua/executor.h" #include "nvim/lua/executor.h"
#include "nvim/marktree.h"
#include "nvim/memory.h" #include "nvim/memory.h"
#include "nvim/memory_defs.h" #include "nvim/memory_defs.h"
#include "nvim/message.h" #include "nvim/message.h"
@ -84,6 +85,17 @@ Integer nvim_buf_get_number(Buffer buffer, Error *err)
return buf->b_fnum; return buf->b_fnum;
} }
static 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);
}
/// Clears highlights and virtual text from namespace and range of lines /// Clears highlights and virtual text from namespace and range of lines
/// ///
/// @deprecated use |nvim_buf_clear_namespace()|. /// @deprecated use |nvim_buf_clear_namespace()|.
@ -102,6 +114,80 @@ void nvim_buf_clear_highlight(Buffer buffer, Integer ns_id, Integer line_start,
nvim_buf_clear_namespace(buffer, ns_id, line_start, line_end, err); nvim_buf_clear_namespace(buffer, ns_id, line_start, line_end, err);
} }
/// Adds a highlight to buffer.
///
/// @deprecated use |nvim_buf_set_extmark()| or |vim.hl.range()|
///
/// 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)
FUNC_API_DEPRECATED_SINCE(13)
{
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;
}
/// Set the virtual text (annotation) for a buffer line. /// Set the virtual text (annotation) for a buffer line.
/// ///
/// @deprecated use nvim_buf_set_extmark to use full virtual text functionality. /// @deprecated use nvim_buf_set_extmark to use full virtual text functionality.

View File

@ -49,7 +49,7 @@ void api_extmark_free_all_mem(void)
/// Creates a new namespace or gets an existing one. [namespace]() /// Creates a new namespace or gets an existing one. [namespace]()
/// ///
/// Namespaces are used for buffer highlights and virtual text, see /// 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 /// Namespaces can be named or anonymous. If `name` matches an existing
/// namespace, the associated id is returned. If `name` is an empty string /// namespace, the associated id is returned. If `name` is an empty string
@ -857,95 +857,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); 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 /// Clears |namespace|d objects (highlights, |extmarks|, virtual text) from
/// a region. /// a region.
/// ///