widgets(terminal): handle horizontal tabs
This commit is contained in:
parent
1c5ecae8f0
commit
c14a100eed
2 changed files with 52 additions and 12 deletions
|
@ -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())
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue