on master help sign in
Load alt default theme if true color is not supported

* Move `runtime/themes/base16_default_terminal.toml` to `base16_theme.toml` alongside `theme.toml` * Use `terminfo` crate to detect whether the terminal supports true color and, if the user has no theme configured and their terminal does not support true color, load the alt default theme instead of the normal default. Remove `terminfo` dependency, use `COLORTERM` env instead Prevent user from switching to an unsupported theme Add `true-color-override` option If the terminal is wrongly detected to not support true color, `true-color-override = true` will override the detection. Rename `true-color-override` to `true-color`

commit98ce2a301da25152563137047377026d72fd644c authorOmnikar <Omnikar5@gmail.com> dateSun 14 Nov 2021, 07:26 (5 years ago) parent43d17c4
8 files changed+62−20
runtime/themes/base16_terminal.toml → base16_theme.toml book/src/configuration.md+1 helix-term/src/application.rs+19−9 helix-term/src/commands.rs+12−2 helix-term/src/lib.rs+6 helix-term/src/ui/mod.rs+1 helix-view/src/editor.rs+3−9 helix-view/src/theme.rs+20
runtime/themes/base16_terminal.toml → base16_theme.tomlrenamed

The content is the same.

book/src/configuration.md+1
@@ -23,6 +23,7 @@ To override global configuration parameters, create a `config.toml` file located
2323| `idle-timeout` | Time in milliseconds since last keypress before idle timers trigger. Used for autocompletion, set to 0 for instant. | `400` |
2424| `completion-trigger-len` | The min-length of word under cursor to trigger autocompletion | `2` |
2525| `auto-info` | Whether to display infoboxes | `true` |
26+| `true-color` | Set to `true` to override automatic detection of terminal truecolor support in the event of a false negative. | `false` |
2627
2728`[editor.filepicker]` section of the config. Sets options for file picker and global search. All but the last key listed in the default file-picker configuration below are IgnoreOptions: whether hidden files and files listed within ignore files are ignored by (not visible in) the helix file picker and global search. There is also one other key, `max-depth` available, which is not defined by default.
2829
helix-term/src/application.rs+19−9
@@ -76,17 +76,27 @@ impl Application {
7676 None => Ok(def_lang_conf),
7777 };
7878
79− let theme = if let Some(theme) = &config.theme {
80− match theme_loader.load(theme) {
81− Ok(theme) => theme,
82− Err(e) => {
83− log::warn!("failed to load theme `{}` - {}", theme, e);
79+ let true_color = config.editor.true_color || crate::true_color();
80+ let theme = config
81+ .theme
82+ .as_ref()
83+ .and_then(|theme| {
84+ theme_loader
85+ .load(theme)
86+ .map_err(|e| {
87+ log::warn!("failed to load theme `{}` - {}", theme, e);
88+ e
89+ })
90+ .ok()
91+ .filter(|theme| (true_color || theme.is_16_color()))
92+ })
93+ .unwrap_or_else(|| {
94+ if true_color {
8495 theme_loader.default()
96+ } else {
97+ theme_loader.base16_default()
8598 }
86− }
87− } else {
88− theme_loader.default()
89− };
99+ });
90100
91101 let syn_loader_conf: helix_core::syntax::Configuration = lang_conf
92102 .and_then(|conf| conf.try_into())
helix-term/src/commands.rs+12−2
@@ -2366,8 +2366,18 @@ pub mod cmd {
23662366 args: &[Cow<str>],
23672367 _event: PromptEvent,
23682368 ) -> anyhow::Result<()> {
2369− let theme = args.first().context("theme not provided")?;
2370− cx.editor.set_theme_from_name(theme)
2369+ let theme = args.first().context("Theme not provided")?;
2370+ let theme = cx
2371+ .editor
2372+ .theme_loader
2373+ .load(theme)
2374+ .with_context(|| format!("Failed setting theme {}", theme))?;
2375+ let true_color = cx.editor.config.true_color || crate::true_color();
2376+ if !(true_color || theme.is_16_color()) {
2377+ bail!("Unsupported theme: theme requires true color support");
2378+ }
2379+ cx.editor.set_theme(theme);
2380+ Ok(())
23712381 }
23722382
23732383 fn yank_main_selection_to_clipboard(
helix-term/src/lib.rs+6
@@ -9,3 +9,9 @@ pub mod config;
99pub mod job;
1010pub mod keymap;
1111pub mod ui;
12+
13+fn true_color() -> bool {
14+ std::env::var("COLORTERM")
15+ .map(|v| matches!(v.as_str(), "truecolor" | "24bit"))
16+ .unwrap_or(false)
17+}
helix-term/src/ui/mod.rs+1
@@ -186,6 +186,7 @@ pub mod completers {
186186 &helix_core::config_dir().join("themes"),
187187 ));
188188 names.push("default".into());
189+ names.push("base16_default".into());
189190
190191 let mut names: Vec<_> = names
191192 .into_iter()
helix-view/src/editor.rs+3−9
@@ -105,6 +105,8 @@ pub struct Config {
105105 /// Whether to display infoboxes. Defaults to true.
106106 pub auto_info: bool,
107107 pub file_picker: FilePickerConfig,
108+ /// Set to `true` to override automatic detection of terminal truecolor support in the event of a false negative. Defaults to `false`.
109+ pub true_color: bool,
108110}
109111
110112#[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize)]
@@ -137,6 +139,7 @@ impl Default for Config {
137139 completion_trigger_len: 2,
138140 auto_info: true,
139141 file_picker: FilePickerConfig::default(),
142+ true_color: false,
140143 }
141144 }
142145}
@@ -265,15 +268,6 @@ impl Editor {
265268 self._refresh();
266269 }
267270
268− pub fn set_theme_from_name(&mut self, theme: &str) -> anyhow::Result<()> {
269− let theme = self
270− .theme_loader
271− .load(theme.as_ref())
272− .with_context(|| format!("failed setting theme `{}`", theme))?;
273− self.set_theme(theme);
274− Ok(())
275− }
276−
277271 /// Refreshes the language server for a given document
278272 pub fn refresh_language_server(&mut self, doc_id: DocumentId) -> Option<()> {
279273 let doc = self.documents.get_mut(&doc_id)?;
helix-view/src/theme.rs+20
@@ -15,6 +15,10 @@ pub use crate::graphics::{Color, Modifier, Style};
1515pub static DEFAULT_THEME: Lazy<Theme> = Lazy::new(|| {
1616 toml::from_slice(include_bytes!("../../theme.toml")).expect("Failed to parse default theme")
1717});
18+pub static BASE16_DEFAULT_THEME: Lazy<Theme> = Lazy::new(|| {
19+ toml::from_slice(include_bytes!("../../base16_theme.toml"))
20+ .expect("Failed to parse base 16 default theme")
21+});
1822
1923#[derive(Clone, Debug)]
2024pub struct Loader {
@@ -35,6 +39,9 @@ impl Loader {
3539 if name == "default" {
3640 return Ok(self.default());
3741 }
42+ if name == "base16_default" {
43+ return Ok(self.base16_default());
44+ }
3845 let filename = format!("{}.toml", name);
3946
4047 let user_path = self.user_dir.join(&filename);
@@ -74,6 +81,11 @@ impl Loader {
7481 pub fn default(&self) -> Theme {
7582 DEFAULT_THEME.clone()
7683 }
84+
85+ /// Returns the alternative 16-color default theme
86+ pub fn base16_default(&self) -> Theme {
87+ BASE16_DEFAULT_THEME.clone()
88+ }
7789}
7890
7991#[derive(Clone, Debug)]
@@ -154,6 +166,14 @@ impl Theme {
154166 pub fn find_scope_index(&self, scope: &str) -> Option<usize> {
155167 self.scopes().iter().position(|s| s == scope)
156168 }
169+
170+ pub fn is_16_color(&self) -> bool {
171+ self.styles.iter().all(|(_, style)| {
172+ [style.fg, style.bg]
173+ .into_iter()
174+ .all(|color| !matches!(color, Some(Color::Rgb(..))))
175+ })
176+ }
157177}
158178
159179struct ThemePalette {