From 9ef16a1628722958b6e14fe9274006e50ed6682d Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 27 Oct 2019 15:05:59 -0700 Subject: doc: vim.fn, vim.call(), vim.api [ci skip] --- src/nvim/api/buffer.c | 49 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 17 deletions(-) (limited to 'src/nvim/api/buffer.c') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 3e1209d1b1..cb74c4227b 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -101,25 +101,39 @@ String buffer_get_line(Buffer buffer, Integer index, Error *err) return rv; } -/// Activates buffer-update events on a channel, or as lua callbacks. +/// Activates buffer-update events on a channel, or as Lua callbacks. +/// +/// @see |nvim_buf_detach()| +/// @see |api-buffer-updates-lua| /// /// @param channel_id /// @param buffer Buffer handle, or 0 for current buffer -/// @param send_buffer Set to true if the initial notification should contain -/// the whole buffer. If so, the first notification will be a -/// `nvim_buf_lines_event`. Otherwise, the first notification will be -/// a `nvim_buf_changedtick_event`. Not used for lua callbacks. +/// @param send_buffer True if the initial notification should contain the +/// whole buffer: first notification will be `nvim_buf_lines_event`. +/// Else the first notification will be `nvim_buf_changedtick_event`. +/// Not for Lua callbacks. /// @param opts Optional parameters. -/// - `on_lines`: lua callback received on change. -/// - `on_changedtick`: lua callback received on changedtick -/// increment without text change. -/// - `utf_sizes`: include UTF-32 and UTF-16 size of -/// the replaced region. -/// See |api-buffer-updates-lua| for more information +/// - on_lines: Lua callback invoked on change. +/// Return `true` to detach. Args: +/// - buffer handle +/// - b:changedtick +/// - first line that changed (zero-indexed) +/// - last line that was changed +/// - last line in the updated range +/// - byte count of previous contents +/// - deleted_codepoints (if `utf_sizes` is true) +/// - deleted_codeunits (if `utf_sizes` is true) +/// - on_changedtick: Lua callback invoked on changedtick +/// increment without text change. Args: +/// - buffer handle +/// - b:changedtick +/// - on_detach: Lua callback invoked on detach. Args: +/// - buffer handle +/// - utf_sizes: include UTF-32 and UTF-16 size of the replaced +/// region, as args to `on_lines`. /// @param[out] err Error details, if any -/// @return False when updates couldn't be enabled because the buffer isn't -/// loaded or `opts` contained an invalid key; otherwise True. -/// TODO: LUA_API_NO_EVAL +/// @return False if attach failed (invalid parameter, or buffer isn't loaded); +/// otherwise True. TODO: LUA_API_NO_EVAL Boolean nvim_buf_attach(uint64_t channel_id, Buffer buffer, Boolean send_buffer, @@ -183,13 +197,14 @@ error: /// Deactivates buffer-update events on the channel. /// -/// For Lua callbacks see |api-lua-detach|. +/// @see |nvim_buf_attach()| +/// @see |api-lua-detach| for detaching Lua callbacks /// /// @param channel_id /// @param buffer Buffer handle, or 0 for current buffer /// @param[out] err Error details, if any -/// @return False when updates couldn't be disabled because the buffer -/// isn't loaded; otherwise True. +/// @return False if detach failed (because the buffer isn't loaded); +/// otherwise True. Boolean nvim_buf_detach(uint64_t channel_id, Buffer buffer, Error *err) -- cgit From 1cb4674547828a315b7aef5b6c635726b3bc12e5 Mon Sep 17 00:00:00 2001 From: Marco Hinz Date: Sun, 10 Nov 2019 16:38:04 +0100 Subject: api: add nvim_buf_get_virtual_text() (#11354) This adds the missing partner function of nvim_buf_set_virtual_text(). --- src/nvim/api/buffer.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) (limited to 'src/nvim/api/buffer.c') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index cb74c4227b..10250be044 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -1207,7 +1207,57 @@ free_exit: return 0; } -Dictionary nvim__buf_stats(Buffer buffer, Error *err) +/// Get the virtual text (annotation) for a buffer line. +/// +/// The virtual text is returned as list of lists, whereas the inner lists have +/// either one or two elements. The first element is the actual text, the +/// optional second element is the highlight group. +/// +/// The format is exactly the same as given to nvim_buf_set_virtual_text(). +/// +/// If there is no virtual text associated with the given line, an empty list +/// is returned. +/// +/// @param buffer Buffer handle, or 0 for current buffer +/// @param line Line to get the virtual text from (zero-indexed) +/// @param[out] err Error details, if any +/// @return List of virtual text chunks +Array nvim_buf_get_virtual_text(Buffer buffer, Integer lnum, Error *err) + FUNC_API_SINCE(7) +{ + Array chunks = ARRAY_DICT_INIT; + + buf_T *buf = find_buffer_by_handle(buffer, err); + if (!buf) { + return chunks; + } + + if (lnum < 0 || lnum >= MAXLNUM) { + api_set_error(err, kErrorTypeValidation, "Line number outside range"); + return chunks; + } + + BufhlLine *lineinfo = bufhl_tree_ref(&buf->b_bufhl_info, (linenr_T)(lnum + 1), + false); + if (!lineinfo) { + return chunks; + } + + for (size_t i = 0; i < lineinfo->virt_text.size; i++) { + Array chunk = ARRAY_DICT_INIT; + VirtTextChunk *vtc = &lineinfo->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)); + } + + return chunks; +} + +Dictionary nvim__uf_stats(Buffer buffer, Error *err) { Dictionary rv = ARRAY_DICT_INIT; -- cgit From 181486d7e614c1a417ec0f555cdfd25716cb5e38 Mon Sep 17 00:00:00 2001 From: Marco Hinz Date: Mon, 11 Nov 2019 19:25:10 +0100 Subject: api: fix typo in debug function name --- src/nvim/api/buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/api/buffer.c') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 10250be044..257e02ec4f 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -1257,7 +1257,7 @@ Array nvim_buf_get_virtual_text(Buffer buffer, Integer lnum, Error *err) return chunks; } -Dictionary nvim__uf_stats(Buffer buffer, Error *err) +Dictionary nvim__buf_stats(Buffer buffer, Error *err) { Dictionary rv = ARRAY_DICT_INIT; -- cgit From a9065a50518ef59351f9d0d32041a991a751653f Mon Sep 17 00:00:00 2001 From: timeyyy Date: Wed, 18 Jan 2017 13:20:07 +0100 Subject: nsmarks: initial commit --- src/nvim/api/buffer.c | 217 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 216 insertions(+), 1 deletion(-) (limited to 'src/nvim/api/buffer.c') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 10250be044..a77c33e891 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -23,7 +23,10 @@ #include "nvim/memory.h" #include "nvim/misc1.h" #include "nvim/ex_cmds.h" +#include "nvim/map_defs.h" +#include "nvim/map.h" #include "nvim/mark.h" +#include "nvim/mark_extended.h" #include "nvim/fileio.h" #include "nvim/move.h" #include "nvim/syntax.h" @@ -544,7 +547,8 @@ void nvim_buf_set_lines(uint64_t channel_id, (linenr_T)(end - 1), MAXLNUM, (long)extra, - false); + false, + kExtmarkUndo); changed_lines((linenr_T)start, 0, (linenr_T)end, (long)extra, true); fix_cursor((linenr_T)start, (linenr_T)end, (linenr_T)extra); @@ -999,6 +1003,213 @@ ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err) return rv; } +/// Returns position info for a given extmark id +/// +/// @param buffer The buffer handle +/// @param namespace a identifier returned previously with nvim_create_namespace +/// @param id the extmark id +/// @param[out] err Details of an error that may have occurred +/// @return (row, col) tuple or empty list () if extmark id was absent +ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer namespace, + Integer id, Error *err) + FUNC_API_SINCE(6) +{ + Array rv = ARRAY_DICT_INIT; + + buf_T *buf = find_buffer_by_handle(buffer, err); + + if (!buf) { + return rv; + } + + if (!ns_initialized((uint64_t)namespace)) { + api_set_error(err, kErrorTypeValidation, _("Invalid mark namespace")); + return rv; + } + + ExtendedMark *extmark = extmark_from_id(buf, + (uint64_t)namespace, + (uint64_t)id); + if (!extmark) { + return rv; + } + ADD(rv, INTEGER_OBJ((Integer)extmark->line->lnum-1)); + ADD(rv, INTEGER_OBJ((Integer)extmark->col-1)); + return rv; +} + +/// List extmarks in a range (inclusive) +/// +/// range ends can be specified as (row, col) tuples, as well as extmark +/// ids in the same namespace. In addition, 0 and -1 works as shorthands +/// for (0,0) and (-1,-1) respectively, so that all marks in the buffer can be +/// quieried as: +/// +/// all_marks = nvim_buf_get_extmarks(0, my_ns, 0, -1, -1) +/// +/// If end is a lower position than start, then the range will be traversed +/// backwards. This is mostly used with limited amount, to be able to get the +/// first marks prior to a given position. +/// +/// @param buffer The buffer handle +/// @param namespace An id returned previously from nvim_create_namespace +/// @param lower One of: extmark id, (row, col) or 0, -1 for buffer ends +/// @param upper One of: extmark id, (row, col) or 0, -1 for buffer ends +/// @param amount Maximum number of marks to return or -1 for all marks found +/// /// @param[out] err Details of an error that may have occurred +/// @return [[nsmark_id, row, col], ...] +Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, + Object start, Object end, Integer amount, + Error *err) + FUNC_API_SINCE(6) +{ + 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 mark namespace")); + return rv; + } + + if (amount == 0) { + return rv; + } + + + bool reverse = false; + + linenr_T l_lnum; + colnr_T l_col; + if (!set_extmark_index_from_obj(buf, ns_id, start, &l_lnum, &l_col, err)) { + return rv; + } + + linenr_T u_lnum; + colnr_T u_col; + if (!set_extmark_index_from_obj(buf, ns_id, end, &u_lnum, &u_col, err)) { + return rv; + } + + if (l_lnum > u_lnum || (l_lnum == u_lnum && l_col > u_col)) { + reverse = true; + linenr_T tmp_lnum = l_lnum; + l_lnum = u_lnum; + u_lnum = tmp_lnum; + colnr_T tmp_col = l_col; + l_col = u_col; + u_col = tmp_col; + } + + + ExtmarkArray marks = extmark_get(buf, (uint64_t)ns_id, l_lnum, l_col, + u_lnum, u_col, (int64_t)amount, + reverse); + + for (size_t i = 0; i < kv_size(marks); i++) { + Array mark = ARRAY_DICT_INIT; + ExtendedMark *extmark = kv_A(marks, i); + ADD(mark, INTEGER_OBJ((Integer)extmark->mark_id)); + ADD(mark, INTEGER_OBJ(extmark->line->lnum-1)); + ADD(mark, INTEGER_OBJ(extmark->col-1)); + ADD(rv, ARRAY_OBJ(mark)); + } + + kv_destroy(marks); + return rv; +} + +/// Create or update a namespaced mark at a position +/// +/// If an invalid namespace is given, an error will be raised. +/// +/// @param buffer The buffer handle +/// @param ns_id a identifier returned previously with nvim_create_namespace +/// @param id The extmark's id or 0 for next free id +/// @param row The row to set the extmark to. +/// @param col The column to set the extmark to. +/// @param[out] err Details of an error that may have occurred +/// @return the nsmark_id for a new mark, or 0 for an update +Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer id, + Integer line, Integer col, Error *err) + FUNC_API_SINCE(6) +{ + buf_T *buf = find_buffer_by_handle(buffer, err); + if (!buf) { + return 0; + } + + if (!ns_initialized((uint64_t)ns_id)) { + api_set_error(err, kErrorTypeValidation, _("Invalid mark namespace")); + return 0; + } + + size_t len = 0; + if (line < 0 || line > buf->b_ml.ml_line_count) { + api_set_error(err, kErrorTypeValidation, "line value outside range"); + return 0; + } else if (line < buf->b_ml.ml_line_count) { + len = STRLEN(ml_get_buf(curbuf, (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"); + return 0; + } + + uint64_t id_num; + if (id == 0) { + id_num = extmark_free_id_get(buf, (uint64_t)ns_id); + } else if (id > 0) { + id_num = (uint64_t)id; + } else { + api_set_error(err, kErrorTypeValidation, _("Invalid mark id")); + return 0; + } + + bool new = extmark_set(buf, (uint64_t)ns_id, id_num, + (linenr_T)line+1, + (colnr_T)col+1, + kExtmarkUndo); + + if (new) { + return (Integer)id_num; + } else { + return 0; + } +} + +/// Remove an extmark +/// +/// @param buffer The buffer handle +/// @param ns_id a identifier returned previously with nvim_create_namespace +/// @param id The extmarks's id +/// @param[out] err Details of an error that may have occurred +/// @return true on success, false if no extmarks found +Boolean nvim_buf_del_extmark(Buffer buffer, + Integer ns_id, + Integer id, + Error *err) + FUNC_API_SINCE(6) +{ + 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 mark namespace")); + return false; + } + + return extmark_del(buf, (uint64_t)ns_id, (uint64_t)id, kExtmarkUndo); +} + /// Adds a highlight to buffer. /// /// Useful for plugins that dynamically generate highlights to a buffer @@ -1097,6 +1308,10 @@ void nvim_buf_clear_namespace(Buffer buffer, } bufhl_clear_line_range(buf, (int)ns_id, (int)line_start+1, (int)line_end); + extmark_clear(buf, ns_id == -1 ? 0 : (uint64_t)ns_id, + (linenr_T)line_start+1, + (linenr_T)line_end, + kExtmarkUndo); } /// Clears highlights and virtual text from namespace and range of lines -- cgit From 18a8b702c0ce7a8bacd84f6c95e440ae23a3299e Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sat, 9 Nov 2019 12:41:50 +0100 Subject: extmark: review changes --- src/nvim/api/buffer.c | 87 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 30 deletions(-) (limited to 'src/nvim/api/buffer.c') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index a77c33e891..24fa963fbc 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -1003,16 +1003,16 @@ ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err) return rv; } -/// Returns position info for a given extmark id +/// Returns position for a given extmark id /// /// @param buffer The buffer handle /// @param namespace a identifier returned previously with nvim_create_namespace /// @param id the extmark id /// @param[out] err Details of an error that may have occurred /// @return (row, col) tuple or empty list () if extmark id was absent -ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer namespace, +ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id, Integer id, Error *err) - FUNC_API_SINCE(6) + FUNC_API_SINCE(7) { Array rv = ARRAY_DICT_INIT; @@ -1022,13 +1022,13 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer namespace, return rv; } - if (!ns_initialized((uint64_t)namespace)) { - api_set_error(err, kErrorTypeValidation, _("Invalid mark namespace")); + if (!ns_initialized((uint64_t)ns_id)) { + api_set_error(err, kErrorTypeValidation, _("Invalid ns_id")); return rv; } ExtendedMark *extmark = extmark_from_id(buf, - (uint64_t)namespace, + (uint64_t)ns_id, (uint64_t)id); if (!extmark) { return rv; @@ -1052,16 +1052,17 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer namespace, /// first marks prior to a given position. /// /// @param buffer The buffer handle -/// @param namespace An id returned previously from nvim_create_namespace +/// @param ns_id An id returned previously from nvim_create_namespace /// @param lower One of: extmark id, (row, col) or 0, -1 for buffer ends /// @param upper One of: extmark id, (row, col) or 0, -1 for buffer ends -/// @param amount Maximum number of marks to return or -1 for all marks found -/// /// @param[out] err Details of an error that may have occurred +/// @param opts additional options. Supports the keys: +/// - amount: Maximum number of marks to return +/// @param[out] err Details of an error that may have occurred /// @return [[nsmark_id, row, col], ...] Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, - Object start, Object end, Integer amount, + Object start, Object end, Dictionary opts, Error *err) - FUNC_API_SINCE(6) + FUNC_API_SINCE(7) { Array rv = ARRAY_DICT_INIT; @@ -1071,9 +1072,26 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, } if (!ns_initialized((uint64_t)ns_id)) { - api_set_error(err, kErrorTypeValidation, _("Invalid mark namespace")); + api_set_error(err, kErrorTypeValidation, _("Invalid ns_id")); return rv; } + Integer amount = -1; + + for (size_t i = 0; i < opts.size; i++) { + String k = opts.items[i].key; + Object *v = &opts.items[i].value; + if (strequal("amount", k.data)) { + if (v->type != kObjectTypeInteger) { + api_set_error(err, kErrorTypeValidation, "amount is not an integer"); + return rv; + } + amount = v->data.integer; + v->data.integer = LUA_NOREF; + } else { + api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); + return rv; + } + } if (amount == 0) { return rv; @@ -1122,20 +1140,30 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, return rv; } -/// Create or update a namespaced mark at a position +/// Create or update an extmark at a position /// /// If an invalid namespace is given, an error will be raised. /// +/// To create a new extmark, pass in id=0. The new extmark id will be +/// returned. To move an existing mark, pass in 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. +/// This is mainly useful over RPC, to avoid needing to wait for the return +/// value. +/// /// @param buffer The buffer handle /// @param ns_id a identifier returned previously with nvim_create_namespace -/// @param id The extmark's id or 0 for next free id +/// @param id The extmark's id or 0 to create a new mark. /// @param row The row to set the extmark to. /// @param col The column to set the extmark to. +/// @param opts Optional parameters. Currently not used. /// @param[out] err Details of an error that may have occurred -/// @return the nsmark_id for a new mark, or 0 for an update +/// @return the id of the extmark. Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer id, - Integer line, Integer col, Error *err) - FUNC_API_SINCE(6) + Integer line, Integer col, + Dictionary opts, Error *err) + FUNC_API_SINCE(7) { buf_T *buf = find_buffer_by_handle(buffer, err); if (!buf) { @@ -1143,7 +1171,12 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer id, } if (!ns_initialized((uint64_t)ns_id)) { - api_set_error(err, kErrorTypeValidation, _("Invalid mark namespace")); + api_set_error(err, kErrorTypeValidation, _("Invalid ns_id")); + return 0; + } + + if (opts.size > 0) { + api_set_error(err, kErrorTypeValidation, "opts dict isn't empty"); return 0; } @@ -1172,16 +1205,10 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer id, return 0; } - bool new = extmark_set(buf, (uint64_t)ns_id, id_num, - (linenr_T)line+1, - (colnr_T)col+1, - kExtmarkUndo); + extmark_set(buf, (uint64_t)ns_id, id_num, + (linenr_T)line+1, (colnr_T)col+1, kExtmarkUndo); - if (new) { - return (Integer)id_num; - } else { - return 0; - } + return (Integer)id_num; } /// Remove an extmark @@ -1190,12 +1217,12 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer id, /// @param ns_id a identifier returned previously with nvim_create_namespace /// @param id The extmarks's id /// @param[out] err Details of an error that may have occurred -/// @return true on success, false if no extmarks found +/// @return true on success, false if the extmark was not found. Boolean nvim_buf_del_extmark(Buffer buffer, Integer ns_id, Integer id, Error *err) - FUNC_API_SINCE(6) + FUNC_API_SINCE(7) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -1203,7 +1230,7 @@ Boolean nvim_buf_del_extmark(Buffer buffer, return false; } if (!ns_initialized((uint64_t)ns_id)) { - api_set_error(err, kErrorTypeValidation, _("Invalid mark namespace")); + api_set_error(err, kErrorTypeValidation, _("Invalid ns_id")); return false; } -- cgit From 54473e9a677b001b47b1fe528b6056e9feed0f60 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 10 Nov 2019 16:52:14 -0800 Subject: doc [ci skip] --- src/nvim/api/buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/api/buffer.c') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 5909fd7c02..58011702ac 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -1058,7 +1058,7 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id, /// @param opts additional options. Supports the keys: /// - amount: Maximum number of marks to return /// @param[out] err Details of an error that may have occurred -/// @return [[nsmark_id, row, col], ...] +/// @return [[extmark_id, row, col], ...] Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object end, Dictionary opts, Error *err) -- cgit From 2d7e1c32a87655b78cd23f2a3ad9a7a140493bd5 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 11 Nov 2019 22:04:21 -0800 Subject: extmark: rename ExtendedMark => Extmark --- src/nvim/api/buffer.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src/nvim/api/buffer.c') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 58011702ac..9ec96840d1 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -1027,9 +1027,7 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id, return rv; } - ExtendedMark *extmark = extmark_from_id(buf, - (uint64_t)ns_id, - (uint64_t)id); + Extmark *extmark = extmark_from_id(buf, (uint64_t)ns_id, (uint64_t)id); if (!extmark) { return rv; } @@ -1129,7 +1127,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, for (size_t i = 0; i < kv_size(marks); i++) { Array mark = ARRAY_DICT_INIT; - ExtendedMark *extmark = kv_A(marks, i); + Extmark *extmark = kv_A(marks, i); ADD(mark, INTEGER_OBJ((Integer)extmark->mark_id)); ADD(mark, INTEGER_OBJ(extmark->line->lnum-1)); ADD(mark, INTEGER_OBJ(extmark->col-1)); -- cgit From af53a0c0123338575dd59934449d7fe836835d1c Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 17 Nov 2019 19:06:59 -0800 Subject: doc: Lua [ci skip] #11378 - Rework :help lua-commands - Rename if_lua.txt => lua.txt --- src/nvim/api/buffer.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'src/nvim/api/buffer.c') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 9ec96840d1..a5f8b0974e 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -106,6 +106,14 @@ String buffer_get_line(Buffer buffer, Integer index, Error *err) /// Activates buffer-update events on a channel, or as Lua callbacks. /// +/// Example (Lua): capture buffer updates in a global `events` variable +/// (use "print(vim.inspect(events))" to see its contents): +///
+///   events = {}
+///   vim.api.nvim_buf_attach(0, false, {
+///     on_lines=function(...) table.insert(events, {...}) end})
+/// 
+/// /// @see |nvim_buf_detach()| /// @see |api-buffer-updates-lua| /// @@ -1041,18 +1049,18 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id, /// range ends can be specified as (row, col) tuples, as well as extmark /// ids in the same namespace. In addition, 0 and -1 works as shorthands /// for (0,0) and (-1,-1) respectively, so that all marks in the buffer can be -/// quieried as: +/// queried as: /// -/// all_marks = nvim_buf_get_extmarks(0, my_ns, 0, -1, -1) +/// all_marks = nvim_buf_get_extmarks(0, my_ns, 0, -1, {}) /// /// If end is a lower position than start, then the range will be traversed -/// backwards. This is mostly used with limited amount, to be able to get the +/// backwards. This is mostly useful with limited amount, to be able to get the /// first marks prior to a given position. /// /// @param buffer The buffer handle /// @param ns_id An id returned previously from nvim_create_namespace -/// @param lower One of: extmark id, (row, col) or 0, -1 for buffer ends -/// @param upper One of: extmark id, (row, col) or 0, -1 for buffer ends +/// @param start One of: extmark id, (row, col) or 0, -1 for buffer ends +/// @param end One of: extmark id, (row, col) or 0, -1 for buffer ends /// @param opts additional options. Supports the keys: /// - amount: Maximum number of marks to return /// @param[out] err Details of an error that may have occurred @@ -1153,7 +1161,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, /// @param buffer The buffer handle /// @param ns_id a identifier returned previously with nvim_create_namespace /// @param id The extmark's id or 0 to create a new mark. -/// @param row The row to set the extmark to. +/// @param line The row to set the extmark to. /// @param col The column to set the extmark to. /// @param opts Optional parameters. Currently not used. /// @param[out] err Details of an error that may have occurred -- cgit From fd5710ae9a3bcbc0f9cbb71de9e39253350ff09c Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 25 Nov 2019 01:08:02 -0800 Subject: doc + extmarks tweaks #11421 - nvim_buf_get_extmarks: rename "amount" => "limit" - rename `set_extmark_index_from_obj` --- src/nvim/api/buffer.c | 139 ++++++++++++++++++++++++++++---------------------- 1 file changed, 78 insertions(+), 61 deletions(-) (limited to 'src/nvim/api/buffer.c') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index a5f8b0974e..448ade5e4b 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -1013,10 +1013,10 @@ ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err) /// Returns position for a given extmark id /// -/// @param buffer The buffer handle -/// @param namespace a identifier returned previously with nvim_create_namespace -/// @param id the extmark id -/// @param[out] err Details of an error that may have occurred +/// @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 (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, Error *err) @@ -1044,30 +1044,50 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id, return rv; } -/// List extmarks in a range (inclusive) -/// -/// range ends can be specified as (row, col) tuples, as well as extmark -/// ids in the same namespace. In addition, 0 and -1 works as shorthands -/// for (0,0) and (-1,-1) respectively, so that all marks in the buffer can be -/// queried as: -/// -/// all_marks = nvim_buf_get_extmarks(0, my_ns, 0, -1, {}) -/// -/// If end is a lower position than start, then the range will be traversed -/// backwards. This is mostly useful with limited amount, to be able to get the -/// first marks prior to a given position. -/// -/// @param buffer The buffer handle -/// @param ns_id An id returned previously from nvim_create_namespace -/// @param start One of: extmark id, (row, col) or 0, -1 for buffer ends -/// @param end One of: extmark id, (row, col) or 0, -1 for buffer ends -/// @param opts additional options. Supports the keys: -/// - amount: Maximum number of marks to return -/// @param[out] err Details of an error that may have occurred -/// @return [[extmark_id, row, col], ...] -Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, - Object start, Object end, Dictionary opts, - Error *err) +/// 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: +/// +///
+///   nvim_buf_get_extmarks(0, my_ns, 0, -1, {})
+///   nvim_buf_get_extmarks(0, my_ns, [0,0], [-1,-1], {})
+/// 
+/// +/// If `end` is less than `start`, traversal works backwards. (Useful +/// with `limit`, to get the first marks prior to a given position.) +/// +/// Example: +/// +///
+///   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))
+/// 
+/// +/// @param buffer Buffer handle, or 0 for current buffer +/// @param ns_id Namespace id from |nvim_create_namespace()| +/// @param start Start of range, given as (row, col) or valid extmark id +/// (whose position defines the bound) +/// @param end End of range, given as (row, col) or valid extmark id +/// (whose position defines the bound) +/// @param opts Optional parameters. Keys: +/// - limit: Maximum number of marks to return +/// @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; @@ -1081,17 +1101,17 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, api_set_error(err, kErrorTypeValidation, _("Invalid ns_id")); return rv; } - Integer amount = -1; + Integer limit = -1; for (size_t i = 0; i < opts.size; i++) { String k = opts.items[i].key; Object *v = &opts.items[i].value; - if (strequal("amount", k.data)) { + if (strequal("limit", k.data)) { if (v->type != kObjectTypeInteger) { - api_set_error(err, kErrorTypeValidation, "amount is not an integer"); + api_set_error(err, kErrorTypeValidation, "limit is not an integer"); return rv; } - amount = v->data.integer; + limit = v->data.integer; v->data.integer = LUA_NOREF; } else { api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); @@ -1099,7 +1119,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, } } - if (amount == 0) { + if (limit == 0) { return rv; } @@ -1108,13 +1128,13 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, linenr_T l_lnum; colnr_T l_col; - if (!set_extmark_index_from_obj(buf, ns_id, start, &l_lnum, &l_col, err)) { + if (!extmark_get_index_from_obj(buf, ns_id, start, &l_lnum, &l_col, err)) { return rv; } linenr_T u_lnum; colnr_T u_col; - if (!set_extmark_index_from_obj(buf, ns_id, end, &u_lnum, &u_col, err)) { + if (!extmark_get_index_from_obj(buf, ns_id, end, &u_lnum, &u_col, err)) { return rv; } @@ -1129,9 +1149,8 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, } - ExtmarkArray marks = extmark_get(buf, (uint64_t)ns_id, l_lnum, l_col, - u_lnum, u_col, (int64_t)amount, - reverse); + ExtmarkArray marks = extmark_get(buf, (uint64_t)ns_id, l_lnum, l_col, u_lnum, + u_col, (int64_t)limit, reverse); for (size_t i = 0; i < kv_size(marks); i++) { Array mark = ARRAY_DICT_INIT; @@ -1146,26 +1165,23 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, return rv; } -/// Create or update an extmark at a position +/// Creates or updates an extmark. /// -/// If an invalid namespace is given, an error will be raised. -/// -/// To create a new extmark, pass in id=0. The new extmark id will be -/// returned. To move an existing mark, pass in its id. +/// 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. -/// This is mainly useful over RPC, to avoid needing to wait for the return -/// value. -/// -/// @param buffer The buffer handle -/// @param ns_id a identifier returned previously with nvim_create_namespace -/// @param id The extmark's id or 0 to create a new mark. -/// @param line The row to set the extmark to. -/// @param col The column to set the extmark to. -/// @param opts Optional parameters. Currently not used. -/// @param[out] err Details of an error that may have occurred -/// @return the id of the extmark. +/// (Useful over RPC, to avoid waiting for the return value.) +/// +/// @param buffer Buffer handle, or 0 for current buffer +/// @param ns_id Namespace id from |nvim_create_namespace()| +/// @param id Extmark id, or 0 to create new +/// @param line Line number where to place the mark +/// @param col Column where to place the mark +/// @param opts Optional parameters. Currently not used. +/// @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 id, Integer line, Integer col, Dictionary opts, Error *err) @@ -1217,13 +1233,13 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer id, return (Integer)id_num; } -/// Remove an extmark +/// Removes an extmark. /// -/// @param buffer The buffer handle -/// @param ns_id a identifier returned previously with nvim_create_namespace -/// @param id The extmarks's id -/// @param[out] err Details of an error that may have occurred -/// @return true on success, false if the extmark was not found. +/// @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, @@ -1309,7 +1325,8 @@ Integer nvim_buf_add_highlight(Buffer buffer, return ns_id; } -/// Clears namespaced objects, highlights and virtual text, from a line range +/// 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. -- cgit From 4a77df2e518a51ffd5a5fe311424b4b5305009a7 Mon Sep 17 00:00:00 2001 From: notomo Date: Tue, 26 Nov 2019 00:50:30 +0900 Subject: [RFC] extmark: fix E315 in nvim_buf_set_extmark (#11449) extmark: need to use buf instead of curbuf --- src/nvim/api/buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/api/buffer.c') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 448ade5e4b..8f5718d97e 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -1207,7 +1207,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer id, api_set_error(err, kErrorTypeValidation, "line value outside range"); return 0; } else if (line < buf->b_ml.ml_line_count) { - len = STRLEN(ml_get_buf(curbuf, (linenr_T)line+1, false)); + len = STRLEN(ml_get_buf(buf, (linenr_T)line+1, false)); } if (col == -1) { -- cgit From 440695c29696f261337227e5c419aa1cf313c2dd Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sat, 28 Sep 2019 14:27:20 +0200 Subject: tree-sitter: implement query functionality and highlighting prototype [skip.lint] --- src/nvim/api/buffer.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 87 insertions(+), 4 deletions(-) (limited to 'src/nvim/api/buffer.c') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 8f5718d97e..e6f8f73b9d 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -169,21 +169,21 @@ Boolean nvim_buf_attach(uint64_t channel_id, goto error; } cb.on_lines = v->data.luaref; - v->data.integer = LUA_NOREF; + v->data.luaref = LUA_NOREF; } else if (is_lua && strequal("on_changedtick", k.data)) { if (v->type != kObjectTypeLuaRef) { api_set_error(err, kErrorTypeValidation, "callback is not a function"); goto error; } cb.on_changedtick = v->data.luaref; - v->data.integer = LUA_NOREF; + v->data.luaref = LUA_NOREF; } else if (is_lua && strequal("on_detach", k.data)) { if (v->type != kObjectTypeLuaRef) { api_set_error(err, kErrorTypeValidation, "callback is not a function"); goto error; } cb.on_detach = v->data.luaref; - v->data.integer = LUA_NOREF; + v->data.luaref = LUA_NOREF; } else if (is_lua && strequal("utf_sizes", k.data)) { if (v->type != kObjectTypeBoolean) { api_set_error(err, kErrorTypeValidation, "utf_sizes must be boolean"); @@ -231,6 +231,90 @@ Boolean nvim_buf_detach(uint64_t channel_id, return true; } +static void buf_clear_luahl(buf_T *buf, bool force) +{ + if (buf->b_luahl || force) { + executor_free_luaref(buf->b_luahl_start); + executor_free_luaref(buf->b_luahl_window); + executor_free_luaref(buf->b_luahl_line); + executor_free_luaref(buf->b_luahl_end); + } + buf->b_luahl_start = LUA_NOREF; + buf->b_luahl_window = LUA_NOREF; + buf->b_luahl_line = LUA_NOREF; + buf->b_luahl_end = LUA_NOREF; +} + +/// Unstabilized interface for defining syntax hl in lua. +/// +/// This is not yet safe for general use, lua callbacks will need to +/// be restricted, like textlock and probably other stuff. +/// +/// The API on_line/nvim__put_attr is quite raw and not intended to be the +/// final shape. Ideally this should operate on chunks larger than a single +/// line to reduce interpreter overhead, and generate annotation objects +/// (bufhl/virttext) on the fly but using the same representation. +void nvim__buf_set_luahl(uint64_t channel_id, Buffer buffer, + DictionaryOf(LuaRef) opts, Error *err) + FUNC_API_LUA_ONLY +{ + buf_T *buf = find_buffer_by_handle(buffer, err); + + if (!buf) { + return; + } + + redraw_buf_later(buf, NOT_VALID); + buf_clear_luahl(buf, false); + + for (size_t i = 0; i < opts.size; i++) { + String k = opts.items[i].key; + Object *v = &opts.items[i].value; + if (strequal("on_start", k.data)) { + if (v->type != kObjectTypeLuaRef) { + api_set_error(err, kErrorTypeValidation, "callback is not a function"); + goto error; + } + buf->b_luahl_start = v->data.luaref; + v->data.luaref = LUA_NOREF; + } else if (strequal("on_window", k.data)) { + if (v->type != kObjectTypeLuaRef) { + api_set_error(err, kErrorTypeValidation, "callback is not a function"); + goto error; + } + buf->b_luahl_window = v->data.luaref; + v->data.luaref = LUA_NOREF; + } else if (strequal("on_line", k.data)) { + if (v->type != kObjectTypeLuaRef) { + api_set_error(err, kErrorTypeValidation, "callback is not a function"); + goto error; + } + buf->b_luahl_line = v->data.luaref; + v->data.luaref = LUA_NOREF; + } else { + api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); + goto error; + } + } + buf->b_luahl = true; + return; +error: + buf_clear_luahl(buf, true); + buf->b_luahl = false; +} + +void nvim__buf_redraw_range(Buffer buffer, Integer first, Integer last, + Error *err) + FUNC_API_LUA_ONLY +{ + buf_T *buf = find_buffer_by_handle(buffer, err); + if (!buf) { + return; + } + + redraw_buf_range_later(buf, (linenr_T)first+1, (linenr_T)last); +} + /// Sets a buffer line /// /// @deprecated use nvim_buf_set_lines instead. @@ -1112,7 +1196,6 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, return rv; } limit = v->data.integer; - v->data.integer = LUA_NOREF; } else { api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); return rv; -- cgit From ca1a00edd6d6345b848a28d077d6a192528f811e Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Tue, 14 Jan 2020 12:45:09 +0100 Subject: extmarks/bufhl: reimplement using new marktree data structure Add new "splice" interface for tracking buffer changes at the byte level. This will later be reused for byte-resolution buffer updates. (Implementation has been started, but using undocumented "_on_bytes" option now as interface hasn't been finalized). Use this interface to improve many edge cases of extmark adjustment. Changed tests indicate previously incorrect behavior. Adding tests for more edge cases will be follow-up work (overlaps on_bytes tests) Don't consider creation/deletion of marks an undoable event by itself. This behavior was never documented, and imposes complexity for little gain. Add nvim__buf_add_decoration temporary API for direct access to the new implementation. This should be refactored into a proper API for decorations, probably involving a huge dict. fixes #11598 --- src/nvim/api/buffer.c | 253 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 177 insertions(+), 76 deletions(-) (limited to 'src/nvim/api/buffer.c') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index e6f8f73b9d..3106011fe2 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -170,6 +170,14 @@ Boolean nvim_buf_attach(uint64_t channel_id, } cb.on_lines = v->data.luaref; v->data.luaref = LUA_NOREF; + } else if (is_lua && strequal("_on_bytes", k.data)) { + // NB: undocumented, untested and incomplete interface! + if (v->type != kObjectTypeLuaRef) { + api_set_error(err, kErrorTypeValidation, "callback is not a function"); + goto error; + } + cb.on_bytes = v->data.luaref; + v->data.luaref = LUA_NOREF; } else if (is_lua && strequal("on_changedtick", k.data)) { if (v->type != kObjectTypeLuaRef) { api_set_error(err, kErrorTypeValidation, "callback is not a function"); @@ -201,6 +209,7 @@ Boolean nvim_buf_attach(uint64_t channel_id, error: // TODO(bfredl): ASAN build should check that the ref table is empty? executor_free_luaref(cb.on_lines); + executor_free_luaref(cb.on_bytes); executor_free_luaref(cb.on_changedtick); executor_free_luaref(cb.on_detach); return false; @@ -639,7 +648,6 @@ void nvim_buf_set_lines(uint64_t channel_id, (linenr_T)(end - 1), MAXLNUM, (long)extra, - false, kExtmarkUndo); changed_lines((linenr_T)start, 0, (linenr_T)end, (long)extra, true); @@ -1119,12 +1127,12 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id, return rv; } - Extmark *extmark = extmark_from_id(buf, (uint64_t)ns_id, (uint64_t)id); - if (!extmark) { + ExtmarkInfo extmark = extmark_from_id(buf, (uint64_t)ns_id, (uint64_t)id); + if (extmark.row < 0) { return rv; } - ADD(rv, INTEGER_OBJ((Integer)extmark->line->lnum-1)); - ADD(rv, INTEGER_OBJ((Integer)extmark->col-1)); + ADD(rv, INTEGER_OBJ((Integer)extmark.row)); + ADD(rv, INTEGER_OBJ((Integer)extmark.col)); return rv; } @@ -1204,43 +1212,39 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, if (limit == 0) { return rv; + } else if (limit < 0) { + limit = INT64_MAX; } bool reverse = false; - linenr_T l_lnum; + int l_row; colnr_T l_col; - if (!extmark_get_index_from_obj(buf, ns_id, start, &l_lnum, &l_col, err)) { + if (!extmark_get_index_from_obj(buf, ns_id, start, &l_row, &l_col, err)) { return rv; } - linenr_T u_lnum; + int u_row; colnr_T u_col; - if (!extmark_get_index_from_obj(buf, ns_id, end, &u_lnum, &u_col, err)) { + if (!extmark_get_index_from_obj(buf, ns_id, end, &u_row, &u_col, err)) { return rv; } - if (l_lnum > u_lnum || (l_lnum == u_lnum && l_col > u_col)) { + if (l_row > u_row || (l_row == u_row && l_col > u_col)) { reverse = true; - linenr_T tmp_lnum = l_lnum; - l_lnum = u_lnum; - u_lnum = tmp_lnum; - colnr_T tmp_col = l_col; - l_col = u_col; - u_col = tmp_col; } - ExtmarkArray marks = extmark_get(buf, (uint64_t)ns_id, l_lnum, l_col, u_lnum, + ExtmarkArray 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++) { Array mark = ARRAY_DICT_INIT; - Extmark *extmark = kv_A(marks, i); - ADD(mark, INTEGER_OBJ((Integer)extmark->mark_id)); - ADD(mark, INTEGER_OBJ(extmark->line->lnum-1)); - ADD(mark, INTEGER_OBJ(extmark->col-1)); + ExtmarkInfo extmark = kv_A(marks, i); + ADD(mark, INTEGER_OBJ((Integer)extmark.mark_id)); + ADD(mark, INTEGER_OBJ(extmark.row)); + ADD(mark, INTEGER_OBJ(extmark.col)); ADD(rv, ARRAY_OBJ(mark)); } @@ -1301,17 +1305,15 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer id, } uint64_t id_num; - if (id == 0) { - id_num = extmark_free_id_get(buf, (uint64_t)ns_id); - } else if (id > 0) { + if (id >= 0) { id_num = (uint64_t)id; } else { api_set_error(err, kErrorTypeValidation, _("Invalid mark id")); return 0; } - extmark_set(buf, (uint64_t)ns_id, id_num, - (linenr_T)line+1, (colnr_T)col+1, kExtmarkUndo); + id_num = extmark_set(buf, (uint64_t)ns_id, id_num, + (int)line, (colnr_T)col, kExtmarkUndo); return (Integer)id_num; } @@ -1339,7 +1341,7 @@ Boolean nvim_buf_del_extmark(Buffer buffer, return false; } - return extmark_del(buf, (uint64_t)ns_id, (uint64_t)id, kExtmarkUndo); + return extmark_del(buf, (uint64_t)ns_id, (uint64_t)id); } /// Adds a highlight to buffer. @@ -1373,7 +1375,7 @@ Boolean nvim_buf_del_extmark(Buffer buffer, /// @param[out] err Error details, if any /// @return The ns_id that was used Integer nvim_buf_add_highlight(Buffer buffer, - Integer ns_id, + Integer src_id, String hl_group, Integer line, Integer col_start, @@ -1398,14 +1400,31 @@ Integer nvim_buf_add_highlight(Buffer buffer, col_end = MAXCOL; } + uint64_t ns_id = src2ns(&src_id); + + if (!(0 <= line && line < buf->b_ml.ml_line_count)) { + // safety check, we can't add marks outside the range + return src_id; + } + int hlg_id = 0; if (hl_group.size > 0) { hlg_id = syn_check_group((char_u *)hl_group.data, (int)hl_group.size); + } else { + return src_id; + } + + int end_line = (int)line; + if (col_end == MAXCOL) { + col_end = 0; + end_line++; } - ns_id = bufhl_add_hl(buf, (int)ns_id, hlg_id, (linenr_T)line+1, - (colnr_T)col_start+1, (colnr_T)col_end); - return ns_id; + ns_id = extmark_add_decoration(buf, ns_id, hlg_id, + (int)line, (colnr_T)col_start, + end_line, (colnr_T)col_end, + VIRTTEXT_EMPTY); + return src_id; } /// Clears namespaced objects (highlights, extmarks, virtual text) from @@ -1439,12 +1458,9 @@ void nvim_buf_clear_namespace(Buffer buffer, if (line_end < 0 || line_end > MAXLNUM) { line_end = MAXLNUM; } - - bufhl_clear_line_range(buf, (int)ns_id, (int)line_start+1, (int)line_end); - extmark_clear(buf, ns_id == -1 ? 0 : (uint64_t)ns_id, - (linenr_T)line_start+1, - (linenr_T)line_end, - kExtmarkUndo); + extmark_clear(buf, (ns_id < 0 ? 0 : (uint64_t)ns_id), + (int)line_start, 0, + (int)line_end-1, MAXCOL); } /// Clears highlights and virtual text from namespace and range of lines @@ -1467,6 +1483,43 @@ void nvim_buf_clear_highlight(Buffer buffer, nvim_buf_clear_namespace(buffer, ns_id, line_start, line_end, err); } +static VirtText parse_virt_text(Array chunks, Error *err) +{ + VirtText virt_text = 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 = chunk.items[0].data.string; + char *text = transstr(str.size > 0 ? str.data : ""); // allocates + + int hl_id = 0; + if (chunk.size == 2) { + String hl = chunk.items[1].data.string; + if (hl.size > 0) { + hl_id = syn_check_group((char_u *)hl.data, (int)hl.size); + } + } + kv_push(virt_text, ((VirtTextChunk){ .text = text, .hl_id = hl_id })); + } + + return virt_text; + +free_exit: + clear_virttext(&virt_text); + return virt_text; +} + /// Set the virtual text (annotation) for a buffer line. /// @@ -1496,7 +1549,7 @@ void nvim_buf_clear_highlight(Buffer buffer, /// @param[out] err Error details, if any /// @return The ns_id that was used Integer nvim_buf_set_virtual_text(Buffer buffer, - Integer ns_id, + Integer src_id, Integer line, Array chunks, Dictionary opts, @@ -1518,41 +1571,26 @@ Integer nvim_buf_set_virtual_text(Buffer buffer, return 0; } - VirtText virt_text = 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 = chunk.items[0].data.string; - char *text = transstr(str.size > 0 ? str.data : ""); // allocates + uint64_t ns_id = src2ns(&src_id); - int hl_id = 0; - if (chunk.size == 2) { - String hl = chunk.items[1].data.string; - if (hl.size > 0) { - hl_id = syn_check_group((char_u *)hl.data, (int)hl.size); - } - } - kv_push(virt_text, ((VirtTextChunk){ .text = text, .hl_id = hl_id })); + VirtText virt_text = parse_virt_text(chunks, err); + if (ERROR_SET(err)) { + return 0; } - ns_id = bufhl_add_virt_text(buf, (int)ns_id, (linenr_T)line+1, - virt_text); - return ns_id; -free_exit: - kv_destroy(virt_text); - return 0; + VirtText *existing = extmark_find_virttext(buf, (int)line, ns_id); + + if (existing) { + clear_virttext(existing); + *existing = virt_text; + return src_id; + } + + extmark_add_decoration(buf, ns_id, 0, + (int)line, 0, -1, -1, + virt_text); + return src_id; } /// Get the virtual text (annotation) for a buffer line. @@ -1570,7 +1608,7 @@ free_exit: /// @param line Line to get the virtual text from (zero-indexed) /// @param[out] err Error details, if any /// @return List of virtual text chunks -Array nvim_buf_get_virtual_text(Buffer buffer, Integer lnum, Error *err) +Array nvim_buf_get_virtual_text(Buffer buffer, Integer line, Error *err) FUNC_API_SINCE(7) { Array chunks = ARRAY_DICT_INIT; @@ -1580,20 +1618,20 @@ Array nvim_buf_get_virtual_text(Buffer buffer, Integer lnum, Error *err) return chunks; } - if (lnum < 0 || lnum >= MAXLNUM) { + if (line < 0 || line >= MAXLNUM) { api_set_error(err, kErrorTypeValidation, "Line number outside range"); return chunks; } - BufhlLine *lineinfo = bufhl_tree_ref(&buf->b_bufhl_info, (linenr_T)(lnum + 1), - false); - if (!lineinfo) { + VirtText *virt_text = extmark_find_virttext(buf, (int)line, 0); + + if (!virt_text) { return chunks; } - for (size_t i = 0; i < lineinfo->virt_text.size; i++) { + for (size_t i = 0; i < virt_text->size; i++) { Array chunk = ARRAY_DICT_INIT; - VirtTextChunk *vtc = &lineinfo->virt_text.items[i]; + VirtTextChunk *vtc = &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( @@ -1605,6 +1643,59 @@ Array nvim_buf_get_virtual_text(Buffer buffer, Integer lnum, Error *err) return chunks; } +Integer nvim__buf_add_decoration(Buffer buffer, Integer ns_id, String hl_group, + Integer start_row, Integer start_col, + Integer end_row, Integer end_col, + Array virt_text, + Error *err) +{ + buf_T *buf = find_buffer_by_handle(buffer, err); + if (!buf) { + return 0; + } + + if (!ns_initialized((uint64_t)ns_id)) { + api_set_error(err, kErrorTypeValidation, _("Invalid ns_id")); + return 0; + } + + + if (start_row < 0 || start_row >= MAXLNUM || end_row > MAXCOL) { + api_set_error(err, kErrorTypeValidation, "Line number outside range"); + return 0; + } + + if (start_col < 0 || start_col > MAXCOL || end_col > MAXCOL) { + api_set_error(err, kErrorTypeValidation, "Column value outside range"); + return 0; + } + if (end_row < 0 || end_col < 0) { + end_row = -1; + end_col = -1; + } + + if (start_row >= buf->b_ml.ml_line_count + || end_row >= buf->b_ml.ml_line_count) { + // safety check, we can't add marks outside the range + return 0; + } + + int hlg_id = 0; + if (hl_group.size > 0) { + hlg_id = syn_check_group((char_u *)hl_group.data, (int)hl_group.size); + } + + VirtText vt = parse_virt_text(virt_text, err); + if (ERROR_SET(err)) { + return 0; + } + + uint64_t mark_id = extmark_add_decoration(buf, (uint64_t)ns_id, hlg_id, + (int)start_row, (colnr_T)start_col, + (int)end_row, (colnr_T)end_col, vt); + return (Integer)mark_id; +} + Dictionary nvim__buf_stats(Buffer buffer, Error *err) { Dictionary rv = ARRAY_DICT_INIT; @@ -1626,6 +1717,16 @@ Dictionary nvim__buf_stats(Buffer buffer, Error *err) // this exists to debug issues PUT(rv, "dirty_bytes", INTEGER_OBJ((Integer)buf->deleted_bytes)); + u_header_T *uhp = NULL; + if (buf->b_u_curhead != NULL) { + uhp = buf->b_u_curhead; + } else if (buf->b_u_newhead) { + uhp = buf->b_u_newhead; + } + if (uhp) { + PUT(rv, "uhp_extmark_size", INTEGER_OBJ((Integer)kv_size(uhp->uh_extmark))); + } + return rv; } -- cgit From 48a869dc6d29514e943070da9f22f702f5179826 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Mon, 20 Jan 2020 19:29:12 +0100 Subject: shed biking: it's always extmarks, never marks extended --- src/nvim/api/buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/api/buffer.c') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 3106011fe2..a666ed92da 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -26,7 +26,7 @@ #include "nvim/map_defs.h" #include "nvim/map.h" #include "nvim/mark.h" -#include "nvim/mark_extended.h" +#include "nvim/extmark.h" #include "nvim/fileio.h" #include "nvim/move.h" #include "nvim/syntax.h" -- cgit From a26943e9b3e1ca4fe6e25407fd6a96bfd444385f Mon Sep 17 00:00:00 2001 From: Bruno Roy Date: Thu, 13 Feb 2020 23:09:42 -0800 Subject: clang bug: Dead assignment `ns_id` Remove a dead assignment of the `ns_id` variable in the `src/nvim/api/buffer.c` file. Refer: https://neovim.io/doc/reports/clang/report-f279da.html#EndPath --- src/nvim/api/buffer.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/nvim/api/buffer.c') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index a666ed92da..645fb653e5 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -1420,10 +1420,10 @@ Integer nvim_buf_add_highlight(Buffer buffer, end_line++; } - ns_id = extmark_add_decoration(buf, ns_id, hlg_id, - (int)line, (colnr_T)col_start, - end_line, (colnr_T)col_end, - VIRTTEXT_EMPTY); + extmark_add_decoration(buf, ns_id, hlg_id, + (int)line, (colnr_T)col_start, + end_line, (colnr_T)col_end, + VIRTTEXT_EMPTY); return src_id; } -- cgit From 93c6eb4a668b52394667feca86d5e57731828528 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sat, 22 Feb 2020 12:59:39 -0800 Subject: PVS/V618: fix printf-style args #11888 We intentionally do not translate API errors. ref: https://github.com/neovim/neovim/issues/6150 --- src/nvim/api/buffer.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/nvim/api/buffer.c') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 645fb653e5..7578f0fbc5 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -1123,7 +1123,7 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id, } if (!ns_initialized((uint64_t)ns_id)) { - api_set_error(err, kErrorTypeValidation, _("Invalid ns_id")); + api_set_error(err, kErrorTypeValidation, "Invalid ns_id"); return rv; } @@ -1190,7 +1190,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, } if (!ns_initialized((uint64_t)ns_id)) { - api_set_error(err, kErrorTypeValidation, _("Invalid ns_id")); + api_set_error(err, kErrorTypeValidation, "Invalid ns_id"); return rv; } Integer limit = -1; @@ -1280,7 +1280,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer id, } if (!ns_initialized((uint64_t)ns_id)) { - api_set_error(err, kErrorTypeValidation, _("Invalid ns_id")); + api_set_error(err, kErrorTypeValidation, "Invalid ns_id"); return 0; } @@ -1308,7 +1308,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer id, if (id >= 0) { id_num = (uint64_t)id; } else { - api_set_error(err, kErrorTypeValidation, _("Invalid mark id")); + api_set_error(err, kErrorTypeValidation, "Invalid mark id"); return 0; } @@ -1337,7 +1337,7 @@ Boolean nvim_buf_del_extmark(Buffer buffer, return false; } if (!ns_initialized((uint64_t)ns_id)) { - api_set_error(err, kErrorTypeValidation, _("Invalid ns_id")); + api_set_error(err, kErrorTypeValidation, "Invalid ns_id"); return false; } @@ -1655,7 +1655,7 @@ Integer nvim__buf_add_decoration(Buffer buffer, Integer ns_id, String hl_group, } if (!ns_initialized((uint64_t)ns_id)) { - api_set_error(err, kErrorTypeValidation, _("Invalid ns_id")); + api_set_error(err, kErrorTypeValidation, "Invalid ns_id"); return 0; } -- cgit From 69d019f3bdc7aebbda87cecb0d31913bedf6a87c Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sat, 14 Mar 2020 15:01:40 -0400 Subject: pvs/v560: remove redundant line check --- src/nvim/api/buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/api/buffer.c') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 7578f0fbc5..b345dcaccd 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -1402,7 +1402,7 @@ Integer nvim_buf_add_highlight(Buffer buffer, uint64_t ns_id = src2ns(&src_id); - if (!(0 <= line && line < buf->b_ml.ml_line_count)) { + if (!(line < buf->b_ml.ml_line_count)) { // safety check, we can't add marks outside the range return src_id; } -- cgit From 52cd8bf507d44bd5bad3f9c915ef6def7b6623c4 Mon Sep 17 00:00:00 2001 From: Hirokazu Hata Date: Tue, 19 May 2020 14:26:17 +0900 Subject: doc: fix vim.api.nvim_buf_attach callback arguments --- src/nvim/api/buffer.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/nvim/api/buffer.c') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index b345dcaccd..18474c6588 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -126,6 +126,7 @@ String buffer_get_line(Buffer buffer, Integer index, Error *err) /// @param opts Optional parameters. /// - on_lines: Lua callback invoked on change. /// Return `true` to detach. Args: +/// - the string "lines" /// - buffer handle /// - b:changedtick /// - first line that changed (zero-indexed) @@ -136,9 +137,11 @@ String buffer_get_line(Buffer buffer, Integer index, Error *err) /// - deleted_codeunits (if `utf_sizes` is true) /// - on_changedtick: Lua callback invoked on changedtick /// increment without text change. Args: +/// - the string "changedtick" /// - buffer handle /// - b:changedtick /// - on_detach: Lua callback invoked on detach. Args: +/// - the string "detach" /// - buffer handle /// - utf_sizes: include UTF-32 and UTF-16 size of the replaced /// region, as args to `on_lines`. -- cgit From 7b529e7912517af078e005dd7b06b3d042be9cb7 Mon Sep 17 00:00:00 2001 From: TJ DeVries Date: Thu, 2 Jul 2020 07:09:17 -0400 Subject: doc: fix scripts and regenerate (#12506) * Fix some small doc issues * doc: fixup * doc: fixup * Fix lint and rebase * Remove bad advice * Ugh, stupid mpack files... * Don't let people include these for now until they specifically want to * Prevent duplicate tag --- src/nvim/api/buffer.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/nvim/api/buffer.c') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 18474c6588..8e61976c4b 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -42,6 +42,8 @@ /// \defgroup api-buffer /// +/// \brief For more information on buffers, see |buffers| +/// /// Unloaded Buffers:~ /// /// Buffers may be unloaded by the |:bunload| command or the buffer's -- cgit