authorgravatar for git@paperclover.netclover caruso <git@paperclover.net> 2026-01-12 21:50:39-08:00
committergravatar for git@paperclover.netclover caruso <git@paperclover.net> 2026-03-21 18:03:28-07:00
log5d86be6df8d71ae44648092495743af3856e7a43
treee3d1bfb3d733c3fdbb7f4234633ff7a3a9e1af5a
parentcc38595e32e4d7e0ea1b6c76a91bb71adf34c3ec
signature Signed by SSH key SHA256:xbd+BjjhyBfwk7GVoURf9Yx0gzDerHbvYv7SddNWmAs

feat(lib/ansi): more cursor control codes

- movement: `cursorDown`, `cursorRight`, and `cursorLeft` - `cursorSave` and `cursorRestore`

1 files changed, 22 insertions(+), 1 deletions(-)

lib/string/ansi.ts+22-1
...@@ -131,10 +131,27 @@ export function bgRgb(r: number, g: number, b: number): string {...@@ -131,10 +131,27 @@ export function bgRgb(r: number, g: number, b: number): string {
131131
132// cursor management132// cursor management
133133
134/** save the position of the cursor, restored with {@linkcode cursorRestore}. */
135export const cursorSave: string = "\x1b7";
136/** restore the position of the cursor, saved with {@linkcode cursorSave}. */
137export const cursorRestore: string = "\x1b8";
138
134/** move the cursor up `n` units. */139/** move the cursor up `n` units. */
135export function cursorUp(n: number): string {140export function cursorUp(n: number): string {
136 return n ? `\x1b[${n}A` : "";141 return n ? `\x1b[${n}A` : "";
137}142}
143/** move the cursor down `n` units. */
144export function cursorDown(n: number): string {
145 return n ? `\x1b[${n}B` : "";
146}
147/** move the cursor right `n` units. */
148export function cursorRight(n: number): string {
149 return n ? `\x1b[${n}C` : "";
150}
151/** move the cursor right `n` units. */
152export function cursorLeft(n: number): string {
153 return n ? `\x1b[${n}D` : "";
154}
138/** move the cursor to the start of it's current line. */155/** move the cursor to the start of it's current line. */
139export const startOfLine: string = "\r";156export const startOfLine: string = "\r";
140/** move the cursor to the start of the next line. */157/** move the cursor to the start of the next line. */
...@@ -211,7 +228,8 @@ export function debugAnsi(text: string): string {...@@ -211,7 +228,8 @@ export function debugAnsi(text: string): string {
211 "fgMagenta", "fgWhite", "fgBrightBlack", "fgBrightRed",228 "fgMagenta", "fgWhite", "fgBrightBlack", "fgBrightRed",
212 "fgBrightGreen", "fgBrightYellow", "fgBrightBlue", "fgBrightMagenta",229 "fgBrightGreen", "fgBrightYellow", "fgBrightBlue", "fgBrightMagenta",
213 "fgBrightCyan", "fgBrightWhite", "clearToEndOfLine", "clearToStartOfLine",230 "fgBrightCyan", "fgBrightWhite", "clearToEndOfLine", "clearToStartOfLine",
214 "clearFullLine", "syncStart", "syncEnd", "bold", "dim", "resetWeight"231 "clearFullLine", "syncStart", "syncEnd", "bold", "dim", "resetWeight",
232 "cursorSave", "cursorRestore"
215 ];233 ];
216 for (const key of verbaitim) {234 for (const key of verbaitim) {
217 text = text.replaceAll(235 text = text.replaceAll(
...@@ -220,6 +238,9 @@ export function debugAnsi(text: string): string {...@@ -220,6 +238,9 @@ export function debugAnsi(text: string): string {
220 );238 );
221 }239 }
222 text = text.replace(/\x1b\[(\d+)A/g, style(fgYellow, "$${cursorUp($1)}"));240 text = text.replace(/\x1b\[(\d+)A/g, style(fgYellow, "$${cursorUp($1)}"));
241 text = text.replace(/\x1b\[(\d+)B/g, style(fgYellow, "$${cursorDown($1)}"));
242 text = text.replace(/\x1b\[(\d+)C/g, style(fgYellow, "$${cursorRight($1)}"));
243 text = text.replace(/\x1b\[(\d+)D/g, style(fgYellow, "$${cursorLeft($1)}"));
223 text = text.replace(/\n/g, style(fgRed, "\\n"));244 text = text.replace(/\n/g, style(fgRed, "\\n"));
224 text = text.replace(/\r/g, style(fgMagenta, "\\r"));245 text = text.replace(/\r/g, style(fgMagenta, "\\r"));
225 return text;246 return text;