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.
This commit is contained in:
Uzair Aftab
2026-08-02 23:12:53 +02:00
parent 9e30f70f23
commit 5b70f208bc

View File

@@ -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;
}
}