mirror of
https://github.com/neovim/neovim.git
synced 2024-09-17 20:58:20 -04:00
Merge 7ee02ad56e
into 3b54adc6c6
This commit is contained in:
commit
72f0808079
@ -167,6 +167,13 @@ void changed_internal(buf_T *buf)
|
||||
static void changed_lines_invalidate_win(win_T *wp, linenr_T lnum, colnr_T col, linenr_T lnume,
|
||||
linenr_T xtra)
|
||||
{
|
||||
// If lines haven been inserted/deleted and the buffer has virt_lines,
|
||||
// invalidate the line after the changed lines as some virt_lines may
|
||||
// now be drawn above a different line.
|
||||
if (xtra != 0 && buf_meta_total(wp->w_buffer, kMTMetaLines) > 0) {
|
||||
lnume++;
|
||||
}
|
||||
|
||||
// If the changed line is in a range of previously folded lines,
|
||||
// compare with the first line in that range.
|
||||
if (wp->w_cursor.lnum <= lnum) {
|
||||
@ -195,12 +202,7 @@ static void changed_lines_invalidate_win(win_T *wp, linenr_T lnum, colnr_T col,
|
||||
if (wp->w_lines[i].wl_lnum >= lnum) {
|
||||
// Do not change wl_lnum at index zero, it is used to compare with w_topline.
|
||||
// Invalidate it instead.
|
||||
// If lines haven been inserted/deleted and the buffer has virt_lines,
|
||||
// invalidate the line after the changed lines as some virt_lines may
|
||||
// now be drawn above a different line.
|
||||
if (i == 0 || wp->w_lines[i].wl_lnum < lnume
|
||||
|| (xtra != 0 && wp->w_lines[i].wl_lnum == lnume
|
||||
&& buf_meta_total(wp->w_buffer, kMTMetaLines) > 0)) {
|
||||
if (i == 0 || wp->w_lines[i].wl_lnum < lnume) {
|
||||
// line included in change
|
||||
wp->w_lines[i].wl_valid = false;
|
||||
} else if (xtra != 0) {
|
||||
@ -503,6 +505,10 @@ void deleted_lines(linenr_T lnum, linenr_T count)
|
||||
/// be triggered to display the cursor.
|
||||
void deleted_lines_mark(linenr_T lnum, int count)
|
||||
{
|
||||
u_header_T *uhp = u_force_get_undo_header(curbuf);
|
||||
extmark_undo_vec_t *uvp = uhp ? &uhp->uh_extmark : NULL;
|
||||
size_t prev_uvp_size = uvp ? kv_size(*uvp) : 0;
|
||||
|
||||
bool made_empty = (count > 0) && curbuf->b_ml.ml_flags & ML_EMPTY;
|
||||
|
||||
mark_adjust(lnum, (linenr_T)(lnum + count - 1), MAXLNUM, -(linenr_T)count, kExtmarkNOOP);
|
||||
@ -510,6 +516,10 @@ void deleted_lines_mark(linenr_T lnum, int count)
|
||||
extmark_adjust(curbuf, lnum, (linenr_T)(lnum + count - 1), MAXLNUM,
|
||||
-(linenr_T)count + (made_empty ? 1 : 0), kExtmarkUndo);
|
||||
changed_lines(curbuf, lnum, 0, lnum + (linenr_T)count, (linenr_T)(-count), true);
|
||||
|
||||
if (uvp) {
|
||||
extmark_redraw_after_delete(uvp, prev_uvp_size);
|
||||
}
|
||||
}
|
||||
|
||||
/// Marks the area to be redrawn after a change.
|
||||
@ -521,6 +531,13 @@ void deleted_lines_mark(linenr_T lnum, int count)
|
||||
/// @param xtra number of extra lines (negative when deleting)
|
||||
void changed_lines_redraw_buf(buf_T *buf, linenr_T lnum, linenr_T lnume, linenr_T xtra)
|
||||
{
|
||||
// If lines haven been inserted/deleted and the buffer has virt_lines,
|
||||
// mark the line after the changed lines to be redrawn as some virt_lines may
|
||||
// now be drawn above a different line.
|
||||
if (xtra != 0 && buf_meta_total(buf, kMTMetaLines) > 0) {
|
||||
lnume++;
|
||||
}
|
||||
|
||||
if (buf->b_mod_set) {
|
||||
// find the maximum area that must be redisplayed
|
||||
buf->b_mod_top = MIN(buf->b_mod_top, lnum);
|
||||
|
@ -99,7 +99,6 @@ void decor_redraw(buf_T *buf, int row1, int row2, int col1, DecorInline decor)
|
||||
linenr_T vt_lnum = row1 + 1 + below;
|
||||
redraw_buf_line_later(buf, vt_lnum, true);
|
||||
if (vt->flags & kVTIsLines || vt->pos == kVPosInline) {
|
||||
// changed_lines_redraw_buf(buf, vt_lnum, vt_lnum + 1, 0);
|
||||
colnr_T vt_col = vt->flags & kVTIsLines ? 0 : col1;
|
||||
changed_lines_invalidate_buf(buf, vt_lnum, vt_col, vt_lnum + 1, 0);
|
||||
}
|
||||
|
@ -116,8 +116,9 @@ static void extmark_setraw(buf_T *buf, uint64_t mark, int row, colnr_T col, bool
|
||||
// SavePos from a modified mark. Avoid adding that to the decor again.
|
||||
invalid = invalid && mt_invalid(key);
|
||||
|
||||
assert(buf->b_mod_set);
|
||||
// Only the position before undo needs to be redrawn here,
|
||||
// as the position after undo should be marked as changed.
|
||||
// as the position after undo should have been marked as changed.
|
||||
if (!invalid && mt_decor_any(key) && key.pos.row != row) {
|
||||
decor_redraw(buf, key.pos.row, key.pos.row, key.pos.col, mt_decor(key));
|
||||
}
|
||||
@ -413,6 +414,29 @@ void extmark_splice_delete(buf_T *buf, int l_row, colnr_T l_col, int u_row, coln
|
||||
}
|
||||
}
|
||||
|
||||
/// Mark new positions of extmarks in the range for redraw after deleting lines.
|
||||
/// This should be called after marking changed lines for redraw and splicing extmarks,
|
||||
/// otherwise the range marked for redraw will be larger than needed.
|
||||
void extmark_redraw_after_delete(extmark_undo_vec_t *uvp, size_t prev_uvp_size)
|
||||
{
|
||||
assert(curbuf->b_mod_set);
|
||||
for (size_t i = prev_uvp_size; i < kv_size(*uvp); i++) {
|
||||
const ExtmarkUndoObject *item = &kv_A(*uvp, i);
|
||||
if (item->type != kExtmarkSavePos) {
|
||||
continue;
|
||||
}
|
||||
const ExtmarkSavePos *pos = &item->data.savepos;
|
||||
if (pos->invalidated) {
|
||||
continue;
|
||||
}
|
||||
MarkTreeIter itr[1] = { 0 };
|
||||
MTKey key = marktree_lookup(curbuf->b_marktree, pos->mark, itr);
|
||||
if (mt_decor_any(key)) {
|
||||
decor_redraw(curbuf, key.pos.row, key.pos.row, key.pos.col, mt_decor(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// undo or redo an extmark operation
|
||||
void extmark_apply_undo(ExtmarkUndoObject undo_info, bool undo)
|
||||
{
|
||||
|
@ -2412,13 +2412,14 @@ static void u_undoredo(bool undo, bool do_buf_event)
|
||||
// Adjust Extmarks
|
||||
if (undo) {
|
||||
for (int i = (int)kv_size(curhead->uh_extmark) - 1; i > -1; i--) {
|
||||
extmark_apply_undo(kv_A(curhead->uh_extmark, i), undo);
|
||||
extmark_apply_undo(kv_A(curhead->uh_extmark, i), true);
|
||||
}
|
||||
// redo
|
||||
} else {
|
||||
for (int i = 0; i < (int)kv_size(curhead->uh_extmark); i++) {
|
||||
extmark_apply_undo(kv_A(curhead->uh_extmark, i), undo);
|
||||
extmark_apply_undo(kv_A(curhead->uh_extmark, i), false);
|
||||
}
|
||||
extmark_redraw_after_delete(&curhead->uh_extmark, 0);
|
||||
}
|
||||
if (curhead->uh_flags & UH_RELOAD) {
|
||||
// TODO(bfredl): this is a bit crude. When 'undoreload' is used we
|
||||
|
@ -4114,6 +4114,67 @@ describe('decorations: inline virtual text', function()
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
it('is redrawn correctly after delete or redo #27370', function()
|
||||
screen:try_resize(50, 12)
|
||||
exec([[
|
||||
call setline(1, ['aaa', 'bbb', 'ccc', 'ddd', 'eee', 'fff'])
|
||||
call setline(3, repeat('c', winwidth(0) - 1))
|
||||
]])
|
||||
api.nvim_buf_set_extmark(0, ns, 1, 0, { virt_text = { { '!!!' } }, virt_text_pos = 'inline' })
|
||||
feed('j')
|
||||
local before_delete = [[
|
||||
aaa |
|
||||
!!!^bbb |
|
||||
ccccccccccccccccccccccccccccccccccccccccccccccccc |
|
||||
ddd |
|
||||
eee |
|
||||
fff |
|
||||
{1:~ }|*5
|
||||
|
|
||||
]]
|
||||
screen:expect(before_delete)
|
||||
feed('dd')
|
||||
local after_delete = [[
|
||||
aaa |
|
||||
!!!^ccccccccccccccccccccccccccccccccccccccccccccccc|
|
||||
cc |
|
||||
ddd |
|
||||
eee |
|
||||
fff |
|
||||
{1:~ }|*5
|
||||
|
|
||||
]]
|
||||
screen:expect(after_delete)
|
||||
command('silent undo')
|
||||
screen:expect(before_delete)
|
||||
command('silent redo')
|
||||
screen:expect(after_delete)
|
||||
command('silent undo')
|
||||
screen:expect(before_delete)
|
||||
command('set report=100')
|
||||
feed('yypk2P')
|
||||
before_delete = [[
|
||||
aaa |
|
||||
^bbb |
|
||||
bbb |
|
||||
!!!bbb |
|
||||
bbb |
|
||||
ccccccccccccccccccccccccccccccccccccccccccccccccc |
|
||||
ddd |
|
||||
eee |
|
||||
fff |
|
||||
{1:~ }|*2
|
||||
|
|
||||
]]
|
||||
screen:expect(before_delete)
|
||||
feed('4dd')
|
||||
screen:expect(after_delete)
|
||||
command('silent undo')
|
||||
screen:expect(before_delete)
|
||||
command('silent redo')
|
||||
screen:expect(after_delete)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('decorations: virtual lines', function()
|
||||
|
Loading…
Reference in New Issue
Block a user