Skip to content

Commit ad32993

Browse files
authored
Support loading custom syntax themes from a file (#2565)
1 parent 92ef9f6 commit ad32993

File tree

6 files changed

+50
-11
lines changed

6 files changed

+50
-11
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
## Unreleased
99

1010
### Added
11+
* support loading custom syntax highlighting themes from a file [[@acuteenvy](https://github.com/acuteenvy)] ([#2565](https://github.com/gitui-org/gitui/pull/2565))
1112
* Select syntax highlighting theme out of the defaults from syntect [[@vasilismanol](https://github.com/vasilismanol)] ([#1931](https://github.com/extrawurst/gitui/issues/1931))
1213
* new command-line option to override the default log file path (`--logfile`) [[@acuteenvy](https://github.com/acuteenvy)] ([#2539](https://github.com/gitui-org/gitui/pull/2539))
1314

Cargo.lock

+23
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ syntect = { version = "5.2", default-features = false, features = [
5656
"parsing",
5757
"default-syntaxes",
5858
"default-themes",
59+
"plist-load",
5960
"html",
6061
] }
6162
tui-textarea = "0.7"

src/args.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ pub fn process_cmdline() -> Result<CliArgs> {
4949
.get_one::<String>("theme")
5050
.map_or_else(|| PathBuf::from("theme.ron"), PathBuf::from);
5151

52-
let theme = get_app_config_path()?.join(arg_theme);
52+
let confpath = get_app_config_path()?;
53+
fs::create_dir_all(&confpath)?;
54+
let theme = confpath.join(arg_theme);
5355

5456
let notify_watcher: bool =
5557
*arg_matches.get_one("watcher").unwrap_or(&false);
@@ -166,7 +168,6 @@ pub fn get_app_config_path() -> Result<PathBuf> {
166168
.ok_or_else(|| anyhow!("failed to find os config dir."))?;
167169

168170
path.push("gitui");
169-
fs::create_dir_all(&path)?;
170171
Ok(path)
171172
}
172173

src/keys/key_config.rs

+1
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ mod tests {
136136
#[test]
137137
fn test_symbolic_links() {
138138
let app_home = get_app_config_path().unwrap();
139+
fs::create_dir_all(&app_home).unwrap();
139140
// save current config
140141
let original_key_list_path = app_home.join(KEY_LIST_FILENAME);
141142
let renamed_key_list = if original_key_list_path.exists() {

src/ui/syntax_text.rs

+21-9
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use asyncgit::{
22
asyncjob::{AsyncJob, RunParams},
33
ProgressPercent,
44
};
5-
use once_cell::sync::Lazy;
5+
use once_cell::sync::{Lazy, OnceCell};
66
use ratatui::text::{Line, Span};
77
use scopetime::scope_time;
88
use std::{
@@ -14,7 +14,7 @@ use std::{
1414
use syntect::{
1515
highlighting::{
1616
FontStyle, HighlightState, Highlighter,
17-
RangedHighlightIterator, Style, ThemeSet,
17+
RangedHighlightIterator, Style, Theme, ThemeSet,
1818
},
1919
parsing::{ParseState, ScopeStack, SyntaxSet},
2020
};
@@ -35,7 +35,7 @@ pub struct SyntaxText {
3535

3636
static SYNTAX_SET: Lazy<SyntaxSet> =
3737
Lazy::new(two_face::syntax::extra_no_newlines);
38-
static THEME_SET: Lazy<ThemeSet> = Lazy::new(ThemeSet::load_defaults);
38+
static THEME: OnceCell<Theme> = OnceCell::new();
3939

4040
pub struct AsyncProgressBuffer {
4141
current: usize,
@@ -89,13 +89,25 @@ impl SyntaxText {
8989
ParseState::new(syntax)
9090
};
9191

92-
let theme =
93-
THEME_SET.themes.get(syntax).unwrap_or_else(|| {
94-
log::error!("The syntax theme:\"{}\" cannot be found. Using default theme:\"{}\" instead.", syntax, DEFAULT_SYNTAX_THEME);
95-
&THEME_SET.themes[DEFAULT_SYNTAX_THEME]
96-
});
97-
let highlighter = Highlighter::new(theme);
92+
let theme = THEME.get_or_try_init(|| -> Result<Theme, asyncgit::Error> {
93+
let theme_path = crate::args::get_app_config_path()
94+
.map_err(|e| asyncgit::Error::Generic(e.to_string()))?.join(format!("{syntax}.tmTheme"));
95+
96+
match ThemeSet::get_theme(&theme_path) {
97+
Ok(t) => return Ok(t),
98+
Err(e) => log::info!("could not load '{}': {e}, trying from the set of default themes", theme_path.display()),
99+
}
98100

101+
let mut theme_set = ThemeSet::load_defaults();
102+
if let Some(t) = theme_set.themes.remove(syntax) {
103+
return Ok(t);
104+
}
105+
106+
log::error!("the syntax theme '{syntax}' cannot be found. Using default theme ('{DEFAULT_SYNTAX_THEME}') instead");
107+
Ok(theme_set.themes.remove(DEFAULT_SYNTAX_THEME).expect("the default theme should be there"))
108+
})?;
109+
110+
let highlighter = Highlighter::new(theme);
99111
let mut syntax_lines: Vec<SyntaxLine> = Vec::new();
100112

101113
let mut highlight_state =

0 commit comments

Comments
 (0)