mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
various fixes
This commit is contained in:
@ -4,10 +4,8 @@ const std = @import("std");
|
|||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
const stdout = std.io.getStdOut().writer();
|
const stdout = std.io.getStdOut().writer();
|
||||||
try stdout.print("A\nB\n", .{});
|
try stdout.print("A\nB\n\n", .{});
|
||||||
|
|
||||||
try stdout.print("\x0D", .{}); // CR
|
|
||||||
try stdout.print("\x0A", .{}); // LF
|
|
||||||
try stdout.print("\x1B[H", .{}); // Top-left
|
try stdout.print("\x1B[H", .{}); // Top-left
|
||||||
try stdout.print("\x1BM", .{}); // Reverse-Index
|
try stdout.print("\x1BM", .{}); // Reverse-Index
|
||||||
try stdout.print("D", .{});
|
try stdout.print("D", .{});
|
||||||
|
@ -591,7 +591,7 @@ fn renderTimerCallback(t: *libuv.Timer) void {
|
|||||||
// Stream Callbacks
|
// Stream Callbacks
|
||||||
|
|
||||||
pub fn print(self: *Window, c: u21) !void {
|
pub fn print(self: *Window, c: u21) !void {
|
||||||
try self.terminal.print(self.alloc, c);
|
try self.terminal.print(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bell(self: Window) !void {
|
pub fn bell(self: Window) !void {
|
||||||
@ -604,11 +604,11 @@ pub fn backspace(self: *Window) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn horizontalTab(self: *Window) !void {
|
pub fn horizontalTab(self: *Window) !void {
|
||||||
try self.terminal.horizontalTab(self.alloc);
|
try self.terminal.horizontalTab();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn linefeed(self: *Window) !void {
|
pub fn linefeed(self: *Window) !void {
|
||||||
self.terminal.linefeed(self.alloc);
|
self.terminal.linefeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn carriageReturn(self: *Window) !void {
|
pub fn carriageReturn(self: *Window) !void {
|
||||||
@ -668,7 +668,7 @@ pub fn deleteLines(self: *Window, count: usize) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn reverseIndex(self: *Window) !void {
|
pub fn reverseIndex(self: *Window) !void {
|
||||||
try self.terminal.reverseIndex(self.alloc);
|
try self.terminal.reverseIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setTopAndBottomMargin(self: *Window, top: u16, bot: u16) !void {
|
pub fn setTopAndBottomMargin(self: *Window, top: u16, bot: u16) !void {
|
||||||
|
@ -163,12 +163,12 @@ pub fn setAttribute(self: *Terminal, attr: sgr.Attribute) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print(self: *Terminal, alloc: Allocator, c: u21) !void {
|
pub fn print(self: *Terminal, c: u21) !void {
|
||||||
const tracy = trace(@src());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
|
|
||||||
// Build our cell
|
// Build our cell
|
||||||
const cell = try self.getOrPutCell(alloc, self.cursor.x, self.cursor.y);
|
const cell = self.screen.getCell(self.cursor.y, self.cursor.x);
|
||||||
cell.* = self.cursor.pen;
|
cell.* = self.cursor.pen;
|
||||||
cell.char = @intCast(u32, c);
|
cell.char = @intCast(u32, c);
|
||||||
|
|
||||||
@ -181,12 +181,28 @@ pub fn print(self: *Terminal, alloc: Allocator, c: u21) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Move the cursor to the previous line in the scrolling region, possibly
|
||||||
|
/// scrolling.
|
||||||
|
///
|
||||||
|
/// If the cursor is outside of the scrolling region, move the cursor one
|
||||||
|
/// line up if it is not on the top-most line of the screen.
|
||||||
|
///
|
||||||
|
/// If the cursor is inside the scrolling region:
|
||||||
|
///
|
||||||
|
/// * If the cursor is on the top-most line of the scrolling region:
|
||||||
|
/// invoke scroll down with amount=1
|
||||||
|
/// * If the cursor is not on the top-most line of the scrolling region:
|
||||||
|
/// move the cursor one line up
|
||||||
|
///
|
||||||
// TODO: test
|
// TODO: test
|
||||||
pub fn reverseIndex(self: *Terminal, alloc: Allocator) !void {
|
pub fn reverseIndex(self: *Terminal) !void {
|
||||||
if (self.cursor.y == 0)
|
// TODO: scrolling region
|
||||||
try self.scrollDown(alloc)
|
|
||||||
else
|
if (self.cursor.y == 0) {
|
||||||
|
try self.scrollDown();
|
||||||
|
} else {
|
||||||
self.cursor.y -|= 1;
|
self.cursor.y -|= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set Cursor Position. Move cursor to the position indicated
|
// Set Cursor Position. Move cursor to the position indicated
|
||||||
@ -383,13 +399,13 @@ pub fn backspace(self: *Terminal) void {
|
|||||||
|
|
||||||
/// Horizontal tab moves the cursor to the next tabstop, clearing
|
/// Horizontal tab moves the cursor to the next tabstop, clearing
|
||||||
/// the screen to the left the tabstop.
|
/// the screen to the left the tabstop.
|
||||||
pub fn horizontalTab(self: *Terminal, alloc: Allocator) !void {
|
pub fn horizontalTab(self: *Terminal) !void {
|
||||||
const tracy = trace(@src());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
|
|
||||||
while (self.cursor.x < self.cols) {
|
while (self.cursor.x < self.cols) {
|
||||||
// Clear
|
// Clear
|
||||||
try self.print(alloc, ' ');
|
try self.print(' ');
|
||||||
|
|
||||||
// If the last cursor position was a tabstop we return. We do
|
// If the last cursor position was a tabstop we return. We do
|
||||||
// "last cursor position" because we want a space to be written
|
// "last cursor position" because we want a space to be written
|
||||||
@ -407,7 +423,7 @@ pub fn carriageReturn(self: *Terminal) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Linefeed moves the cursor to the next line.
|
/// Linefeed moves the cursor to the next line.
|
||||||
pub fn linefeed(self: *Terminal, alloc: Allocator) void {
|
pub fn linefeed(self: *Terminal) void {
|
||||||
const tracy = trace(@src());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
|
|
||||||
@ -415,7 +431,7 @@ pub fn linefeed(self: *Terminal, alloc: Allocator) void {
|
|||||||
// common because most terminals live with a full screen so we do this
|
// common because most terminals live with a full screen so we do this
|
||||||
// check first.
|
// check first.
|
||||||
if (self.cursor.y == self.rows - 1) {
|
if (self.cursor.y == self.rows - 1) {
|
||||||
self.scrollUp(alloc);
|
self.scrollUp();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -514,12 +530,11 @@ pub fn deleteLines(self: *Terminal, alloc: Allocator, count: usize) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Scroll the text up by one row.
|
/// Scroll the text up by one row.
|
||||||
pub fn scrollUp(self: *Terminal, alloc: Allocator) void {
|
pub fn scrollUp(self: *Terminal) void {
|
||||||
const tracy = trace(@src());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
|
|
||||||
_ = alloc;
|
self.screen.scroll(1);
|
||||||
self.screen.scroll(-1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scroll the given region up.
|
/// Scroll the given region up.
|
||||||
@ -553,12 +568,11 @@ fn scrollUpRegion(
|
|||||||
|
|
||||||
/// Scroll the text down by one row.
|
/// Scroll the text down by one row.
|
||||||
/// TODO: test
|
/// TODO: test
|
||||||
pub fn scrollDown(self: *Terminal, alloc: Allocator) !void {
|
pub fn scrollDown(self: *Terminal) !void {
|
||||||
const tracy = trace(@src());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
|
|
||||||
_ = alloc;
|
self.screen.scroll(-1);
|
||||||
self.screen.scroll(1);
|
|
||||||
const top = self.screen.getRow(0);
|
const top = self.screen.getRow(0);
|
||||||
for (top) |*cell| cell.char = 0;
|
for (top) |*cell| cell.char = 0;
|
||||||
}
|
}
|
||||||
@ -604,7 +618,7 @@ test "Terminal: input with no control characters" {
|
|||||||
defer t.deinit(testing.allocator);
|
defer t.deinit(testing.allocator);
|
||||||
|
|
||||||
// Basic grid writing
|
// Basic grid writing
|
||||||
for ("hello") |c| try t.print(testing.allocator, c);
|
for ("hello") |c| try t.print(c);
|
||||||
try testing.expectEqual(@as(usize, 0), t.cursor.y);
|
try testing.expectEqual(@as(usize, 0), t.cursor.y);
|
||||||
try testing.expectEqual(@as(usize, 5), t.cursor.x);
|
try testing.expectEqual(@as(usize, 5), t.cursor.x);
|
||||||
{
|
{
|
||||||
@ -619,10 +633,10 @@ test "Terminal: linefeed and carriage return" {
|
|||||||
defer t.deinit(testing.allocator);
|
defer t.deinit(testing.allocator);
|
||||||
|
|
||||||
// Basic grid writing
|
// Basic grid writing
|
||||||
for ("hello") |c| try t.print(testing.allocator, c);
|
for ("hello") |c| try t.print(c);
|
||||||
t.carriageReturn();
|
t.carriageReturn();
|
||||||
t.linefeed(testing.allocator);
|
t.linefeed();
|
||||||
for ("world") |c| try t.print(testing.allocator, c);
|
for ("world") |c| try t.print(c);
|
||||||
try testing.expectEqual(@as(usize, 1), t.cursor.y);
|
try testing.expectEqual(@as(usize, 1), t.cursor.y);
|
||||||
try testing.expectEqual(@as(usize, 5), t.cursor.x);
|
try testing.expectEqual(@as(usize, 5), t.cursor.x);
|
||||||
{
|
{
|
||||||
@ -633,14 +647,13 @@ test "Terminal: linefeed and carriage return" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test "Terminal: backspace" {
|
test "Terminal: backspace" {
|
||||||
const alloc = testing.allocator;
|
|
||||||
var t = try init(testing.allocator, 80, 80);
|
var t = try init(testing.allocator, 80, 80);
|
||||||
defer t.deinit(testing.allocator);
|
defer t.deinit(testing.allocator);
|
||||||
|
|
||||||
// BS
|
// BS
|
||||||
for ("hello") |c| try t.print(alloc, c);
|
for ("hello") |c| try t.print(c);
|
||||||
t.backspace();
|
t.backspace();
|
||||||
try t.print(alloc, 'y');
|
try t.print('y');
|
||||||
try testing.expectEqual(@as(usize, 0), t.cursor.y);
|
try testing.expectEqual(@as(usize, 0), t.cursor.y);
|
||||||
try testing.expectEqual(@as(usize, 5), t.cursor.x);
|
try testing.expectEqual(@as(usize, 5), t.cursor.x);
|
||||||
{
|
{
|
||||||
@ -656,12 +669,12 @@ test "Terminal: horizontal tabs" {
|
|||||||
defer t.deinit(alloc);
|
defer t.deinit(alloc);
|
||||||
|
|
||||||
// HT
|
// HT
|
||||||
try t.print(alloc, '1');
|
try t.print('1');
|
||||||
try t.horizontalTab(alloc);
|
try t.horizontalTab();
|
||||||
try testing.expectEqual(@as(usize, 8), t.cursor.x);
|
try testing.expectEqual(@as(usize, 8), t.cursor.x);
|
||||||
|
|
||||||
// HT
|
// HT
|
||||||
try t.horizontalTab(alloc);
|
try t.horizontalTab();
|
||||||
try testing.expectEqual(@as(usize, 16), t.cursor.x);
|
try testing.expectEqual(@as(usize, 16), t.cursor.x);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -715,23 +728,23 @@ test "Terminal: setScrollingRegion" {
|
|||||||
defer t.deinit(alloc);
|
defer t.deinit(alloc);
|
||||||
|
|
||||||
// Initial value
|
// Initial value
|
||||||
try t.print(alloc, 'A');
|
try t.print('A');
|
||||||
t.carriageReturn();
|
t.carriageReturn();
|
||||||
t.linefeed(alloc);
|
t.linefeed();
|
||||||
try t.print(alloc, 'B');
|
try t.print('B');
|
||||||
t.carriageReturn();
|
t.carriageReturn();
|
||||||
t.linefeed(alloc);
|
t.linefeed();
|
||||||
try t.print(alloc, 'C');
|
try t.print('C');
|
||||||
t.carriageReturn();
|
t.carriageReturn();
|
||||||
t.linefeed(alloc);
|
t.linefeed();
|
||||||
try t.print(alloc, 'D');
|
try t.print('D');
|
||||||
|
|
||||||
t.cursorUp(2);
|
t.cursorUp(2);
|
||||||
t.deleteLines(alloc, 1);
|
t.deleteLines(alloc, 1);
|
||||||
|
|
||||||
try t.print(alloc, 'E');
|
try t.print('E');
|
||||||
t.carriageReturn();
|
t.carriageReturn();
|
||||||
t.linefeed(alloc);
|
t.linefeed();
|
||||||
|
|
||||||
// We should be
|
// We should be
|
||||||
try testing.expectEqual(@as(usize, 0), t.cursor.x);
|
try testing.expectEqual(@as(usize, 0), t.cursor.x);
|
||||||
@ -750,19 +763,19 @@ test "Terminal: insertLines" {
|
|||||||
defer t.deinit(alloc);
|
defer t.deinit(alloc);
|
||||||
|
|
||||||
// Initial value
|
// Initial value
|
||||||
try t.print(alloc, 'A');
|
try t.print('A');
|
||||||
t.carriageReturn();
|
t.carriageReturn();
|
||||||
t.linefeed(alloc);
|
t.linefeed();
|
||||||
try t.print(alloc, 'B');
|
try t.print('B');
|
||||||
t.carriageReturn();
|
t.carriageReturn();
|
||||||
t.linefeed(alloc);
|
t.linefeed();
|
||||||
try t.print(alloc, 'C');
|
try t.print('C');
|
||||||
t.carriageReturn();
|
t.carriageReturn();
|
||||||
t.linefeed(alloc);
|
t.linefeed();
|
||||||
try t.print(alloc, 'D');
|
try t.print('D');
|
||||||
t.carriageReturn();
|
t.carriageReturn();
|
||||||
t.linefeed(alloc);
|
t.linefeed();
|
||||||
try t.print(alloc, 'E');
|
try t.print('E');
|
||||||
|
|
||||||
// Move to row 2
|
// Move to row 2
|
||||||
t.setCursorPos(2, 1);
|
t.setCursorPos(2, 1);
|
||||||
@ -783,25 +796,25 @@ test "Terminal: insertLines with scroll region" {
|
|||||||
defer t.deinit(alloc);
|
defer t.deinit(alloc);
|
||||||
|
|
||||||
// Initial value
|
// Initial value
|
||||||
try t.print(alloc, 'A');
|
try t.print('A');
|
||||||
t.carriageReturn();
|
t.carriageReturn();
|
||||||
t.linefeed(alloc);
|
t.linefeed();
|
||||||
try t.print(alloc, 'B');
|
try t.print('B');
|
||||||
t.carriageReturn();
|
t.carriageReturn();
|
||||||
t.linefeed(alloc);
|
t.linefeed();
|
||||||
try t.print(alloc, 'C');
|
try t.print('C');
|
||||||
t.carriageReturn();
|
t.carriageReturn();
|
||||||
t.linefeed(alloc);
|
t.linefeed();
|
||||||
try t.print(alloc, 'D');
|
try t.print('D');
|
||||||
t.carriageReturn();
|
t.carriageReturn();
|
||||||
t.linefeed(alloc);
|
t.linefeed();
|
||||||
try t.print(alloc, 'E');
|
try t.print('E');
|
||||||
|
|
||||||
t.setScrollingRegion(1, 2);
|
t.setScrollingRegion(1, 2);
|
||||||
t.setCursorPos(1, 1);
|
t.setCursorPos(1, 1);
|
||||||
try t.insertLines(alloc, 1);
|
try t.insertLines(alloc, 1);
|
||||||
|
|
||||||
try t.print(alloc, 'X');
|
try t.print('X');
|
||||||
|
|
||||||
{
|
{
|
||||||
var str = try t.plainString(testing.allocator);
|
var str = try t.plainString(testing.allocator);
|
||||||
@ -816,19 +829,19 @@ test "Terminal: insertLines more than remaining" {
|
|||||||
defer t.deinit(alloc);
|
defer t.deinit(alloc);
|
||||||
|
|
||||||
// Initial value
|
// Initial value
|
||||||
try t.print(alloc, 'A');
|
try t.print('A');
|
||||||
t.carriageReturn();
|
t.carriageReturn();
|
||||||
t.linefeed(alloc);
|
t.linefeed();
|
||||||
try t.print(alloc, 'B');
|
try t.print('B');
|
||||||
t.carriageReturn();
|
t.carriageReturn();
|
||||||
t.linefeed(alloc);
|
t.linefeed();
|
||||||
try t.print(alloc, 'C');
|
try t.print('C');
|
||||||
t.carriageReturn();
|
t.carriageReturn();
|
||||||
t.linefeed(alloc);
|
t.linefeed();
|
||||||
try t.print(alloc, 'D');
|
try t.print('D');
|
||||||
t.carriageReturn();
|
t.carriageReturn();
|
||||||
t.linefeed(alloc);
|
t.linefeed();
|
||||||
try t.print(alloc, 'E');
|
try t.print('E');
|
||||||
|
|
||||||
// Move to row 2
|
// Move to row 2
|
||||||
t.setCursorPos(2, 1);
|
t.setCursorPos(2, 1);
|
||||||
@ -842,3 +855,63 @@ test "Terminal: insertLines more than remaining" {
|
|||||||
try testing.expectEqualStrings("A", str);
|
try testing.expectEqualStrings("A", str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "Terminal: reverseIndex" {
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
var t = try init(alloc, 2, 5);
|
||||||
|
defer t.deinit(alloc);
|
||||||
|
|
||||||
|
// Initial value
|
||||||
|
try t.print('A');
|
||||||
|
t.carriageReturn();
|
||||||
|
t.linefeed();
|
||||||
|
try t.print('B');
|
||||||
|
t.carriageReturn();
|
||||||
|
t.linefeed();
|
||||||
|
try t.print('C');
|
||||||
|
try t.reverseIndex();
|
||||||
|
try t.print('D');
|
||||||
|
t.carriageReturn();
|
||||||
|
t.linefeed();
|
||||||
|
t.carriageReturn();
|
||||||
|
t.linefeed();
|
||||||
|
|
||||||
|
{
|
||||||
|
var str = try t.plainString(testing.allocator);
|
||||||
|
defer testing.allocator.free(str);
|
||||||
|
try testing.expectEqualStrings("A\nBD\nC", str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test "Terminal: reverseIndex from the top" {
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
var t = try init(alloc, 2, 5);
|
||||||
|
defer t.deinit(alloc);
|
||||||
|
|
||||||
|
try t.print('A');
|
||||||
|
t.carriageReturn();
|
||||||
|
t.linefeed();
|
||||||
|
try t.print('B');
|
||||||
|
t.carriageReturn();
|
||||||
|
t.linefeed();
|
||||||
|
t.carriageReturn();
|
||||||
|
t.linefeed();
|
||||||
|
|
||||||
|
t.setCursorPos(1, 1);
|
||||||
|
try t.reverseIndex();
|
||||||
|
try t.print('D');
|
||||||
|
|
||||||
|
t.carriageReturn();
|
||||||
|
t.linefeed();
|
||||||
|
t.setCursorPos(1, 1);
|
||||||
|
try t.reverseIndex();
|
||||||
|
try t.print('E');
|
||||||
|
t.carriageReturn();
|
||||||
|
t.linefeed();
|
||||||
|
|
||||||
|
{
|
||||||
|
var str = try t.plainString(testing.allocator);
|
||||||
|
defer testing.allocator.free(str);
|
||||||
|
try testing.expectEqualStrings("E\nD\nA\nB", str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user