Browse Source

Merge #11376 'extmark: renames, docs'

tags/nightly
Justin M. Keyes 3 weeks ago
parent
commit
db436d5277
No account linked to committer's email address
8 changed files with 79 additions and 85 deletions
  1. +25
    -24
      runtime/doc/api.txt
  2. +3
    -5
      src/nvim/api/buffer.c
  3. +4
    -8
      src/nvim/api/private/helpers.c
  4. +1
    -1
      src/nvim/buffer_defs.h
  5. +2
    -2
      src/nvim/ex_cmds.c
  6. +24
    -25
      src/nvim/mark_extended.c
  7. +11
    -11
      src/nvim/mark_extended.h
  8. +9
    -9
      src/nvim/mark_extended_defs.h

+ 25
- 24
runtime/doc/api.txt View File

@@ -441,38 +441,39 @@ Example: create a float with scratch buffer: >
==============================================================================
Extended marks *api-extended-marks*

An extended mark (extmark) represents a buffer annotation that follows
movements as the buffer changes. They could be used to represent cursors,
folds, misspelled words, and anything else that needs to track a logical
location in the buffer over time.
Extended marks (extmarks) represent buffer annotations that track text changes
in the buffer. They could be used to represent cursors, folds, misspelled
words, and anything else that needs to track a logical location in the buffer
over time.

Example:

We will set an extmark at the first row and third column. As the API is zero-
indexed, use row and column counts 0 and 2:
We will set an extmark at the first row and third column. |api-indexing| is
zero-indexed, so we use row=0 and column=2. Passing id=0 creates a new mark
and returns the id: >

`let g:mark_ns = nvim_create_namespace('myplugin')`
`let g:mark_id = nvim_buf_set_extmark(0, g:mark_ns, 0, 0, 2)`
let g:mark_ns = nvim_create_namespace('myplugin')
let g:mark_id = nvim_buf_set_extmark(0, g:mark_ns, 0, 0, 2, {})

Passing in id=0 creates a new mark and returns the id. we can look-up a mark
by its id:
We can get a mark by its id: >

`echo nvim_buf_get_extmark_by_id(0, g:mark_ns, g:mark_id)`
=> [0, 2]
echo nvim_buf_get_extmark_by_id(0, g:mark_ns, g:mark_id)
=> [0, 2]

Or we can look-up all marks in a buffer for our namespace (or by a range):
`echo nvim_buf_get_extmarks(0, g:mark_ns, 0, -1, -1)`
=> [[1, 0, 2]]
We can get all marks in a buffer for our namespace (or by a range): >

Deleting the text all around an extended mark does not remove it. If you want
to remove an extended mark, use the |nvim_buf_del_extmark()| function.
echo nvim_buf_get_extmarks(0, g:mark_ns, 0, -1, -1)
=> [[1, 0, 2]]

The namespace ensures your plugin doesn't have to deal with extmarks created
by another plugin.
Deleting all text surrounding an extmark does not remove the extmark. To
remove an extmark use |nvim_buf_del_extmark()|.

Mark positions changed by an edit will be restored on undo/redo. Creating and
deleting marks doesn't count as a buffer change on itself, i e new undo
states will not be created only for marks.
Namespaces allow your plugin to manage only its own extmarks, ignoring those
created by another plugin.

Extmark positions changed by an edit will be restored on undo/redo. Creating
and deleting extmarks is not a buffer change, thus new undo states are not
created for extmark changes.

==============================================================================
Global Functions *api-global*
@@ -1820,10 +1821,10 @@ nvim_buf_get_extmarks({buffer}, {ns_id}, {start}, {end}, {opts})
{upper} One of: extmark id, (row, col) or 0, -1 for
buffer ends
{opts} additional options. Supports the keys:
• amount: Maximum number of marks to return
• amount: Maximum number of marks to return

Return: ~
[[nsmark_id, row, col], ...]
[[extmark_id, row, col], ...]

*nvim_buf_set_extmark()*
nvim_buf_set_extmark({buffer}, {ns_id}, {id}, {line}, {col}, {opts})

+ 3
- 5
src/nvim/api/buffer.c View File

@@ -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;
}
@@ -1058,7 +1056,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)
@@ -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));

+ 4
- 8
src/nvim/api/private/helpers.c View File

@@ -1512,11 +1512,8 @@ ArrayOf(Dictionary) keymap_array(String mode, buf_T *buf)
// If throw == true then an error will be raised if nothing
// was found
// Returns NULL if something went wrong
ExtendedMark *extmark_from_id_or_pos(Buffer buffer,
Integer namespace,
Object id,
Error *err,
bool throw)
Extmark *extmark_from_id_or_pos(Buffer buffer, Integer namespace, Object id,
Error *err, bool throw)
{
buf_T *buf = find_buffer_by_handle(buffer, err);

@@ -1524,7 +1521,7 @@ ExtendedMark *extmark_from_id_or_pos(Buffer buffer,
return NULL;
}

ExtendedMark *extmark = NULL;
Extmark *extmark = NULL;
if (id.type == kObjectTypeArray) {
if (id.data.array.size != 2) {
api_set_error(err, kErrorTypeValidation,
@@ -1603,8 +1600,7 @@ bool set_extmark_index_from_obj(buf_T *buf, Integer namespace,
return false;
}

ExtendedMark *extmark = extmark_from_id(buf, (uint64_t)namespace,
(uint64_t)id);
Extmark *extmark = extmark_from_id(buf, (uint64_t)namespace, (uint64_t)id);
if (extmark) {
*lnum = extmark->line->lnum;
*colnr = extmark->col;

+ 1
- 1
src/nvim/buffer_defs.h View File

@@ -810,7 +810,7 @@ struct file_buffer {

PMap(uint64_t) *b_extmark_ns; // extmark namespaces
kbtree_t(extmarklines) b_extlines; // extmarks
kvec_t(ExtMarkLine *) b_extmark_move_space; // temp space for extmarks
kvec_t(ExtmarkLine *) b_extmark_move_space; // temp space for extmarks

// array of channel_id:s which have asked to receive updates for this
// buffer.

+ 2
- 2
src/nvim/ex_cmds.c View File

@@ -3457,9 +3457,9 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout,
linenr_T newline_in_pat = 0;
linenr_T newline_in_sub = 0;

// inccomand tests fail without this check
// inccommand tests fail without this check
if (!preview) {
// Requried for Undo to work for nsmarks,
// Required for Undo to work for extmarks.
u_save_cursor();
}


+ 24
- 25
src/nvim/mark_extended.c View File

@@ -53,12 +53,12 @@
int extmark_set(buf_T *buf, uint64_t ns, uint64_t id,
linenr_T lnum, colnr_T col, ExtmarkOp op)
{
ExtendedMark *extmark = extmark_from_id(buf, ns, id);
Extmark *extmark = extmark_from_id(buf, ns, id);
if (!extmark) {
extmark_create(buf, ns, id, lnum, col, op);
return true;
} else {
ExtMarkLine *extmarkline = extmark->line;
ExtmarkLine *extmarkline = extmark->line;
extmark_update(extmark, buf, ns, id, lnum, col, op, NULL);
if (kb_size(&extmarkline->items) == 0) {
kb_del(extmarklines, &buf->b_extlines, extmarkline);
@@ -72,7 +72,7 @@ int extmark_set(buf_T *buf, uint64_t ns, uint64_t id,
// Returns 0 on missing id
int extmark_del(buf_T *buf, uint64_t ns, uint64_t id, ExtmarkOp op)
{
ExtendedMark *extmark = extmark_from_id(buf, ns, id);
Extmark *extmark = extmark_from_id(buf, ns, id);
if (!extmark) {
return 0;
}
@@ -180,7 +180,7 @@ static void extmark_create(buf_T *buf, uint64_t ns, uint64_t id,
}

// Create or get a line
ExtMarkLine *extmarkline = extmarkline_ref(buf, lnum, true);
ExtmarkLine *extmarkline = extmarkline_ref(buf, lnum, true);
// Create and put mark on the line
extmark_put(col, id, extmarkline, ns);

@@ -197,7 +197,7 @@ static void extmark_create(buf_T *buf, uint64_t ns, uint64_t id,

// update the position of an extmark
// to update while iterating pass the markitems itr
static void extmark_update(ExtendedMark *extmark, buf_T *buf,
static void extmark_update(Extmark *extmark, buf_T *buf,
uint64_t ns, uint64_t id,
linenr_T lnum, colnr_T col,
ExtmarkOp op, kbitr_t(markitems) *mitr)
@@ -207,10 +207,10 @@ static void extmark_update(ExtendedMark *extmark, buf_T *buf,
u_extmark_update(buf, ns, id, extmark->line->lnum, extmark->col,
lnum, col);
}
ExtMarkLine *old_line = extmark->line;
ExtmarkLine *old_line = extmark->line;
// Move the mark to a new line and update column
if (old_line->lnum != lnum) {
ExtMarkLine *ref_line = extmarkline_ref(buf, lnum, true);
ExtmarkLine *ref_line = extmarkline_ref(buf, lnum, true);
extmark_put(col, id, ref_line, ns);
// Update the hashmap
ExtmarkNs *ns_obj = pmap_get(uint64_t)(buf->b_extmark_ns, ns);
@@ -234,7 +234,7 @@ static void extmark_update(ExtendedMark *extmark, buf_T *buf,
}
}

static int extmark_delete(ExtendedMark *extmark,
static int extmark_delete(Extmark *extmark,
buf_T *buf,
uint64_t ns,
uint64_t id,
@@ -250,7 +250,7 @@ static int extmark_delete(ExtendedMark *extmark,
pmap_del(uint64_t)(ns_obj->map, id);

// Remove the mark mark from the line
ExtMarkLine *extmarkline = extmark->line;
ExtmarkLine *extmarkline = extmark->line;
kb_del(markitems, &extmarkline->items, *extmark);
// Remove the line if there are no more marks in the line
if (kb_size(&extmarkline->items) == 0) {
@@ -261,7 +261,7 @@ static int extmark_delete(ExtendedMark *extmark,
}

// Lookup an extmark by id
ExtendedMark *extmark_from_id(buf_T *buf, uint64_t ns, uint64_t id)
Extmark *extmark_from_id(buf_T *buf, uint64_t ns, uint64_t id)
{
if (!buf->b_extmark_ns) {
return NULL;
@@ -270,7 +270,7 @@ ExtendedMark *extmark_from_id(buf_T *buf, uint64_t ns, uint64_t id)
if (!ns_obj || !kh_size(ns_obj->map->table)) {
return NULL;
}
ExtMarkLine *extmarkline = pmap_get(uint64_t)(ns_obj->map, id);
ExtmarkLine *extmarkline = pmap_get(uint64_t)(ns_obj->map, id);
if (!extmarkline) {
return NULL;
}
@@ -285,8 +285,7 @@ ExtendedMark *extmark_from_id(buf_T *buf, uint64_t ns, uint64_t id)
}

// Lookup an extmark by position
ExtendedMark *extmark_from_pos(buf_T *buf,
uint64_t ns, linenr_T lnum, colnr_T col)
Extmark *extmark_from_pos(buf_T *buf, uint64_t ns, linenr_T lnum, colnr_T col)
{
if (!buf->b_extmark_ns) {
return NULL;
@@ -842,7 +841,7 @@ static bool extmark_col_adjust_impl(buf_T *buf, linenr_T lnum,
{
bool marks_exist = false;

ExtMarkLine *extmarkline = extmarkline_ref(buf, lnum, false);
ExtmarkLine *extmarkline = extmarkline_ref(buf, lnum, false);
if (!extmarkline) {
return false;
}
@@ -968,7 +967,7 @@ void extmark_adjust(buf_T *buf,
ExtmarkOp undo,
bool end_temp)
{
ExtMarkLine *_extline;
ExtmarkLine *_extline;

// btree needs to be kept ordered to work, so far only :move requires this
// 2nd call with end_temp = true unpack the lines from the temp position
@@ -990,7 +989,7 @@ void extmark_adjust(buf_T *buf,
// Careful! marks from deleted region can end up on en extisting extmarkline
// that is goinig to be adjusted to the target position.
linenr_T join_num = line1 - amount_after;
ExtMarkLine *joinline = (join_num > line2
ExtmarkLine *joinline = (join_num > line2
? extmarkline_ref(buf, join_num, false) : NULL);

// extmark_adjust is already redoable, the copy should only be for undo
@@ -1031,7 +1030,7 @@ bool extmark_copy_and_place(buf_T *buf,
linenr_T u_lnum, colnr_T u_col,
linenr_T p_lnum, colnr_T p_col,
ExtmarkOp undo, bool delete,
ExtMarkLine *destline)
ExtmarkLine *destline)

{
bool marks_moved = false;
@@ -1045,7 +1044,7 @@ bool extmark_copy_and_place(buf_T *buf,
// marks within the same extmarkline. Too keep it simple, first delete all
// items from the extmarkline and put them back in the right order.
FOR_ALL_EXTMARKLINES(buf, l_lnum, u_lnum, {
kvec_t(ExtendedMark) temp_space = KV_INITIAL_VALUE;
kvec_t(Extmark) temp_space = KV_INITIAL_VALUE;
bool same_line = extmarkline == destline;
FOR_ALL_EXTMARKS_IN_LINE(extmarkline->items,
(extmarkline->lnum > l_lnum) ? 0 : l_col,
@@ -1068,7 +1067,7 @@ bool extmark_copy_and_place(buf_T *buf,
})
if (same_line) {
for (size_t i = 0; i < kv_size(temp_space); i++) {
ExtendedMark mark = kv_A(temp_space, i);
Extmark mark = kv_A(temp_space, i);
extmark_put(p_col, mark.mark_id, extmarkline, mark.ns_id);
}
kv_destroy(temp_space);
@@ -1087,10 +1086,10 @@ bool extmark_copy_and_place(buf_T *buf,
}

// Get reference to line in kbtree_t, allocating it if neccessary.
ExtMarkLine *extmarkline_ref(buf_T *buf, linenr_T lnum, bool put)
ExtmarkLine *extmarkline_ref(buf_T *buf, linenr_T lnum, bool put)
{
kbtree_t(extmarklines) *b = &buf->b_extlines;
ExtMarkLine t, **pp;
ExtmarkLine t, **pp;
t.lnum = lnum;

pp = kb_get(extmarklines, b, &t);
@@ -1098,7 +1097,7 @@ ExtMarkLine *extmarkline_ref(buf_T *buf, linenr_T lnum, bool put)
if (!put) {
return NULL;
}
ExtMarkLine *p = xcalloc(sizeof(ExtMarkLine), 1);
ExtmarkLine *p = xcalloc(sizeof(ExtmarkLine), 1);
p->lnum = lnum;
// p->items zero initialized
kb_put(extmarklines, b, p);
@@ -1108,7 +1107,7 @@ ExtMarkLine *extmarkline_ref(buf_T *buf, linenr_T lnum, bool put)
return *pp;
}

void extmarkline_free(ExtMarkLine *extmarkline)
void extmarkline_free(ExtmarkLine *extmarkline)
{
kb_destroy(markitems, (&extmarkline->items));
xfree(extmarkline);
@@ -1118,9 +1117,9 @@ void extmarkline_free(ExtMarkLine *extmarkline)
///
/// caller must ensure combination of id and ns_id isn't in use.
void extmark_put(colnr_T col, uint64_t id,
ExtMarkLine *extmarkline, uint64_t ns)
ExtmarkLine *extmarkline, uint64_t ns)
{
ExtendedMark t;
Extmark t;
t.col = col;
t.mark_id = id;
t.line = extmarkline;

+ 11
- 11
src/nvim/mark_extended.h View File

@@ -15,12 +15,12 @@
// see FOR_ALL_? for documentation
#define FOR_ALL_EXTMARKLINES(buf, l_lnum, u_lnum, code)\
kbitr_t(extmarklines) itr;\
ExtMarkLine t;\
ExtmarkLine t;\
t.lnum = l_lnum;\
if (!kb_itr_get(extmarklines, &buf->b_extlines, &t, &itr)) { \
kb_itr_next(extmarklines, &buf->b_extlines, &itr);\
}\
ExtMarkLine *extmarkline;\
ExtmarkLine *extmarkline;\
for (; kb_itr_valid(&itr); kb_itr_next(extmarklines, \
&buf->b_extlines, &itr)) { \
extmarkline = kb_itr_key(&itr);\
@@ -33,12 +33,12 @@
// see FOR_ALL_? for documentation
#define FOR_ALL_EXTMARKLINES_PREV(buf, l_lnum, u_lnum, code)\
kbitr_t(extmarklines) itr;\
ExtMarkLine t;\
ExtmarkLine t;\
t.lnum = u_lnum;\
if (!kb_itr_get(extmarklines, &buf->b_extlines, &t, &itr)) { \
kb_itr_prev(extmarklines, &buf->b_extlines, &itr);\
}\
ExtMarkLine *extmarkline;\
ExtmarkLine *extmarkline;\
for (; kb_itr_valid(&itr); kb_itr_prev(extmarklines, \
&buf->b_extlines, &itr)) { \
extmarkline = kb_itr_key(&itr);\
@@ -51,7 +51,7 @@
// see FOR_ALL_? for documentation
#define FOR_ALL_EXTMARKS(buf, ns, l_lnum, l_col, u_lnum, u_col, code)\
kbitr_t(markitems) mitr;\
ExtendedMark mt;\
Extmark mt;\
mt.ns_id = ns;\
mt.mark_id = 0;\
mt.line = NULL;\
@@ -60,7 +60,7 @@
if (!kb_itr_get(markitems, &extmarkline->items, mt, &mitr)) { \
kb_itr_next(markitems, &extmarkline->items, &mitr);\
} \
ExtendedMark *extmark;\
Extmark *extmark;\
for (; \
kb_itr_valid(&mitr); \
kb_itr_next(markitems, &extmarkline->items, &mitr)) { \
@@ -77,7 +77,7 @@
// see FOR_ALL_? for documentation
#define FOR_ALL_EXTMARKS_PREV(buf, ns, l_lnum, l_col, u_lnum, u_col, code)\
kbitr_t(markitems) mitr;\
ExtendedMark mt;\
Extmark mt;\
mt.mark_id = sizeof(uint64_t);\
mt.ns_id = ns;\
FOR_ALL_EXTMARKLINES_PREV(buf, l_lnum, u_lnum, { \
@@ -85,7 +85,7 @@
if (!kb_itr_get(markitems, &extmarkline->items, mt, &mitr)) { \
kb_itr_prev(markitems, &extmarkline->items, &mitr);\
} \
ExtendedMark *extmark;\
Extmark *extmark;\
for (; \
kb_itr_valid(&mitr); \
kb_itr_prev(markitems, &extmarkline->items, &mitr)) { \
@@ -101,7 +101,7 @@

#define FOR_ALL_EXTMARKS_IN_LINE(items, l_col, u_col, code)\
kbitr_t(markitems) mitr;\
ExtendedMark mt;\
Extmark mt;\
mt.ns_id = 0;\
mt.mark_id = 0;\
mt.line = NULL;\
@@ -110,7 +110,7 @@
if (!kb_itr_get(markitems, &items, mt, &mitr)) { \
kb_itr_next(markitems, &items, &mitr);\
} \
ExtendedMark *extmark;\
Extmark *extmark;\
for (; kb_itr_valid(&mitr); kb_itr_next(markitems, &items, &mitr)) { \
extmark = &kb_itr_key(&mitr);\
if (extmark->col > extmarkline_u_col) { \
@@ -126,7 +126,7 @@ typedef struct ExtmarkNs { // For namespacing extmarks
} ExtmarkNs;


typedef kvec_t(ExtendedMark *) ExtmarkArray;
typedef kvec_t(Extmark *) ExtmarkArray;


// Undo/redo extmarks

+ 9
- 9
src/nvim/mark_extended_defs.h View File

@@ -6,21 +6,21 @@
#include "nvim/lib/kbtree.h"
#include "nvim/lib/kvec.h"

struct ExtMarkLine;
struct ExtmarkLine;

typedef struct ExtendedMark
typedef struct Extmark
{
uint64_t ns_id;
uint64_t mark_id;
struct ExtMarkLine *line;
struct ExtmarkLine *line;
colnr_T col;
} ExtendedMark;
} Extmark;


// We only need to compare columns as rows are stored in a different tree.
// Marks are ordered by: position, namespace, mark_id
// This improves moving marks but slows down all other use cases (searches)
static inline int extmark_cmp(ExtendedMark a, ExtendedMark b)
static inline int extmark_cmp(Extmark a, Extmark b)
{
int cmp = kb_generic_cmp(a.col, b.col);
if (cmp != 0) {
@@ -35,16 +35,16 @@ static inline int extmark_cmp(ExtendedMark a, ExtendedMark b)


#define markitems_cmp(a, b) (extmark_cmp((a), (b)))
KBTREE_INIT(markitems, ExtendedMark, markitems_cmp, 10)
KBTREE_INIT(markitems, Extmark, markitems_cmp, 10)

typedef struct ExtMarkLine
typedef struct ExtmarkLine
{
linenr_T lnum;
kbtree_t(markitems) items;
} ExtMarkLine;
} ExtmarkLine;

#define EXTMARKLINE_CMP(a, b) (kb_generic_cmp((a)->lnum, (b)->lnum))
KBTREE_INIT(extmarklines, ExtMarkLine *, EXTMARKLINE_CMP, 10)
KBTREE_INIT(extmarklines, ExtmarkLine *, EXTMARKLINE_CMP, 10)


typedef struct undo_object ExtmarkUndoObject;

Loading…
Cancel
Save