widgets(terminal): handle horizontal tabs

This commit is contained in:
Tim Culverhouse 2024-06-10 06:37:10 -05:00
parent 1c5ecae8f0
commit c14a100eed
2 changed files with 52 additions and 12 deletions

View file

@ -332,6 +332,19 @@ pub fn cursorLeft(self: *Screen, n: usize) void {
self.cursor.col = self.cursor.col -| n; self.cursor.col = self.cursor.col -| n;
} }
pub fn cursorRight(self: *Screen, n: usize) void {
if (self.withinScrollingRegion())
self.cursor.col = @min(
self.cursor.col + n,
self.scrolling_region.right,
)
else
self.cursor.col = @min(
self.cursor.col + n,
self.width,
);
}
pub fn cursorDown(self: *Screen, n: usize) void { pub fn cursorDown(self: *Screen, n: usize) void {
self.cursor.pending_wrap = false; self.cursor.pending_wrap = false;
if (self.withinScrollingRegion()) if (self.withinScrollingRegion())

View file

@ -67,6 +67,8 @@ should_quit: bool = false,
mode: Mode = .{}, mode: Mode = .{},
tab_stops: std.ArrayList(u16),
event_queue: Queue = .{}, event_queue: Queue = .{},
/// initialize a Terminal. This sets the size of the underlying pty and allocates the sizes of the /// initialize a Terminal. This sets the size of the underlying pty and allocates the sizes of the
@ -85,6 +87,11 @@ pub fn init(
.env_map = env, .env_map = env,
.pty = pty, .pty = pty,
}; };
var tabs = try std.ArrayList(u16).initCapacity(allocator, opts.winsize.cols / 8);
var col: u16 = 0;
while (col < opts.winsize.cols) : (col += 8) {
try tabs.append(col);
}
return .{ return .{
.allocator = allocator, .allocator = allocator,
.pty = pty, .pty = pty,
@ -94,6 +101,7 @@ pub fn init(
.back_screen_pri = try Screen.init(allocator, opts.winsize.cols, opts.winsize.rows + opts.scrollback_size), .back_screen_pri = try Screen.init(allocator, opts.winsize.cols, opts.winsize.rows + opts.scrollback_size),
.back_screen_alt = try Screen.init(allocator, opts.winsize.cols, opts.winsize.rows), .back_screen_alt = try Screen.init(allocator, opts.winsize.cols, opts.winsize.rows),
.unicode = unicode, .unicode = unicode,
.tab_stops = tabs,
}; };
} }
@ -124,6 +132,7 @@ pub fn deinit(self: *Terminal) void {
self.front_screen.deinit(self.allocator); self.front_screen.deinit(self.allocator);
self.back_screen_pri.deinit(self.allocator); self.back_screen_pri.deinit(self.allocator);
self.back_screen_alt.deinit(self.allocator); self.back_screen_alt.deinit(self.allocator);
self.tab_stops.deinit();
} }
pub fn spawn(self: *Terminal) !void { pub fn spawn(self: *Terminal) !void {
@ -275,17 +284,7 @@ fn run(self: *Terminal) !void {
self.back_screen.cursor.pending_wrap = false; self.back_screen.cursor.pending_wrap = false;
var iter = seq.iterator(u16); var iter = seq.iterator(u16);
const delta = iter.next() orelse 1; const delta = iter.next() orelse 1;
const within = self.back_screen.withinScrollingRegion(); self.back_screen.cursorRight(delta);
if (within)
self.back_screen.cursor.col = @min(
self.back_screen.cursor.col + delta,
self.back_screen.scrolling_region.right,
)
else
self.back_screen.cursor.col = @min(
self.back_screen.cursor.col + delta,
self.back_screen.width,
);
}, },
// Cursor Left // Cursor Left
'D', 'j' => { 'D', 'j' => {
@ -307,6 +306,13 @@ fn run(self: *Terminal) !void {
self.back_screen.cursorUp(delta); self.back_screen.cursorUp(delta);
self.carriageReturn(); self.carriageReturn();
}, },
// Horizontal Positional Absolute
'G', '`' => {
var iter = seq.iterator(u16);
const col = iter.next() orelse 1;
self.back_screen.cursor.col = col -| 1;
},
// Cursor Absolute Position
'H', 'f' => { 'H', 'f' => {
var iter = seq.iterator(u16); var iter = seq.iterator(u16);
const row = iter.next() orelse 1; const row = iter.next() orelse 1;
@ -314,6 +320,11 @@ fn run(self: *Terminal) !void {
self.back_screen.cursor.col = col -| 1; self.back_screen.cursor.col = col -| 1;
self.back_screen.cursor.row = row -| 1; self.back_screen.cursor.row = row -| 1;
}, },
'I' => {
var iter = seq.iterator(u16);
const n = iter.next() orelse 1;
self.horizontalTab(n);
},
'K' => { 'K' => {
// TODO selective erase (private_marker == '?') // TODO selective erase (private_marker == '?')
var iter = seq.iterator(u8); var iter = seq.iterator(u8);
@ -392,7 +403,7 @@ inline fn handleC0(self: *Terminal, b: ansi.C0) !void {
.ENQ => {}, .ENQ => {},
.BEL => self.event_queue.push(.bell), .BEL => self.event_queue.push(.bell),
.BS => self.back_screen.cursorLeft(1), .BS => self.back_screen.cursorLeft(1),
.HT => {}, // TODO: HT .HT => self.horizontalTab(1),
.LF, .VT, .FF => try self.back_screen.index(), .LF, .VT, .FF => try self.back_screen.index(),
.CR => self.carriageReturn(), .CR => self.carriageReturn(),
.SO => {}, // TODO: Charset shift out .SO => {}, // TODO: Charset shift out
@ -444,3 +455,19 @@ pub fn carriageReturn(self: *Terminal) void {
else else
0; 0;
} }
pub fn horizontalTab(self: *Terminal, n: usize) void {
// Get the current cursor position
const col = self.back_screen.cursor.col;
// Find desired final position
var i: usize = 0;
const final = for (self.tab_stops.items) |ts| {
if (ts <= col) continue;
i += 1;
if (i == n) break ts;
} else self.back_screen.width - 1;
// Move right the delta
self.back_screen.cursorRight(final - col);
}