Skip to content

Commit

Permalink
Merge pull request #13679 from chentau/gravity
Browse files Browse the repository at this point in the history
Extmarks api: allow for gravity
  • Loading branch information
bfredl committed Jan 22, 2021
2 parents 1607dd0 + 2ac0ca2 commit b803bfa
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 8 deletions.
42 changes: 39 additions & 3 deletions src/nvim/api/buffer.c
Expand Up @@ -1400,6 +1400,13 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id,
/// 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.
/// @param[out] err Error details, if any
/// @return Id of the created/updated extmark
Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
Expand Down Expand Up @@ -1440,6 +1447,10 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
DecorPriority priority = DECOR_PRIORITY_BASE;
colnr_T col2 = 0;
VirtText virt_text = KV_INITIAL_VALUE;
bool right_gravity = true;
bool end_right_gravity = false;
bool end_gravity_set = false;

for (size_t i = 0; i < opts.size; i++) {
String k = opts.items[i].key;
Object *v = &opts.items[i].value;
Expand Down Expand Up @@ -1522,12 +1533,35 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
goto error;
}
priority = (DecorPriority)v->data.integer;
} else if (strequal("right_gravity", k.data)) {
if (v->type != kObjectTypeBoolean) {
api_set_error(err, kErrorTypeValidation,
"right_gravity must be a boolean");
goto error;
}
right_gravity = v->data.boolean;
} else if (strequal("end_right_gravity", k.data)) {
if (v->type != kObjectTypeBoolean) {
api_set_error(err, kErrorTypeValidation,
"end_right_gravity must be a boolean");
goto error;
}
end_right_gravity = v->data.boolean;
end_gravity_set = true;
} else {
api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data);
goto error;
}
}

// Only error out if they try to set end_right_gravity without
// setting end_col or end_line
if (line2 == -1 && col2 == 0 && end_gravity_set) {
api_set_error(err, kErrorTypeValidation,
"cannot set end_right_gravity "
"without setting end_line or end_col");
}

if (col2 >= 0) {
if (line2 >= 0 && line2 < buf->b_ml.ml_line_count) {
len = STRLEN(ml_get_buf(buf, (linenr_T)line2 + 1, false));
Expand Down Expand Up @@ -1572,7 +1606,8 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
}

id = extmark_set(buf, (uint64_t)ns_id, id, (int)line, (colnr_T)col,
line2, col2, decor, kExtmarkNoUndo);
line2, col2, decor, right_gravity,
end_right_gravity, kExtmarkNoUndo);
}

return (Integer)id;
Expand Down Expand Up @@ -1687,7 +1722,7 @@ Integer nvim_buf_add_highlight(Buffer buffer,
extmark_set(buf, ns_id, 0,
(int)line, (colnr_T)col_start,
end_line, (colnr_T)col_end,
decor_hl(hl_id), kExtmarkNoUndo);
decor_hl(hl_id), true, false, kExtmarkNoUndo);
return src_id;
}

Expand Down Expand Up @@ -1796,7 +1831,8 @@ Integer nvim_buf_set_virtual_text(Buffer buffer,
Decoration *decor = xcalloc(1, sizeof(*decor));
decor->virt_text = virt_text;

extmark_set(buf, ns_id, 0, (int)line, 0, -1, -1, decor, kExtmarkNoUndo);
extmark_set(buf, ns_id, 0, (int)line, 0, -1, -1, decor, true,
false, kExtmarkNoUndo);
return src_id;
}

Expand Down
2 changes: 1 addition & 1 deletion src/nvim/decoration.c
Expand Up @@ -69,7 +69,7 @@ void bufhl_add_hl_pos_offset(buf_T *buf,
}
(void)extmark_set(buf, (uint64_t)src_id, 0,
(int)lnum-1, hl_start, (int)lnum-1+end_off, hl_end,
decor, kExtmarkNoUndo);
decor, true, false, kExtmarkNoUndo);
}
}

Expand Down
9 changes: 5 additions & 4 deletions src/nvim/extmark.c
Expand Up @@ -71,7 +71,8 @@ static ExtmarkNs *buf_ns_ref(buf_T *buf, uint64_t ns_id, bool put) {
/// @returns the mark id
uint64_t extmark_set(buf_T *buf, uint64_t ns_id, uint64_t id,
int row, colnr_T col, int end_row, colnr_T end_col,
Decoration *decor, ExtmarkOp op)
Decoration *decor, bool right_gravity,
bool end_right_gravity, ExtmarkOp op)
{
ExtmarkNs *ns = buf_ns_ref(buf, ns_id, true);
assert(ns != NULL);
Expand Down Expand Up @@ -109,10 +110,10 @@ uint64_t extmark_set(buf_T *buf, uint64_t ns_id, uint64_t id,

if (end_row > -1) {
mark = marktree_put_pair(buf->b_marktree,
row, col, true,
end_row, end_col, false);
row, col, right_gravity,
end_row, end_col, end_right_gravity);
} else {
mark = marktree_put(buf->b_marktree, row, col, true);
mark = marktree_put(buf->b_marktree, row, col, right_gravity);
}

revised:
Expand Down
34 changes: 34 additions & 0 deletions test/functional/api/extmark_spec.lua
Expand Up @@ -1389,6 +1389,40 @@ describe('API/extmarks', function()
undo]],false)
eq(2, meths.eval('1+1')) -- did not crash
end)

it('works with left and right gravity', function()
-- right gravity should move with inserted text, while
-- left gravity should stay in place.
curbufmeths.set_extmark(ns, 0, 5, {right_gravity = false})
curbufmeths.set_extmark(ns, 0, 5, {right_gravity = true})
feed([[Aasdfasdf]])

eq({ {1, 0, 5}, {2, 0, 13} },
curbufmeths.get_extmarks(ns, 0, -1, {}))

-- but both move when text is inserted before
feed([[<esc>Iasdf<esc>]])
-- eq({}, curbufmeths.get_lines(0, -1, true))
eq({ {1, 0, 9}, {2, 0, 17} },
curbufmeths.get_extmarks(ns, 0, -1, {}))

-- clear text
curbufmeths.set_text(0, 0, 0, 17, {})

-- handles set_text correctly as well
eq({ {1, 0, 0}, {2, 0, 0} },
meths.buf_get_extmarks(0, ns, 0, -1, {}))
curbufmeths.set_text(0, 0, 0, 0, {'asdfasdf'})
eq({ {1, 0, 0}, {2, 0, 8} },
curbufmeths.get_extmarks(ns, 0, -1, {}))

feed('u')
-- handles pasting
meths.exec([[let @a='asdfasdf']], false)
feed([["ap]])
eq({ {1, 0, 0}, {2, 0, 8} },
meths.buf_get_extmarks(0, ns, 0, -1, {}))
end)
end)

describe('Extmarks buffer api with many marks', function()
Expand Down

0 comments on commit b803bfa

Please sign in to comment.