8ef11355e7
- Added native text utilities in pi-natives (visible width, truncation, slicing, segment extraction) - Wired pi-tui to use native implementations with short-string JS fast path - Optimized key matching via cached parsed key ids - Refactored visual truncation to reuse Text instances - Reduced theme color lookups by switching from Map to plain records - Regenerated WASM artifacts Benchmarks (after vs before, lower is better): - truncateToWidth/ansi: 20.37ms vs 38.13ms (2000 iters) - sliceWithWidth/ansi: 5.12ms vs 20.39ms - extractSegments/ansi: 8.92ms vs 27.60ms - truncateToVisualLines: 3.51ms vs 411.55ms (500 iters) - visibleWidth/ansi: 0.24ms vs 0.31ms
58 lines
1.7 KiB
TypeScript
58 lines
1.7 KiB
TypeScript
import { visibleWidth, wrapTextWithAnsi, truncateToWidth, sliceWithWidth, extractSegments } from "../src/utils";
|
|
import { matchesKey } from "../src/keys";
|
|
|
|
const ITERATIONS = 2000;
|
|
|
|
const samples = {
|
|
plain: "hello world this is a plain ASCII string with some words",
|
|
ansi: "\x1b[31mred text\x1b[0m and \x1b[4munderlined content\x1b[24m with emoji 😅😅",
|
|
links: "prefix \x1b]8;;https://example.com\x07link\x1b]8;;\x07 suffix",
|
|
wide: "日本語のテキストとemoji 🚀✨ mixed with ascii",
|
|
wrapped: "This is a long line that should wrap multiple times when rendered with ANSI \x1b[32mcolors\x1b[0m and tabs\tbetween words.",
|
|
};
|
|
|
|
const wrapWidth = 40;
|
|
|
|
function bench(name: string, fn: () => void): number {
|
|
const start = performance.now();
|
|
for (let i = 0; i < ITERATIONS; i++) {
|
|
fn();
|
|
}
|
|
const elapsed = performance.now() - start;
|
|
const perOp = (elapsed / ITERATIONS).toFixed(4);
|
|
console.log(`${name}: ${elapsed.toFixed(2)}ms total (${perOp}ms/op)`);
|
|
return elapsed;
|
|
}
|
|
|
|
console.log(`Text layout benchmark (${ITERATIONS} iterations)\n`);
|
|
|
|
bench("visibleWidth/plain", () => {
|
|
visibleWidth(samples.plain);
|
|
});
|
|
|
|
bench("visibleWidth/ansi", () => {
|
|
visibleWidth(samples.ansi);
|
|
});
|
|
|
|
bench("truncateToWidth/ansi", () => {
|
|
truncateToWidth(samples.ansi, 32, "…", true);
|
|
});
|
|
|
|
bench("wrapTextWithAnsi/ansi", () => {
|
|
wrapTextWithAnsi(samples.wrapped, wrapWidth);
|
|
});
|
|
|
|
bench("sliceWithWidth/ansi", () => {
|
|
sliceWithWidth(samples.ansi, 3, 18, true);
|
|
});
|
|
|
|
bench("extractSegments/ansi", () => {
|
|
extractSegments(samples.ansi, 10, 20, 15, true);
|
|
});
|
|
|
|
bench("matchesKey", () => {
|
|
matchesKey("\x1b[A", "up");
|
|
matchesKey("\x1b[1;5C", "ctrl+right");
|
|
matchesKey("\x1b[1;2D", "shift+left");
|
|
});
|