From 5b70f208bc6870bb32f13720376840edc3c5ed31 Mon Sep 17 00:00:00 2001 From: Uzair Aftab Date: Sun, 2 Aug 2026 23:12:53 +0200 Subject: [PATCH] terminal: print repeated characters through printSlice While doing some work on my tmux fork I noticed multiple parts of libghostty-vt was slower than tmux equivalents(isolated). Turns out they do some smart stuff there. printRepeat called print() once per repeat, so something like \x1b[2000b ran grapheme checks, width lookups, wrap handling, etc etc 2000 times. printSlice is already documented as semantically identical to calling print per codepoint, so this just feeds the repeated codepoint through it in 4096-entry stack chunks. Simple runs take the batched fast path, and anything that needs care falls back to the previous behaviour. --- src/terminal/Terminal.zig | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/terminal/Terminal.zig b/src/terminal/Terminal.zig index b73b0a53d..92bb9e690 100644 --- a/src/terminal/Terminal.zig +++ b/src/terminal/Terminal.zig @@ -490,9 +490,19 @@ pub fn printString(self: *Terminal, str: []const u8) !void { /// Print the previous printed character a repeated amount of times. pub fn printRepeat(self: *Terminal, count_req: usize) !void { - if (self.previous_char) |c| { - const count = @max(count_req, 1); - for (0..count) |_| try self.print(c); + const c = self.previous_char orelse return; + var remaining = @max(count_req, 1); + + // Print the repeated codepoint in slices so that eligible runs + // take the batched printSlice fast path. printSlice is semantically + // identical to calling print per codepoint: ineligible characters + // or terminal states (insert mode, grapheme clustering, hyperlinks, + // etc.) fall back to the per-codepoint print() path internally. + var buf: [4096]u32 = @splat(c); + while (remaining > 0) { + const n = @min(remaining, buf.len); + try self.printSlice(buf[0..n]); + remaining -= n; } }