Choose Theme Based on The Terminal's Color Scheme
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](https://github.com/sharkdp/bat/pull/2797#discussion_r1522164896).

For additional background, see also my PR to delta: https://github.com/dandavison/delta/pull/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`.~~

~~Detection can be controlled via `--color-scheme`:~~
* ~~`auto` - detect from terminal~~
* ~~`auto:always` - always detect from terminal, even if output is redirected~~
* ~~`dark`~~
* ~~`light`~~
* ~~`system` - detect from OS (macOS only)~~

`--theme` / `BAT_THEME` takes some special values to control detection:
* `auto` (default) - detect from terminal
* `auto:always` - always detect from terminal, even if output is redirected
* `auto:system` - detect from OS (macOS only)
* `dark` - Always use the theme configured in `--theme-dark`
* `light` - Always use the theme configured in `--theme-light`

I thought it might be useful to include `dark` and `light` as special values as a user may have configured dark and light themes via the env var / config but wants to override.

## Latency and Terminal Support
terminal-colorsaurus includes [Measurements](https://github.com/bash/terminal-colorsaurus/blob/main/doc/latency.md) 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**.

<details>
<summary>How does this work?</summary>

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.

</details>

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](https://github.com/bash/terminal-colorsaurus/blob/main/doc/windows.md). 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 https://github.com/dalance/termbg/issues/8 referenced somewhere in the discussion, but I am unable to reproduce the issue. I am running macOS Ventura 13.6.4.~~

The color scheme is detected from the terminal by default, but can be detected from the OS instead by passing ~~`--color-scheme=system`~~ `--theme=auto:system`.

## Open Questions
~~* [ ] Should I keep `--detect-color-scheme` or remove it?~~
* [ ] Is the additional startup cost acceptable?

[`terminal-colorsaurus`]: https://github.com/bash/terminal-colorsaurus
## Thanks!

As always and once again, thank you @sharkdp for your time and effort.  Hopefully I'm not being a nuisance with these requests.

## Homework

This is not a direct duplicate of #641 or #689, but it is related.  I think that `bat` can be improved beyond its current suggestion of manually running `defaults read` by performing actual detection of background colors, and exposing multiple theme options.

## Current State

Currently, `bat` allows specification of a SINGLE theme, via either `$BAT_THEME` or `--theme`.  This is great, and fits most use-cases.  The [README.md proposes a way to work around this](https://github.com/sharkdp/bat#dark-mode), which is macOS Terminal.app-specific, and a little hacky.  I think `bat` can do even better (and work on more platforms than macOS)!

When distributing tools built upon `bat`, it's not generally predictable what background color / terminal theme a user has configured for `{Terminal.app,iTerm2.app,Konsole,gnome-terminal,etc}`.

Additionally, the default theme (i.e. no `--theme` nor `$BAT_THEME`) may not be appropriate for a given terminal (and the work-around does not fix this).

Finally, the theme may actually need to change, if the user has multiple different terminal profiles, or if the color scheme of the profile changes based on external factors (such as the default Terminal.app theme, which may change based on the current time of day).

## Feature

It would be nice to have `bat` attempt to do some forms of auto-detection of the terminal's default background color, and allow the user to supply `$BAT_THEME_DARK` and `$BAT_THEME_LIGHT`, one of which is auto-selected by `bat`.

These should probably have lower precedence of `$BAT_THEME` and `--theme`.

There are several reasons for wanting this:

* Users who use macOS's "Auto" appearance switches between "Light" and "Dark" at various times of day, so a single theme isn't sufficient.
* Projects which build upon `bat` may want to provide *modified* themes (and cache, and .bin files) to work around features that `bat` doesn't have yet (e.g. #1745) and forcefully override e.g. `$BAT_THEME` with their modified theme.  These tools may wish to provide two themes -- one for light mode, and one for dark mode.

## Libraries and Other Prior Work

There are several projects that may be directly usable, or usable for inspiration and mechanism, for auto-detecting a light or dark terminal.

### `termbg`

Rust library that claims to do exactly what's needed.

However, it has at least one bug on macOS for Terminal.app: https://github.com/dalance/termbg/issues/8

https://github.com/dalance/termbg

### `rust-dark-light`

Rust project, not sure how well it works or what systems are supported.

https://github.com/frewsxcv/rust-dark-light

### `termenv`

While written in Go, this is a whole library for manipulating colors, and also features UNIX- and Windows-compatible light/dark mode detection.

In particular, it has one function that does what we need:

```go
// Returns whether terminal uses a dark-ish background
darkTheme := termenv.HasDarkBackground()
```

https://github.com/muesli/termenv

## Implementation Details - SKIP THIS SECTION, SEE ABOVE

**Update: I did some more searching, and found several Rust (and other) libraries which may be usable to achieve this.  `termbg` is very promising, and worked in all terminals I tested via `cargo run`.  This section can be ignored.**

Realistically, background color detection of the "current terminal" could likely be its own tool / library.

Detection of whether the foreground is a light or dark color is in itself a challenge.  I've proposed some possibilities below, but I expect that the mechanism used by `git-delta` is likely sound.

Separately, determining whether a specific color is "light" or "dark" is pretty difficult, but I expect that checking that all three of R, G, and B are below some threshold (say, 0x60) you could say that it's a "dark" theme and anything else (e.g. #00ff00) would be a "light" theme.

### Linux

#### xterm

A little bit of Googling around shows that Xterm, at least (and possibly other terminals) respond to certain escape sequences with their color configurations: https://unix.stackexchange.com/a/172674

This may be more generically applicable than just `xterm` itself, which is why I listed this first.

#### gnome-terminal

I can't speak to this, but it's a starting point.  Copied from https://unix.stackexchange.com/a/133920:

```
$ dconf list /org/gnome/terminal/legacy/profiles:/
<profile id>

$ dconf read /org/gnome/terminal/legacy/profiles:/<profile id>/background-color
'rgb(0,0,0)'
```

### macOS

A generic way to check for whether the theme should be light or dark is to check `defaults read -globalDomain AppleInterfaceStyle` (~10ms), which either emits nothing (for Light mode) or "Dark".  Note that if the user configures "Auto", the output of this value will reflect the _current_ setting.

#### iTerm2

This terminal can be detected via the environment, and will have `TERM_PROGRAM=iTerm.app`.

For iTerm2, it should be possible to determine the foreground color from its configuration plist and the `$ITERM_PROFILE` environment variable.

For example, in Python one can do:

```py
#!/usr/bin/env python3
import plistlib
import os

plist = plistlib.load(open('Library/Preferences/com.googlecode.iterm2.plist', 'rb'))
profile = os.getenv('ITERM_PROFILE', 'Default')

def hexify(color):
    r = int(color['Red Component'] * 255) << 16
    g = int(color['Green Component'] * 255) << 8
    b = int(color['Blue Component'] * 255)
    return '#%06x' % (r | g | b)

for b in plist['New Bookmarks']:
    if b['Name'] != profile:
        continue
    print(f"Foreground: {hexify(b['Foreground Color'])}")
    print(f"Background: {hexify(b['Background Color'])}")
    break
```

Which, for me, with Solarized Dark as my theme, prints out:

```
Foreground: #839496
Background: #002b36
```

#### Terminal.app

This terminal can be detected via the environment, and will have `TERM_PROGRAM=Apple_Terminal`.

Terminal.app is more complicated, because it uses NSKeyedArchiver and serialized NSColor objects.

However, for the built-in Profiles (which I expect most users to use one of), we can pretty easily classify them with a simple shell script.  Note that the script takes ~160ms to run, despite being a single line, so it might make sense to cache it for some short period of time (e.g. 1 minute).

```
#!/usr/bin/env osascript
tell application "Terminal" to return name of current settings of first window
```

This will cause a TCC prompt if it's run from another application, e.g. iTerm2.app, but that should realistically never happen for color detection.  The output is the current Profile name, e.g. "Basic", "Grass", "Homebrew", and so on.  Since there's only 10 themes, it should be easy to just have a mapping for each one.

It is important to note that the actual colors of the "Basic" profile for Terminal.app is affected by `AppleInterfaceStyle`, as mentioned above (background may be black OR white depending on the setting).  I have not tested other Terminal.app themes.
Support for different themes based on Terminal color scheme
diff --git a/.gitignore b/.gitignore
index a3ea8cff59..fbfe6ac6b7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
 **/*.rs.bk
 
 # Generated files
+/assets/completions/_bat.ps1
 /assets/completions/bat.bash
 /assets/completions/bat.fish
 /assets/completions/bat.zsh
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1dd80c485a..fdbbf86703 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@
 - Syntax highlighting for JavaScript files that start with `#!/usr/bin/env bun` #2913 (@sharunkumar)
 - `bat --strip-ansi={never,always,auto}` to remove ANSI escape sequences from bat's input, see #2999 (@eth-p)
 - Add or remove individual style components without replacing all styles #2929 (@eth-p)
+- Automatically choose theme based on the terminal's color scheme, see #2896 (@bash)
 - Add option `--binary=as-text` for printing binary content, see issue #2974 and PR #2976 (@einfachIrgendwer0815)
 
 ## Bugfixes
@@ -78,6 +79,9 @@
   - [BREAKING] `SyntaxMapping::mappings` is replaced by `SyntaxMapping::{builtin,custom,all}_mappings`
 - Make `Controller::run_with_error_handler`'s error handler `FnMut`, see #2831 (@rhysd)
 - Improve compile time by 20%, see #2815 (@dtolnay)
+- Add `theme::theme` for choosing an appropriate theme based on the
+  terminal's color scheme, see #2896 (@bash)
+  - [BREAKING] Remove `HighlightingAssets::default_theme`. Use `theme::default_theme` instead.
 
 # v0.24.0
 
diff --git a/Cargo.lock b/Cargo.lock
index 0f24284554..a6d47a198e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -149,6 +149,7 @@ dependencies = [
  "shell-words",
  "syntect",
  "tempfile",
+ "terminal-colorsaurus",
  "thiserror",
  "toml",
  "unicode-width",
@@ -625,6 +626,12 @@ version = "0.14.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12"
 
+[[package]]
+name = "hermit-abi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
+
 [[package]]
 name = "home"
 version = "0.5.9"
@@ -751,9 +758,9 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
 
 [[package]]
 name = "memchr"
-version = "2.6.4"
+version = "2.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
 
 [[package]]
 name = "miniz_oxide"
@@ -764,6 +771,18 @@ dependencies = [
  "adler2",
 ]
 
+[[package]]
+name = "mio"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4929e1f84c5e54c3ec6141cd5d8b5a5c055f031f80cf78f2072920173cb4d880"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "wasi",
+ "windows-sys 0.52.0",
+]
+
 [[package]]
 name = "nix"
 version = "0.29.0"
@@ -1308,6 +1327,30 @@ dependencies = [
  "winapi-util",
 ]
 
+[[package]]
+name = "terminal-colorsaurus"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f99bb1dc5cde9eada5a8f466641240f9d5b9f55291d675df4160b097fbfa42e"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "memchr",
+ "mio",
+ "terminal-trx",
+]
+
+[[package]]
+name = "terminal-trx"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d4c86910e10c782a02d3b7606de43cf7ebd80e1fafdca8e49a0db2b0d4611f0"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "windows-sys 0.52.0",
+]
+
 [[package]]
 name = "terminal_size"
 version = "0.3.0"
diff --git a/Cargo.toml b/Cargo.toml
index 67327460b2..f0a80346f0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -68,6 +68,7 @@ bytesize = { version = "1.3.0" }
 encoding_rs = "0.8.35"
 os_str_bytes = { version = "~7.0", optional = true }
 run_script = { version = "^0.10.1", optional = true}
+terminal-colorsaurus = "0.4"
 
 [dependencies.git2]
 version = "0.19"
diff --git a/README.md b/README.md
index 4ffd7fe986..d45d555b3c 100644
--- a/README.md
+++ b/README.md
@@ -482,8 +482,10 @@ the following command (you need [`fzf`](https://github.com/junegunn/fzf) for thi
 bat --list-themes | fzf --preview="bat --theme={} --color=always /path/to/file"
 ```
 
-`bat` looks good on a dark background by default. However, if your terminal uses a
-light background, some themes like `GitHub` or `OneHalfLight` will work better for you.
+`bat` automatically picks a fitting theme depending on your terminal's background color.
+You can use the `--theme-light` / `--theme-light` options or the `BAT_THEME_DARK` / `BAT_THEME_LIGHT` environment variables
+to customize the themes used. This is especially useful if you frequently switch between dark and light mode.
+
 You can also use a custom theme by following the
 ['Adding new themes' section below](https://github.com/sharkdp/bat#adding-new-themes).
 
diff --git a/assets/completions/_bat.ps1.in b/assets/completions/_bat.ps1.in
index c0c151e1ed..b6f62aae67 100644
--- a/assets/completions/_bat.ps1.in
+++ b/assets/completions/_bat.ps1.in
@@ -37,6 +37,8 @@ Register-ArgumentCompleter -Native -CommandName '{{PROJECT_EXECUTABLE}}' -Script
             [CompletionResult]::new('-m', 'm', [CompletionResultType]::ParameterName, 'Use the specified syntax for files matching the glob pattern (''*.cpp:C++'').')
             [CompletionResult]::new('--map-syntax', 'map-syntax', [CompletionResultType]::ParameterName, 'Use the specified syntax for files matching the glob pattern (''*.cpp:C++'').')
             [CompletionResult]::new('--theme', 'theme', [CompletionResultType]::ParameterName, 'Set the color theme for syntax highlighting.')
+            [CompletionResult]::new('--theme-dark', 'theme', [CompletionResultType]::ParameterName, 'Set the color theme for syntax highlighting for dark backgrounds.')
+            [CompletionResult]::new('--theme-light', 'theme', [CompletionResultType]::ParameterName, 'Set the color theme for syntax highlighting for light backgrounds.')
             [CompletionResult]::new('--style', 'style', [CompletionResultType]::ParameterName, 'Comma-separated list of style elements to display (*default*, auto, full, plain, changes, header, header-filename, header-filesize, grid, rule, numbers, snip).')
             [CompletionResult]::new('-r', 'r', [CompletionResultType]::ParameterName, 'Only print the lines from N to M.')
             [CompletionResult]::new('--line-range', 'line-range', [CompletionResultType]::ParameterName, 'Only print the lines from N to M.')
diff --git a/assets/completions/bat.bash.in b/assets/completions/bat.bash.in
index f314bb2529..90931f2450 100644
--- a/assets/completions/bat.bash.in
+++ b/assets/completions/bat.bash.in
@@ -113,6 +113,13 @@ _bat() {
 		return 0
 		;;
 	--theme)
+    	local IFS=$'\n'
+    	COMPREPLY=($(compgen -W "auto${IFS}auto:always${IFS}auto:system${IFS}dark${IFS}light${IFS}$("$1" --list-themes)" -- "$cur"))
+                    __bat_escape_completions
+    	return 0
+    	;;
+	--theme-dark | \
+	--theme-light)
 		local IFS=$'\n'
 		COMPREPLY=($(compgen -W "$("$1" --list-themes)" -- "$cur"))
                 __bat_escape_completions
@@ -170,6 +177,8 @@ _bat() {
 			--map-syntax
 			--ignored-suffix
 			--theme
+			--theme-dark
+			--theme-light
 			--list-themes
 			--squeeze-blank
 			--squeeze-limit
diff --git a/assets/completions/bat.fish.in b/assets/completions/bat.fish.in
index 788f71b093..e27127064e 100644
--- a/assets/completions/bat.fish.in
+++ b/assets/completions/bat.fish.in
@@ -129,6 +129,14 @@ set -l tabs_opts '
     8\t
 '
 
+set -l special_themes '
+    auto\tdefault,\ Choose\ a\ theme\ based\ on\ dark\ or\ light\ mode
+    auto:always\tChoose\ a\ theme\ based\ on\ dark\ or\ light\ mode
+    auto:system\tChoose\ a\ theme\ based\ on\ dark\ or\ light\ mode
+    dark\tUse\ the\ theme\ specified\ by\ --theme-dark
+    light\tUse\ the\ theme\ specified\ by\ --theme-light
+'
+
 # Completions:
 
 complete -c $bat -l acknowledgements -d "Print acknowledgements" -n __fish_is_first_arg
@@ -203,7 +211,11 @@ complete -c $bat -l tabs -x -a "$tabs_opts" -d "Set tab width" -n __bat_no_excl_
 
 complete -c $bat -l terminal-width -x -d "Set terminal <width>, +<offset>, or -<offset>" -n __bat_no_excl_args
 
-complete -c $bat -l theme -x -a "(command $bat --list-themes | command cat)" -d "Set the syntax highlighting theme" -n __bat_no_excl_args
+complete -c $bat -l theme -x -a "$special_themes(command $bat --list-themes | command cat)" -d "Set the syntax highlighting theme" -n __bat_no_excl_args
+
+complete -c $bat -l theme-dark -x -a "(command $bat --list-themes | command cat)" -d "Set the syntax highlighting theme for dark backgrounds" -n __bat_no_excl_args
+
+complete -c $bat -l theme-light -x -a "(command $bat --list-themes | command cat)" -d "Set the syntax highlighting theme for light backgrounds" -n __bat_no_excl_args
 
 complete -c $bat -s V -l version -f -d "Show version information" -n __fish_is_first_arg
 
diff --git a/assets/completions/bat.zsh.in b/assets/completions/bat.zsh.in
index 7d03abb3b2..76b981b69b 100644
--- a/assets/completions/bat.zsh.in
+++ b/assets/completions/bat.zsh.in
@@ -42,7 +42,9 @@ _{{PROJECT_EXECUTABLE}}_main() {
         --decorations='[specify when to show the decorations]:when:(auto never always)'
         --paging='[specify when to use the pager]:when:(auto never always)'
         '(-m --map-syntax)'{-m+,--map-syntax=}'[map a glob pattern to an existing syntax name]: :->syntax-maps'
-        '(--theme)'--theme='[set the color theme for syntax highlighting]:theme:->themes'
+        '(--theme)'--theme='[set the color theme for syntax highlighting]:theme:->theme_preferences'
+        '(--theme-dark)'--theme-dark='[set the color theme for syntax highlighting for dark backgrounds]:theme:->themes'
+        '(--theme-light)'--theme-light='[set the color theme for syntax highlighting for light backgrounds]:theme:->themes'
         '(: --list-themes --list-languages -L)'--list-themes'[show all supported highlighting themes]'
         --style='[comma-separated list of style elements to display]: : _values "style [default]"
             default auto full plain changes header header-filename header-filesize grid rule numbers snip'
@@ -82,7 +84,13 @@ _{{PROJECT_EXECUTABLE}}_main() {
 
         themes)
             local -a themes expl
-            themes=( ${(f)"$(_call_program themes {{PROJECT_EXECUTABLE}} --list-themes)"} )
+            themes=(${(f)"$(_call_program themes {{PROJECT_EXECUTABLE}} --list-themes)"} )
+
+            _wanted themes expl 'theme' compadd -a themes && ret=0
+        ;;
+        theme_preferences)
+            local -a themes expl
+            themes=(auto dark light auto:always auto:system ${(f)"$(_call_program themes {{PROJECT_EXECUTABLE}} --list-themes)"} )
 
             _wanted themes expl 'theme' compadd -a themes && ret=0
         ;;
diff --git a/assets/manual/bat.1.in b/assets/manual/bat.1.in
index 2bc0a3a534..ccc7062910 100644
--- a/assets/manual/bat.1.in
+++ b/assets/manual/bat.1.in
@@ -152,9 +152,38 @@ will use JSON syntax, and ignore '.dev'
 .HP
 \fB\-\-theme\fR <theme>
 .IP
-Set the theme for syntax highlighting. Use '\-\-list\-themes' to see all available themes.
-To set a default theme, add the '\-\-theme="..."' option to the configuration file or
-export the BAT_THEME environment variable (e.g.: export BAT_THEME="...").
+Set the theme for syntax highlighting. Use \fB\-\-list\-themes\fP to see all available themes.
+To set a default theme, add the \fB\-\-theme="..."\fP option to the configuration file or
+export the \fBBAT_THEME\fP environment variable (e.g.: \fBexport BAT_THEME="..."\fP).
+
+Special values:
+.RS
+.IP "auto (\fIdefault\fR)"
+Picks a dark or light theme depending on the terminal's colors.
+Use \fB-\-theme\-light\fR and \fB-\-theme\-dark\fR to customize the selected theme.
+.IP "auto:always"
+Variation of \fBauto\fR where where the terminal's colors are detected even when the output is redirected.
+.IP "auto:system (macOS only)"
+Variation of \fBauto\fR where the color scheme is detected from the system-wide preference instead.
+.IP "dark"
+Use the dark theme specified by \fB-\-theme-dark\fR.
+.IP "light"
+Use the light theme specified by \fB-\-theme-light\fR.
+.RE
+.HP
+\fB\-\-theme\-dark\fR <theme>
+.IP
+Sets the theme name for syntax highlighting used when the terminal uses a dark background.
+To set a default theme, add the \fB\-\-theme-dark="..."\fP option to the configuration file or
+export the \fBBAT_THEME_DARK\fP environment variable (e.g. \fBexport BAT_THEME_DARK="..."\fP).
+This option only has an effect when \fB\-\-theme\fP option is set to \fBauto\fR or \fBdark\fR.
+.HP
+\fB\-\-theme\-light\fR <theme>
+.IP
+Sets the theme name for syntax highlighting used when the terminal uses a dark background.
+To set a default theme, add the \fB\-\-theme-dark="..."\fP option to the configuration file or
+export the \fBBAT_THEME_LIGHT\fP environment variable (e.g. \fBexport BAT_THEME_LIGHT="..."\fP).
+This option only has an effect when \fB\-\-theme\fP option is set to \fBauto\fR or \fBlight\fR.
 .HP
 \fB\-\-list\-themes\fR
 .IP
@@ -307,7 +336,7 @@ To use the preprocessor, call:
 
 \fB{{PROJECT_EXECUTABLE}} --lessopen\fR
 
-Alternatively, the preprocessor may be enabled by default by adding the '\-\-lessopen' option to the configuration file. 
+Alternatively, the preprocessor may be enabled by default by adding the '\-\-lessopen' option to the configuration file.
 
 To temporarily disable the preprocessor if it is enabled by default, call:
 
@@ -323,7 +352,7 @@ Enable the $LESSOPEN preprocessor.
 .IP
 Disable the $LESSOPEN preprocessor if enabled (overrides --lessopen)
 .PP
-For more information, see the "INPUT PREPROCESSOR" section of less(1).  
+For more information, see the "INPUT PREPROCESSOR" section of less(1).
 
 .SH "MORE INFORMATION"
 
diff --git a/doc/long-help.txt b/doc/long-help.txt
index 87fb5d9663..85d595b980 100644
--- a/doc/long-help.txt
+++ b/doc/long-help.txt
@@ -119,6 +119,27 @@ Options:
           Set the theme for syntax highlighting. Use '--list-themes' to see all available themes. To
           set a default theme, add the '--theme="..."' option to the configuration file or export
           the BAT_THEME environment variable (e.g.: export BAT_THEME="...").
+          
+          Special values:
+          
+            * auto: Picks a dark or light theme depending on the terminal's colors (default).
+                    Use '--theme-light' and '--theme-dark' to customize the selected theme.
+              * auto:always: Detect the terminal's colors even when the output is redirected.
+              * auto:system: Detect the color scheme from the system-wide preference (macOS only).
+            * dark: Use the dark theme specified by '--theme-dark'.
+            * light: Use the light theme specified by '--theme-light'.
+
+      --theme-light <theme>
+          Sets the theme name for syntax highlighting used when the terminal uses a light
+          background. Use '--list-themes' to see all available themes. To set a default theme, add
+          the '--theme-light="..." option to the configuration file or export the BAT_THEME_LIGHT
+          environment variable (e.g. export BAT_THEME_LIGHT="...").
+
+      --theme-dark <theme>
+          Sets the theme name for syntax highlighting used when the terminal uses a dark background.
+          Use '--list-themes' to see all available themes. To set a default theme, add the
+          '--theme-dark="..." option to the configuration file or export the BAT_THEME_DARK
+          environment variable (e.g. export BAT_THEME_DARK="...").
 
       --list-themes
           Display a list of supported themes for syntax highlighting.
diff --git a/doc/short-help.txt b/doc/short-help.txt
index 16b9eb05c0..ba06ef3065 100644
--- a/doc/short-help.txt
+++ b/doc/short-help.txt
@@ -43,6 +43,10 @@ Options:
           Use the specified syntax for files matching the glob pattern ('*.cpp:C++').
       --theme <theme>
           Set the color theme for syntax highlighting.
+      --theme-light <theme>
+          Sets the color theme for syntax highlighting used for light backgrounds.
+      --theme-dark <theme>
+          Sets the color theme for syntax highlighting used for dark backgrounds.
       --list-themes
           Display all supported highlighting themes.
   -s, --squeeze-blank
diff --git a/src/assets.rs b/src/assets.rs
index 9655553d62..d32ccbd403 100644
--- a/src/assets.rs
+++ b/src/assets.rs
@@ -13,6 +13,7 @@ use crate::error::*;
 use crate::input::{InputReader, OpenedInput};
 use crate::syntax_mapping::ignored_suffixes::IgnoredSuffixes;
 use crate::syntax_mapping::MappingTarget;
+use crate::theme::{default_theme, ColorScheme};
 use crate::{bat_warning, SyntaxMapping};
 
 use lazy_theme_set::LazyThemeSet;
@@ -69,57 +70,6 @@ impl HighlightingAssets {
         }
     }
 
-    /// The default theme.
-    ///
-    /// ### Windows and Linux
-    ///
-    /// Windows and most Linux distributions has a dark terminal theme by
-    /// default. On these platforms, this function always returns a theme that
-    /// looks good on a dark background.
-    ///
-    /// ### macOS
-    ///
-    /// On macOS the default terminal background is light, but it is common that
-    /// Dark Mode is active, which makes the terminal background dark. On this
-    /// platform, the default theme depends on
-    /// ```bash
-    /// defaults read -globalDomain AppleInterfaceStyle
-    /// ```
-    /// To avoid the overhead of the check on macOS, simply specify a theme
-    /// explicitly via `--theme`, `BAT_THEME`, or `~/.config/bat`.
-    ///
-    /// See <https://github.com/sharkdp/bat/issues/1746> and
-    /// <https://github.com/sharkdp/bat/issues/1928> for more context.
-    pub fn default_theme() -> &'static str {
-        #[cfg(not(target_os = "macos"))]
-        {
-            Self::default_dark_theme()
-        }
-        #[cfg(target_os = "macos")]
-        {
-            if macos_dark_mode_active() {
-                Self::default_dark_theme()
-            } else {
-                Self::default_light_theme()
-            }
-        }
-    }
-
-    /**
-     * The default theme that looks good on a dark background.
-     */
-    fn default_dark_theme() -> &'static str {
-        "Monokai Extended"
-    }
-
-    /**
-     * The default theme that looks good on a light background.
-     */
-    #[cfg(target_os = "macos")]
-    fn default_light_theme() -> &'static str {
-        "Monokai Extended Light"
-    }
-
     pub fn from_cache(cache_path: &Path) -> Result<Self> {
         Ok(HighlightingAssets::new(
             SerializedSyntaxSet::FromFile(cache_path.join("syntaxes.bin")),
@@ -248,7 +198,10 @@ impl HighlightingAssets {
                     bat_warning!("Unknown theme '{}', using default.", theme)
                 }
                 self.get_theme_set()
-                    .get(self.fallback_theme.unwrap_or_else(Self::default_theme))
+                    .get(
+                        self.fallback_theme
+                            .unwrap_or_else(|| default_theme(ColorScheme::Dark)),
+                    )
                     .expect("something is very wrong if the default theme is missing")
             }
         }
@@ -399,26 +352,6 @@ fn asset_from_cache<T: serde::de::DeserializeOwned>(
         .map_err(|_| format!("Could not parse cached {description}").into())
 }
 
-#[cfg(target_os = "macos")]
-fn macos_dark_mode_active() -> bool {
-    const PREFERENCES_FILE: &str = "Library/Preferences/.GlobalPreferences.plist";
-    const STYLE_KEY: &str = "AppleInterfaceStyle";
-
-    let preferences_file = home::home_dir()
-        .map(|home| home.join(PREFERENCES_FILE))
-        .expect("Could not get home directory");
-
-    match plist::Value::from_file(preferences_file).map(|file| file.into_dictionary()) {
-        Ok(Some(preferences)) => match preferences.get(STYLE_KEY).and_then(|val| val.as_string()) {
-            Some(value) => value == "Dark",
-            // If the key does not exist, then light theme is currently in use.
-            None => false,
-        },
-        // Unreachable, in theory. All macOS users have a home directory and preferences file setup.
-        Ok(None) | Err(_) => true,
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;
diff --git a/src/bin/bat/app.rs b/src/bin/bat/app.rs
index c7262aa3b6..8f69870f0a 100644
--- a/src/bin/bat/app.rs
+++ b/src/bin/bat/app.rs
@@ -9,6 +9,7 @@ use crate::{
     config::{get_args_from_config_file, get_args_from_env_opts_var, get_args_from_env_vars},
 };
 use bat::style::StyleComponentList;
+use bat::theme::{theme, ThemeName, ThemeOptions, ThemePreference};
 use bat::BinaryBehavior;
 use bat::StripAnsiMode;
 use clap::ArgMatches;
@@ -17,7 +18,6 @@ use console::Term;
 
 use crate::input::{new_file_input, new_stdin_input};
 use bat::{
-    assets::HighlightingAssets,
     bat_warning,
     config::{Config, VisibleLines},
     error::*,
@@ -278,18 +278,7 @@ impl App {
                 Some("auto") => StripAnsiMode::Auto,
                 _ => unreachable!("other values for --strip-ansi are not allowed"),
             },
-            theme: self
-                .matches
-                .get_one::<String>("theme")
-                .map(String::from)
-                .map(|s| {
-                    if s == "default" {
-                        String::from(HighlightingAssets::default_theme())
-                    } else {
-                        s
-                    }
-                })
-                .unwrap_or_else(|| String::from(HighlightingAssets::default_theme())),
+            theme: theme(self.theme_options()).to_string(),
             visible_lines: match self.matches.try_contains_id("diff").unwrap_or_default()
                 && self.matches.get_flag("diff")
             {
@@ -448,4 +437,25 @@ impl App {
 
         Ok(styled_components)
     }
+
+    fn theme_options(&self) -> ThemeOptions {
+        let theme = self
+            .matches
+            .get_one::<String>("theme")
+            .map(|t| ThemePreference::from_str(t).unwrap())
+            .unwrap_or_default();
+        let theme_dark = self
+            .matches
+            .get_one::<String>("theme-dark")
+            .map(|t| ThemeName::from_str(t).unwrap());
+        let theme_light = self
+            .matches
+            .get_one::<String>("theme-light")
+            .map(|t| ThemeName::from_str(t).unwrap());
+        ThemeOptions {
+            theme,
+            theme_dark,
+            theme_light,
+        }
+    }
 }
diff --git a/src/bin/bat/clap_app.rs b/src/bin/bat/clap_app.rs
index ac1f400733..f5e3948e97 100644
--- a/src/bin/bat/clap_app.rs
+++ b/src/bin/bat/clap_app.rs
@@ -393,9 +393,40 @@ pub fn build_app(interactive_output: bool) -> Command {
                      see all available themes. To set a default theme, add the \
                      '--theme=\"...\"' option to the configuration file or export the \
                      BAT_THEME environment variable (e.g.: export \
-                     BAT_THEME=\"...\").",
+                     BAT_THEME=\"...\").\n\n\
+                     Special values:\n\n  \
+                     * auto: Picks a dark or light theme depending on the terminal's colors (default).\n          \
+                     Use '--theme-light' and '--theme-dark' to customize the selected theme.\n    \
+                     * auto:always: Detect the terminal's colors even when the output is redirected.\n    \
+                     * auto:system: Detect the color scheme from the system-wide preference (macOS only).\n  \
+                     * dark: Use the dark theme specified by '--theme-dark'.\n  \
+                     * light: Use the light theme specified by '--theme-light'.",
                 ),
         )
+        .arg(
+            Arg::new("theme-light")
+                .long("theme-light")
+                .overrides_with("theme-light")
+                .value_name("theme")
+                .help("Sets the color theme for syntax highlighting used for light backgrounds.")
+                .long_help(
+                    "Sets the theme name for syntax highlighting used when the terminal uses a light background. \
+                    Use '--list-themes' to see all available themes. To set a default theme, add the \
+                    '--theme-light=\"...\" option to the configuration file or export the BAT_THEME_LIGHT \
+                    environment variable (e.g. export BAT_THEME_LIGHT=\"...\")."),
+        )
+        .arg(
+            Arg::new("theme-dark")
+                .long("theme-dark")
+                .overrides_with("theme-dark")
+                .value_name("theme")
+                .help("Sets the color theme for syntax highlighting used for dark backgrounds.")
+                .long_help(
+                    "Sets the theme name for syntax highlighting used when the terminal uses a dark background. \
+                    Use '--list-themes' to see all available themes. To set a default theme, add the \
+                    '--theme-dark=\"...\" option to the configuration file or export the BAT_THEME_DARK \
+                    environment variable (e.g. export BAT_THEME_DARK=\"...\")."),
+        )
         .arg(
             Arg::new("list-themes")
                 .long("list-themes")
diff --git a/src/bin/bat/config.rs b/src/bin/bat/config.rs
index 6fa18f0958..a0ee7ba302 100644
--- a/src/bin/bat/config.rs
+++ b/src/bin/bat/config.rs
@@ -140,7 +140,9 @@ fn get_args_from_str(content: &str) -> Result<Vec<OsString>, shell_words::ParseE
 pub fn get_args_from_env_vars() -> Vec<OsString> {
     [
         ("--tabs", "BAT_TABS"),
-        ("--theme", "BAT_THEME"),
+        ("--theme", bat::theme::env::BAT_THEME),
+        ("--theme-dark", bat::theme::env::BAT_THEME_DARK),
+        ("--theme-light", bat::theme::env::BAT_THEME_LIGHT),
         ("--pager", "BAT_PAGER"),
         ("--paging", "BAT_PAGING"),
         ("--style", "BAT_STYLE"),
diff --git a/src/bin/bat/main.rs b/src/bin/bat/main.rs
index 3b74ec7589..7b7bafe600 100644
--- a/src/bin/bat/main.rs
+++ b/src/bin/bat/main.rs
@@ -14,6 +14,7 @@ use std::io::{BufReader, Write};
 use std::path::Path;
 use std::process;
 
+use bat::theme::DetectColorScheme;
 use nu_ansi_term::Color::Green;
 use nu_ansi_term::Style;
 
@@ -30,12 +31,12 @@ use directories::PROJECT_DIRS;
 use globset::GlobMatcher;
 
 use bat::{
-    assets::HighlightingAssets,
     config::Config,
     controller::Controller,
     error::*,
     input::Input,
     style::{StyleComponent, StyleComponents},
+    theme::{color_scheme, default_theme, ColorScheme},
     MappingTarget, PagingMode,
 };
 
@@ -189,7 +190,12 @@ fn theme_preview_file<'a>() -> Input<'a> {
     Input::from_reader(Box::new(BufReader::new(THEME_PREVIEW_DATA)))
 }
 
-pub fn list_themes(cfg: &Config, config_dir: &Path, cache_dir: &Path) -> Result<()> {
+pub fn list_themes(
+    cfg: &Config,
+    config_dir: &Path,
+    cache_dir: &Path,
+    detect_color_scheme: DetectColorScheme,
+) -> Result<()> {
     let assets = assets_from_cache_or_binary(cfg.use_custom_assets, cache_dir)?;
     let mut config = cfg.clone();
     let mut style = HashSet::new();
@@ -200,10 +206,14 @@ pub fn list_themes(cfg: &Config, config_dir: &Path, cache_dir: &Path) -> Result<
     let stdout = io::stdout();
     let mut stdout = stdout.lock();
 
-    let default_theme = HighlightingAssets::default_theme();
+    let default_theme_name = default_theme(color_scheme(detect_color_scheme).unwrap_or_default());
     for theme in assets.themes() {
-        let default_theme_info = if !config.loop_through && default_theme == theme {
+        let default_theme_info = if !config.loop_through && default_theme_name == theme {
             " (default)"
+        } else if default_theme(ColorScheme::Dark) == theme {
+            " (default dark)"
+        } else if default_theme(ColorScheme::Light) == theme {
+            " (default light)"
         } else {
             ""
         };
@@ -371,7 +381,7 @@ fn run() -> Result<bool> {
                 };
                 run_controller(inputs, &plain_config, cache_dir)
             } else if app.matches.get_flag("list-themes") {
-                list_themes(&config, config_dir, cache_dir)?;
+                list_themes(&config, config_dir, cache_dir, DetectColorScheme::default())?;
                 Ok(true)
             } else if app.matches.get_flag("config-file") {
                 println!("{}", config_file().to_string_lossy());
diff --git a/src/lib.rs b/src/lib.rs
index a015913e40..502427a774 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -49,6 +49,7 @@ pub(crate) mod printer;
 pub mod style;
 pub(crate) mod syntax_mapping;
 mod terminal;
+pub mod theme;
 mod vscreen;
 pub(crate) mod wrapping;
 
diff --git a/src/pretty_printer.rs b/src/pretty_printer.rs
index eb123ea339..51c9af80c4 100644
--- a/src/pretty_printer.rs
+++ b/src/pretty_printer.rs
@@ -245,7 +245,9 @@ impl<'a> PrettyPrinter<'a> {
         self
     }
 
-    /// Specify the highlighting theme
+    /// Specify the highlighting theme.
+    /// You can use [`crate::theme::theme`] to pick a theme based on user preferences
+    /// and the terminal's background color.
     pub fn theme(&mut self, theme: impl AsRef<str>) -> &mut Self {
         self.config.theme = theme.as_ref().to_owned();
         self
diff --git a/src/theme.rs b/src/theme.rs
new file mode 100644
index 0000000000..9fbef23886
--- /dev/null
+++ b/src/theme.rs
@@ -0,0 +1,571 @@
+//! Utilities for choosing an appropriate theme for syntax highlighting.
+
+use std::convert::Infallible;
+use std::fmt;
+use std::io::IsTerminal as _;
+use std::str::FromStr;
+
+/// Environment variable names.
+pub mod env {
+    /// See [`crate::theme::ThemeOptions::theme`].
+    pub const BAT_THEME: &str = "BAT_THEME";
+    /// See [`crate::theme::ThemeOptions::theme_dark`].
+    pub const BAT_THEME_DARK: &str = "BAT_THEME";
+    /// See [`crate::theme::ThemeOptions::theme_light`].
+    pub const BAT_THEME_LIGHT: &str = "BAT_THEME";
+}
+
+/// Chooses an appropriate theme or falls back to a default theme
+/// based on the user-provided options and the color scheme of the terminal.
+///
+/// Intentionally returns a [`ThemeResult`] instead of a simple string so
+/// that downstream consumers such as `delta` can easily apply their own
+/// default theme and can use the detected color scheme elsewhere.
+pub fn theme(options: ThemeOptions) -> ThemeResult {
+    theme_impl(options, &TerminalColorSchemeDetector)
+}
+
+/// The default theme, suitable for the given color scheme.
+/// Use [`theme`] if you want to automatically detect the color scheme from the terminal.
+pub const fn default_theme(color_scheme: ColorScheme) -> &'static str {
+    match color_scheme {
+        ColorScheme::Dark => "Monokai Extended",
+        ColorScheme::Light => "Monokai Extended Light",
+    }
+}
+
+/// Detects the color scheme from the terminal.
+pub fn color_scheme(when: DetectColorScheme) -> Option<ColorScheme> {
+    color_scheme_impl(when, &TerminalColorSchemeDetector)
+}
+
+/// Options for configuring the theme used for syntax highlighting.
+/// Used together with [`theme`].
+#[derive(Debug, Clone, Default, PartialEq, Eq)]
+pub struct ThemeOptions {
+    /// Configures how the theme is chosen. If set to a [`ThemePreference::Fixed`] value,
+    /// then the given theme is used regardless of the terminal's background color.
+    /// This corresponds with the `BAT_THEME` environment variable and the `--theme` option.
+    pub theme: ThemePreference,
+    /// The theme to use in case the terminal uses a dark background with light text.
+    /// This corresponds with the `BAT_THEME_DARK` environment variable and the `--theme-dark` option.
+    pub theme_dark: Option<ThemeName>,
+    /// The theme to use in case the terminal uses a light background with dark text.
+    /// This corresponds with the `BAT_THEME_LIGHT` environment variable and the `--theme-light` option.
+    pub theme_light: Option<ThemeName>,
+}
+
+/// What theme should `bat` use?
+///
+/// The easiest way to construct this is from a string:
+/// ```
+/// # use bat::theme::{ThemePreference, DetectColorScheme};
+/// let preference = ThemePreference::new("auto:system");
+/// assert_eq!(ThemePreference::Auto(DetectColorScheme::System), preference);
+/// ```
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum ThemePreference {
+    /// Choose between [`ThemeOptions::theme_dark`] and [`ThemeOptions::theme_light`]
+    /// based on the terminal's color scheme.
+    Auto(DetectColorScheme),
+    /// Always use the same theme regardless of the terminal's color scheme.
+    Fixed(ThemeName),
+    /// Use a dark theme.
+    Dark,
+    /// Use a light theme.
+    Light,
+}
+
+impl Default for ThemePreference {
+    fn default() -> Self {
+        ThemePreference::Auto(Default::default())
+    }
+}
+
+impl ThemePreference {
+    /// Creates a theme preference from a string.
+    pub fn new(s: impl Into<String>) -> Self {
+        use ThemePreference::*;
+        let s = s.into();
+        match s.as_str() {
+            "auto" => Auto(Default::default()),
+            "auto:always" => Auto(DetectColorScheme::Always),
+            "auto:system" => Auto(DetectColorScheme::System),
+            "dark" => Dark,
+            "light" => Light,
+            _ => Fixed(ThemeName::new(s)),
+        }
+    }
+}
+
+impl FromStr for ThemePreference {
+    type Err = Infallible;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        Ok(ThemePreference::new(s))
+    }
+}
+
+impl fmt::Display for ThemePreference {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use ThemePreference::*;
+        match self {
+            Auto(DetectColorScheme::Auto) => f.write_str("auto"),
+            Auto(DetectColorScheme::Always) => f.write_str("auto:always"),
+            Auto(DetectColorScheme::System) => f.write_str("auto:system"),
+            Fixed(theme) => theme.fmt(f),
+            Dark => f.write_str("dark"),
+            Light => f.write_str("light"),
+        }
+    }
+}
+
+/// The name of a theme or the default theme.
+///
+/// ```
+/// # use bat::theme::ThemeName;
+/// assert_eq!(ThemeName::Default, ThemeName::new("default"));
+/// assert_eq!(ThemeName::Named("example".to_string()), ThemeName::new("example"));
+/// ```
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum ThemeName {
+    Named(String),
+    Default,
+}
+
+impl ThemeName {
+    /// Creates a theme name from a string.
+    pub fn new(s: impl Into<String>) -> Self {
+        let s = s.into();
+        if s == "default" {
+            ThemeName::Default
+        } else {
+            ThemeName::Named(s)
+        }
+    }
+}
+
+impl FromStr for ThemeName {
+    type Err = Infallible;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        Ok(ThemeName::new(s))
+    }
+}
+
+impl fmt::Display for ThemeName {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            ThemeName::Named(t) => f.write_str(t),
+            ThemeName::Default => f.write_str("default"),
+        }
+    }
+}
+
+#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum DetectColorScheme {
+    /// Only query the terminal for its colors when appropriate (i.e. when the the output is not redirected).
+    #[default]
+    Auto,
+    /// Always query the terminal for its colors.
+    Always,
+    /// Detect the system-wide dark/light preference (macOS only).
+    System,
+}
+
+/// The color scheme used to pick a fitting theme. Defaults to [`ColorScheme::Dark`].
+#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum ColorScheme {
+    #[default]
+    Dark,
+    Light,
+}
+
+/// The resolved theme and the color scheme as determined from
+/// the terminal, OS or fallback.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct ThemeResult {
+    /// The theme selected according to the [`ThemeOptions`].
+    pub theme: ThemeName,
+    /// Either the user's chosen color scheme, the terminal's color scheme, the OS's
+    /// color scheme or `None` if the color scheme was not detected because the user chose a fixed theme.
+    pub color_scheme: Option<ColorScheme>,
+}
+
+impl fmt::Display for ThemeResult {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match &self.theme {
+            ThemeName::Named(name) => f.write_str(name),
+            ThemeName::Default => f.write_str(default_theme(self.color_scheme.unwrap_or_default())),
+        }
+    }
+}
+
+fn theme_impl(options: ThemeOptions, detector: &dyn ColorSchemeDetector) -> ThemeResult {
+    // Implementation note: This function is mostly pure (i.e. it has no side effects) for the sake of testing.
+    // All the side effects (e.g. querying the terminal for its colors) are performed in the detector.
+    match options.theme {
+        ThemePreference::Fixed(theme) => ThemeResult {
+            theme,
+            color_scheme: None,
+        },
+        ThemePreference::Dark => choose_theme_opt(Some(ColorScheme::Dark), options),
+        ThemePreference::Light => choose_theme_opt(Some(ColorScheme::Light), options),
+        ThemePreference::Auto(when) => choose_theme_opt(color_scheme_impl(when, detector), options),
+    }
+}
+
+fn choose_theme_opt(color_scheme: Option<ColorScheme>, options: ThemeOptions) -> ThemeResult {
+    ThemeResult {
+        color_scheme,
+        theme: color_scheme
+            .and_then(|c| choose_theme(options, c))
+            .unwrap_or(ThemeName::Default),
+    }
+}
+
+fn choose_theme(options: ThemeOptions, color_scheme: ColorScheme) -> Option<ThemeName> {
+    match color_scheme {
+        ColorScheme::Dark => options.theme_dark,
+        ColorScheme::Light => options.theme_light,
+    }
+}
+
+fn color_scheme_impl(
+    when: DetectColorScheme,
+    detector: &dyn ColorSchemeDetector,
+) -> Option<ColorScheme> {
+    let should_detect = match when {
+        DetectColorScheme::Auto => detector.should_detect(),
+        DetectColorScheme::Always => true,
+        DetectColorScheme::System => return color_scheme_from_system(),
+    };
+    should_detect.then(|| detector.detect()).flatten()
+}
+
+trait ColorSchemeDetector {
+    fn should_detect(&self) -> bool;
+
+    fn detect(&self) -> Option<ColorScheme>;
+}
+
+struct TerminalColorSchemeDetector;
+
+impl ColorSchemeDetector for TerminalColorSchemeDetector {
+    fn should_detect(&self) -> bool {
+        // Querying the terminal for its colors via OSC 10 / OSC 11 requires "exclusive" access
+        // since we read/write from the terminal and enable/disable raw mode.
+        // This causes race conditions with pagers such as less when they are attached to the
+        // same terminal as us.
+        //
+        // This is usually only an issue when the output is manually piped to a pager.
+        // For example: `bat Cargo.toml | less`.
+        // Otherwise, if we start the pager ourselves, then there's no race condition
+        // since the pager is started *after* the color is detected.
+        std::io::stdout().is_terminal()
+    }
+
+    fn detect(&self) -> Option<ColorScheme> {
+        use terminal_colorsaurus::{color_scheme, ColorScheme as ColorsaurusScheme, QueryOptions};
+        match color_scheme(QueryOptions::default()).ok()? {
+            ColorsaurusScheme::Dark => Some(ColorScheme::Dark),
+            ColorsaurusScheme::Light => Some(ColorScheme::Light),
+        }
+    }
+}
+
+#[cfg(not(target_os = "macos"))]
+fn color_scheme_from_system() -> Option<ColorScheme> {
+    crate::bat_warning!(
+        "Theme 'auto:system' is only supported on macOS, \
+        using default."
+    );
+    None
+}
+
+#[cfg(target_os = "macos")]
+fn color_scheme_from_system() -> Option<ColorScheme> {
+    const PREFERENCES_FILE: &str = "Library/Preferences/.GlobalPreferences.plist";
+    const STYLE_KEY: &str = "AppleInterfaceStyle";
+
+    let preferences_file = home::home_dir()
+        .map(|home| home.join(PREFERENCES_FILE))
+        .expect("Could not get home directory");
+
+    match plist::Value::from_file(preferences_file).map(|file| file.into_dictionary()) {
+        Ok(Some(preferences)) => match preferences.get(STYLE_KEY).and_then(|val| val.as_string()) {
+            Some("Dark") => Some(ColorScheme::Dark),
+            // If the key does not exist, then light theme is currently in use.
+            Some(_) | None => Some(ColorScheme::Light),
+        },
+        // Unreachable, in theory. All macOS users have a home directory and preferences file setup.
+        Ok(None) | Err(_) => None,
+    }
+}
+
+#[cfg(test)]
+impl ColorSchemeDetector for Option<ColorScheme> {
+    fn should_detect(&self) -> bool {
+        true
+    }
+
+    fn detect(&self) -> Option<ColorScheme> {
+        *self
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::ColorScheme::*;
+    use super::*;
+    use std::cell::Cell;
+    use std::iter;
+
+    mod color_scheme_detection {
+        use super::*;
+
+        #[test]
+        fn not_called_for_dark_or_light() {
+            for theme in [ThemePreference::Dark, ThemePreference::Light] {
+                let detector = DetectorStub::should_detect(Some(Dark));
+                let options = ThemeOptions {
+                    theme,
+                    ..Default::default()
+                };
+                _ = theme_impl(options, &detector);
+                assert!(!detector.was_called.get());
+            }
+        }
+
+        #[test]
+        fn called_for_always() {
+            let detectors = [
+                DetectorStub::should_detect(Some(Dark)),
+                DetectorStub::should_not_detect(),
+            ];
+            for detector in detectors {
+                let options = ThemeOptions {
+                    theme: ThemePreference::Auto(DetectColorScheme::Always),
+                    ..Default::default()
+                };
+                _ = theme_impl(options, &detector);
+                assert!(detector.was_called.get());
+            }
+        }
+
+        #[test]
+        fn called_for_auto_if_should_detect() {
+            let detector = DetectorStub::should_detect(Some(Dark));
+            _ = theme_impl(ThemeOptions::default(), &detector);
+            assert!(detector.was_called.get());
+        }
+
+        #[test]
+        fn not_called_for_auto_if_not_should_detect() {
+            let detector = DetectorStub::should_not_detect();
+            _ = theme_impl(ThemeOptions::default(), &detector);
+            assert!(!detector.was_called.get());
+        }
+    }
+
+    mod precedence {
+        use super::*;
+
+        #[test]
+        fn theme_is_preferred_over_light_or_dark_themes() {
+            for color_scheme in optional(color_schemes()) {
+                for options in [
+                    ThemeOptions {
+                        theme: ThemePreference::Fixed(ThemeName::Named("Theme".to_string())),
+                        ..Default::default()
+                    },
+                    ThemeOptions {
+                        theme: ThemePreference::Fixed(ThemeName::Named("Theme".to_string())),
+                        theme_dark: Some(ThemeName::Named("Dark Theme".to_string())),
+                        theme_light: Some(ThemeName::Named("Light Theme".to_string())),
+                        ..Default::default()
+                    },
+                ] {
+                    let detector = ConstantDetector(color_scheme);
+                    assert_eq!("Theme", theme_impl(options, &detector).to_string());
+                }
+            }
+        }
+
+        #[test]
+        fn detector_is_not_called_if_theme_is_present() {
+            let options = ThemeOptions {
+                theme: ThemePreference::Fixed(ThemeName::Named("Theme".to_string())),
+                ..Default::default()
+            };
+            let detector = DetectorStub::should_detect(Some(Dark));
+            _ = theme_impl(options, &detector);
+            assert!(!detector.was_called.get());
+        }
+    }
+
+    mod default_theme {
+        use super::*;
+
+        #[test]
+        fn default_dark_if_unable_to_detect_color_scheme() {
+            let detector = ConstantDetector(None);
+            assert_eq!(
+                default_theme(ColorScheme::Dark),
+                theme_impl(ThemeOptions::default(), &detector).to_string()
+            );
+        }
+
+        // For backwards compatibility, if the default theme is requested
+        // explicitly through BAT_THEME, we always pick the default dark theme.
+        #[test]
+        fn default_dark_if_requested_explicitly_through_theme() {
+            for color_scheme in optional(color_schemes()) {
+                let options = ThemeOptions {
+                    theme: ThemePreference::Fixed(ThemeName::Default),
+                    ..Default::default()
+                };
+                let detector = ConstantDetector(color_scheme);
+                assert_eq!(
+                    default_theme(ColorScheme::Dark),
+                    theme_impl(options, &detector).to_string()
+                );
+            }
+        }
+
+        #[test]
+        fn varies_depending_on_color_scheme() {
+            for color_scheme in color_schemes() {
+                for options in [
+                    ThemeOptions::default(),
+                    ThemeOptions {
+                        theme_dark: Some(ThemeName::Default),
+                        theme_light: Some(ThemeName::Default),
+                        ..Default::default()
+                    },
+                ] {
+                    let detector = ConstantDetector(Some(color_scheme));
+                    assert_eq!(
+                        default_theme(color_scheme),
+                        theme_impl(options, &detector).to_string()
+                    );
+                }
+            }
+        }
+    }
+
+    mod choosing {
+        use super::*;
+
+        #[test]
+        fn chooses_default_theme_if_unknown() {
+            let options = ThemeOptions {
+                theme_dark: Some(ThemeName::Named("Dark".to_string())),
+                theme_light: Some(ThemeName::Named("Light".to_string())),
+                ..Default::default()
+            };
+            let detector = ConstantDetector(None);
+            assert_eq!(
+                default_theme(ColorScheme::default()),
+                theme_impl(options, &detector).to_string()
+            );
+        }
+
+        #[test]
+        fn chooses_dark_theme_if_dark_or_unknown() {
+            let options = ThemeOptions {
+                theme_dark: Some(ThemeName::Named("Dark".to_string())),
+                theme_light: Some(ThemeName::Named("Light".to_string())),
+                ..Default::default()
+            };
+            let detector = ConstantDetector(Some(ColorScheme::Dark));
+            assert_eq!("Dark", theme_impl(options, &detector).to_string());
+        }
+
+        #[test]
+        fn chooses_light_theme_if_light() {
+            let options = ThemeOptions {
+                theme_dark: Some(ThemeName::Named("Dark".to_string())),
+                theme_light: Some(ThemeName::Named("Light".to_string())),
+                ..Default::default()
+            };
+            let detector = ConstantDetector(Some(ColorScheme::Light));
+            assert_eq!("Light", theme_impl(options, &detector).to_string());
+        }
+    }
+
+    mod theme_preference {
+        use super::*;
+
+        #[test]
+        fn values_roundtrip_via_display() {
+            let prefs = [
+                ThemePreference::Auto(DetectColorScheme::Auto),
+                ThemePreference::Auto(DetectColorScheme::Always),
+                ThemePreference::Auto(DetectColorScheme::System),
+                ThemePreference::Fixed(ThemeName::Default),
+                ThemePreference::Fixed(ThemeName::new("foo")),
+                ThemePreference::Dark,
+                ThemePreference::Light,
+            ];
+            for pref in prefs {
+                assert_eq!(pref, ThemePreference::new(&pref.to_string()));
+            }
+        }
+    }
+
+    struct DetectorStub {
+        should_detect: bool,
+        color_scheme: Option<ColorScheme>,
+        was_called: Cell<bool>,
+    }
+
+    impl DetectorStub {
+        fn should_detect(color_scheme: Option<ColorScheme>) -> Self {
+            DetectorStub {
+                should_detect: true,
+                color_scheme,
+                was_called: Cell::default(),
+            }
+        }
+
+        fn should_not_detect() -> Self {
+            DetectorStub {
+                should_detect: false,
+                color_scheme: None,
+                was_called: Cell::default(),
+            }
+        }
+    }
+
+    impl ColorSchemeDetector for DetectorStub {
+        fn should_detect(&self) -> bool {
+            self.should_detect
+        }
+
+        fn detect(&self) -> Option<ColorScheme> {
+            self.was_called.set(true);
+            self.color_scheme
+        }
+    }
+
+    struct ConstantDetector(Option<ColorScheme>);
+
+    impl ColorSchemeDetector for ConstantDetector {
+        fn should_detect(&self) -> bool {
+            true
+        }
+
+        fn detect(&self) -> Option<ColorScheme> {
+            self.0
+        }
+    }
+
+    fn optional<T>(value: impl Iterator<Item = T>) -> impl Iterator<Item = Option<T>> {
+        value.map(Some).chain(iter::once(None))
+    }
+
+    fn color_schemes() -> impl Iterator<Item = ColorScheme> {
+        [Dark, Light].into_iter()
+    }
+}

diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs
index 59cc83b37a..cd5c0846ff 100644
--- a/tests/integration_tests.rs
+++ b/tests/integration_tests.rs
@@ -273,11 +273,8 @@ fn squeeze_limit_line_numbers() {
 
 #[test]
 fn list_themes_with_colors() {
-    #[cfg(target_os = "macos")]
-    let default_theme_chunk = "Monokai Extended Light\x1B[0m (default)";
-
-    #[cfg(not(target_os = "macos"))]
     let default_theme_chunk = "Monokai Extended\x1B[0m (default)";
+    let default_light_theme_chunk = "Monokai Extended Light\x1B[0m (default light)";
 
     bat()
         .arg("--color=always")
@@ -286,16 +283,14 @@ fn list_themes_with_colors() {
         .success()
         .stdout(predicate::str::contains("DarkNeon").normalize())
         .stdout(predicate::str::contains(default_theme_chunk).normalize())
+        .stdout(predicate::str::contains(default_light_theme_chunk).normalize())
         .stdout(predicate::str::contains("Output the square of a number.").normalize());
 }
 
 #[test]
 fn list_themes_without_colors() {
-    #[cfg(target_os = "macos")]
-    let default_theme_chunk = "Monokai Extended Light (default)";
-
-    #[cfg(not(target_os = "macos"))]
     let default_theme_chunk = "Monokai Extended (default)";
+    let default_light_theme_chunk = "Monokai Extended Light (default light)";
 
     bat()
         .arg("--color=never")
@@ -304,7 +299,8 @@ fn list_themes_without_colors() {
         .assert()
         .success()
         .stdout(predicate::str::contains("DarkNeon").normalize())
-        .stdout(predicate::str::contains(default_theme_chunk).normalize());
+        .stdout(predicate::str::contains(default_theme_chunk).normalize())
+        .stdout(predicate::str::contains(default_light_theme_chunk).normalize());
 }
 
 #[test]
@@ -414,6 +410,7 @@ fn no_args_doesnt_break() {
     // as the slave end of a pseudo terminal. Although both point to the same "file", bat should
     // not exit, because in this case it is safe to read and write to the same fd, which is why
     // this test exists.
+
     let OpenptyResult { master, slave } = openpty(None, None).expect("Couldn't open pty.");
     let mut master = File::from(master);
     let stdin_file = File::from(slave);
@@ -424,6 +421,7 @@ fn no_args_doesnt_break() {
     let mut child = bat_raw_command()
         .stdin(stdin)
         .stdout(stdout)
+        .env("TERM", "dumb") // Suppresses color detection
         .spawn()
         .expect("Failed to start.");
 

{"header": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "grid_numbers": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "changes": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "changes_grid": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "theme::tests::precedence::theme_is_preferred_over_light_or_dark_themes": {"run": "NONE", "test": "NONE", "fix": "PASS"}, "syntaxes": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "grid_rule": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "header_numbers_rule": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "changes_header": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "plain": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "changes_grid_header": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "changes_grid_header_rule": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "grid_header_numbers": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "changes_rule": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "theme::tests::default_theme::varies_depending_on_color_scheme": {"run": "NONE", "test": "NONE", "fix": "PASS"}, "theme::tests::choosing::chooses_light_theme_if_light": {"run": "NONE", "test": "NONE", "fix": "PASS"}, "grid_header_rule": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "numbers": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "changes_grid_header_numbers": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "theme::tests::color_scheme_detection::called_for_always": {"run": "NONE", "test": "NONE", "fix": "PASS"}, "changes_grid_numbers": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "theme::tests::color_scheme_detection::called_for_auto_if_should_detect": {"run": "NONE", "test": "NONE", "fix": "PASS"}, "theme::tests::color_scheme_detection::not_called_for_auto_if_not_should_detect": {"run": "NONE", "test": "NONE", "fix": "PASS"}, "changes_header_rule": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "full": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "no_duplicate_extensions": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "theme::tests::choosing::chooses_dark_theme_if_dark_or_unknown": {"run": "NONE", "test": "NONE", "fix": "PASS"}, "theme::tests::color_scheme_detection::not_called_for_dark_or_light": {"run": "NONE", "test": "NONE", "fix": "PASS"}, "theme::tests::theme_preference::values_roundtrip_via_display": {"run": "NONE", "test": "NONE", "fix": "PASS"}, "list_themes_with_colors": {"run": "PASS", "test": "FAIL", "fix": "PASS"}, "grid_header": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "theme::tests::precedence::detector_is_not_called_if_theme_is_present": {"run": "NONE", "test": "NONE", "fix": "PASS"}, "changes_grid_rule": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "header_rule": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "rule": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "header_numbers": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "theme::tests::default_theme::default_dark_if_unable_to_detect_color_scheme": {"run": "NONE", "test": "NONE", "fix": "PASS"}, "changes_grid_header_numbers_rule": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "theme::tests::default_theme::default_dark_if_requested_explicitly_through_theme": {"run": "NONE", "test": "NONE", "fix": "PASS"}, "list_themes_without_colors": {"run": "PASS", "test": "FAIL", "fix": "PASS"}, "changes_header_numbers": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "grid": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "changes_numbers": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "theme::tests::choosing::chooses_default_theme_if_unknown": {"run": "NONE", "test": "NONE", "fix": "PASS"}}
{"squeeze_blank": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "highlighting_independant_from_map_syntax_case": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "basic": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "tabs_4": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "no_line_wrapping_with_s_flag": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "tabs_4_env_overrides_config": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "vscreen::tests::test_escape_sequence_offsets_iterator_parses_csi_thats_broken": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "filename_multiple_err": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "style_components_can_be_overidden": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "syntax_mapping::tests::all_fixed_builtin_mappings_can_compile": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "accepts_no_custom_assets_arg": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "short_help": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "style::test::style_component_list_to_components": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "tabs_8_wrapped": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "map_syntax_and_ignored_suffix_work_together": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "show_all_extends_tab_markers_to_next_tabstop_width_8": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "all_jobs_not_missing_any_jobs": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "line_range::test_parse_fail": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "show_all_mode": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "style::test::style_component_list_to_components_expands_subcomponents": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "tabs_numbers": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "line_range_first_two": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "file_with_invalid_utf8_filename": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "strip_ansi_auto_strips_ansi_when_detected_syntax_by_filename": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "assets::build_assets::acknowledgements::tests::test_append_to_acknowledgements_adds_newline_if_missing": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "line_range::test_parse_plus_fail": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "show_all_with_unicode": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "less::test_parse_less_version_wrong_program": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "line_range::test_ranges_open_low": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "empty_file_leads_to_empty_output_with_grid_enabled": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "config_location_from_bat_config_dir_variable": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "vscreen::tests::test_escape_sequence_offsets_iterator_parses_osc_with_st": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "pager_overwrite": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "assets::tests::syntax_detection_is_case_insensitive": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "pager_arg_override_env_noconfig": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "tabs_4_arg_overrides_env": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "less::test_parse_less_version_581_2": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "style::test::style_component_list_parse": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "vscreen::tests::test_escape_sequence_offsets_iterator_parses_csi_with_parameters": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "concatenate_empty_both": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "vscreen::tests::test_escape_sequence_offsets_iterator_parses_csi": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "long_help": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "line_range::test_parse_minus_fail": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "no_wrapping_with_chop_long_lines": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "empty_file_leads_to_empty_output_with_rule_enabled": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "pager_most_from_bat_pager_env_var": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "ansi_highlight_underline": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "paging_does_not_override_simple_plain": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "pager_more": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "squeeze_blank_line_numbers": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "vscreen::tests::test_escape_sequence_offsets_iterator_parses_nf_thats_broken": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "assets::tests::syntax_detection_with_extension_mapping_to_unknown": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "env_var_bat_pager_value_bat": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "cache_build": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "pager_most_from_pager_env_var": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "style::test::style_component_list_to_components_removes_negated": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "clap_app::verify_app": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "line_range::test_parse_plus_overflow": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "line_range::test_parse_full": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "header_env_basic": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "tabs_4_arg_overrides_env_noconfig": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "vscreen::tests::test_escape_sequence_iterator_iterates": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "plain_mode_does_not_add_nonexisting_newline": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "does_not_print_unwanted_file_named_cache": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "preprocessor::test_strip_ansi": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "concatenate_empty_between": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "line_range::test_parse_partial_min": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "style::test::style_component_list_expand_negates_subcomponents": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "header_padding_rule": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "no_broken_osc_emit_with_line_wrapping": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "config::default_config_should_include_all_lines": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "strip_ansi_always_strips_ansi": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "pager_basic_arg": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "binary_as_text": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "style::test::style_component_list_to_components_precedence_overrides_previous_lists": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "concatenate_stdin": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "vscreen::tests::test_escape_sequence_offsets_iterator_parses_text": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "ansi_hyperlink_emitted_when_wrapped": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "pager_basic": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "header_binary": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "no_line_wrapping_when_set_to_never": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "vscreen::tests::test_escape_sequence_offsets_iterator_parses_osc_with_bel": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "line_range::test_ranges_all": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "config::multi_line": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "vscreen::tests::test_escape_sequence_offsets_iterator_parses_csi_with_intermediates": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "tabs_passthrough_wrapped": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "less::test_parse_less_version_busybox": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "vscreen::tests::test_escape_sequence_offsets_iterator_parses_text_stops_at_esc": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "pager_most_with_arg": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "alias_pager_disable_long_overrides_short": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "pager_failed_to_parse": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "all_global_git_config_locations_syntax_mapping_work": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "header_default": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "bom_stripped_when_no_color_and_not_loop_through": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "vscreen::tests::test_escape_sequence_offsets_iterator_parses_osc_thats_broken": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "config_location_when_generating": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "syntax_mapping::tests::builtin_mappings_work": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "assets::tests::syntax_detection_basic": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "less::test_parse_less_version_invalid_utf_8": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "basic_set_terminal_title": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "config::multiple": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "no_paging_short_arg": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "no_paging_arg": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "strip_ansi_never_does_not_strip_ansi": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "stdin_to_stdout_cycle": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "fail_non_existing": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "vscreen::tests::test_escape_sequence_offsets_iterator_parses_nf": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "assets::build_assets::acknowledgements::tests::test_normalize_license_text_with_windows_line_endings": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "can_print_file_named_cache": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "first_file_cyclic_is_ok": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "config_location_test": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "strip_ansi_does_not_strip_when_show_nonprintable": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "squeeze_limit_line_numbers": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "show_all_extends_tab_markers_to_next_tabstop": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "line_wrapping_when_auto": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "assets::tests::syntax_detection_with_custom_mapping": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "line_range::test_ranges_open_high": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "line_range_last_3": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "theme_arg_overrides_env": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "enable_pager_if_pp_flag_comes_before_paging": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "input::utf16le": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "pager_disable": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "filename_stdin_binary": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "line_numbers": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "theme_arg_overrides_env_withconfig": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "assets::tests::syntax_detection_well_defined_mapping_for_duplicate_extensions": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "header_full_basic": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "concatenate_empty_last": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "squeeze_limit": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "bom_not_stripped_in_loop_through_mode": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "snip": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "header_padding": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "concatenate": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "can_print_file_starting_with_cache": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "filename_stdin": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "list_themes_to_piped_output": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "env_var_pager_value_bat": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "line_range::test_parse_partial_max": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "pager_arg_override_env_withconfig": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "pager_env_pager_nooverride_config": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "concatenate_single_line": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "no_first_line_fallback_when_mapping_to_invalid_syntax": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "line_range::test_parse_minus_success": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "stdin": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "basic_io_cycle": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "fail_directory": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "empty_file_cycle_is_ok": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "strip_ansi_auto_strips_ansi_when_provided_syntax_by_option": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "assets::tests::syntax_detection_invalid_utf8": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "ansi_passthrough_emit": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "vscreen::tests::test_escape_sequence_offsets_iterator_iterates": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "pager_value_bat": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "config::quotes": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "concatenate_single_line_empty": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "acknowledgements": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "tabs_passthrough": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "line_range::test_ranges_none": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "preprocessor::test_try_parse_utf8_char": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "style::test::style_component_list_default_builds_on_auto": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "syntax_mapping::tests::custom_mappings_precedence": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "config::empty": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "line_range_multiple": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "env_var_bat_paging": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "theme_env_overrides_config": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "input::basic": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "syntax_mapping::tests::custom_mappings_work": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "filename_multiple_ok": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "config::default_config_should_highlight_no_lines": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "line_range::test_ranges_advanced": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "style_components_will_merge": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "line_range::test_parse_minus_edge_cases_success": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "line_range_2_3": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "style::test::style_component_list_to_components_precedence_merges_previous_lists": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "can_print_file_named_cache_with_additional_argument": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "tabs_8": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "header_full_padding": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "config::single": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "bom_stripped_when_colored_output": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "concatenate_empty_first": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "assets::tests::syntax_detection_stdin_filename": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "tabs_4_wrapped": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "less::test_parse_less_version_529": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "ignored_suffix_arg": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "vscreen::tests::test_sgr_attributes_do_not_leak_into_wrong_field": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "line_range::test_parse_plus": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "header_full_padding_rule": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "enable_pager_if_disable_paging_flag_comes_before_paging": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "syntax_mapping::tests::custom_mappings_override_builtin": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "header_arg_overrides_env": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "pager_env_bat_pager_override_config": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "header_default_is_default": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "do_not_detect_different_syntax_for_stdin_and_files": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "style_components_will_merge_with_env_var": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "syntax_mapping::tests::builtin_mappings_matcher_only_compile_once": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "less::test_parse_less_version_551": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "line_range::test_parse_single": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "header_very_narrow_terminal": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "vscreen::tests::test_escape_sequence_offsets_iterator_parses_csi_with_parameters_and_intermediates": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "assets::tests::syntax_detection_same_for_inputkinds": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "strip_ansi_auto_does_not_strip_ansi_when_plain_text_by_option": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "line_range::test_ranges_simple": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "assets::tests::syntax_detection_for_symlinked_file": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "cache_clear": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "grid_for_file_without_newline": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "strip_ansi_auto_does_not_strip_when_plain_text_by_filename": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "diagnostic_sanity_check": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "utf16": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "less::test_parse_less_version_487": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "disable_pager_if_pp_flag_comes_after_paging": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "unicode_wrap": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "simple_plain_does_not_override_paging": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "strip_ansi_does_not_affect_simple_printer": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "config::comments": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "pager_most_from_pager_arg": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "syntax_mapping::ignored_suffixes::internal_suffixes": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "config_read_arguments_from_file": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "ansi_sgr_emitted_when_wrapped": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "highlighting_is_skipped_on_long_lines": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "assets::tests::syntax_detection_first_line": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "grid_overrides_rule": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "header_basic": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "disable_pager_if_disable_paging_flag_comes_after_paging": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "alias_pager_disable": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "concatenate_empty_first_and_last": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "no_pager_arg": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "ansi_sgr_joins_attributes_when_wrapped": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "do_not_panic_regression_tests": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "do_not_exit_directory": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "style_components_can_be_removed": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "syntax_mapping::ignored_suffixes::external_suffixes": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "show_all_with_caret_notation": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "assets::build_assets::acknowledgements::tests::test_normalize_license_text": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "no_args_doesnt_break": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "header_full_binary": {"run": "PASS", "test": "PASS", "fix": "PASS"}}
{"list_themes_with_colors": {"run": "PASS", "test": "FAIL", "fix": "PASS"}, "list_themes_without_colors": {"run": "PASS", "test": "FAIL", "fix": "PASS"}}
{"header": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "grid_numbers": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "changes": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "changes_grid": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "theme::tests::precedence::theme_is_preferred_over_light_or_dark_themes": {"run": "NONE", "test": "NONE", "fix": "PASS"}, "syntaxes": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "grid_rule": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "header_numbers_rule": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "changes_header": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "plain": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "changes_grid_header": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "changes_grid_header_rule": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "grid_header_numbers": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "changes_rule": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "theme::tests::default_theme::varies_depending_on_color_scheme": {"run": "NONE", "test": "NONE", "fix": "PASS"}, "theme::tests::choosing::chooses_light_theme_if_light": {"run": "NONE", "test": "NONE", "fix": "PASS"}, "grid_header_rule": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "numbers": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "changes_grid_header_numbers": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "theme::tests::color_scheme_detection::called_for_always": {"run": "NONE", "test": "NONE", "fix": "PASS"}, "changes_grid_numbers": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "theme::tests::color_scheme_detection::called_for_auto_if_should_detect": {"run": "NONE", "test": "NONE", "fix": "PASS"}, "theme::tests::color_scheme_detection::not_called_for_auto_if_not_should_detect": {"run": "NONE", "test": "NONE", "fix": "PASS"}, "changes_header_rule": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "full": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "no_duplicate_extensions": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "theme::tests::choosing::chooses_dark_theme_if_dark_or_unknown": {"run": "NONE", "test": "NONE", "fix": "PASS"}, "theme::tests::color_scheme_detection::not_called_for_dark_or_light": {"run": "NONE", "test": "NONE", "fix": "PASS"}, "theme::tests::theme_preference::values_roundtrip_via_display": {"run": "NONE", "test": "NONE", "fix": "PASS"}, "grid_header": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "theme::tests::precedence::detector_is_not_called_if_theme_is_present": {"run": "NONE", "test": "NONE", "fix": "PASS"}, "changes_grid_rule": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "header_rule": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "rule": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "header_numbers": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "theme::tests::default_theme::default_dark_if_unable_to_detect_color_scheme": {"run": "NONE", "test": "NONE", "fix": "PASS"}, "changes_grid_header_numbers_rule": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "theme::tests::default_theme::default_dark_if_requested_explicitly_through_theme": {"run": "NONE", "test": "NONE", "fix": "PASS"}, "changes_header_numbers": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "grid": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "changes_numbers": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "theme::tests::choosing::chooses_default_theme_if_unknown": {"run": "NONE", "test": "NONE", "fix": "PASS"}}
{"passed_count": 265, "failed_count": 0, "skipped_count": 3, "passed_tests": ["squeeze_blank", "highlighting_independant_from_map_syntax_case", "line_wrapping_when_auto", "basic", "tabs_4", "assets::tests::syntax_detection_with_custom_mapping", "no_line_wrapping_with_s_flag", "tabs_4_env_overrides_config", "header", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_csi_thats_broken", "filename_multiple_err", "line_range::test_ranges_open_high", "line_range_last_3", "style_components_can_be_overidden", "theme_arg_overrides_env", "enable_pager_if_pp_flag_comes_before_paging", "syntax_mapping::tests::all_fixed_builtin_mappings_can_compile", "accepts_no_custom_assets_arg", "input::utf16le", "short_help", "grid_numbers", "changes_header_rule", "pager_disable", "filename_stdin_binary", "style::test::style_component_list_to_components", "tabs_8_wrapped", "line_numbers", "map_syntax_and_ignored_suffix_work_together", "theme_arg_overrides_env_withconfig", "assets::tests::syntax_detection_well_defined_mapping_for_duplicate_extensions", "header_full_basic", "concatenate_empty_last", "show_all_extends_tab_markers_to_next_tabstop_width_8", "all_jobs_not_missing_any_jobs", "squeeze_limit", "bom_not_stripped_in_loop_through_mode", "snip", "header_padding", "line_range::test_parse_fail", "concatenate", "can_print_file_starting_with_cache", "show_all_mode", "list_themes_to_piped_output", "env_var_pager_value_bat", "line_range::test_parse_partial_max", "filename_stdin", "pager_arg_override_env_withconfig", "changes", "pager_env_pager_nooverride_config", "style::test::style_component_list_to_components_expands_subcomponents", "changes_grid", "concatenate_single_line", "no_first_line_fallback_when_mapping_to_invalid_syntax", "line_range::test_parse_minus_success", "stdin", "line_range_first_two", "tabs_numbers", "basic_io_cycle", "fail_directory", "strip_ansi_auto_strips_ansi_when_detected_syntax_by_filename", "assets::build_assets::acknowledgements::tests::test_append_to_acknowledgements_adds_newline_if_missing", "line_range::test_parse_plus_fail", "show_all_with_unicode", "strip_ansi_auto_strips_ansi_when_provided_syntax_by_option", "empty_file_cycle_is_ok", "less::test_parse_less_version_wrong_program", "line_range::test_ranges_open_low", "assets::tests::syntax_detection_invalid_utf8", "no_duplicate_extensions", "full", "ansi_passthrough_emit", "empty_file_leads_to_empty_output_with_grid_enabled", "config_location_from_bat_config_dir_variable", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_osc_with_st", "vscreen::tests::test_escape_sequence_offsets_iterator_iterates", "pager_value_bat", "pager_overwrite", "assets::tests::syntax_detection_is_case_insensitive", "config::quotes", "pager_arg_override_env_noconfig", "tabs_4_arg_overrides_env", "less::test_parse_less_version_581_2", "acknowledgements", "style::test::style_component_list_parse", "tabs_passthrough", "concatenate_single_line_empty", "file_with_invalid_utf8_filename", "line_range::test_ranges_none", "preprocessor::test_try_parse_utf8_char", "style::test::style_component_list_default_builds_on_auto", "syntax_mapping::tests::custom_mappings_precedence", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_csi_with_parameters", "config::empty", "syntaxes", "grid_rule", "concatenate_empty_both", "line_range_multiple", "env_var_bat_paging", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_csi", "theme_env_overrides_config", "input::basic", "header_numbers_rule", "syntax_mapping::tests::custom_mappings_work", "long_help", "filename_multiple_ok", "line_range::test_parse_minus_fail", "config::default_config_should_highlight_no_lines", "no_wrapping_with_chop_long_lines", "empty_file_leads_to_empty_output_with_rule_enabled", "pager_most_from_bat_pager_env_var", "line_range::test_ranges_advanced", "style_components_will_merge", "line_range::test_parse_minus_edge_cases_success", "line_range_2_3", "changes_header", "list_themes_with_colors", "style::test::style_component_list_to_components_precedence_merges_previous_lists", "ansi_highlight_underline", "paging_does_not_override_simple_plain", "pager_more", "squeeze_blank_line_numbers", "grid_header", "can_print_file_named_cache_with_additional_argument", "tabs_8", "header_full_padding", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_nf_thats_broken", "assets::tests::syntax_detection_with_extension_mapping_to_unknown", "env_var_bat_pager_value_bat", "plain", "cache_build", "pager_most_from_pager_env_var", "style::test::style_component_list_to_components_removes_negated", "config::single", "clap_app::verify_app", "concatenate_empty_first", "bom_stripped_when_colored_output", "line_range::test_parse_plus_overflow", "line_range::test_parse_full", "header_env_basic", "assets::tests::syntax_detection_stdin_filename", "tabs_4_wrapped", "tabs_4_arg_overrides_env_noconfig", "less::test_parse_less_version_529", "vscreen::tests::test_escape_sequence_iterator_iterates", "plain_mode_does_not_add_nonexisting_newline", "does_not_print_unwanted_file_named_cache", "preprocessor::test_strip_ansi", "vscreen::tests::test_sgr_attributes_do_not_leak_into_wrong_field", "line_range::test_parse_partial_min", "line_range::test_parse_plus", "style::test::style_component_list_expand_negates_subcomponents", "header_padding_rule", "ignored_suffix_arg", "concatenate_empty_between", "header_full_padding_rule", "no_broken_osc_emit_with_line_wrapping", "changes_grid_header", "changes_grid_rule", "config::default_config_should_include_all_lines", "enable_pager_if_disable_paging_flag_comes_before_paging", "strip_ansi_always_strips_ansi", "syntax_mapping::tests::custom_mappings_override_builtin", "header_arg_overrides_env", "pager_env_bat_pager_override_config", "pager_basic_arg", "header_default_is_default", "changes_grid_header_rule", "do_not_detect_different_syntax_for_stdin_and_files", "binary_as_text", "header_rule", "style::test::style_component_list_to_components_precedence_overrides_previous_lists", "style_components_will_merge_with_env_var", "concatenate_stdin", "rule", "syntax_mapping::tests::builtin_mappings_matcher_only_compile_once", "header_numbers", "less::test_parse_less_version_551", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_text", "line_range::test_parse_single", "ansi_hyperlink_emitted_when_wrapped", "pager_basic", "grid_header_numbers", "header_binary", "header_very_narrow_terminal", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_csi_with_parameters_and_intermediates", "no_line_wrapping_when_set_to_never", "changes_rule", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_osc_with_bel", "assets::tests::syntax_detection_same_for_inputkinds", "line_range::test_ranges_all", "config::multi_line", "changes_grid_header_numbers_rule", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_csi_with_intermediates", "tabs_passthrough_wrapped", "strip_ansi_auto_does_not_strip_ansi_when_plain_text_by_option", "less::test_parse_less_version_busybox", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_text_stops_at_esc", "pager_most_with_arg", "line_range::test_ranges_simple", "alias_pager_disable_long_overrides_short", "assets::tests::syntax_detection_for_symlinked_file", "cache_clear", "grid_for_file_without_newline", "strip_ansi_auto_does_not_strip_when_plain_text_by_filename", "diagnostic_sanity_check", "pager_failed_to_parse", "utf16", "grid_header_rule", "less::test_parse_less_version_487", "numbers", "disable_pager_if_pp_flag_comes_after_paging", "unicode_wrap", "all_global_git_config_locations_syntax_mapping_work", "header_default", "list_themes_without_colors", "simple_plain_does_not_override_paging", "strip_ansi_does_not_affect_simple_printer", "config::comments", "bom_stripped_when_no_color_and_not_loop_through", "pager_most_from_pager_arg", "changes_grid_header_numbers", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_osc_thats_broken", "syntax_mapping::ignored_suffixes::internal_suffixes", "config_location_when_generating", "config_read_arguments_from_file", "syntax_mapping::tests::builtin_mappings_work", "ansi_sgr_emitted_when_wrapped", "highlighting_is_skipped_on_long_lines", "assets::tests::syntax_detection_basic", "less::test_parse_less_version_invalid_utf_8", "basic_set_terminal_title", "config::multiple", "assets::tests::syntax_detection_first_line", "grid_overrides_rule", "header_basic", "disable_pager_if_disable_paging_flag_comes_after_paging", "changes_header_numbers", "alias_pager_disable", "no_paging_short_arg", "concatenate_empty_first_and_last", "no_pager_arg", "no_paging_arg", "stdin_to_stdout_cycle", "strip_ansi_never_does_not_strip_ansi", "ansi_sgr_joins_attributes_when_wrapped", "fail_non_existing", "changes_grid_numbers", "grid", "changes_numbers", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_nf", "assets::build_assets::acknowledgements::tests::test_normalize_license_text_with_windows_line_endings", "do_not_panic_regression_tests", "can_print_file_named_cache", "first_file_cyclic_is_ok", "do_not_exit_directory", "config_location_test", "style_components_can_be_removed", "syntax_mapping::ignored_suffixes::external_suffixes", "show_all_with_caret_notation", "assets::build_assets::acknowledgements::tests::test_normalize_license_text", "no_args_doesnt_break", "strip_ansi_does_not_strip_when_show_nonprintable", "squeeze_limit_line_numbers", "header_full_binary", "show_all_extends_tab_markers_to_next_tabstop"], "failed_tests": [], "skipped_tests": ["config_overrides_system_config", "use_systemwide_config", "all_themes_are_present"]}
{"passed_count": 234, "failed_count": 2, "skipped_count": 1, "passed_tests": ["squeeze_blank", "highlighting_independant_from_map_syntax_case", "line_wrapping_when_auto", "basic", "tabs_4", "assets::tests::syntax_detection_with_custom_mapping", "no_line_wrapping_with_s_flag", "tabs_4_env_overrides_config", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_csi_thats_broken", "filename_multiple_err", "line_range::test_ranges_open_high", "line_range_last_3", "style_components_can_be_overidden", "enable_pager_if_pp_flag_comes_before_paging", "theme_arg_overrides_env", "syntax_mapping::tests::all_fixed_builtin_mappings_can_compile", "accepts_no_custom_assets_arg", "input::utf16le", "short_help", "pager_disable", "filename_stdin_binary", "style::test::style_component_list_to_components", "tabs_8_wrapped", "line_numbers", "map_syntax_and_ignored_suffix_work_together", "theme_arg_overrides_env_withconfig", "assets::tests::syntax_detection_well_defined_mapping_for_duplicate_extensions", "header_full_basic", "concatenate_empty_last", "show_all_extends_tab_markers_to_next_tabstop_width_8", "all_jobs_not_missing_any_jobs", "squeeze_limit", "bom_not_stripped_in_loop_through_mode", "snip", "header_padding", "line_range::test_parse_fail", "concatenate", "can_print_file_starting_with_cache", "filename_stdin", "show_all_mode", "list_themes_to_piped_output", "line_range::test_parse_partial_max", "pager_arg_override_env_withconfig", "env_var_pager_value_bat", "pager_env_pager_nooverride_config", "style::test::style_component_list_to_components_expands_subcomponents", "concatenate_single_line", "no_first_line_fallback_when_mapping_to_invalid_syntax", "line_range::test_parse_minus_success", "stdin", "line_range_first_two", "file_with_invalid_utf8_filename", "basic_io_cycle", "tabs_numbers", "strip_ansi_auto_strips_ansi_when_detected_syntax_by_filename", "assets::build_assets::acknowledgements::tests::test_append_to_acknowledgements_adds_newline_if_missing", "line_range::test_parse_plus_fail", "show_all_with_unicode", "strip_ansi_auto_strips_ansi_when_provided_syntax_by_option", "fail_directory", "less::test_parse_less_version_wrong_program", "empty_file_cycle_is_ok", "line_range::test_ranges_open_low", "assets::tests::syntax_detection_invalid_utf8", "ansi_passthrough_emit", "empty_file_leads_to_empty_output_with_grid_enabled", "config_location_from_bat_config_dir_variable", "vscreen::tests::test_escape_sequence_offsets_iterator_iterates", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_osc_with_st", "pager_value_bat", "pager_overwrite", "assets::tests::syntax_detection_is_case_insensitive", "config::quotes", "pager_arg_override_env_noconfig", "tabs_4_arg_overrides_env", "less::test_parse_less_version_581_2", "acknowledgements", "style::test::style_component_list_parse", "concatenate_single_line_empty", "tabs_passthrough", "line_range::test_ranges_none", "preprocessor::test_try_parse_utf8_char", "style::test::style_component_list_default_builds_on_auto", "syntax_mapping::tests::custom_mappings_precedence", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_csi_with_parameters", "config::empty", "concatenate_empty_both", "line_range_multiple", "env_var_bat_paging", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_csi", "theme_env_overrides_config", "input::basic", "syntax_mapping::tests::custom_mappings_work", "long_help", "filename_multiple_ok", "line_range::test_parse_minus_fail", "config::default_config_should_highlight_no_lines", "no_wrapping_with_chop_long_lines", "pager_most_from_bat_pager_env_var", "empty_file_leads_to_empty_output_with_rule_enabled", "line_range::test_ranges_advanced", "style_components_will_merge", "line_range::test_parse_minus_edge_cases_success", "line_range_2_3", "style::test::style_component_list_to_components_precedence_merges_previous_lists", "ansi_highlight_underline", "paging_does_not_override_simple_plain", "pager_more", "squeeze_blank_line_numbers", "can_print_file_named_cache_with_additional_argument", "tabs_8", "header_full_padding", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_nf_thats_broken", "assets::tests::syntax_detection_with_extension_mapping_to_unknown", "env_var_bat_pager_value_bat", "cache_build", "pager_most_from_pager_env_var", "style::test::style_component_list_to_components_removes_negated", "config::single", "clap_app::verify_app", "bom_stripped_when_colored_output", "concatenate_empty_first", "line_range::test_parse_plus_overflow", "line_range::test_parse_full", "header_env_basic", "assets::tests::syntax_detection_stdin_filename", "tabs_4_wrapped", "tabs_4_arg_overrides_env_noconfig", "less::test_parse_less_version_529", "vscreen::tests::test_escape_sequence_iterator_iterates", "ignored_suffix_arg", "plain_mode_does_not_add_nonexisting_newline", "preprocessor::test_strip_ansi", "vscreen::tests::test_sgr_attributes_do_not_leak_into_wrong_field", "line_range::test_parse_partial_min", "line_range::test_parse_plus", "style::test::style_component_list_expand_negates_subcomponents", "header_padding_rule", "concatenate_empty_between", "does_not_print_unwanted_file_named_cache", "header_full_padding_rule", "no_broken_osc_emit_with_line_wrapping", "config::default_config_should_include_all_lines", "enable_pager_if_disable_paging_flag_comes_before_paging", "strip_ansi_always_strips_ansi", "syntax_mapping::tests::custom_mappings_override_builtin", "header_arg_overrides_env", "pager_env_bat_pager_override_config", "pager_basic_arg", "header_default_is_default", "do_not_detect_different_syntax_for_stdin_and_files", "binary_as_text", "style::test::style_component_list_to_components_precedence_overrides_previous_lists", "concatenate_stdin", "style_components_will_merge_with_env_var", "syntax_mapping::tests::builtin_mappings_matcher_only_compile_once", "less::test_parse_less_version_551", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_text", "line_range::test_parse_single", "ansi_hyperlink_emitted_when_wrapped", "pager_basic", "header_binary", "header_very_narrow_terminal", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_csi_with_parameters_and_intermediates", "no_line_wrapping_when_set_to_never", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_osc_with_bel", "assets::tests::syntax_detection_same_for_inputkinds", "line_range::test_ranges_all", "config::multi_line", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_csi_with_intermediates", "tabs_passthrough_wrapped", "strip_ansi_auto_does_not_strip_ansi_when_plain_text_by_option", "less::test_parse_less_version_busybox", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_text_stops_at_esc", "pager_most_with_arg", "line_range::test_ranges_simple", "alias_pager_disable_long_overrides_short", "assets::tests::syntax_detection_for_symlinked_file", "cache_clear", "diagnostic_sanity_check", "grid_for_file_without_newline", "strip_ansi_auto_does_not_strip_when_plain_text_by_filename", "pager_failed_to_parse", "utf16", "less::test_parse_less_version_487", "disable_pager_if_pp_flag_comes_after_paging", "unicode_wrap", "all_global_git_config_locations_syntax_mapping_work", "simple_plain_does_not_override_paging", "strip_ansi_does_not_affect_simple_printer", "header_default", "bom_stripped_when_no_color_and_not_loop_through", "config::comments", "pager_most_from_pager_arg", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_osc_thats_broken", "syntax_mapping::ignored_suffixes::internal_suffixes", "config_location_when_generating", "config_read_arguments_from_file", "syntax_mapping::tests::builtin_mappings_work", "ansi_sgr_emitted_when_wrapped", "highlighting_is_skipped_on_long_lines", "assets::tests::syntax_detection_basic", "less::test_parse_less_version_invalid_utf_8", "basic_set_terminal_title", "config::multiple", "assets::tests::syntax_detection_first_line", "grid_overrides_rule", "header_basic", "disable_pager_if_disable_paging_flag_comes_after_paging", "alias_pager_disable", "no_paging_short_arg", "concatenate_empty_first_and_last", "no_pager_arg", "no_paging_arg", "fail_non_existing", "stdin_to_stdout_cycle", "ansi_sgr_joins_attributes_when_wrapped", "strip_ansi_never_does_not_strip_ansi", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_nf", "assets::build_assets::acknowledgements::tests::test_normalize_license_text_with_windows_line_endings", "do_not_panic_regression_tests", "can_print_file_named_cache", "first_file_cyclic_is_ok", "do_not_exit_directory", "config_location_test", "style_components_can_be_removed", "syntax_mapping::ignored_suffixes::external_suffixes", "show_all_with_caret_notation", "assets::build_assets::acknowledgements::tests::test_normalize_license_text", "no_args_doesnt_break", "strip_ansi_does_not_strip_when_show_nonprintable", "squeeze_limit_line_numbers", "header_full_binary", "show_all_extends_tab_markers_to_next_tabstop"], "failed_tests": ["list_themes_with_colors", "list_themes_without_colors"], "skipped_tests": ["all_themes_are_present"]}
{"passed_count": 278, "failed_count": 0, "skipped_count": 3, "passed_tests": ["squeeze_blank", "highlighting_independant_from_map_syntax_case", "line_wrapping_when_auto", "basic", "tabs_4", "assets::tests::syntax_detection_with_custom_mapping", "no_line_wrapping_with_s_flag", "tabs_4_env_overrides_config", "header", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_csi_thats_broken", "filename_multiple_err", "line_range::test_ranges_open_high", "line_range_last_3", "style_components_can_be_overidden", "theme_arg_overrides_env", "enable_pager_if_pp_flag_comes_before_paging", "syntax_mapping::tests::all_fixed_builtin_mappings_can_compile", "accepts_no_custom_assets_arg", "input::utf16le", "short_help", "grid_numbers", "changes_header_rule", "pager_disable", "filename_stdin_binary", "style::test::style_component_list_to_components", "tabs_8_wrapped", "line_numbers", "map_syntax_and_ignored_suffix_work_together", "theme_arg_overrides_env_withconfig", "assets::tests::syntax_detection_well_defined_mapping_for_duplicate_extensions", "header_full_basic", "concatenate_empty_last", "show_all_extends_tab_markers_to_next_tabstop_width_8", "all_jobs_not_missing_any_jobs", "squeeze_limit", "bom_not_stripped_in_loop_through_mode", "snip", "header_padding", "line_range::test_parse_fail", "concatenate", "can_print_file_starting_with_cache", "filename_stdin", "list_themes_to_piped_output", "env_var_pager_value_bat", "line_range::test_parse_partial_max", "show_all_mode", "pager_arg_override_env_withconfig", "changes", "pager_env_pager_nooverride_config", "style::test::style_component_list_to_components_expands_subcomponents", "changes_grid", "concatenate_single_line", "no_first_line_fallback_when_mapping_to_invalid_syntax", "line_range::test_parse_minus_success", "stdin", "line_range_first_two", "file_with_invalid_utf8_filename", "basic_io_cycle", "tabs_numbers", "strip_ansi_auto_strips_ansi_when_detected_syntax_by_filename", "assets::build_assets::acknowledgements::tests::test_append_to_acknowledgements_adds_newline_if_missing", "line_range::test_parse_plus_fail", "show_all_with_unicode", "strip_ansi_auto_strips_ansi_when_provided_syntax_by_option", "fail_directory", "less::test_parse_less_version_wrong_program", "empty_file_cycle_is_ok", "theme::tests::precedence::theme_is_preferred_over_light_or_dark_themes", "line_range::test_ranges_open_low", "assets::tests::syntax_detection_invalid_utf8", "no_duplicate_extensions", "full", "ansi_passthrough_emit", "empty_file_leads_to_empty_output_with_grid_enabled", "config_location_from_bat_config_dir_variable", "vscreen::tests::test_escape_sequence_offsets_iterator_iterates", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_osc_with_st", "pager_value_bat", "pager_overwrite", "assets::tests::syntax_detection_is_case_insensitive", "config::quotes", "pager_arg_override_env_noconfig", "tabs_4_arg_overrides_env", "less::test_parse_less_version_581_2", "acknowledgements", "style::test::style_component_list_parse", "concatenate_single_line_empty", "tabs_passthrough", "line_range::test_ranges_none", "preprocessor::test_try_parse_utf8_char", "style::test::style_component_list_default_builds_on_auto", "syntax_mapping::tests::custom_mappings_precedence", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_csi_with_parameters", "config::empty", "syntaxes", "grid_rule", "concatenate_empty_both", "line_range_multiple", "env_var_bat_paging", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_csi", "theme_env_overrides_config", "theme::tests::choosing::chooses_dark_theme_if_dark_or_unknown", "input::basic", "header_numbers_rule", "theme::tests::color_scheme_detection::not_called_for_dark_or_light", "theme::tests::theme_preference::values_roundtrip_via_display", "syntax_mapping::tests::custom_mappings_work", "long_help", "filename_multiple_ok", "line_range::test_parse_minus_fail", "config::default_config_should_highlight_no_lines", "no_wrapping_with_chop_long_lines", "empty_file_leads_to_empty_output_with_rule_enabled", "pager_most_from_bat_pager_env_var", "line_range::test_ranges_advanced", "style_components_will_merge", "line_range::test_parse_minus_edge_cases_success", "line_range_2_3", "changes_header", "list_themes_with_colors", "style::test::style_component_list_to_components_precedence_merges_previous_lists", "ansi_highlight_underline", "paging_does_not_override_simple_plain", "pager_more", "squeeze_blank_line_numbers", "grid_header", "can_print_file_named_cache_with_additional_argument", "theme::tests::precedence::detector_is_not_called_if_theme_is_present", "header_full_padding", "tabs_8", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_nf_thats_broken", "assets::tests::syntax_detection_with_extension_mapping_to_unknown", "env_var_bat_pager_value_bat", "plain", "cache_build", "pager_most_from_pager_env_var", "style::test::style_component_list_to_components_removes_negated", "config::single", "clap_app::verify_app", "bom_stripped_when_colored_output", "concatenate_empty_first", "line_range::test_parse_plus_overflow", "line_range::test_parse_full", "header_env_basic", "assets::tests::syntax_detection_stdin_filename", "tabs_4_wrapped", "tabs_4_arg_overrides_env_noconfig", "less::test_parse_less_version_529", "vscreen::tests::test_escape_sequence_iterator_iterates", "plain_mode_does_not_add_nonexisting_newline", "does_not_print_unwanted_file_named_cache", "preprocessor::test_strip_ansi", "vscreen::tests::test_sgr_attributes_do_not_leak_into_wrong_field", "line_range::test_parse_partial_min", "line_range::test_parse_plus", "style::test::style_component_list_expand_negates_subcomponents", "concatenate_empty_between", "header_padding_rule", "changes_grid_header", "header_full_padding_rule", "no_broken_osc_emit_with_line_wrapping", "changes_grid_rule", "config::default_config_should_include_all_lines", "enable_pager_if_disable_paging_flag_comes_before_paging", "strip_ansi_always_strips_ansi", "ignored_suffix_arg", "syntax_mapping::tests::custom_mappings_override_builtin", "header_arg_overrides_env", "pager_env_bat_pager_override_config", "pager_basic_arg", "header_default_is_default", "changes_grid_header_rule", "do_not_detect_different_syntax_for_stdin_and_files", "binary_as_text", "header_rule", "style::test::style_component_list_to_components_precedence_overrides_previous_lists", "style_components_will_merge_with_env_var", "concatenate_stdin", "rule", "syntax_mapping::tests::builtin_mappings_matcher_only_compile_once", "header_numbers", "less::test_parse_less_version_551", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_text", "line_range::test_parse_single", "ansi_hyperlink_emitted_when_wrapped", "pager_basic", "grid_header_numbers", "header_binary", "header_very_narrow_terminal", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_csi_with_parameters_and_intermediates", "no_line_wrapping_when_set_to_never", "changes_rule", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_osc_with_bel", "theme::tests::default_theme::default_dark_if_unable_to_detect_color_scheme", "line_range::test_ranges_all", "assets::tests::syntax_detection_same_for_inputkinds", "theme::tests::default_theme::varies_depending_on_color_scheme", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_csi_with_intermediates", "config::multi_line", "theme::tests::default_theme::default_dark_if_requested_explicitly_through_theme", "tabs_passthrough_wrapped", "strip_ansi_auto_does_not_strip_ansi_when_plain_text_by_option", "theme::tests::choosing::chooses_light_theme_if_light", "changes_grid_header_numbers_rule", "less::test_parse_less_version_busybox", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_text_stops_at_esc", "pager_most_with_arg", "line_range::test_ranges_simple", "alias_pager_disable_long_overrides_short", "assets::tests::syntax_detection_for_symlinked_file", "cache_clear", "diagnostic_sanity_check", "grid_for_file_without_newline", "strip_ansi_auto_does_not_strip_when_plain_text_by_filename", "pager_failed_to_parse", "utf16", "grid_header_rule", "less::test_parse_less_version_487", "numbers", "disable_pager_if_pp_flag_comes_after_paging", "unicode_wrap", "all_global_git_config_locations_syntax_mapping_work", "header_default", "list_themes_without_colors", "simple_plain_does_not_override_paging", "bom_stripped_when_no_color_and_not_loop_through", "config::comments", "strip_ansi_does_not_affect_simple_printer", "pager_most_from_pager_arg", "changes_grid_header_numbers", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_osc_thats_broken", "syntax_mapping::ignored_suffixes::internal_suffixes", "config_location_when_generating", "config_read_arguments_from_file", "syntax_mapping::tests::builtin_mappings_work", "ansi_sgr_emitted_when_wrapped", "highlighting_is_skipped_on_long_lines", "theme::tests::color_scheme_detection::called_for_always", "assets::tests::syntax_detection_basic", "less::test_parse_less_version_invalid_utf_8", "basic_set_terminal_title", "config::multiple", "assets::tests::syntax_detection_first_line", "grid_overrides_rule", "header_basic", "disable_pager_if_disable_paging_flag_comes_after_paging", "changes_header_numbers", "alias_pager_disable", "no_paging_short_arg", "concatenate_empty_first_and_last", "no_pager_arg", "no_paging_arg", "fail_non_existing", "strip_ansi_never_does_not_strip_ansi", "ansi_sgr_joins_attributes_when_wrapped", "stdin_to_stdout_cycle", "changes_grid_numbers", "grid", "changes_numbers", "vscreen::tests::test_escape_sequence_offsets_iterator_parses_nf", "assets::build_assets::acknowledgements::tests::test_normalize_license_text_with_windows_line_endings", "do_not_panic_regression_tests", "can_print_file_named_cache", "first_file_cyclic_is_ok", "config_location_test", "do_not_exit_directory", "style_components_can_be_removed", "syntax_mapping::ignored_suffixes::external_suffixes", "show_all_with_caret_notation", "assets::build_assets::acknowledgements::tests::test_normalize_license_text", "no_args_doesnt_break", "strip_ansi_does_not_strip_when_show_nonprintable", "theme::tests::color_scheme_detection::called_for_auto_if_should_detect", "theme::tests::color_scheme_detection::not_called_for_auto_if_not_should_detect", "squeeze_limit_line_numbers", "header_full_binary", "show_all_extends_tab_markers_to_next_tabstop", "theme::tests::choosing::chooses_default_theme_if_unknown"], "failed_tests": [], "skipped_tests": ["config_overrides_system_config", "use_systemwide_config", "all_themes_are_present"]}