Merge pull request #1160 from mitchellh/cursor-scroll

terminal: resize cols should treat old cursor pos as active point
This commit is contained in:
Mitchell Hashimoto
2023-12-26 14:02:24 -08:00
committed by GitHub
2 changed files with 96 additions and 2 deletions

View File

@ -2734,7 +2734,7 @@ pub fn resize(self: *Screen, rows: usize, cols: usize) !void {
// Convert our cursor coordinates to screen coordinates because
// we may have to reflow the cursor if the line it is on is unwrapped.
const cursor_pos = (point.Viewport{
const cursor_pos = (point.Active{
.x = old.cursor.x,
.y = old.cursor.y,
}).toScreen(&old);
@ -2948,7 +2948,7 @@ pub fn resize(self: *Screen, rows: usize, cols: usize) !void {
// Convert our cursor coordinates to screen coordinates because
// we may have to reflow the cursor if the line it is on is moved.
const cursor_pos = (point.Viewport{
const cursor_pos = (point.Active{
.x = old.cursor.x,
.y = old.cursor.y,
}).toScreen(&old);
@ -6372,6 +6372,72 @@ test "Screen: resize more cols perfect split" {
try s.resize(3, 10);
}
// https://github.com/mitchellh/ghostty/issues/1159
test "Screen: resize (no reflow) more cols with scrollback scrolled up" {
const testing = std.testing;
const alloc = testing.allocator;
var s = try init(alloc, 3, 5, 5);
defer s.deinit();
const str = "1\n2\n3\n4\n5\n6\n7\n8";
try s.testWriteString(str);
// Cursor at bottom
try testing.expectEqual(@as(usize, 1), s.cursor.x);
try testing.expectEqual(@as(usize, 2), s.cursor.y);
try s.scroll(.{ .viewport = -4 });
{
const contents = try s.testString(alloc, .viewport);
defer alloc.free(contents);
try testing.expectEqualStrings("2\n3\n4", contents);
}
try s.resize(3, 8);
{
const contents = try s.testString(alloc, .screen);
defer alloc.free(contents);
try testing.expectEqualStrings(str, contents);
}
// Cursor remains at bottom
try testing.expectEqual(@as(usize, 1), s.cursor.x);
try testing.expectEqual(@as(usize, 2), s.cursor.y);
}
// https://github.com/mitchellh/ghostty/issues/1159
test "Screen: resize (no reflow) less cols with scrollback scrolled up" {
const testing = std.testing;
const alloc = testing.allocator;
var s = try init(alloc, 3, 5, 5);
defer s.deinit();
const str = "1\n2\n3\n4\n5\n6\n7\n8";
try s.testWriteString(str);
// Cursor at bottom
try testing.expectEqual(@as(usize, 1), s.cursor.x);
try testing.expectEqual(@as(usize, 2), s.cursor.y);
try s.scroll(.{ .viewport = -4 });
{
const contents = try s.testString(alloc, .viewport);
defer alloc.free(contents);
try testing.expectEqualStrings("2\n3\n4", contents);
}
try s.resize(3, 4);
{
const contents = try s.testString(alloc, .screen);
defer alloc.free(contents);
try testing.expectEqualStrings(str, contents);
}
// Cursor remains at bottom
try testing.expectEqual(@as(usize, 1), s.cursor.x);
try testing.expectEqual(@as(usize, 2), s.cursor.y);
}
test "Screen: resize more cols no reflow preserves semantic prompt" {
const testing = std.testing;
const alloc = testing.allocator;

View File

@ -6,6 +6,34 @@ const Screen = terminal.Screen;
// use different types so that we can lean on type-safety to get the
// exact expected type of point.
/// Active is a point within the active part of the screen.
pub const Active = struct {
x: usize = 0,
y: usize = 0,
pub fn toScreen(self: Active, screen: *const Screen) ScreenPoint {
return .{
.x = self.x,
.y = screen.history + self.y,
};
}
test "toScreen with scrollback" {
const testing = std.testing;
const alloc = testing.allocator;
var s = try Screen.init(alloc, 3, 5, 3);
defer s.deinit();
const str = "1\n2\n3\n4\n5\n6\n7\n8";
try s.testWriteString(str);
try testing.expectEqual(ScreenPoint{
.x = 1,
.y = 5,
}, (Active{ .x = 1, .y = 2 }).toScreen(&s));
}
};
/// Viewport is a point within the viewport of the screen.
pub const Viewport = struct {
x: usize = 0,