aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api/buffer.c
diff options
context:
space:
mode:
authorBjörn Linse <bjorn.linse@gmail.com>2021-10-25 22:29:02 +0200
committerBjörn Linse <bjorn.linse@gmail.com>2021-10-25 22:33:40 +0200
commitc8882ca7e75e2f085ec2e0943d5afa09efc9c8ca (patch)
tree19317872a166dc5bf3a0f50490281d8b4a2fc1b4 /src/nvim/api/buffer.c
parent09e96fe6096f07365eb65b51bb7f2fd0f1b043b0 (diff)
downloadrneovim-c8882ca7e75e2f085ec2e0943d5afa09efc9c8ca.tar.gz
rneovim-c8882ca7e75e2f085ec2e0943d5afa09efc9c8ca.tar.bz2
rneovim-c8882ca7e75e2f085ec2e0943d5afa09efc9c8ca.zip
refactor(api): move extmark API to its own file
Diffstat (limited to 'src/nvim/api/buffer.c')
-rw-r--r--src/nvim/api/buffer.c697
1 files changed, 0 insertions, 697 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 92fcb59b34..cbfb63581f 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -32,7 +32,6 @@
#include "nvim/misc1.h"
#include "nvim/move.h"
#include "nvim/ops.h"
-#include "nvim/syntax.h"
#include "nvim/undo.h"
#include "nvim/vim.h"
#include "nvim/window.h"
@@ -1238,702 +1237,6 @@ ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err)
return rv;
}
-static Array extmark_to_array(ExtmarkInfo extmark, bool id, bool add_dict)
-{
- Array rv = ARRAY_DICT_INIT;
- if (id) {
- ADD(rv, INTEGER_OBJ((Integer)extmark.mark_id));
- }
- ADD(rv, INTEGER_OBJ(extmark.row));
- ADD(rv, INTEGER_OBJ(extmark.col));
-
- if (add_dict) {
- Dictionary dict = ARRAY_DICT_INIT;
-
- if (extmark.end_row >= 0) {
- PUT(dict, "end_row", INTEGER_OBJ(extmark.end_row));
- PUT(dict, "end_col", INTEGER_OBJ(extmark.end_col));
- }
-
- if (extmark.decor) {
- Decoration *decor = extmark.decor;
- if (decor->hl_id) {
- String name = cstr_to_string((const char *)syn_id2name(decor->hl_id));
- PUT(dict, "hl_group", STRING_OBJ(name));
- }
- if (kv_size(decor->virt_text)) {
- Array chunks = ARRAY_DICT_INIT;
- for (size_t i = 0; i < decor->virt_text.size; i++) {
- Array chunk = ARRAY_DICT_INIT;
- VirtTextChunk *vtc = &decor->virt_text.items[i];
- ADD(chunk, STRING_OBJ(cstr_to_string(vtc->text)));
- if (vtc->hl_id > 0) {
- ADD(chunk,
- STRING_OBJ(cstr_to_string((const char *)syn_id2name(vtc->hl_id))));
- }
- ADD(chunks, ARRAY_OBJ(chunk));
- }
- PUT(dict, "virt_text", ARRAY_OBJ(chunks));
- }
-
- PUT(dict, "priority", INTEGER_OBJ(decor->priority));
- }
-
- if (dict.size) {
- ADD(rv, DICTIONARY_OBJ(dict));
- }
- }
-
- return rv;
-}
-
-/// Gets the position (0-indexed) of an extmark.
-///
-/// @param buffer Buffer handle, or 0 for current buffer
-/// @param ns_id Namespace id from |nvim_create_namespace()|
-/// @param id Extmark id
-/// @param opts Optional parameters. Keys:
-/// - details: Whether to include the details dict
-/// @param[out] err Error details, if any
-/// @return 0-indexed (row, col) tuple or empty list () if extmark id was
-/// absent
-ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id,
- Integer id, Dictionary opts,
- Error *err)
- FUNC_API_SINCE(7)
-{
- Array rv = ARRAY_DICT_INIT;
-
- buf_T *buf = find_buffer_by_handle(buffer, err);
-
- if (!buf) {
- return rv;
- }
-
- if (!ns_initialized((uint64_t)ns_id)) {
- api_set_error(err, kErrorTypeValidation, "Invalid ns_id");
- return rv;
- }
-
- bool details = false;
- for (size_t i = 0; i < opts.size; i++) {
- String k = opts.items[i].key;
- Object *v = &opts.items[i].value;
- if (strequal("details", k.data)) {
- if (v->type == kObjectTypeBoolean) {
- details = v->data.boolean;
- } else if (v->type == kObjectTypeInteger) {
- details = v->data.integer;
- } else {
- api_set_error(err, kErrorTypeValidation, "details is not an boolean");
- return rv;
- }
- } else {
- api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data);
- return rv;
- }
- }
-
-
- ExtmarkInfo extmark = extmark_from_id(buf, (uint64_t)ns_id, (uint64_t)id);
- if (extmark.row < 0) {
- return rv;
- }
- return extmark_to_array(extmark, false, details);
-}
-
-/// Gets extmarks in "traversal order" from a |charwise| region defined by
-/// buffer positions (inclusive, 0-indexed |api-indexing|).
-///
-/// Region can be given as (row,col) tuples, or valid extmark ids (whose
-/// positions define the bounds). 0 and -1 are understood as (0,0) and (-1,-1)
-/// respectively, thus the following are equivalent:
-///
-/// <pre>
-/// nvim_buf_get_extmarks(0, my_ns, 0, -1, {})
-/// nvim_buf_get_extmarks(0, my_ns, [0,0], [-1,-1], {})
-/// </pre>
-///
-/// If `end` is less than `start`, traversal works backwards. (Useful
-/// with `limit`, to get the first marks prior to a given position.)
-///
-/// Example:
-///
-/// <pre>
-/// local a = vim.api
-/// local pos = a.nvim_win_get_cursor(0)
-/// local ns = a.nvim_create_namespace('my-plugin')
-/// -- Create new extmark at line 1, column 1.
-/// local m1 = a.nvim_buf_set_extmark(0, ns, 0, 0, 0, {})
-/// -- Create new extmark at line 3, column 1.
-/// local m2 = a.nvim_buf_set_extmark(0, ns, 0, 2, 0, {})
-/// -- Get extmarks only from line 3.
-/// local ms = a.nvim_buf_get_extmarks(0, ns, {2,0}, {2,0}, {})
-/// -- Get all marks in this buffer + namespace.
-/// local all = a.nvim_buf_get_extmarks(0, ns, 0, -1, {})
-/// print(vim.inspect(ms))
-/// </pre>
-///
-/// @param buffer Buffer handle, or 0 for current buffer
-/// @param ns_id Namespace id from |nvim_create_namespace()|
-/// @param start Start of range: a 0-indexed (row, col) or valid extmark id
-/// (whose position defines the bound). |api-indexing|
-/// @param end End of range (inclusive): a 0-indexed (row, col) or valid
-/// extmark id (whose position defines the bound). |api-indexing|
-/// @param opts Optional parameters. Keys:
-/// - limit: Maximum number of marks to return
-/// - details Whether to include the details dict
-/// @param[out] err Error details, if any
-/// @return List of [extmark_id, row, col] tuples in "traversal order".
-Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object end, Dictionary opts,
- Error *err)
- FUNC_API_SINCE(7)
-{
- Array rv = ARRAY_DICT_INIT;
-
- buf_T *buf = find_buffer_by_handle(buffer, err);
- if (!buf) {
- return rv;
- }
-
- if (!ns_initialized((uint64_t)ns_id)) {
- api_set_error(err, kErrorTypeValidation, "Invalid ns_id");
- return rv;
- }
-
- Integer limit = -1;
- bool details = false;
-
- for (size_t i = 0; i < opts.size; i++) {
- String k = opts.items[i].key;
- Object *v = &opts.items[i].value;
- if (strequal("limit", k.data)) {
- if (v->type != kObjectTypeInteger) {
- api_set_error(err, kErrorTypeValidation, "limit is not an integer");
- return rv;
- }
- limit = v->data.integer;
- } else if (strequal("details", k.data)) {
- if (v->type == kObjectTypeBoolean) {
- details = v->data.boolean;
- } else if (v->type == kObjectTypeInteger) {
- details = v->data.integer;
- } else {
- api_set_error(err, kErrorTypeValidation, "details is not an boolean");
- return rv;
- }
- } else {
- api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data);
- return rv;
- }
- }
-
- if (limit == 0) {
- return rv;
- } else if (limit < 0) {
- limit = INT64_MAX;
- }
-
-
- bool reverse = false;
-
- int l_row;
- colnr_T l_col;
- if (!extmark_get_index_from_obj(buf, ns_id, start, &l_row, &l_col, err)) {
- return rv;
- }
-
- int u_row;
- colnr_T u_col;
- if (!extmark_get_index_from_obj(buf, ns_id, end, &u_row, &u_col, err)) {
- return rv;
- }
-
- if (l_row > u_row || (l_row == u_row && l_col > u_col)) {
- reverse = true;
- }
-
-
- ExtmarkInfoArray marks = extmark_get(buf, (uint64_t)ns_id, l_row, l_col,
- u_row, u_col, (int64_t)limit, reverse);
-
- for (size_t i = 0; i < kv_size(marks); i++) {
- ADD(rv, ARRAY_OBJ(extmark_to_array(kv_A(marks, i), true, (bool)details)));
- }
-
- kv_destroy(marks);
- return rv;
-}
-
-/// Creates or updates an extmark.
-///
-/// To create a new extmark, pass id=0. The extmark id will be returned.
-/// To move an existing mark, pass its id.
-///
-/// It is also allowed to create a new mark by passing in a previously unused
-/// id, but the caller must then keep track of existing and unused ids itself.
-/// (Useful over RPC, to avoid waiting for the return value.)
-///
-/// Using the optional arguments, it is possible to use this to highlight
-/// a range of text, and also to associate virtual text to the mark.
-///
-/// @param buffer Buffer handle, or 0 for current buffer
-/// @param ns_id Namespace id from |nvim_create_namespace()|
-/// @param line Line where to place the mark, 0-based. |api-indexing|
-/// @param col Column where to place the mark, 0-based. |api-indexing|
-/// @param opts Optional parameters.
-/// - id : id of the extmark to edit.
-/// - end_line : ending line of the mark, 0-based inclusive.
-/// - 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
-/// can either be a a single highlight group, or an array of
-/// multiple highlight groups that will be stacked
-/// (highest priority last). A highlight group can be supplied
-/// either as a string or as an integer, the latter which
-/// can be obtained using |nvim_get_hl_id_by_name|.
-/// - virt_text_pos : position of virtual text. Possible values:
-/// - "eol": right after eol character (default)
-/// - "overlay": display over the specified column, without
-/// shifting the underlying text.
-/// - "right_align": display right aligned in the window.
-/// - virt_text_win_col : position the virtual text at a fixed
-/// window column (starting from the first
-/// text column)
-/// - virt_text_hide : hide the virtual text when the background
-/// text is selected or hidden due to
-/// horizontal scroll 'nowrap'
-/// - hl_mode : control how highlights are combined with the
-/// highlights of the text. Currently only affects
-/// virt_text highlights, but might affect `hl_group`
-/// in later versions.
-/// - "replace": only show the virt_text color. This is the
-/// default
-/// - "combine": combine with background text color
-/// - "blend": blend with background text color.
-///
-/// - 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.
-///
-/// - 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
-/// 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.
-/// - priority: a priority value for the highlight group. For
-/// example treesitter highlighting uses a value of 100.
-/// @param[out] err Error details, if any
-/// @return Id of the created/updated extmark
-Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer col,
- Dict(set_extmark) *opts, Error *err)
- FUNC_API_SINCE(7)
-{
- Decoration decor = DECORATION_INIT;
-
- buf_T *buf = find_buffer_by_handle(buffer, err);
- if (!buf) {
- goto error;
- }
-
- if (!ns_initialized((uint64_t)ns_id)) {
- api_set_error(err, kErrorTypeValidation, "Invalid ns_id");
- goto error;
- }
-
- uint64_t id = 0;
- if (opts->id.type == kObjectTypeInteger && opts->id.data.integer > 0) {
- id = (uint64_t)opts->id.data.integer;
- } else if (HAS_KEY(opts->id)) {
- api_set_error(err, kErrorTypeValidation, "id is not a positive integer");
- goto error;
- }
-
- int line2 = -1;
- if (opts->end_line.type == kObjectTypeInteger) {
- Integer val = opts->end_line.data.integer;
- if (val < 0 || val > buf->b_ml.ml_line_count) {
- api_set_error(err, kErrorTypeValidation, "end_line value outside range");
- goto error;
- } else {
- line2 = (int)val;
- }
- } else if (HAS_KEY(opts->end_line)) {
- api_set_error(err, kErrorTypeValidation, "end_line is not an integer");
- goto error;
- }
-
- colnr_T col2 = -1;
- if (opts->end_col.type == kObjectTypeInteger) {
- Integer val = opts->end_col.data.integer;
- if (val < 0 || val > MAXCOL) {
- api_set_error(err, kErrorTypeValidation, "end_col value outside range");
- goto error;
- } else {
- col2 = (int)val;
- }
- } else if (HAS_KEY(opts->end_col)) {
- api_set_error(err, kErrorTypeValidation, "end_col is not an integer");
- goto error;
- }
-
- if (HAS_KEY(opts->hl_group)) {
- decor.hl_id = object_to_hl_id(opts->hl_group, "hl_group", err);
- if (ERROR_SET(err)) {
- goto error;
- }
- }
-
- if (opts->virt_text.type == kObjectTypeArray) {
- decor.virt_text = parse_virt_text(opts->virt_text.data.array, err,
- &decor.virt_text_width);
- if (ERROR_SET(err)) {
- goto error;
- }
- } else if (HAS_KEY(opts->virt_text)) {
- api_set_error(err, kErrorTypeValidation, "virt_text is not an Array");
- goto error;
- }
-
- if (opts->virt_text_pos.type == kObjectTypeString) {
- String str = opts->virt_text_pos.data.string;
- if (strequal("eol", str.data)) {
- decor.virt_text_pos = kVTEndOfLine;
- } else if (strequal("overlay", str.data)) {
- decor.virt_text_pos = kVTOverlay;
- } else if (strequal("right_align", str.data)) {
- decor.virt_text_pos = kVTRightAlign;
- } else {
- api_set_error(err, kErrorTypeValidation, "virt_text_pos: invalid value");
- goto error;
- }
- } else if (HAS_KEY(opts->virt_text_pos)) {
- api_set_error(err, kErrorTypeValidation, "virt_text_pos is not a String");
- goto error;
- }
-
- if (opts->virt_text_win_col.type == kObjectTypeInteger) {
- decor.col = (int)opts->virt_text_win_col.data.integer;
- decor.virt_text_pos = kVTWinCol;
- } else if (HAS_KEY(opts->virt_text_win_col)) {
- api_set_error(err, kErrorTypeValidation,
- "virt_text_win_col is not a Number of the correct size");
- goto error;
- }
-
-#define OPTION_TO_BOOL(target, name, val) \
- target = api_object_to_bool(opts-> name, #name, val, err); \
- if (ERROR_SET(err)) { \
- goto error; \
- }
-
- OPTION_TO_BOOL(decor.virt_text_hide, virt_text_hide, false);
- OPTION_TO_BOOL(decor.hl_eol, hl_eol, false);
-
- if (opts->hl_mode.type == kObjectTypeString) {
- String str = opts->hl_mode.data.string;
- if (strequal("replace", str.data)) {
- decor.hl_mode = kHlModeReplace;
- } else if (strequal("combine", str.data)) {
- decor.hl_mode = kHlModeCombine;
- } else if (strequal("blend", str.data)) {
- decor.hl_mode = kHlModeBlend;
- } else {
- api_set_error(err, kErrorTypeValidation,
- "virt_text_pos: invalid value");
- goto error;
- }
- } else if (HAS_KEY(opts->hl_mode)) {
- api_set_error(err, kErrorTypeValidation, "hl_mode is not a String");
- goto error;
- }
-
- bool virt_lines_leftcol = false;
- OPTION_TO_BOOL(virt_lines_leftcol, virt_lines_leftcol, false);
-
- if (opts->virt_lines.type == kObjectTypeArray) {
- Array a = opts->virt_lines.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(decor.virt_lines, ((struct virt_line){ jtem, virt_lines_leftcol }));
- if (ERROR_SET(err)) {
- goto error;
- }
- }
- } else if (HAS_KEY(opts->virt_lines)) {
- api_set_error(err, kErrorTypeValidation, "virt_lines is not an Array");
- goto error;
- }
-
-
- OPTION_TO_BOOL(decor.virt_lines_above, virt_lines_above, false);
-
- if (opts->priority.type == kObjectTypeInteger) {
- Integer val = opts->priority.data.integer;
-
- if (val < 0 || val > UINT16_MAX) {
- api_set_error(err, kErrorTypeValidation, "priority is not a valid value");
- goto error;
- }
- decor.priority = (DecorPriority)val;
- } else if (HAS_KEY(opts->priority)) {
- api_set_error(err, kErrorTypeValidation, "priority is not a Number of the correct size");
- goto error;
- }
-
- bool right_gravity = true;
- OPTION_TO_BOOL(right_gravity, right_gravity, true);
-
- // Only error out if they try to set end_right_gravity without
- // setting end_col or end_line
- if (line2 == -1 && col2 == -1 && HAS_KEY(opts->end_right_gravity)) {
- api_set_error(err, kErrorTypeValidation,
- "cannot set end_right_gravity without setting end_line or end_col");
- goto error;
- }
-
- bool end_right_gravity = false;
- OPTION_TO_BOOL(end_right_gravity, end_right_gravity, false);
-
- size_t len = 0;
-
- bool ephemeral = false;
- OPTION_TO_BOOL(ephemeral, ephemeral, false);
-
- if (line < 0 || line > buf->b_ml.ml_line_count) {
- api_set_error(err, kErrorTypeValidation, "line value outside range");
- goto error;
- } else if (line < buf->b_ml.ml_line_count) {
- len = ephemeral ? MAXCOL : STRLEN(ml_get_buf(buf, (linenr_T)line+1, false));
- }
-
- if (col == -1) {
- col = (Integer)len;
- } else if (col < -1 || col > (Integer)len) {
- api_set_error(err, kErrorTypeValidation, "col value outside range");
- goto error;
- }
-
- if (col2 >= 0) {
- if (line2 >= 0 && line2 < buf->b_ml.ml_line_count) {
- len = ephemeral ? MAXCOL : STRLEN(ml_get_buf(buf, (linenr_T)line2 + 1, false));
- } else if (line2 == buf->b_ml.ml_line_count) {
- // We are trying to add an extmark past final newline
- len = 0;
- } else {
- // reuse len from before
- line2 = (int)line;
- }
- if (col2 > (Integer)len) {
- api_set_error(err, kErrorTypeValidation, "end_col value outside range");
- goto error;
- }
- } else if (line2 >= 0) {
- col2 = 0;
- }
-
- Decoration *d = NULL;
-
- if (ephemeral) {
- d = &decor;
- } else if (kv_size(decor.virt_text) || kv_size(decor.virt_lines)
- || decor.priority != DECOR_PRIORITY_BASE
- || decor.hl_eol) {
- // TODO(bfredl): this is a bit sketchy. eventually we should
- // have predefined decorations for both marks/ephemerals
- d = xcalloc(1, sizeof(*d));
- *d = decor;
- } else if (decor.hl_id) {
- d = decor_hl(decor.hl_id);
- }
-
- // TODO(bfredl): synergize these two branches even more
- if (ephemeral && decor_state.buf == buf) {
- decor_add_ephemeral((int)line, (int)col, line2, col2, &decor);
- } else {
- if (ephemeral) {
- api_set_error(err, kErrorTypeException, "not yet implemented");
- goto error;
- }
-
- 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(decor.virt_lines)) {
- redraw_buf_line_later(buf, MIN(buf->b_ml.ml_line_count, line+1+(decor.virt_lines_above?0:1)));
- }
- }
-
- return (Integer)id;
-
-error:
- clear_virttext(&decor.virt_text);
- return 0;
-}
-
-/// Removes an extmark.
-///
-/// @param buffer Buffer handle, or 0 for current buffer
-/// @param ns_id Namespace id from |nvim_create_namespace()|
-/// @param id Extmark id
-/// @param[out] err Error details, if any
-/// @return true if the extmark was found, else false
-Boolean nvim_buf_del_extmark(Buffer buffer, Integer ns_id, Integer id, Error *err)
- FUNC_API_SINCE(7)
-{
- buf_T *buf = find_buffer_by_handle(buffer, err);
-
- if (!buf) {
- return false;
- }
- if (!ns_initialized((uint64_t)ns_id)) {
- api_set_error(err, kErrorTypeValidation, "Invalid ns_id");
- return false;
- }
-
- return extmark_del(buf, (uint64_t)ns_id, (uint64_t)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;
- }
-
- if (line < 0 || line >= MAXLNUM) {
- api_set_error(err, kErrorTypeValidation, "Line number outside range");
- return 0;
- }
- if (col_start < 0 || col_start > MAXCOL) {
- api_set_error(err, kErrorTypeValidation, "Column value outside range");
- return 0;
- }
- if (col_end < 0 || col_end > MAXCOL) {
- col_end = MAXCOL;
- }
-
- uint64_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, (int)hl_group.size);
- } else {
- return ns_id;
- }
-
- int end_line = (int)line;
- if (col_end == MAXCOL) {
- col_end = 0;
- end_line++;
- }
-
- extmark_set(buf, ns, NULL,
- (int)line, (colnr_T)col_start,
- end_line, (colnr_T)col_end,
- decor_hl(hl_id), true, false, kExtmarkNoUndo);
- return ns_id;
-}
-
-/// Clears namespaced objects (highlights, extmarks, virtual text) from
-/// a region.
-///
-/// Lines are 0-indexed. |api-indexing| To clear the namespace in the entire
-/// buffer, specify line_start=0 and line_end=-1.
-///
-/// @param buffer Buffer handle, or 0 for current buffer
-/// @param ns_id Namespace to clear, or -1 to clear all namespaces.
-/// @param line_start Start of range of lines to clear
-/// @param line_end End of range of lines to clear (exclusive) or -1 to clear
-/// to end of buffer.
-/// @param[out] err Error details, if any
-void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start, Integer line_end,
- Error *err)
- FUNC_API_SINCE(5)
-{
- buf_T *buf = find_buffer_by_handle(buffer, err);
- if (!buf) {
- return;
- }
-
- if (line_start < 0 || line_start >= MAXLNUM) {
- api_set_error(err, kErrorTypeValidation, "Line number outside range");
- return;
- }
- if (line_end < 0 || line_end > MAXLNUM) {
- line_end = MAXLNUM;
- }
- extmark_clear(buf, (ns_id < 0 ? 0 : (uint64_t)ns_id),
- (int)line_start, 0,
- (int)line_end-1, MAXCOL);
-}
/// call a function with buffer as temporary current buffer
///