mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-05-13 16:37:27 +00:00
Cursor tracking tests
Also fix extra x movement for tracked cursors
This commit is contained in:
parent
c4a32862d1
commit
97449dfddb
5 changed files with 51 additions and 29 deletions
|
|
@ -11,7 +11,6 @@
|
|||
|
||||
// TODO: Handle selection with multicell
|
||||
// TODO: URL detection with multicell
|
||||
// TODO: Handle restitch of multiline chars
|
||||
|
||||
typedef union CellAttrs {
|
||||
struct {
|
||||
|
|
|
|||
|
|
@ -155,16 +155,15 @@ init_src_line(Rewrap *r) {
|
|||
}
|
||||
|
||||
static void
|
||||
update_tracked_cursors(Rewrap *r, index_type num_cells, index_type y, index_type x_limit) {
|
||||
update_tracked_cursors(Rewrap *r, index_type num_cells, index_type src_y, index_type dest_y, index_type x_limit) {
|
||||
for (TrackCursor *t = r->cursors; !t->is_sentinel; t++) {
|
||||
if (t->y == y && r->src_x <= t->x && (t->x < r->src_x + num_cells || t->x >= x_limit)) {
|
||||
if (t->y == src_y && r->src_x <= t->x && (t->x < r->src_x + num_cells || t->x >= x_limit)) {
|
||||
if (r->current_dest_line_is_last_history_line) {
|
||||
t->dest_x = 0; t->dest_y = 0;
|
||||
} else {
|
||||
index_type x = t->x;
|
||||
if (x >= x_limit) x = MAX(1u, x_limit) - 1;
|
||||
t->dest_y = r->dest_y;
|
||||
t->dest_x = r->dest_x + (x - r->src_x + (x > 0));
|
||||
t->dest_y = dest_y;
|
||||
t->dest_x = r->dest_x + (t->x - r->src_x);
|
||||
if (t->dest_x > r->dest_xnum) t->dest_x = r->dest_xnum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -197,7 +196,7 @@ copy_multiline_extra_lines(Rewrap *r, CPUCell *src_cell, index_type mc_width) {
|
|||
linebuf_init_line_at(r->scratch, i - 1, &r->dest_scratch);
|
||||
linebuf_mark_line_dirty(r->scratch, i - 1);
|
||||
copy_range(&r->src_scratch, r->src_x, &r->dest_scratch, r->dest_x, mc_width);
|
||||
update_tracked_cursors(r, mc_width, r->src_y + i, r->src_xnum + 10000 /* ensure cursor is moved only if in region being copied */);
|
||||
update_tracked_cursors(r, mc_width, r->src_y + i, r->dest_y + i, r->src_xnum + 10000 /* ensure cursor is moved only if in region being copied */);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -209,15 +208,18 @@ multiline_copy_src_to_dest(Rewrap *r) {
|
|||
c = &r->src.cpu_cells[r->src_x];
|
||||
if (c->is_multicell) {
|
||||
mc_width = mcd_x_limit(c);
|
||||
if (c->y || mc_width > r->dest_xnum) {
|
||||
update_tracked_cursors(r, mc_width, r->src_y, r->src_x_limit);
|
||||
if (mc_width > r->dest_xnum) {
|
||||
update_tracked_cursors(r, mc_width, r->src_y, r->dest_y, r->src_x_limit);
|
||||
r->src_x += mc_width;
|
||||
continue;
|
||||
} else if (c->y) {
|
||||
r->src_x += mc_width;
|
||||
continue;
|
||||
}
|
||||
} else mc_width = 1;
|
||||
find_space_in_dest(r, mc_width);
|
||||
copy_range(&r->src, r->src_x, &r->dest, r->dest_x, mc_width);
|
||||
update_tracked_cursors(r, mc_width, r->src_y, r->src_x_limit);
|
||||
update_tracked_cursors(r, mc_width, r->src_y, r->dest_y, r->src_x_limit);
|
||||
if (c->scale > 1) copy_multiline_extra_lines(r, c, mc_width);
|
||||
r->src_x += mc_width; r->dest_x += mc_width;
|
||||
}
|
||||
|
|
@ -249,7 +251,7 @@ fast_copy_src_to_dest(Rewrap *r) {
|
|||
}
|
||||
}
|
||||
copy_range(&r->src, r->src_x, &r->dest, r->dest_x, num);
|
||||
update_tracked_cursors(r, num, r->src_y, r->src_x_limit);
|
||||
update_tracked_cursors(r, num, r->src_y, r->dest_y, r->src_x_limit);
|
||||
r->src_x += num; r->dest_x += num;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -217,8 +217,8 @@ screen_dirty_sprite_positions(Screen *self) {
|
|||
}
|
||||
|
||||
static HistoryBuf*
|
||||
realloc_hb(HistoryBuf *old, unsigned int lines, unsigned int columns, ANSIBuf *as_ansi_buf) {
|
||||
HistoryBuf *ans = alloc_historybuf(lines, columns, 0, old->text_cache);
|
||||
realloc_hb(HistoryBuf *old, unsigned int columns, ANSIBuf *as_ansi_buf) {
|
||||
HistoryBuf *ans = alloc_historybuf(old->ynum, columns, 0, old->text_cache);
|
||||
if (ans == NULL) { PyErr_NoMemory(); return NULL; }
|
||||
ans->pagerhist = old->pagerhist; old->pagerhist = NULL;
|
||||
historybuf_rewrap(old, ans, as_ansi_buf);
|
||||
|
|
@ -397,7 +397,7 @@ screen_resize(Screen *self, unsigned int lines, unsigned int columns) {
|
|||
|
||||
// Resize main linebuf
|
||||
bool history_buf_last_line_is_split = history_buf_endswith_wrap(self->historybuf);
|
||||
HistoryBuf *nh = realloc_hb(self->historybuf, self->historybuf->ynum, columns, &self->as_ansi_buf);
|
||||
HistoryBuf *nh = realloc_hb(self->historybuf, columns, &self->as_ansi_buf);
|
||||
if (nh == NULL) return false;
|
||||
Py_CLEAR(self->historybuf); self->historybuf = nh;
|
||||
RAII_PyObject(prompt_copy, NULL);
|
||||
|
|
|
|||
|
|
@ -466,6 +466,12 @@ def test_multicell(self: TestMulticell) -> None:
|
|||
s.resize(*o)
|
||||
s.reset()
|
||||
|
||||
def mc(x=None, y=None):
|
||||
if x is not None:
|
||||
s.cursor.x = x
|
||||
if y is not None:
|
||||
s.cursor.y = y
|
||||
|
||||
reset()
|
||||
multicell(s, 'a', scale=2)
|
||||
before = as_ansi()
|
||||
|
|
@ -474,27 +480,43 @@ def test_multicell(self: TestMulticell) -> None:
|
|||
|
||||
reset()
|
||||
s.draw('a' * (s.columns - 2) + '😛' + 'bb')
|
||||
mc(4, 0)
|
||||
s.resize(s.lines, s.columns-1)
|
||||
self.ae('\x1b[maaaa\x1b[m😛bb', as_ansi().rstrip())
|
||||
assert_cursor_at(0, 1)
|
||||
reset()
|
||||
s.draw('a' * (s.columns - 2) + '😛' + 'bb')
|
||||
mc(0, 1)
|
||||
s.resize(s.lines, s.columns-2)
|
||||
assert_cursor_at(2, 1)
|
||||
self.ae('\x1b[maaaa\x1b[m😛bb', as_ansi().rstrip())
|
||||
reset()
|
||||
s.draw('a' * (s.columns - 2) + '😛' + 'bb')
|
||||
mc(5, 0)
|
||||
s.resize(s.lines, s.columns-3)
|
||||
self.ae('\x1b[maaa\x1b[ma😛\x1b[mbb', as_ansi().rstrip()) # ]]]]]]]
|
||||
assert_cursor_at(2, 1)
|
||||
|
||||
def resize(lines, cols, cursorx=None, cursory=None):
|
||||
mc(cursorx, cursory)
|
||||
before = s.cursor.x, s.cursor.y
|
||||
cell = s.cpu_cells(s.cursor.y, s.cursor.x)
|
||||
cell.pop('next_char_was_wrapped')
|
||||
s.resize(lines, cols)
|
||||
ncell = s.cpu_cells(s.cursor.y, s.cursor.x)
|
||||
ncell.pop('next_char_was_wrapped')
|
||||
self.ae(cell, ncell, f'Cursor moved from: {before} to {(s.cursor.x, s.cursor.y)}')
|
||||
|
||||
reset()
|
||||
multicell(s, 'a', scale=3), s.draw('b'*(s.columns-3))
|
||||
s.resize(s.lines, s.columns-1)
|
||||
resize(s.lines, s.columns-1, 5, 0)
|
||||
self.ae('\x1b[m\x1b]66;w=1:s=3;a\x07bb\x1b[mb', as_ansi().rstrip()) # ]]
|
||||
ac(0, 0, is_multicell=True)
|
||||
ac(0, 1, is_multicell=True)
|
||||
ac(3, 1, is_multicell=False, text='b')
|
||||
reset()
|
||||
s.draw('X'), multicell(s, 'a', scale=3), s.draw('12345')
|
||||
s.resize(s.lines, s.columns-1)
|
||||
resize(s.lines, s.columns-1, 4, 0)
|
||||
self.ae('\x1b[mX\x1b]66;w=1:s=3;a\x071\x1b[m23\x1b[m45', as_ansi().rstrip()) # ]]
|
||||
for y in (0, 1):
|
||||
ac(0, y, is_multicell=False), ac(1, y, is_multicell=True), ac(3, y, is_multicell=True)
|
||||
|
|
@ -502,17 +524,17 @@ def test_multicell(self: TestMulticell) -> None:
|
|||
|
||||
reset()
|
||||
s.draw('a'*(s.columns - 2)), s.draw('😛'), s.linefeed(), s.carriage_return(), s.draw('123')
|
||||
s.resize(s.lines, s.columns-1)
|
||||
resize(s.lines, s.columns-1, 5, 0)
|
||||
self.ae('\x1b[maaaa\x1b[m😛\n\x1b[m123', as_ansi().rstrip()) # ]]]]]]]
|
||||
|
||||
reset()
|
||||
s.draw('a'*(s.columns - 1)), s.draw('😛'), s.draw('bcd')
|
||||
s.resize(s.lines, s.columns + 1)
|
||||
resize(s.lines, s.columns + 1, 0, 1)
|
||||
self.ae('\x1b[maaaaa😛\x1b[mbcd', as_ansi().rstrip()) # ]]]]]]]
|
||||
|
||||
reset()
|
||||
s.draw('a'*s.columns), s.draw('😛'), s.draw('bcd')
|
||||
s.resize(s.lines, s.columns + 1)
|
||||
resize(s.lines, s.columns + 1, 0, 1)
|
||||
self.ae('\x1b[maaaaaa\x1b[m😛bcd', as_ansi().rstrip()) # ]]]]]]]
|
||||
ac(s.columns-1, 0, next_char_was_wrapped=True)
|
||||
s.resize(s.lines, s.columns + 1)
|
||||
|
|
@ -520,7 +542,7 @@ def test_multicell(self: TestMulticell) -> None:
|
|||
|
||||
reset()
|
||||
s.draw('a'*(s.columns - 1)), multicell(s, 'X', scale=2), s.draw('bcd')
|
||||
s.resize(s.lines, s.columns + 1)
|
||||
resize(s.lines, s.columns + 1, 0, 2)
|
||||
self.ae('\x1b[maaaaa\x1b]66;w=1:s=2;X\x07\x1b[mbcd', as_ansi().rstrip()) # ]]]]]]]
|
||||
for y in (0, 1):
|
||||
for x in (1, 2):
|
||||
|
|
@ -539,13 +561,13 @@ def test_multicell(self: TestMulticell) -> None:
|
|||
|
||||
reset()
|
||||
multicell(s, 'X', scale=4), s.draw('abc')
|
||||
s.resize(3, 3)
|
||||
resize(3, 3, 5, 0)
|
||||
self.ae('\x1b[mabc', as_ansi().rstrip()) # ]]]]]]]
|
||||
reset()
|
||||
multicell(s, 'X', width=4), s.draw('abc')
|
||||
s.resize(3, 3)
|
||||
resize(3, 3, 4, 0)
|
||||
self.ae('\x1b[mabc', as_ansi().rstrip()) # ]]]]]]]
|
||||
reset()
|
||||
s.draw('1'), multicell(s, 'X', width=4), s.draw('abc')
|
||||
s.resize(3, 3)
|
||||
resize(3, 3, 5, 0)
|
||||
self.ae('\x1b[m1ab\x1b[mc', as_ansi().rstrip()) # ]]]]]]]
|
||||
|
|
|
|||
|
|
@ -302,9 +302,8 @@ class TestScreen(BaseTest):
|
|||
self.assertTrue(s.historybuf.endswith_wrap())
|
||||
self.ae(str(s.historybuf), '111122')
|
||||
self.ae(at(), text + '\n')
|
||||
# for some reason rewrap_inner moves the cursor by one cell to the right
|
||||
self.ae((s.cursor.x, s.cursor.y), (4, 0))
|
||||
self.ae(ac(), 'c')
|
||||
self.ae((s.cursor.x, s.cursor.y), (3, 0))
|
||||
self.ae(ac(), 'b')
|
||||
s = self.create_screen(cols=4, lines=4, scrollback=4)
|
||||
s.draw('1111222'), s.linefeed(), s.carriage_return()
|
||||
s.draw('333344445555')
|
||||
|
|
@ -324,10 +323,10 @@ class TestScreen(BaseTest):
|
|||
s.cursor.x, s.cursor.y = 1, 1
|
||||
self.ae(ac(), 'b')
|
||||
s.resize(s.lines, s.columns * 2)
|
||||
self.ae(ac(), 'c')
|
||||
self.ae(ac(), 'b')
|
||||
self.ae(str(s.historybuf), '11112222')
|
||||
self.ae(at(), text + '\n\n')
|
||||
self.ae((s.cursor.x, s.cursor.y), (2, 0))
|
||||
self.ae((s.cursor.x, s.cursor.y), (1, 0))
|
||||
|
||||
# test that trailing blank line is preserved on resize
|
||||
s = self.create_screen(cols=5, lines=5, scrollback=15)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue