Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

installer: Fix terminal colors. #3445

Merged
merged 1 commit into from Mar 25, 2020
Merged

Conversation

gnprice
Copy link
Contributor

@gnprice gnprice commented Mar 25, 2020

The install-multi-user script uses blue, green, and red colors, as
well as bold and underline, to add helpful formatting that helps
structure its rather voluminous output.

Unfortunately, the terminal escape sequences it uses are not quite
well-formed. The relevant information is all there, just obscured
by some extra noise, a leading parameter 38. Empirically, the
result is:

  • On macOS, in both Terminal.app and iTerm2, the spurious 38 is
    ignored, the rest of the escape sequence is applied, and the colors
    show up as intended.

  • On Linux, in at least gnome-terminal and xterm, the spurious 38
    and the next parameter after it are ignored, and what's left is
    applied. So in the sequence 38;4;32, the 4 (underline) is
    ignored but the 32 (green) takes effect; in a more typical sequence
    like 38;34, the 34 (blue) is ignored and nothing happens.

These codes are all unchanged since this script's origins as a
Darwin-only script -- so the fact that they work fine in common macOS
terminals goes some way to explain how the bug arose.

Happily, we can make the colors work as intended by just deleting the
extra 38;. Tested in all four terminals mentioned above; the new
codes work correctly on all of them, and on the two macOS terminals
they work exactly the same as before.


In a bit more technical detail -- perhaps more than anyone, me
included, ever wanted to know, but now that I've gone and learned it
I'll write it down anyway :) -- here's what's happening in these codes:

An ECMA-48 "control sequence" begins with \033[ aka "CSI", contains
any number of parameters as semicolon-separated decimal numbers (plus
sometimes other wrinkles), and ends with a byte from 0x40..0x7e. In
our case, with m aka "SGR", "Select Graphic Rendition".

An SGR control sequence \033[...m sets colors, fonts, text styles,
etc. In particular a parameter 31 means red, 32 green, 34 blue,
4 underline, and 0 means reset to normal. Those are all we use.

There is also a 38. This is used for setting colors too... but it
needs arguments. 38;5;nn is color nn from a 256-color palette, and
38;2;rr;gg;bb has the given RGB values.

There is no meaning defined for 38;1 or 38;34 etc. On seeing a
parameter 38 followed by an unrecognized argument for it, apparently
some implementations (as seen on macOS) discard only the 38 and
others (as seen on Linux) discard the argument too before resuming.

The install-multi-user script uses blue, green, and red colors, as
well as bold and underline, to add helpful formatting that helps
structure its rather voluminous output.

Unfortunately, the terminal escape sequences it uses are not quite
well-formed.  The relevant information is all there, just obscured
by some extra noise, a leading parameter `38`.  Empirically, the
result is:

 * On macOS, in both Terminal.app and iTerm2, the spurious `38` is
   ignored, the rest of the escape sequence is applied, and the colors
   show up as intended.

 * On Linux, in at least gnome-terminal and xterm, the spurious `38`
   and the next parameter after it are ignored, and what's left is
   applied.  So in the sequence `38;4;32`, the 4 (underline) is
   ignored but the 32 (green) takes effect; in a more typical sequence
   like `38;34`, the 34 (blue) is ignored and nothing happens.

These codes are all unchanged since this script's origins as a
Darwin-only script -- so the fact that they work fine in common macOS
terminals goes some way to explain how the bug arose.

Happily, we can make the colors work as intended by just deleting the
extra `38;`.  Tested in all four terminals mentioned above; the new
codes work correctly on all of them, and on the two macOS terminals
they work exactly the same as before.

---

In a bit more technical detail -- perhaps more than anyone, me
included, ever wanted to know, but now that I've gone and learned it
I'll write it down anyway :) -- here's what's happening in these codes:

An ECMA-48 "control sequence" begins with `\033[` aka "CSI", contains
any number of parameters as semicolon-separated decimal numbers (plus
sometimes other wrinkles), and ends with a byte from 0x40..0x7e.  In
our case, with `m` aka "SGR", "Select Graphic Rendition".

An SGR control sequence `\033[...m` sets colors, fonts, text styles,
etc.  In particular a parameter `31` means red, `32` green, `34` blue,
`4` underline, and `0` means reset to normal.  Those are all we use.

There is also a `38`.  This is used for setting colors too... but it
needs arguments.  `38;5;nn` is color nn from a 256-color palette, and
`38;2;rr;gg;bb` has the given RGB values.

There is no meaning defined for `38;1` or `38;34` etc.  On seeing a
parameter `38` followed by an unrecognized argument for it, apparently
some implementations (as seen on macOS) discard only the `38` and
others (as seen on Linux) discard the argument too before resuming.
@edolstra edolstra merged commit eb1911e into NixOS:master Mar 25, 2020
@gnprice gnprice deleted the pr-installer-colors branch April 2, 2020 04:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants