Cursor positioning after line wrap
When inquirer/prompts line wraps, it seems to frequently mis-position the cursor: https://vimeo.com/manage/videos/1110980503
I've found that it is consistently replicable if I back-space to the previous line. The mis-positioning seems to be similar to the number of characters used for the ANSI color codes around the '?' at the beginning of the line (but that's just a guess).
I'm curious if anyone else can replicate this problem or if it's just me?
Simple replication code is here:
import { input } from '@inquirer/prompts';
const result = await input({
message: 'Type a long line that wraps to see cursor bug:',
});
Interesting, what's your terminal? I was able to reproduce with Warp.
On Warp, I think what happens is the terminal decides to wrap words. Once it does the correct cursor position is lost. I also see that if it's a whitespace causing the wrapping, then there's no issue; the cursor doesn't end up out of sync with the content.
I'm not 100% sure how to address that problem. Maybe we could review how breakLines is implemented so that we force the word-wrapping on all terminals. And then somehow ensure we set the cursor position in a way that'll work across terminals that force a word-wrap on line returns and those that don't.
If someone wants to research options here, help is welcomed as I don't think I'll have time to dig into this one in the coming weeks. š¤š»
I'm using Termius on iPad.
Let me see if I can figure out some options.
@SBoudrias, can I work on this issue?
@MazenSamehR absolutely! I appreciate it š
@SBoudrias I think I found the root cause: wrap-ansi is mainly a word wrapper, not a strict character wrapper. Even with { hard: true }, it still prefers breaking on spaces and only splits mid-word when a single word exceeds the terminal width.
export function breakLines(content: string, width: number): string {
return content
.split('\n')
.flatMap((line) =>
wrapAnsi(line, width, { trim: false, hard: true })
.split('\n')
.map((str) => str.trimEnd()),
)
.join('\n');
}
That means terminals that do their own wrapping can end up disagreeing with our expected wrap points.
Would you be OK if I replace wrap-ansi here with a strict character-based ANSI-safe wrapper, so we can force deterministic wrapping across terminals?
@MazenSamehR okay for me, but I'd prefer not adding an extra dependency if we can save it. If we need one, let's make sure it's maintained by reputable community members.
Totally agreed, Iād also prefer avoiding a new dependency if possible. I can implement a small internal char wrapper in breakLines() to force deterministic wrapping.