mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 08:46:08 +03:00
terminal/new: fix up cursor on grow cols
This commit is contained in:
@ -6442,6 +6442,7 @@ test "Screen: resize more rows with populated scrollback" {
|
||||
}
|
||||
}
|
||||
|
||||
// X
|
||||
test "Screen: resize more rows and cols with wrapping" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
|
@ -457,6 +457,46 @@ fn resizeGrowCols(
|
||||
} else {
|
||||
for (total..self.rows) |_| _ = try self.grow();
|
||||
}
|
||||
|
||||
// If we have a cursor, we need to update the correct y value. I'm
|
||||
// not at all happy about this, I wish we could do this in a more
|
||||
// efficient way as we resize the pages. But at the time of typing this
|
||||
// I can't think of a way and I'd rather get things working. Someone please
|
||||
// help!
|
||||
//
|
||||
// The challenge is that as rows are unwrapped, we want to preserve the
|
||||
// cursor. So for examle if you have "A\nB" where AB is soft-wrapped and
|
||||
// the cursor is on 'B' (x=0, y=1) and you grow the columns, we want
|
||||
// the cursor to remain on B (x=1, y=0) as it grows.
|
||||
//
|
||||
// The easy thing to do would be to count how many rows we unwrapped
|
||||
// and then subtract that from the original y. That's how I started. The
|
||||
// challenge is that if we unwrap with scrollback, our scrollback is
|
||||
// "pulled down" so that the original (x=0,y=0) line is now pushed down.
|
||||
// Detecting this while resizing seems non-obvious. This is a tested case
|
||||
// so if you change this logic, you should see failures or passes if it
|
||||
// works.
|
||||
//
|
||||
// The approach I take instead is if we have a cursor offset, I work
|
||||
// backwards to find the offset we marked while reflowing and update
|
||||
// the y from that. This is _not terrible_ because active areas are
|
||||
// generally small and this is a more or less linear search. Its just
|
||||
// kind of clunky.
|
||||
if (cursor) |c| cursor: {
|
||||
const offset = c.offset orelse break :cursor;
|
||||
var active_it = self.rowIterator(.{ .active = .{} }, null);
|
||||
var y: size.CellCountInt = 0;
|
||||
while (active_it.next()) |it_offset| {
|
||||
if (it_offset.page == offset.page and
|
||||
it_offset.row_offset == offset.row_offset)
|
||||
{
|
||||
c.y = y;
|
||||
break :cursor;
|
||||
}
|
||||
|
||||
y += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We use a cursor to track where we are in the src/dst. This is very
|
||||
@ -672,6 +712,9 @@ fn reflowPage(
|
||||
// better calculate the CHANGE in coordinate by subtracting
|
||||
// our dst from src which will calculate how many rows
|
||||
// we unwrapped to get here.
|
||||
//
|
||||
// Note this doesn't handle when we pull down scrollback.
|
||||
// See the cursor updates in resizeGrowCols for that.
|
||||
c.y -|= src_cursor.y - dst_cursor.y;
|
||||
|
||||
c.offset = .{
|
||||
|
@ -2476,14 +2476,13 @@ test "Screen: resize more cols with populated scrollback" {
|
||||
}
|
||||
|
||||
// Cursor should still be on the "5"
|
||||
// TODO
|
||||
// {
|
||||
// const list_cell = s.pages.getCell(.{ .active = .{
|
||||
// .x = s.cursor.x,
|
||||
// .y = s.cursor.y,
|
||||
// } }).?;
|
||||
// try testing.expectEqual(@as(u21, '5'), list_cell.cell.content.codepoint);
|
||||
// }
|
||||
{
|
||||
const list_cell = s.pages.getCell(.{ .active = .{
|
||||
.x = s.cursor.x,
|
||||
.y = s.cursor.y,
|
||||
} }).?;
|
||||
try testing.expectEqual(@as(u21, '5'), list_cell.cell.content.codepoint);
|
||||
}
|
||||
}
|
||||
|
||||
test "Screen: resize more cols with reflow" {
|
||||
@ -2523,9 +2522,41 @@ test "Screen: resize more cols with reflow" {
|
||||
}
|
||||
|
||||
// Our cursor should've moved
|
||||
// TODO
|
||||
// try testing.expectEqual(@as(size.CellCountInt, 2), s.cursor.x);
|
||||
// try testing.expectEqual(@as(size.CellCountInt, 2), s.cursor.y);
|
||||
try testing.expectEqual(@as(size.CellCountInt, 2), s.cursor.x);
|
||||
try testing.expectEqual(@as(size.CellCountInt, 2), s.cursor.y);
|
||||
}
|
||||
|
||||
test "Screen: resize more rows and cols with wrapping" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
|
||||
var s = try init(alloc, 2, 4, 0);
|
||||
defer s.deinit();
|
||||
const str = "1A2B\n3C4D";
|
||||
try s.testWriteString(str);
|
||||
{
|
||||
const contents = try s.dumpStringAlloc(alloc, .{ .viewport = .{} });
|
||||
defer alloc.free(contents);
|
||||
const expected = "1A\n2B\n3C\n4D";
|
||||
try testing.expectEqualStrings(expected, contents);
|
||||
}
|
||||
|
||||
try s.resize(5, 10);
|
||||
|
||||
// Cursor should move due to wrapping
|
||||
try testing.expectEqual(@as(size.CellCountInt, 3), s.cursor.x);
|
||||
try testing.expectEqual(@as(size.CellCountInt, 1), s.cursor.y);
|
||||
|
||||
{
|
||||
const contents = try s.dumpStringAlloc(alloc, .{ .viewport = .{} });
|
||||
defer alloc.free(contents);
|
||||
try testing.expectEqualStrings(str, contents);
|
||||
}
|
||||
{
|
||||
const contents = try s.dumpStringAlloc(alloc, .{ .screen = .{} });
|
||||
defer alloc.free(contents);
|
||||
try testing.expectEqualStrings(str, contents);
|
||||
}
|
||||
}
|
||||
|
||||
test "Screen: resize less rows no scrollback" {
|
||||
|
Reference in New Issue
Block a user