peterh / liner

Pure Go line editor with history, inspired by linenoise
MIT License
1.04k stars 132 forks source link

Using ansi color escape sequences in prompts causes problems #29

Closed gabriel-comeau closed 9 years ago

gabriel-comeau commented 9 years ago

When I use color sequences in my prompt string I get problems with any non-printing characters afterwards. For example, if I set my prompt to something like this:

line.Prompt("\x1b[0;32mPrompt>\x1b[0m ")

Whenever I hit "up" to view the history, it prints the string correctly at the beginning of the line but then adds tons of white space to the end it. If I try to erase characters from this, the cursor remains far down the line (after the white space) but the characters do get erased.

So either I misunderstood the \x1b[0m reset code's function or something else is going on I'm unaware of.

peterh commented 9 years ago

That's unlikely to work. Sorry.

liner assumes that each rune in a string is one VT100 character wide. You'll see the same bug with combining runes (eg. if you use "e\u0301" instead of "\u00c9" for é) and with double-width runes (some languages/fonts have runes that are twice as wide, for some reason).

I'd accept a patch to fix the width calculation of combining runes. I'm less likely to accept a patch that will parse ANSI escape sequences in the prompt. My goal with liner is cross-compiled portability first, and ANSI sequences don't work on Windows (without a compatibility library) or when $TERM=dumb.

gabriel-comeau commented 9 years ago

In the interim I'd looked into it and saw those calls in refresh() to utf8.RuneCountInString() and figured this was what was going on.

I did this pretty ugly hack in the meantime, which fixes my problem for the moment: https://github.com/gabriel-comeau/liner/commit/4f4c480a1a49aaaf61d57f8cc3ffcf561dbff308

I'd understand if you don't want to pull this in - I wouldn't either!

If I get some time, I will look into the width calculations though - that could be very worthwhile!

peterh commented 9 years ago

http://godoc.org/golang.org/x/text/unicode/norm Iter might help with the rune width calculations. If you don't beat me to it, I'll look into it the next time I have a chance (which is not likely in the next couple of weeks).

peterh commented 9 years ago

Iter only works on normalized runes, and I'd rather return input runes as-is, if possible. Decomposed glyphs now have at least minimal support, without using Iter.