Merge pull request #27061 from luukvbaal/extmark

fix(extmarks): do not remove invalid marks from decor upon deletion
This commit is contained in:
bfredl
2024-01-19 10:49:13 +01:00
committed by GitHub
6 changed files with 45 additions and 29 deletions

View File

@@ -215,8 +215,8 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id,
return extmark_to_array(extmark, false, details, hl_name);
}
/// Gets |extmarks| (including |signs|) in "traversal order" from a |charwise|
/// region defined by buffer positions (inclusive, 0-indexed |api-indexing|).
/// 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)
@@ -234,6 +234,10 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id,
/// the `overlap` option might be useful. Otherwise only the start position
/// of an extmark will be considered.
///
/// Note: legacy signs placed through the |:sign| commands are implemented
/// as extmarks and will show up here. Their details array will contain a
/// `sign_name` field.
///
/// Example:
///
/// ```lua
@@ -434,7 +438,9 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
/// if text around the mark was deleted and then restored by undo.
/// Defaults to true.
/// - invalidate : boolean that indicates whether to hide the
/// extmark if the entirety of its range is deleted. If
/// extmark if the entirety of its range is deleted. For
/// hidden marks, an "invalid" key is added to the "details"
/// array of |nvim_buf_get_extmarks()| and family. If
/// "undo_restore" is false, the extmark is deleted instead.
/// - priority: a priority value for the highlight group or sign
/// attribute. For example treesitter highlighting uses a

View File

@@ -150,7 +150,11 @@ void extmark_del(buf_T *buf, MarkTreeIter *itr, MTKey key, bool restore)
}
if (mt_decor_any(key)) {
buf_decor_remove(buf, key.pos.row, key2.pos.row, mt_decor(key), true);
if (mt_invalid(key)) {
decor_free(mt_decor(key));
} else {
buf_decor_remove(buf, key.pos.row, key2.pos.row, mt_decor(key), true);
}
}
// TODO(bfredl): delete it from current undo header, opportunistically?
@@ -352,14 +356,12 @@ void extmark_splice_delete(buf_T *buf, int l_row, colnr_T l_col, int u_row, coln
// Push mark to undo header
if (only_copy || (uvp != NULL && op == kExtmarkUndo && !mt_no_undo(mark))) {
ExtmarkSavePos pos;
pos.mark = mt_lookup_key(mark);
pos.invalidated = invalidated;
pos.old_row = mark.pos.row;
pos.old_col = mark.pos.col;
pos.row = -1;
pos.col = -1;
ExtmarkSavePos pos = {
.mark = mt_lookup_key(mark),
.invalidated = invalidated,
.old_row = mark.pos.row,
.old_col = mark.pos.col
};
undo.data.savepos = pos;
undo.type = kExtmarkSavePos;
kv_push(*uvp, undo);
@@ -393,22 +395,17 @@ void extmark_apply_undo(ExtmarkUndoObject undo_info, bool undo)
} else if (undo_info.type == kExtmarkSavePos) {
ExtmarkSavePos pos = undo_info.data.savepos;
if (undo) {
if (pos.old_row >= 0) {
extmark_setraw(curbuf, pos.mark, pos.old_row, pos.old_col);
}
if (pos.invalidated) {
if (pos.old_row >= 0
&& extmark_setraw(curbuf, pos.mark, pos.old_row, pos.old_col)
&& pos.invalidated) {
MarkTreeIter itr[1] = { 0 };
MTKey mark = marktree_lookup(curbuf->b_marktree, pos.mark, itr);
mt_itr_rawkey(itr).flags &= (uint16_t) ~MT_FLAG_INVALID;
MTPos end = marktree_get_altpos(curbuf->b_marktree, mark, itr);
buf_put_decor(curbuf, mt_decor(mark), mark.pos.row, end.row);
}
// Redo
} else {
if (pos.row >= 0) {
extmark_setraw(curbuf, pos.mark, pos.row, pos.col);
}
}
// No Redo since kExtmarkSplice will move marks back
} else if (undo_info.type == kExtmarkMove) {
ExtmarkMove move = undo_info.data.move;
if (undo) {

View File

@@ -45,8 +45,6 @@ typedef struct {
uint64_t mark; // raw mark id of the marktree
int old_row;
colnr_T old_col;
int row;
colnr_T col;
bool invalidated;
} ExtmarkSavePos;