1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use super::theme::Theme;
#[cfg(feature = "plist-load")]
use super::settings::*;
use super::super::LoadingError;
use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct ThemeSet {
pub themes: BTreeMap<String, Theme>,
}
impl ThemeSet {
pub fn new() -> ThemeSet {
ThemeSet::default()
}
pub fn discover_theme_paths<P: AsRef<Path>>(folder: P) -> Result<Vec<PathBuf>, LoadingError> {
let mut themes = Vec::new();
for entry in crate::utils::walk_dir(folder) {
let entry = entry.map_err(LoadingError::WalkDir)?;
if entry.path().extension().map_or(false, |e| e == "tmTheme") {
themes.push(entry.path().to_owned());
}
}
Ok(themes)
}
#[cfg(feature = "plist-load")]
pub fn get_theme<P: AsRef<Path>>(path: P) -> Result<Theme, LoadingError> {
let file = std::fs::File::open(path)?;
let mut file = std::io::BufReader::new(file);
Self::load_from_reader(&mut file)
}
#[cfg(feature = "plist-load")]
pub fn load_from_reader<R: std::io::BufRead + std::io::Seek>(r: &mut R) -> Result<Theme, LoadingError> {
Ok(Theme::parse_settings(read_plist(r)?)?)
}
#[cfg(feature = "plist-load")]
pub fn load_from_folder<P: AsRef<Path>>(folder: P) -> Result<ThemeSet, LoadingError> {
let mut theme_set = Self::new();
theme_set.add_from_folder(folder)?;
Ok(theme_set)
}
#[cfg(feature = "plist-load")]
pub fn add_from_folder<P: AsRef<Path>>(&mut self, folder: P) -> Result<(), LoadingError> {
let paths = Self::discover_theme_paths(folder)?;
for p in &paths {
let theme = Self::get_theme(p)?;
let basename =
p.file_stem().and_then(|x| x.to_str()).ok_or(LoadingError::BadPath)?;
self.themes.insert(basename.to_owned(), theme);
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use crate::highlighting::{ThemeSet, Color};
#[cfg(feature = "plist-load")]
#[test]
fn can_parse_common_themes() {
let themes = ThemeSet::load_from_folder("testdata").unwrap();
let all_themes: Vec<&str> = themes.themes.keys().map(|x| &**x).collect();
assert!(all_themes.contains(&"base16-ocean.dark"));
println!("{:?}", all_themes);
let theme = ThemeSet::get_theme("testdata/spacegray/base16-ocean.dark.tmTheme").unwrap();
assert_eq!(theme.name.unwrap(), "Base16 Ocean Dark");
assert_eq!(theme.settings.selection.unwrap(),
Color {
r: 0x4f,
g: 0x5b,
b: 0x66,
a: 0xff,
});
assert_eq!(theme.scopes[0].style.foreground.unwrap(),
Color {
r: 0xc0,
g: 0xc5,
b: 0xce,
a: 0xFF,
});
}
}