mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 16:26:08 +03:00
various methods on Row are grapheme-aware and tested
This commit is contained in:
@ -1499,7 +1499,7 @@ pub fn eraseChars(self: *Window, count: usize) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn insertLines(self: *Window, count: usize) !void {
|
pub fn insertLines(self: *Window, count: usize) !void {
|
||||||
self.terminal.insertLines(count);
|
try self.terminal.insertLines(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insertBlanks(self: *Window, count: usize) !void {
|
pub fn insertBlanks(self: *Window, count: usize) !void {
|
||||||
@ -1507,7 +1507,7 @@ pub fn insertBlanks(self: *Window, count: usize) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn deleteLines(self: *Window, count: usize) !void {
|
pub fn deleteLines(self: *Window, count: usize) !void {
|
||||||
self.terminal.deleteLines(count);
|
try self.terminal.deleteLines(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reverseIndex(self: *Window) !void {
|
pub fn reverseIndex(self: *Window) !void {
|
||||||
@ -1663,7 +1663,7 @@ pub fn setCursorStyle(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn decaln(self: *Window) !void {
|
pub fn decaln(self: *Window) !void {
|
||||||
self.terminal.decaln();
|
try self.terminal.decaln();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tabClear(self: *Window, cmd: terminal.TabClear) !void {
|
pub fn tabClear(self: *Window, cmd: terminal.TabClear) !void {
|
||||||
@ -1687,11 +1687,11 @@ pub fn enquiry(self: *Window) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn scrollDown(self: *Window, count: usize) !void {
|
pub fn scrollDown(self: *Window, count: usize) !void {
|
||||||
self.terminal.scrollDown(count);
|
try self.terminal.scrollDown(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scrollUp(self: *Window, count: usize) !void {
|
pub fn scrollUp(self: *Window, count: usize) !void {
|
||||||
self.terminal.scrollUp(count);
|
try self.terminal.scrollUp(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setActiveStatusDisplay(
|
pub fn setActiveStatusDisplay(
|
||||||
|
@ -235,13 +235,32 @@ pub const Row = struct {
|
|||||||
|
|
||||||
/// Fill the entire row with a copy of a single cell.
|
/// Fill the entire row with a copy of a single cell.
|
||||||
pub fn fill(self: Row, cell: Cell) void {
|
pub fn fill(self: Row, cell: Cell) void {
|
||||||
std.mem.set(StorageCell, self.storage[1..], .{ .cell = cell });
|
self.fillSlice(cell, 0, self.storage.len - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fill a slice of a row.
|
/// Fill a slice of a row.
|
||||||
pub fn fillSlice(self: Row, cell: Cell, start: usize, len: usize) void {
|
pub fn fillSlice(self: Row, cell: Cell, start: usize, len: usize) void {
|
||||||
assert(len <= self.storage.len - 1);
|
assert(len <= self.storage.len - 1);
|
||||||
|
assert(!cell.attrs.grapheme); // you can't fill with graphemes
|
||||||
|
|
||||||
|
// If our row has no graphemes, then this is a fast copy
|
||||||
|
if (!self.storage[0].header.flags.grapheme) {
|
||||||
std.mem.set(StorageCell, self.storage[start + 1 .. len + 1], .{ .cell = cell });
|
std.mem.set(StorageCell, self.storage[start + 1 .. len + 1], .{ .cell = cell });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have graphemes, so we have to clear those first.
|
||||||
|
for (self.storage[start + 1 .. len + 1]) |*storage_cell, x| {
|
||||||
|
if (storage_cell.cell.attrs.grapheme) self.clearGraphemes(x);
|
||||||
|
storage_cell.* = .{ .cell = cell };
|
||||||
|
}
|
||||||
|
|
||||||
|
// We only reset the grapheme flag if we fill the whole row, for now.
|
||||||
|
// We can improve performance by more correctly setting this but I'm
|
||||||
|
// going to defer that until we can measure.
|
||||||
|
if (start == 0 and len == self.storage.len - 1) {
|
||||||
|
self.storage[0].header.flags.grapheme = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a single immutable cell.
|
/// Get a single immutable cell.
|
||||||
@ -292,10 +311,42 @@ pub const Row = struct {
|
|||||||
try gop.value_ptr.append(self.screen.alloc, cp);
|
try gop.value_ptr.append(self.screen.alloc, cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Removes all graphemes associated with a cell.
|
||||||
|
pub fn clearGraphemes(self: Row, x: usize) void {
|
||||||
|
const cell = &self.storage[x + 1].cell;
|
||||||
|
const key = self.getId() + x + 1;
|
||||||
|
cell.attrs.grapheme = false;
|
||||||
|
_ = self.screen.graphemes.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
/// Copy the row src into this row. The row can be from another screen.
|
/// Copy the row src into this row. The row can be from another screen.
|
||||||
pub fn copyRow(self: Row, src: Row) void {
|
pub fn copyRow(self: Row, src: Row) !void {
|
||||||
|
// If we have graphemes, clear first to unset them.
|
||||||
|
if (self.storage[0].header.flags.grapheme) self.clear(.{});
|
||||||
|
|
||||||
|
// If the source has no graphemes (likely) then this is fast.
|
||||||
const end = @minimum(src.storage.len, self.storage.len);
|
const end = @minimum(src.storage.len, self.storage.len);
|
||||||
|
if (!src.storage[0].header.flags.grapheme) {
|
||||||
std.mem.copy(StorageCell, self.storage[1..], src.storage[1..end]);
|
std.mem.copy(StorageCell, self.storage[1..], src.storage[1..end]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source has graphemes, this is slow.
|
||||||
|
for (src.storage[1..end]) |storage, x| {
|
||||||
|
self.storage[x + 1] = .{ .cell = storage.cell };
|
||||||
|
|
||||||
|
// Copy grapheme data if it exists
|
||||||
|
if (storage.cell.attrs.grapheme) {
|
||||||
|
const src_key = src.getId() + x + 1;
|
||||||
|
const src_data = src.screen.graphemes.get(src_key) orelse continue;
|
||||||
|
|
||||||
|
const dst_key = self.getId() + x + 1;
|
||||||
|
const dst_gop = try self.screen.graphemes.getOrPut(self.screen.alloc, dst_key);
|
||||||
|
dst_gop.value_ptr.* = try src_data.copy(self.screen.alloc);
|
||||||
|
|
||||||
|
self.storage[0].header.flags.grapheme = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read-only iterator for the cells in the row.
|
/// Read-only iterator for the cells in the row.
|
||||||
@ -480,6 +531,14 @@ pub const GraphemeData = union(enum) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn copy(self: GraphemeData, alloc: Allocator) !GraphemeData {
|
||||||
|
// If we're not many we're not allocated so just copy on stack.
|
||||||
|
if (self != .many) return self;
|
||||||
|
|
||||||
|
// Heap allocated
|
||||||
|
return GraphemeData{ .many = try alloc.dupe(u21, self.many) };
|
||||||
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
log.warn("Grapheme={}", .{@sizeOf(GraphemeData)});
|
log.warn("Grapheme={}", .{@sizeOf(GraphemeData)});
|
||||||
}
|
}
|
||||||
@ -650,12 +709,12 @@ pub fn getRow(self: *Screen, index: RowIndex) Row {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Copy the row at src to dst.
|
/// Copy the row at src to dst.
|
||||||
pub fn copyRow(self: *Screen, dst: RowIndex, src: RowIndex) void {
|
pub fn copyRow(self: *Screen, dst: RowIndex, src: RowIndex) !void {
|
||||||
// One day we can make this more efficient but for now
|
// One day we can make this more efficient but for now
|
||||||
// we do the easy thing.
|
// we do the easy thing.
|
||||||
const dst_row = self.getRow(dst);
|
const dst_row = self.getRow(dst);
|
||||||
const src_row = self.getRow(src);
|
const src_row = self.getRow(src);
|
||||||
dst_row.copyRow(src_row);
|
try dst_row.copyRow(src_row);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the offset into the storage buffer that the given row can
|
/// Returns the offset into the storage buffer that the given row can
|
||||||
@ -1032,7 +1091,7 @@ pub fn resizeWithoutReflow(self: *Screen, rows: usize, cols: usize) !void {
|
|||||||
|
|
||||||
// Get this row
|
// Get this row
|
||||||
const new_row = self.getRow(.{ .active = y });
|
const new_row = self.getRow(.{ .active = y });
|
||||||
new_row.copyRow(old_row);
|
try new_row.copyRow(old_row);
|
||||||
|
|
||||||
// Next row
|
// Next row
|
||||||
y += 1;
|
y += 1;
|
||||||
@ -1114,7 +1173,7 @@ pub fn resize(self: *Screen, rows: usize, cols: usize) !void {
|
|||||||
|
|
||||||
// Get this row
|
// Get this row
|
||||||
var new_row = self.getRow(.{ .active = y });
|
var new_row = self.getRow(.{ .active = y });
|
||||||
new_row.copyRow(old_row);
|
try new_row.copyRow(old_row);
|
||||||
|
|
||||||
// We need to check if our cursor was on this line. If so,
|
// We need to check if our cursor was on this line. If so,
|
||||||
// we set the new cursor.
|
// we set the new cursor.
|
||||||
@ -1458,6 +1517,93 @@ pub fn testString(self: *Screen, alloc: Allocator, tag: RowIndexTag) ![]const u8
|
|||||||
return try alloc.realloc(buf, str.len);
|
return try alloc.realloc(buf, str.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "Row: clear with graphemes" {
|
||||||
|
const testing = std.testing;
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
|
var s = try init(alloc, 5, 5, 0);
|
||||||
|
defer s.deinit();
|
||||||
|
|
||||||
|
const row = s.getRow(.{ .active = 0 });
|
||||||
|
try testing.expect(row.getId() > 0);
|
||||||
|
try testing.expectEqual(@as(usize, 5), row.lenCells());
|
||||||
|
try testing.expect(!row.header().flags.grapheme);
|
||||||
|
|
||||||
|
// Lets add a cell with a grapheme
|
||||||
|
{
|
||||||
|
const cell = row.getCellPtr(2);
|
||||||
|
cell.*.char = 'A';
|
||||||
|
try row.attachGrapheme(2, 'B');
|
||||||
|
try testing.expect(cell.attrs.grapheme);
|
||||||
|
try testing.expect(row.header().flags.grapheme);
|
||||||
|
try testing.expect(s.graphemes.count() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the row
|
||||||
|
row.clear(.{});
|
||||||
|
try testing.expect(!row.header().flags.grapheme);
|
||||||
|
try testing.expect(s.graphemes.count() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "Row: copy row with graphemes in destination" {
|
||||||
|
const testing = std.testing;
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
|
var s = try init(alloc, 5, 5, 0);
|
||||||
|
defer s.deinit();
|
||||||
|
|
||||||
|
// Source row does NOT have graphemes
|
||||||
|
const row_src = s.getRow(.{ .active = 0 });
|
||||||
|
{
|
||||||
|
const cell = row_src.getCellPtr(2);
|
||||||
|
cell.*.char = 'A';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destination has graphemes
|
||||||
|
const row = s.getRow(.{ .active = 1 });
|
||||||
|
{
|
||||||
|
const cell = row.getCellPtr(1);
|
||||||
|
cell.*.char = 'B';
|
||||||
|
try row.attachGrapheme(1, 'C');
|
||||||
|
try testing.expect(cell.attrs.grapheme);
|
||||||
|
try testing.expect(row.header().flags.grapheme);
|
||||||
|
try testing.expect(s.graphemes.count() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy
|
||||||
|
try row.copyRow(row_src);
|
||||||
|
try testing.expect(!row.header().flags.grapheme);
|
||||||
|
try testing.expect(s.graphemes.count() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "Row: copy row with graphemes in source" {
|
||||||
|
const testing = std.testing;
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
|
var s = try init(alloc, 5, 5, 0);
|
||||||
|
defer s.deinit();
|
||||||
|
|
||||||
|
// Source row does NOT have graphemes
|
||||||
|
const row_src = s.getRow(.{ .active = 0 });
|
||||||
|
{
|
||||||
|
const cell = row_src.getCellPtr(2);
|
||||||
|
cell.*.char = 'A';
|
||||||
|
try row_src.attachGrapheme(2, 'B');
|
||||||
|
try testing.expect(cell.attrs.grapheme);
|
||||||
|
try testing.expect(row_src.header().flags.grapheme);
|
||||||
|
try testing.expect(s.graphemes.count() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destination has no graphemes
|
||||||
|
const row = s.getRow(.{ .active = 1 });
|
||||||
|
try row.copyRow(row_src);
|
||||||
|
try testing.expect(row.header().flags.grapheme);
|
||||||
|
try testing.expect(s.graphemes.count() == 2);
|
||||||
|
|
||||||
|
row_src.clear(.{});
|
||||||
|
try testing.expect(s.graphemes.count() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
test "Screen" {
|
test "Screen" {
|
||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const alloc = testing.allocator;
|
const alloc = testing.allocator;
|
||||||
@ -1758,7 +1904,7 @@ test "Screen: row copy" {
|
|||||||
|
|
||||||
// Copy
|
// Copy
|
||||||
try s.scroll(.{ .delta = 1 });
|
try s.scroll(.{ .delta = 1 });
|
||||||
s.copyRow(.{ .active = 2 }, .{ .active = 0 });
|
try s.copyRow(.{ .active = 2 }, .{ .active = 0 });
|
||||||
|
|
||||||
// Test our contents
|
// Test our contents
|
||||||
var contents = try s.testString(alloc, .viewport);
|
var contents = try s.testString(alloc, .viewport);
|
||||||
|
@ -608,6 +608,9 @@ fn printCell(self: *Terminal, unmapped_c: u21) *Screen.Cell {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the prior value had graphemes, clear those
|
||||||
|
if (cell.attrs.grapheme) row.clearGraphemes(self.screen.cursor.x);
|
||||||
|
|
||||||
// Write
|
// Write
|
||||||
cell.* = self.screen.cursor.pen;
|
cell.* = self.screen.cursor.pen;
|
||||||
cell.char = @intCast(u32, c);
|
cell.char = @intCast(u32, c);
|
||||||
@ -640,7 +643,7 @@ fn clearWideSpacerHead(self: *Terminal) void {
|
|||||||
/// Resets all margins and fills the whole screen with the character 'E'
|
/// Resets all margins and fills the whole screen with the character 'E'
|
||||||
///
|
///
|
||||||
/// Sets the cursor to the top left corner.
|
/// Sets the cursor to the top left corner.
|
||||||
pub fn decaln(self: *Terminal) void {
|
pub fn decaln(self: *Terminal) !void {
|
||||||
const tracy = trace(@src());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
|
|
||||||
@ -654,7 +657,7 @@ pub fn decaln(self: *Terminal) void {
|
|||||||
|
|
||||||
var row: usize = 1;
|
var row: usize = 1;
|
||||||
while (row < self.rows) : (row += 1) {
|
while (row < self.rows) : (row += 1) {
|
||||||
self.screen.getRow(.{ .active = row }).copyRow(filled);
|
try self.screen.getRow(.{ .active = row }).copyRow(filled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -697,7 +700,7 @@ pub fn index(self: *Terminal) !void {
|
|||||||
try self.screen.scroll(.{ .delta = 1 });
|
try self.screen.scroll(.{ .delta = 1 });
|
||||||
} else {
|
} else {
|
||||||
// TODO: test
|
// TODO: test
|
||||||
self.scrollUp(1);
|
try self.scrollUp(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -726,7 +729,7 @@ pub fn reverseIndex(self: *Terminal) !void {
|
|||||||
// TODO: scrolling region
|
// TODO: scrolling region
|
||||||
|
|
||||||
if (self.screen.cursor.y == 0) {
|
if (self.screen.cursor.y == 0) {
|
||||||
self.scrollDown(1);
|
try self.scrollDown(1);
|
||||||
} else {
|
} else {
|
||||||
self.screen.cursor.y -|= 1;
|
self.screen.cursor.y -|= 1;
|
||||||
}
|
}
|
||||||
@ -1128,7 +1131,7 @@ pub fn insertBlanks(self: *Terminal, count: usize) void {
|
|||||||
/// All cleared space is colored according to the current SGR state.
|
/// All cleared space is colored according to the current SGR state.
|
||||||
///
|
///
|
||||||
/// Moves the cursor to the left margin.
|
/// Moves the cursor to the left margin.
|
||||||
pub fn insertLines(self: *Terminal, count: usize) void {
|
pub fn insertLines(self: *Terminal, count: usize) !void {
|
||||||
const tracy = trace(@src());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
|
|
||||||
@ -1149,7 +1152,7 @@ pub fn insertLines(self: *Terminal, count: usize) void {
|
|||||||
|
|
||||||
// Ensure we have the lines populated to the end
|
// Ensure we have the lines populated to the end
|
||||||
while (y > top) : (y -= 1) {
|
while (y > top) : (y -= 1) {
|
||||||
self.screen.copyRow(.{ .active = y }, .{ .active = y - adjusted_count });
|
try self.screen.copyRow(.{ .active = y }, .{ .active = y - adjusted_count });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert count blank lines
|
// Insert count blank lines
|
||||||
@ -1176,7 +1179,7 @@ pub fn insertLines(self: *Terminal, count: usize) void {
|
|||||||
/// cleared space is colored according to the current SGR state.
|
/// cleared space is colored according to the current SGR state.
|
||||||
///
|
///
|
||||||
/// Moves the cursor to the left margin.
|
/// Moves the cursor to the left margin.
|
||||||
pub fn deleteLines(self: *Terminal, count: usize) void {
|
pub fn deleteLines(self: *Terminal, count: usize) !void {
|
||||||
const tracy = trace(@src());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
|
|
||||||
@ -1194,7 +1197,7 @@ pub fn deleteLines(self: *Terminal, count: usize) void {
|
|||||||
// Scroll up the count amount.
|
// Scroll up the count amount.
|
||||||
var y: usize = self.screen.cursor.y;
|
var y: usize = self.screen.cursor.y;
|
||||||
while (y <= self.scrolling_region.bottom - adjusted_count) : (y += 1) {
|
while (y <= self.scrolling_region.bottom - adjusted_count) : (y += 1) {
|
||||||
self.screen.copyRow(.{ .active = y }, .{ .active = y + adjusted_count });
|
try self.screen.copyRow(.{ .active = y }, .{ .active = y + adjusted_count });
|
||||||
}
|
}
|
||||||
|
|
||||||
while (y <= self.scrolling_region.bottom) : (y += 1) {
|
while (y <= self.scrolling_region.bottom) : (y += 1) {
|
||||||
@ -1205,7 +1208,7 @@ pub fn deleteLines(self: *Terminal, count: usize) void {
|
|||||||
|
|
||||||
/// Scroll the text down by one row.
|
/// Scroll the text down by one row.
|
||||||
/// TODO: test
|
/// TODO: test
|
||||||
pub fn scrollDown(self: *Terminal, count: usize) void {
|
pub fn scrollDown(self: *Terminal, count: usize) !void {
|
||||||
const tracy = trace(@src());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
|
|
||||||
@ -1215,7 +1218,7 @@ pub fn scrollDown(self: *Terminal, count: usize) void {
|
|||||||
|
|
||||||
// Move to the top of the scroll region
|
// Move to the top of the scroll region
|
||||||
self.screen.cursor.y = self.scrolling_region.top;
|
self.screen.cursor.y = self.scrolling_region.top;
|
||||||
self.insertLines(count);
|
try self.insertLines(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes amount lines from the top of the scroll region. The remaining lines
|
/// Removes amount lines from the top of the scroll region. The remaining lines
|
||||||
@ -1226,14 +1229,14 @@ pub fn scrollDown(self: *Terminal, count: usize) void {
|
|||||||
///
|
///
|
||||||
/// Does not change the (absolute) cursor position.
|
/// Does not change the (absolute) cursor position.
|
||||||
// TODO: test
|
// TODO: test
|
||||||
pub fn scrollUp(self: *Terminal, count: usize) void {
|
pub fn scrollUp(self: *Terminal, count: usize) !void {
|
||||||
// Preserve the cursor
|
// Preserve the cursor
|
||||||
const cursor = self.screen.cursor;
|
const cursor = self.screen.cursor;
|
||||||
defer self.screen.cursor = cursor;
|
defer self.screen.cursor = cursor;
|
||||||
|
|
||||||
// Move to the top of the scroll region
|
// Move to the top of the scroll region
|
||||||
self.screen.cursor.y = self.scrolling_region.top;
|
self.screen.cursor.y = self.scrolling_region.top;
|
||||||
self.deleteLines(count);
|
try self.deleteLines(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Options for scrolling the viewport of the terminal grid.
|
/// Options for scrolling the viewport of the terminal grid.
|
||||||
@ -1597,7 +1600,7 @@ test "Terminal: deleteLines" {
|
|||||||
try t.print('D');
|
try t.print('D');
|
||||||
|
|
||||||
t.cursorUp(2);
|
t.cursorUp(2);
|
||||||
t.deleteLines(1);
|
try t.deleteLines(1);
|
||||||
|
|
||||||
try t.print('E');
|
try t.print('E');
|
||||||
t.carriageReturn();
|
t.carriageReturn();
|
||||||
@ -1633,7 +1636,7 @@ test "Terminal: deleteLines with scroll region" {
|
|||||||
|
|
||||||
t.setScrollingRegion(1, 3);
|
t.setScrollingRegion(1, 3);
|
||||||
t.setCursorPos(1, 1);
|
t.setCursorPos(1, 1);
|
||||||
t.deleteLines(1);
|
try t.deleteLines(1);
|
||||||
|
|
||||||
try t.print('E');
|
try t.print('E');
|
||||||
t.carriageReturn();
|
t.carriageReturn();
|
||||||
@ -1674,7 +1677,7 @@ test "Terminal: insertLines" {
|
|||||||
t.setCursorPos(2, 1);
|
t.setCursorPos(2, 1);
|
||||||
|
|
||||||
// Insert two lines
|
// Insert two lines
|
||||||
t.insertLines(2);
|
try t.insertLines(2);
|
||||||
|
|
||||||
{
|
{
|
||||||
var str = try t.plainString(testing.allocator);
|
var str = try t.plainString(testing.allocator);
|
||||||
@ -1705,7 +1708,7 @@ test "Terminal: insertLines with scroll region" {
|
|||||||
|
|
||||||
t.setScrollingRegion(1, 2);
|
t.setScrollingRegion(1, 2);
|
||||||
t.setCursorPos(1, 1);
|
t.setCursorPos(1, 1);
|
||||||
t.insertLines(1);
|
try t.insertLines(1);
|
||||||
|
|
||||||
try t.print('X');
|
try t.print('X');
|
||||||
|
|
||||||
@ -1740,7 +1743,7 @@ test "Terminal: insertLines more than remaining" {
|
|||||||
t.setCursorPos(2, 1);
|
t.setCursorPos(2, 1);
|
||||||
|
|
||||||
// Insert a bunch of lines
|
// Insert a bunch of lines
|
||||||
t.insertLines(20);
|
try t.insertLines(20);
|
||||||
|
|
||||||
{
|
{
|
||||||
var str = try t.plainString(testing.allocator);
|
var str = try t.plainString(testing.allocator);
|
||||||
@ -1881,7 +1884,7 @@ test "Terminal: DECALN" {
|
|||||||
t.carriageReturn();
|
t.carriageReturn();
|
||||||
try t.linefeed();
|
try t.linefeed();
|
||||||
try t.print('B');
|
try t.print('B');
|
||||||
t.decaln();
|
try t.decaln();
|
||||||
|
|
||||||
try testing.expectEqual(@as(usize, 0), t.screen.cursor.y);
|
try testing.expectEqual(@as(usize, 0), t.screen.cursor.y);
|
||||||
try testing.expectEqual(@as(usize, 0), t.screen.cursor.x);
|
try testing.expectEqual(@as(usize, 0), t.screen.cursor.x);
|
||||||
|
Reference in New Issue
Block a user