Unexecuted lines are almost invisible against gray terminal background

Issue #16 new
Botond Ballo repo owner created an issue

On one of the computers I use, my terminal background color is a shade of grey very close to the one used for unexecuted lines in the cfviz output, making the latter almost invisible (see attached screenshot).

I'm not sure if there's a way for the frontend to detect the terminal background color, and adjust its coloring accordingly? If not, we may need to ship with several alternative color schemes, and allow the user to choose manually.

Comments (6)

  1. Derek Berger

    This is something I was aware would be a likely issue (see https://bitbucket.org/botond/cfviz/issues/9/improve-colours, third bullet-point).

    As far as I know, there is no way to detect a terminal color scheme. There isn't even a particularly reliable way to detect terminal color support, most of the current methods being either unreliable or kind of hacky (see e.g. https://github.com/ticki/termion/issues/78 for the particular crate being used in our project), or how some simply rely on a list of supported terminals or terminal-emulators (e.g. https://gist.github.com/XVilka/8346728).

    I've thought of three potential solutions:

    1. apply a forced background colour to all text output (whether in "true-colour" or 256-colour modes), which will ensure uniform output across terminals supporting background colouring, but which may produce jarring "blocks" of dark-background output on any terminal with a different background colour.

    2. Add --color-scheme=light and/or --color-scheme=none command line arguments for users who have conflicting color-schemes or simply prefer uncoloured output. This could potentially be handled by having the front-end read a config file before running, or having arguments passed to it via the back-end.

    3. Change the styling of unexecuted lines in some other way that causes emphasis independent of colour, perhaps also customizable via command-line argument or config file. E.g. have all executed lines be bolded, and unexecuted lines plain, or insert characters on the printed output of unexecuted lines, e.g. ### or ## unexecuted! ## to indicate unexecuted lines on terminals that support no styling whatsoever.

    Ultimately, I would like to have all these options available, whether it be via config file or command-line arguments. In the short term, however, the easiest (and most general) fix is simply to force a background colour for output, or directly annotate the output for unexecuted lines.

  2. Botond Ballo reporter

    ls seems to do it somehow:

    • Run ls in a terminal. Observe how the output is color-coded (if it's not, you may need to run ls --color instead).
    • Change your terminal's color scheme.
    • Run ls again. Observe how the output is color-coded, but the colors are different.
  3. Derek Berger

    ls isn't actually doing anything differently, this is just modern terminal emulators being clever: (most) terminal emulators seem to handle custom coloring by changing how the terminal responds to the standard first 16 of all the 8-bit (i.e. the "3/4-bit" or "base16") escape codes, e.g. by mapping the base 16 colour escape sequences to whatever custom 256 or 24-bit color are defined in the scheme.

    On mac, I don't have to run ls -G again after changing a color, the terminal emulator (whether the native Terminal.app or iTerm2) just re-colors instantaneously. Perhaps your terminal emulator handles this differently, only coloring lines and characters corresponding to the scheme that was set at the time. Or perhaps you changed the entire scheme, and this required opening a new terminal window, which hides what is really going on. You should be able to test this by just changing a particular color of your current scheme and seeing if the already-existing output of a previous ls --color command gets recolored in realtime. I suspect it will.

    Either way, if no LS_COLORS environment variable is set up (and I'm sure changing terminal color schemes is not doing this for either of us), I can guarantee ls always outputs the same old base16 escape codes (you can check the source and see if you are really curious). ls only does a very basic check for overall color support.

    From what I can find, there is no general, reliable method for detecting the terminal colors in use. All search results return depressing threads full of dysfunctional and hacky partial solutions. Even apps that would surely have figured out the most general method by now (e.g. Vim / Neovim) only use heuristic guesses, fully solving the problem instead by having the user manually inform the application whether the background is dark or light. The main problems seem to be that modern terminal emulators do custom runtime handling of escape codes, and, even if they aren't doing this, plenty of terminal emulators (cough mac terminals cough) either just don't report enough reliable information on the colors they are using or don't respond to all of the fancy xterm escape sequences that would give the proper info (see e.g. any of these comments).

    Since this means that we can't, in general, make any strong assumptions about how the base16 escape codes nor background colors (which may be completely custom and not queryable) are displayed, there isn't an ideal solution. I suppose I could implement the hacky heuristic checks, but I'm not really motivated to do this since they don't work that well in the first place.

    As far as I can tell, the only solutions are the ones I mentioned earlier. The only 100% guaranteed color solution I can think of is to specifically choose non base16 colors (i.e. safe from custom scheming) for both the background and foreground, so we completely control all output colors. The only 100% guaranteed general solution is not to fully colorize at all, and instead either annotate in some way, or just choose two or three emphasis colors from the base16 set, and assume every user will have set these up to have sufficient contrast with the other colors and his/her terminal background. You just can't have a good heatmap this last way.

    All these options are extremely easy to implement, just annoying in that they require either command-line arguments or a config, and there is no obvious choice for a default option. I think I'll just implement them all so they can be chosen by a command-line flag, and then we can test and see which looks best as a reasonable default.

  4. Botond Ballo reporter

    Thanks for the detailed analysis!

    On mac, I don't have to run ls -G again after changing a color, the terminal emulator (whether the native Terminal.app or iTerm2) just re-colors instantaneously.

    Just to confirm, this is the behaviour I see as well. I just wasn't paying enough attention to notice it when I wrote my previous comment.

    I agree that asking the user to specify a color scheme is a good enough solution, especially if there's a way for them to only do it once (e.g. by putting something in their .gdbinit).

  5. Botond Ballo reporter

    I agree that asking the user to specify a color scheme is a good enough solution, especially if there's a way for them to only do it once (e.g. by putting something in their .gdbinit).

    With #25 fixed, a user can now accomplish this by adding something like the following to their .gdbinit:

    define cfv
       cfviz --color=256  # or whichever mode
       end
    

    (and then running cfv instead of cfviz). Not a super polished solution, but good enough for now.

  6. Log in to comment