diff --git a/CHANGELOG.md b/CHANGELOG.md index 2682d63871..d086e237e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Features +- Make the default macOS theme depend on Dark Mode. See #2197, #1746 (@Enselic) + ## Bugfixes ## Other diff --git a/src/assets.rs b/src/assets.rs index 8126843373..f87d3934e5 100644 --- a/src/assets.rs +++ b/src/assets.rs @@ -69,10 +69,57 @@ 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 and + /// 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 { Ok(HighlightingAssets::new( SerializedSyntaxSet::FromFile(cache_path.join("syntaxes.bin")), @@ -352,6 +399,16 @@ fn asset_from_cache( .map_err(|_| format!("Could not parse cached {}", description).into()) } +#[cfg(target_os = "macos")] +fn macos_dark_mode_active() -> bool { + let mut defaults_cmd = std::process::Command::new("defaults"); + defaults_cmd.args(&["read", "-globalDomain", "AppleInterfaceStyle"]); + match defaults_cmd.output() { + Ok(output) => output.stdout == b"Dark\n", + Err(_) => true, + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 4a32de402b..70d208e3aa 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -1427,6 +1427,8 @@ fn ansi_passthrough_emit() { fn ignored_suffix_arg() { bat() .arg("-f") + .arg("--theme") + .arg("Monokai Extended") .arg("-p") .arg("test.json~") .assert() @@ -1436,6 +1438,8 @@ fn ignored_suffix_arg() { bat() .arg("-f") + .arg("--theme") + .arg("Monokai Extended") .arg("-p") .arg("--ignored-suffix=.suffix") .arg("test.json.suffix") @@ -1446,6 +1450,8 @@ fn ignored_suffix_arg() { bat() .arg("-f") + .arg("--theme") + .arg("Monokai Extended") .arg("-p") .arg("test.json.suffix") .assert() @@ -1463,6 +1469,8 @@ fn highlighting_is_skipped_on_long_lines() { bat() .arg("-f") + .arg("--theme") + .arg("Monokai Extended") .arg("-p") .arg("longline.json") .assert() @@ -1482,6 +1490,8 @@ fn all_global_git_config_locations_syntax_mapping_work() { bat() .env("XDG_CONFIG_HOME", fake_home.join(".config").as_os_str()) .arg("-f") + .arg("--theme") + .arg("Monokai Extended") .arg("-p") .arg("git/.config/git/config") .assert() @@ -1492,6 +1502,8 @@ fn all_global_git_config_locations_syntax_mapping_work() { bat() .env("HOME", fake_home.as_os_str()) .arg("-f") + .arg("--theme") + .arg("Monokai Extended") .arg("-p") .arg("git/.config/git/config") .assert() @@ -1502,6 +1514,8 @@ fn all_global_git_config_locations_syntax_mapping_work() { bat() .env("HOME", fake_home.as_os_str()) .arg("-f") + .arg("--theme") + .arg("Monokai Extended") .arg("-p") .arg("git/.gitconfig") .assert()