summaryrefslogtreecommitdiff
path: root/main.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-07-02 20:06:25 -0300
committerGabriel Schneider <[email protected]>2026-08-01 15:02:07 -0300
commitbead9f0b78380d1428f40fdab339c1c8f88fa626 (patch)
tree960255de5a2cef661ec5d0ad3220a4b2b1738842 /main.zig
parent62ef1882ab7878210f05f06504796849e412c318 (diff)
downloadpardes-bead9f0b78380d1428f40fdab339c1c8f88fa626.tar.gz
pardes-bead9f0b78380d1428f40fdab339c1c8f88fa626.zip
sdl ui backend
Diffstat (limited to 'main.zig')
-rw-r--r--main.zig54
1 files changed, 39 insertions, 15 deletions
diff --git a/main.zig b/main.zig
index 582fc133..d5cfa6c0 100644
--- a/main.zig
+++ b/main.zig
@@ -1,5 +1,5 @@
const std = @import("std");
-const vaxis = @import("vaxis");
+const vaxis = @import("ui");
const ghostty_vt = @import("ghostty-vt");
const Term = @import("term.zig");
const modal = @import("modal.zig");
@@ -191,6 +191,7 @@ const MINW: u16 = 10; // min pane width (cells)
const MINH: u16 = 3; // min pane height (cells)
const MAX_TERMS: usize = 16;
const MAX_COLS: usize = 6;
+const MAX_PTY_DRAIN_EVENTS: usize = 128;
const PREFIX_W: u16 = 5; // file-pane line-number prefix width: "%4d "
const Rect = struct { x: u16, y: u16, w: u16, h: u16 };
@@ -767,10 +768,10 @@ fn pty_set_size(pty: std.Io.File, rows: u16, cols: u16) void {
// One reader task per terminal. Tags each chunk with the terminal's slot id so
// the main loop knows which emulator to feed; posts pty_eof when the shell exits.
fn readPty(io: std.Io, gpa: std.mem.Allocator, pty: std.Io.File, id: usize, loop: *Loop) anyerror!void {
- var read_buf: [0x1000]u8 = undefined;
+ var read_buf: [0x10000]u8 = undefined;
var reader = pty.readerStreaming(io, &read_buf);
while (true) {
- var buf: [0x1000]u8 = undefined;
+ var buf: [0x10000]u8 = undefined;
var vec = [_][]u8{&buf};
const n = reader.interface.readVec(&vec) catch break;
if (n == 0) break;
@@ -783,6 +784,19 @@ fn readPty(io: std.Io, gpa: std.mem.Allocator, pty: std.Io.File, id: usize, loop
loop.postEvent(.{ .pty_eof = id }) catch {};
}
+fn feedPtyRead(gpa: std.mem.Allocator, terms: *[MAX_TERMS]?*Term, active: usize, pr: PtyRead) void {
+ defer gpa.free(pr.bytes);
+ if (pr.id >= MAX_TERMS) return;
+ if (terms[pr.id]) |t| {
+ t.stream.nextSlice(pr.bytes);
+ // follow new output to the bottom, so a command's result shows even in a
+ // pane you didn't focus. Exception: the pane you're actively navigating
+ // in a text mode — don't yank the cursor out from under you.
+ if (!(pr.id == active and t.mode != .tty))
+ t.term.screens.active.scroll(.active);
+ }
+}
+
// fork the pty + boot the emulator. Forking is the dangerous part in a
// multithreaded process, so this does NOT start the reader task (no new
// threads) — call startReader once the term is wired in.
@@ -3054,9 +3068,14 @@ pub fn main(init: std.process.Init) !void {
// middle release, freed on overwrite / app exit.
var chord_arg: ?[]u8 = null;
defer if (chord_arg) |a| gpa.free(a);
+ var pending_event: ?@TypeOf(Command.value) = null;
while (true) {
- const event = try loop.nextEvent();
+ const event = if (pending_event) |ev| blk: {
+ pending_event = null;
+ break :blk ev;
+ } else try loop.nextEvent();
+ var drain_pty_after = false;
switch (event) {
.mouse => |mouse| {
const mcol: u16 = if (mouse.col < 0) 0 else @min(@as(u16, @intCast(mouse.col)), screen_w -| 1);
@@ -3341,7 +3360,6 @@ pub fn main(init: std.process.Init) !void {
}
},
.key_press => |key| kpress: {
-
if (terms[active]) |at| {
// Ctrl-w prefix: helix-style pane focus (Ctrl-w h/j/k/l).
if (ctrl_w_pending) {
@@ -3461,16 +3479,8 @@ pub fn main(init: std.process.Init) !void {
}
},
.pty_read => |pr| {
- defer gpa.free(pr.bytes);
- if (terms[pr.id]) |t| {
- t.stream.nextSlice(pr.bytes);
- // follow new output to the bottom, so a command's result shows
- // even in a pane you didn't focus. Exception: the pane you're
- // actively navigating in a text mode — don't yank the cursor out
- // from under you (it still tracks the bottom on its own there).
- if (!(pr.id == active and t.mode != .tty))
- t.term.screens.active.scroll(.active);
- }
+ feedPtyRead(gpa, &terms, active, pr);
+ drain_pty_after = true;
},
.pty_eof => |id| {
if (terms[id]) |t| {
@@ -3507,6 +3517,20 @@ pub fn main(init: std.process.Init) !void {
else => {},
}
+ if (drain_pty_after) {
+ var drained: usize = 0;
+ while (drained < MAX_PTY_DRAIN_EVENTS) : (drained += 1) {
+ const next = try loop.tryEvent() orelse break;
+ switch (next) {
+ .pty_read => |pr| feedPtyRead(gpa, &terms, active, pr),
+ else => {
+ pending_event = next;
+ break;
+ },
+ }
+ }
+ }
+
// a fresh yank (y/d/c) mirrors out to the system clipboard via OSC 52. Emit
// here where the tty writer + vx are in scope; the vx.render() below flushes.
// ponytail: OSC 52 has a per-terminal size cap, so a huge yank may be