Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extmarks api: allow for gravity #13679

Merged
merged 4 commits into from Jan 22, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
40 changes: 37 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,9 @@ 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;

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,6 +1532,20 @@ 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;
} else {
api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data);
goto error;
Expand All @@ -1546,6 +1570,14 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
col2 = 0;
}

// Only error out if they try to set end_right_gravity to true without
// setting end_col or end_line
if (line2 == 0 && col2 == 0 && end_right_gravity) {
chentoast marked this conversation as resolved.
Show resolved Hide resolved
api_set_error(err, kErrorTypeValidation,
"cannot set end_right_gravity to true "
chentoast marked this conversation as resolved.
Show resolved Hide resolved
"without setting end_line and end_col");
}

// TODO(bfredl): synergize these two branches even more
if (ephemeral && decor_state.buf == buf) {
int attr_id = hl_id > 0 ? syn_id2attr(hl_id) : 0;
Expand All @@ -1572,7 +1604,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 +1720,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 +1829,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