bufhl: use extmark column adjustment for bufhl

NB: this is not the final implementation. Bufhl should be made a
part of the extmark tree, so that "start" adjustment just works
automatically. But "stop" will still need some ad-hoc trickery,
until extended marks natively support ranges (hopefully sooner than
forever).
This commit is contained in:
Björn Linse 2018-06-29 13:35:42 +02:00
parent d5f14b8372
commit bdebe8516c
4 changed files with 241 additions and 1 deletions

View File

@ -5626,6 +5626,86 @@ void bufhl_mark_adjust(buf_T* buf,
}
}
/// Adjust a placed highlight for column changes and joined/broken lines
bool bufhl_mark_col_adjust(buf_T *buf,
linenr_T lnum,
colnr_T mincol,
long lnum_amount,
long col_amount)
{
bool moved = false;
BufhlLine *lineinfo = bufhl_tree_ref(&buf->b_bufhl_info, lnum, false);
if (!lineinfo) {
// Old line empty, nothing to do
return false;
}
// Create the new line below only if needed
BufhlLine *lineinfo2 = NULL;
colnr_T delcol = MAXCOL;
if (lnum_amount == 0 && col_amount < 0) {
delcol = mincol+(int)col_amount;
}
size_t newidx = 0;
for (size_t i = 0; i < kv_size(lineinfo->items); i++) {
BufhlItem *item = &kv_A(lineinfo->items, i);
bool delete = false;
if (item->start >= mincol) {
moved = true;
item->start += (int)col_amount;
if (item->stop < MAXCOL) {
item->stop += (int)col_amount;
}
if (lnum_amount != 0) {
if (lineinfo2 == NULL) {
lineinfo2 = bufhl_tree_ref(&buf->b_bufhl_info,
lnum+lnum_amount, true);
}
kv_push(lineinfo2->items, *item);
delete = true;
}
} else {
if (item->start >= delcol) {
moved = true;
item->start = delcol;
}
if (item->stop == MAXCOL || item->stop+1 >= mincol) {
if (item->stop == MAXCOL) {
if (delcol < MAXCOL
&& delcol > (colnr_T)STRLEN(ml_get_buf(buf, lnum, false))) {
delete = true;
}
} else {
moved = true;
item->stop += (int)col_amount;
}
assert(lnum_amount >= 0);
if (lnum_amount > 0) {
item->stop = MAXCOL;
}
} else if (item->stop+1 >= delcol) {
moved = true;
item->stop = delcol-1;
}
// we covered the entire range with a visual delete or something
if (item->stop < item->start) {
delete = true;
}
}
if (!delete) {
if (i != newidx) {
kv_A(lineinfo->items, newidx) = kv_A(lineinfo->items, i);
}
newidx++;
}
}
kv_size(lineinfo->items) = newidx;
return moved;
}
/// Get highlights to display at a specific line
///

View File

@ -5599,9 +5599,10 @@ insertchar (
do_digraph(-1); /* clear digraphs */
do_digraph(buf[i-1]); /* may be the start of a digraph */
buf[i] = NUL;
colnr_T col_start = curwin->w_cursor.col;
ins_str(buf);
extmark_col_adjust(curbuf, curwin->w_cursor.lnum,
(colnr_T)(curwin->w_cursor.col + 1), 0,
(colnr_T)(col_start + 1), 0,
(long)STRLEN(buf), kExtmarkUndo);
if (flags & INSCHAR_CTRLV) {
redo_literal(*buf);

View File

@ -910,6 +910,9 @@ void extmark_col_adjust(buf_T *buf, linenr_T lnum,
bool marks_moved = extmark_col_adjust_impl(buf, lnum, mincol, lnum_amount,
false, col_amount);
marks_moved |= bufhl_mark_col_adjust(buf, lnum, mincol,
lnum_amount, col_amount);
if (undo == kExtmarkUndo && marks_moved) {
u_extmark_col_adjust(buf, lnum, mincol, lnum_amount, col_amount);
}
@ -938,6 +941,7 @@ void extmark_col_adjust_delete(buf_T *buf, linenr_T lnum,
marks_moved = extmark_col_adjust_impl(buf, lnum, mincol, 0,
true, (long)endcol);
marks_moved |= bufhl_mark_col_adjust(buf, lnum, endcol, 0, mincol-(endcol+1));
// Deletes at the end of the line have different behaviour than the normal
// case when deleted.
// Cleanup any marks that are floating beyond the end of line.

View File

@ -217,6 +217,161 @@ describe('Buffer highlighting', function()
|
]])
end)
it('and adjusting columns', function()
-- insert before
feed('ggiquite <esc>')
screen:expect{grid=[[
quite^ a {5:longer} example |
in {6:order} to {7:de}{5:monstr}{7:ate} |
{7:combin}{8:ing}{9: hi}ghlights |
{9:from }{8:diff}{7:erent} sources |
{1:~ }|
{1:~ }|
{1:~ }|
|
]]}
feed('u')
screen:expect{grid=[[
^a {5:longer} example |
in {6:order} to {7:de}{5:monstr}{7:ate} |
{7:combin}{8:ing}{9: hi}ghlights |
{9:from }{8:diff}{7:erent} sources |
{1:~ }|
{1:~ }|
{1:~ }|
1 change; before #2 0 seconds ago |
]]}
-- change/insert in the middle
feed('+fesAAAA')
screen:expect{grid=[[
a {5:longer} example |
in {6:ordAAAA^r} to {7:de}{5:monstr}{7:ate} |
{7:combin}{8:ing}{9: hi}ghlights |
{9:from }{8:diff}{7:erent} sources |
{1:~ }|
{1:~ }|
{1:~ }|
{7:-- INSERT --} |
]]}
feed('<esc>tdD')
screen:expect{grid=[[
a {5:longer} example |
in {6:ordAAAAr} t^o |
{7:combin}{8:ing}{9: hi}ghlights |
{9:from }{8:diff}{7:erent} sources |
{1:~ }|
{1:~ }|
{1:~ }|
|
]]}
feed('u')
screen:expect{grid=[[
a {5:longer} example |
in {6:ordAAAAr} to^ demonstrate |
{7:combin}{8:ing}{9: hi}ghlights |
{9:from }{8:diff}{7:erent} sources |
{1:~ }|
{1:~ }|
{1:~ }|
1 change; before #4 0 seconds ago |
]]}
feed('u')
screen:expect{grid=[[
a {5:longer} example |
in {6:ord^er} to demonstrate |
{7:combin}{8:ing}{9: hi}ghlights |
{9:from }{8:diff}{7:erent} sources |
{1:~ }|
{1:~ }|
{1:~ }|
1 change; before #3 0 seconds ago |
]]}
end)
it('and joining lines', function()
feed('ggJJJ')
screen:expect{grid=[[
a {5:longer} example in {6:order} to {7:de}{5:monstr}{7:ate}|
{7: combin}{8:ing hi}{7:ghlights^ }{8:from diff}{7:erent sou}|
{7:rces} |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
|
]]}
-- TODO(bfredl): perhaps better undo
feed('uuu')
screen:expect{grid=[[
^a longer example |
in order to demonstrate |
combining highlights |
from different sources |
{1:~ }|
{1:~ }|
{1:~ }|
1 more line; before #2 0 seconds ago |
]]}
end)
it('and splitting lines', function()
feed('2Gtti<cr>')
screen:expect{grid=[[
a {5:longer} example |
in {6:order} |
^ to {7:de}{5:monstr}{7:ate} |
{7:combin}{8:ing}{9: hi}ghlights |
{9:from }{8:diff}{7:erent} sources |
{1:~ }|
{1:~ }|
{7:-- INSERT --} |
]]}
-- TODO(bfredl): keep both "parts" after split, requires proper extmark ranges
feed('<esc>tsi<cr>')
screen:expect{grid=[[
a {5:longer} example |
in {6:order} |
to {7:de}{5:mo} |
^nstrate |
{7:combin}{8:ing}{9: hi}ghlights |
{9:from }{8:diff}{7:erent} sources |
{1:~ }|
{7:-- INSERT --} |
]]}
-- TODO(bfredl): perhaps better undo
feed('<esc>u')
screen:expect{grid=[[
a {5:longer} example |
in {6:order} |
to demo{7:^nstrat}{8:e} |
{7:combin}{8:ing}{9: hi}ghlights |
{9:from }{8:diff}{7:erent} sources |
{1:~ }|
{1:~ }|
1 line less; before #3 0 seconds ago |
]]}
feed('<esc>u')
screen:expect{grid=[[
a {5:longer} example |
in order^ to demonstrate |
{7:combin}{8:ing}{9: hi}ghlights |
{9:from }{8:diff}{7:erent} sources |
{1:~ }|
{1:~ }|
{1:~ }|
1 line less; before #2 0 seconds ago |
]]}
end)
end)
it('prioritizes latest added highlight', function()