AlecAivazis / survey

A golang library for building interactive and accessible prompts with full support for windows and posix terminals.
MIT License
4.08k stars 351 forks source link

[#101] fix incorrect line count on narrow terminals #288

Closed coryb closed 4 years ago

coryb commented 4 years ago

This should fix the long standing issue discussed in #101 with incorrectly counting the lines due to line wrapping on narrow terminals. I suspect the Konsole issue is unrelated to line width, but this should fix the usage in more commonly used terminals on linux and macOs. I have not tried on windows, but it should work.

To verify just make your terminal narrow and run some of the examples in ./examples.

ethack commented 4 years ago

This fixes the duplicate question issue for me. But it introduces a different issue.

It seems to happen in a multiselect when the options are over a certain percent of the terminal width. Every time I use an arrow key to change my selection it shifts the entire prompt up a line, eventually stopping at the top of the terminal window and erasing whatever was in the terminal before. In the gif below my terminal width is 95 and my option strings are each 70 characters (doesn't include the arrow or checkboxes). But if I make my options shorter (60 characters) then everything works as it should and I don't get the shifting effect.

line-issue

I don't know what info is useful for this but I'm happy to test out different things or gather more info. I'm on Linux (Ubuntu based distro) and get the same behavior in two different terminal programs, as well as right inside of Visual Studio Code's terminal.

tomercy commented 4 years ago

It didn't really fix it but rather shortened the duplicated input. If I paste a JWT token I can see a duplicated question and the JWT once again, along with the original question like and half the JWT.

image

Zalgo2462 commented 4 years ago

The new issue results from counting the ANSI control characters embedded in each string when the number of lines is computed via len(line). I'm not sure if there is a good way to get the resulting number of characters printed to the screen other than stripping out the ANSI control characters with regex before counting them.

Importing https://github.com/pborman/ansi and changing the line variable to the following solves the issue on Linux. line, _ := ansi.Strip(s.Bytes())

It might be worthwhile to just generate two templates for every prompt. The additional template would bind the color function to a noop. Then, using the new template, we could generate both the colored and uncolored versions of the output. The renderer would use the uncolored version to determine line counts/ layouts and send the colored version to the terminal.

EDIT: I've implemented the latter idea at #291

AlecAivazis commented 4 years ago

I'm going to close this since it has been merged into master as part of @Zalgo2462's latest PR.

This is probably the longest runnig issue in Survey's existence. I am THRILLED that we finally have something in place. Thank you so so much @coryb and @Zalgo2462!!!