authorgravatar for git@paperclover.netclover caruso <git@paperclover.net> 2026-03-17 23:48:29-07:00
committergravatar for git@paperclover.netclover caruso <git@paperclover.net> 2026-03-21 18:03:28-07:00
log5b403d91b350d337f743d3a99ac0637fd3c12953
treea010799cfbc394934da44161341b1abc71368834
parent2f082aadf24befd5d4005e5734216bd23f5af84c
signature Signed by SSH key SHA256:xbd+BjjhyBfwk7GVoURf9Yx0gzDerHbvYv7SddNWmAs

fix: bug in `trimForTerminal` with ansi escapes


4 files changed, 10 insertions(+), 8 deletions(-)

lib/log.ts+1-1
...@@ -404,7 +404,7 @@ export function createWidgetHost(env: WidgetHostOptions): WidgetHost {...@@ -404,7 +404,7 @@ export function createWidgetHost(env: WidgetHostOptions): WidgetHost {
404 if (rowsLeft === 1) break;404 if (rowsLeft === 1) break;
405 const lines = outText.split("\n").slice(0, rowsLeft);405 const lines = outText.split("\n").slice(0, rowsLeft);
406 newWidgetLines.push(406 newWidgetLines.push(
407 ...lines.map((line) => ansi.trimToWidth(line, columns - 1)),407 ...lines.map((line) => ansi.trimForTerminal(line, columns - 1)),
408 );408 );
409409
410 next = Math.min(next, UNWRAP(internals[w]).frameTime);410 next = Math.min(next, UNWRAP(internals[w]).frameTime);
lib/readme.changes.md+4-1
...@@ -22,7 +22,9 @@...@@ -22,7 +22,9 @@
22 you to give some information about where the cursor was moved to.22 you to give some information about where the cursor was moved to.
23 - messages now do not imply a newline23 - messages now do not imply a newline
24- `render` is now deprecated with no replacement. in the downstream `sitegen`24- `render` is now deprecated with no replacement. in the downstream `sitegen`
25 project, the entire codebase is moving to Marko after depending on both renderers.25 project, the codebase is moving to Marko after depending on both renderers.
26- `string/ansi`
27 - rename `trimToWidth` to `trimForTerminal`
2628
27### features29### features
2830
...@@ -36,6 +38,7 @@...@@ -36,6 +38,7 @@
36 a newline.38 a newline.
37- `async.delay` handles timers longer than 23 days.39- `async.delay` handles timers longer than 23 days.
38- `Lru.revive` recieves bug fixes. this function previously didn't really work.40- `Lru.revive` recieves bug fixes. this function previously didn't really work.
41- `ansi` gets more cursor control constants
3942
40## v343## v3
4144
lib/string/ansi.test.ts+3-3
...@@ -8,13 +8,13 @@ test("widthInTerminal", () => {...@@ -8,13 +8,13 @@ test("widthInTerminal", () => {
8 9,8 9,
9 );9 );
10});10});
11test("trimToWidth", () => {11test("trimForTerminal", () => {
12 assert.equal(12 assert.equal(
13 ansi.trimToWidth("snowmobile", 6),13 ansi.trimForTerminal("snowmobile", 6),
14 "snowmo",14 "snowmo",
15 );15 );
16 assert.equal(16 assert.equal(
17 ansi.trimToWidth("🏳️‍⚧️ " + ansi.style(ansi.bold, "rights"), 5),17 ansi.trimForTerminal("🏳️‍⚧️ " + ansi.style(ansi.bold, "rights"), 5),
18 "🏳️‍⚧️ " + ansi.bold + "ri" + ansi.reset,18 "🏳️‍⚧️ " + ansi.bold + "ri" + ansi.reset,
19 );19 );
20});20});
lib/string/ansi.ts+2-3
...@@ -277,8 +277,7 @@ export function widthInTerminal(str: string): number {...@@ -277,8 +277,7 @@ export function widthInTerminal(str: string): number {
277 * Like `str.slice(0, columns)`, but respecting width in a terminal.277 * Like `str.slice(0, columns)`, but respecting width in a terminal.
278 * preserves ansi escape sequences.278 * preserves ansi escape sequences.
279 */279 */
280// TODO: rename to trimForTerminal280export function trimForTerminal(str: string, columns: number): string {
281export function trimToWidth(str: string, columns: number): string {
282 segmenter ??= new Intl.Segmenter();281 segmenter ??= new Intl.Segmenter();
283 let width = 0;282 let width = 0;
284 let ansi = false;283 let ansi = false;
...@@ -286,7 +285,7 @@ export function trimToWidth(str: string, columns: number): string {...@@ -286,7 +285,7 @@ export function trimToWidth(str: string, columns: number): string {
286 const code = str.charCodeAt(i);285 const code = str.charCodeAt(i);
287 if (code < 32) {286 if (code < 32) {
288 if (code === 0x1b) {287 if (code === 0x1b) {
289 const esc = str.slice().match(ansiEscapes);288 const esc = str.slice(i).match(ansiEscapes);
290 if (esc) i += esc[0].length - 1, ansi = true;289 if (esc) i += esc[0].length - 1, ansi = true;
291 }290 }
292 continue;291 continue;