| /** | |
| * Moves cursor forward (right) by specified number of columns. | |
| * @param count - Number of columns to move forward (default: 1) | |
| * @returns ANSI escape sequence string | |
| */ | |
| export function cursorForward(count: number = 1) { | |
| if (count === 0) return ""; | |
| return `\x1b[${count}C`; | |
| } | |
| /** | |
| * Moves cursor up by specified number of rows. | |
| * @param count - Number of rows to move up (default: 1) | |
| * @param context - Object containing appHeight and terminalHeight | |
| * @returns ANSI escape sequence string | |
| */ | |
| export function cursorUp( | |
| count: number = 1, | |
| context: { appHeight: number; terminalHeight: number }, | |
| ) { | |
| // Ink appends a newline after output unless the app height exceeds the terminal height | |
| // See https://github.com/vadimdemedes/ink/blob/76d221c3639f62c8c2f6c3599d51a1bf51ed1b7b/src/ink.tsx#L1040-L1042 | |
| // So we need to adjust the cursor movement by one row in that case to account for the absence of the newline | |
| const movementCount = | |
| context.appHeight >= context.terminalHeight ? count - 1 : count; | |
| if (movementCount <= 0) return ""; | |
| return `\x1b[${movementCount}A`; | |
| } | |