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

Choose Theme Based on The Terminal's Color Scheme #2896

Open
wants to merge 20 commits into
base: master
Choose a base branch
from

Conversation

bash
Copy link

@bash bash commented Mar 15, 2024

Resolves #1746

This PR is an alternative to #2797. The most notable difference is that this PR uses my own library terminal-colorsaurus instead of termbg.
Among other things, this solves (or at least softens) concerns around timeout / latency.

For additional background, see also my PR to delta: dandavison/delta#1615

Usage

As suggested in #1746, there are two new options with accompanying environment variables:

  • --theme-dark / BAT_THEME_DARK
  • --theme-light / BAT_THEME_LIGHT

By default, bat detects if the terminal is dark or light and uses --theme-<mode> or falls back to the default dark or light theme respectively.

If the detection fails, the terminal is treated as having a dark background.

The --theme option and BAT_THEME env var always overrides these new options for backwards compatibility and to have an easy way to disable color detection. As a consequence --theme=default always uses the default dark theme.

I also decided to add an option for controlling the color detection --detect-color-scheme. I don't think this is strictly necessary and I'm leaning on removing this. The only value that is not achievable through a combination of other options is --detect-color-scheme=always.

Latency and Terminal Support

terminal-colorsaurus includes Measurements for a couple of terminals, both terminals that support OSC 10/OSC 11 and some that don't.

For terminals that don't support OSC 10/OSC 11 querying for the color scheme usually takes well below 100 µs.

How does this work?

Colorsaurus sends two escape sequences: OSC 11 (the actual color querying sequence) followed by DA1 (which is supported by almost all terminals out there). Since terminals answer in the same order as the sequences were received we know that if we receive the answer to DA1 then the terminal does not support OSC 11 and can bail out early and avoid a long timeout.

For terminals that support OSC 10/OSC 11 there's a wide range of latency: Some terminals take less than 100 µs while others usually take around 30 ms.

Windows

Windows is not supported. Calling terminal-colorsaurus on windows is a no-op, so there's no added latency there.

macOS

I have completely removed the current detection via macOS system preferences as terminal-colorsaurus is correctly able to detect whether the terminal is dark or light. I saw dalance/termbg#8 referenced somewhere in the discussion, but I am unable to reproduce the issue. I am running macOS Ventura 13.6.4.

Open Questions

  • Should I keep --detect-color-scheme or remove it?
  • Is the additional startup cost acceptable?

@patbl
Copy link

patbl commented Mar 18, 2024

As suggested in #1746, there are two new options with accompanying environment variables:

  • --theme-dark / BAT_THEME_DARK
  • --theme-light / DELTA_THEME_LIGHT

I think there was a typo (the second one should probably be BAT_THEME_LIGHT).

@bash
Copy link
Author

bash commented Mar 18, 2024

@patbl Yep that's a typo, thanks :)

Lucky me, it's only in the PR description and not in the actual PR changes.

@sersorrel
Copy link

This seems to work well! I do need to specify --detect-color-scheme=always, though – I use bat via lesspipe, and without that flag (actually implemented locally as a patch to change the default, since lesspipe doesn't provide any way to send custom arguments to bat...) the detection doesn't run.

What is the downside of not always doing colour scheme detection? The code briefly mentions a race condition with pagers; am I just lucky to have not hit that myself? What would be the symptoms of this happening?

@bash
Copy link
Author

bash commented Apr 9, 2024

@sersorrel That's great to hear! I'm not familiar with lesspipe, how exactly do you combine bat with lesspipe? Do you pipe bat's output to less?

What is the downside of not always doing colour scheme detection? The code briefly mentions a race condition with pagers.

Yes, exactly :) You can observe the race condition when piping bat's output to less. In that case both processes are started (mostly) simultaneously and try to access the terminal at the same time (both color detection and less read from the terminal and enable / disable "raw mode").

Here's how I witness the race condition:
Run bat --detect-color-scheme always .editorconfig | less.
For me less sometimes won't recognize q for exiting.

@sersorrel
Copy link

sersorrel commented Apr 11, 2024

Honestly, I can't figure out exactly how lesspipe.sh invokes bat... The general mechanism is that less examines $LESSOPEN and pipes the file to it before displaying whatever it prints (whether for syntax highlighting or for e.g. displaying a list of files inside a .zip). lesspipe.sh is a generic script that, when invoked as $LESSOPEN, will look at the filename and apply syntax highlighting or whatever other filtering as appropriate.

I can't reproduce the race condition with that command, interestingly.

@bash
Copy link
Author

bash commented Apr 16, 2024

From a quick (and not thorough) peek at less' source code I think there's indeed no race condition in that case. Less waits for $LESSOPEN to complete before it starts to do its own input processing.

@bash bash force-pushed the dark-light branch 2 times, most recently from 01981dc to 4409c56 Compare April 16, 2024 12:46
Excerpt from the [changelog](https://github.com/bash/terminal-colorsaurus/blob/0.4.0/changelog.md):

> * ⚡ Renamed «color scheme» to «color palette».
> * ⚡ Removed `is_dark_on_light` and `is_light_on_dark` functions. Use `color_scheme` instead.
> * Add new convenience function `color_scheme` which returns a nice `Dark / Light` enum.
> * Add support for urxvt's `rgba:` color format.
> * Further refined the documentation (more organized terminal list, new terminals tested).
> * Improved handling of ambigous color palettes (e.g. when background color is the same as foreground).
> * Queries are now terminated with `ST` (the standard string terminator) instead of `BEL` (which is an xterm extension).
> * 🐛 Fixed `OSC 11` response being visible to users of GNU Screen
     by detecting Screen and erroring before sending any control sequences (bash/terminal-colorsaurus#16).
@bash
Copy link
Author

bash commented May 18, 2024

I have been thinking about the --detect-color-scheme flag lately, maybe it'd be more useful as a more general --color-scheme flag instead. It would take the following values:

  • dark - replaces --detect-color-scheme=never
  • light - replaces --detect-color-scheme=never
  • auto - same as --detect-color-scheme=auto
  • auto:always - same as --detect-color-scheme=always
  • system - detect from OS instead (on macOS)

The main advantage is that to disable auto-detection one can choose between dark or light instead of being stuck on dark.

It also opens the door to more keywords such as system that would use the current mechanism on macOS instead of detecting from the terminal.

Thoughts?

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.

Support for different themes based on Terminal color scheme
3 participants