peterh / liner

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

Invalid Prompt: Color codes #123

Closed aarondl closed 4 years ago

aarondl commented 4 years ago

Hi there @peterh,

Curious why the decision to prevent color codes from being used in a prompt. Out of curiosity I tried removing the checks and it behaves fine.

Maybe it's a case of needing to blacklist/whitelist it on certain systems?

peterh commented 4 years ago

Removing the check: It may appear to behave fine in a limited test, but if your line becomes long enough (or your terminal window becomes narrow enough) you will see liner starts to wrap the line too soon.

Blacklist one platform: No, I will never do that. Liner is vehemently cross-platform. It only supports things that are supported on all platforms.

I'm not inclined to accept any more features at this time. But if I were to accept a colored prompt feature, I would be more likely to accept something with sane syntax (eg. a subset of asciidoc, or a subset of LaTeX/xcolor, or maybe even a subset of HTML) that could be turned into out-of-band color on Windows (or in-band VT100 on everything else), than I would be to accept a VT100 parser.

aarondl commented 4 years ago

In regards to removing the check, you're right. I had thought there was no support baked into the https://github.com/chzyer/readline library but there is, they strip the ANSI codes in order to count the number of runes properly. Not a bad way to do it. I'm trying to move away from that package because it's been abandoned (last commit 2 years ago, no response to issues or PRs, owner stop posting on his twitter linked in the README in 2016).

I didn't want to add any features to this package, just stop it from getting in the way. Of course it appears there would need to be a platform specific rune counting which I suppose is a feature, but it's backwards compatible and invisible at the API level which makes it a pretty appealing change.

Typical color prompt code on Linux/Mac looks like:

l, err := liner.Prompt(color.FgBlue.Sprint("color >"))

For applications that desire color prompts this could simply work. Color packages typically have the ability to turn off color output (#1 #2) so as to avoid the dreaded InvalidPrompt error on systems where the check is still in place (in fact at least the gookit/color one doesn't even need to disable it, since Sprint cannot possibly work it simply returns the string on platforms where ansi codes don't work, no code change required!).

Downside of course is that it could never work on Windows since colors cannot simply be injected in strings as such, you need to use system calls to set the attributes on the terminal before printing the string. Perhaps a package like this one: https://github.com/mattn/go-colorable could be used to allow ansi codes to also work on windows though I 100000% understand not wanting to add any dependencies but perhaps a way to set the underlying writer would be all that's necessary.

To summarize: It seems very possible to add a backwards compatible "stop getting in the way" method of counting runes so as to not get in the way of ansi color codes on systems that support them as a behavioral change and not an API change. Downside being Windows support may not be achievable without a larger feature as you're suggesting (some sort of magic language for color that this package invents) because of the need for syscalls.

Perhaps in this context you might reconsider, if not, well at least I tried and it's time to fork that readline package and merge in all the bug fix PRs /sigh. Open source is hard isn't it? :)

ghost-ng commented 1 year ago

For a work around, you can print the text with colors as you normally would, do not end with a newline - then with liner set the prompt to "" (empty string)

liner.Prompt("")

I did this in windows

downside: inline editing completely clears in out so maybe not as useful

hedyhli commented 1 year ago

I'm trying to move away from that package because it's been abandoned (last commit 2 years ago, no response to issues or PRs, owner stop posting on his twitter linked in the README in 2016).

(Note to others reading the thread) It appears the owner is back since 2021 with both twitter and github repo activity.

For a work around, you can print the text with colors as you normally would, do not end with a newline - then with liner set the prompt to "" (empty string)

liner.Prompt("")

I did this in windows

downside: inline editing completely clears in out so maybe not as useful

My workaround is to set color start before liner.Prompt, then reset color afterwards. The downside for this is that user’s input is also applied the same color. However, this keeps the prompt text while also providing visual separation between prompt input line and outputs.