i3status_rs/themes/
xresources.rs1use log::debug;
2use regex::Regex;
3
4use std::collections::HashMap;
5use std::sync::LazyLock;
6
7use crate::errors::*;
8
9#[cfg(not(test))]
10use std::{env, path::PathBuf};
11
12#[cfg(not(test))]
13fn read_xresources() -> std::io::Result<String> {
14 let home = env::var("HOME").map_err(|_| std::io::Error::other("HOME env var was not set"))?;
15 let xresources = PathBuf::from(home + "/.Xresources");
16 debug!(".Xresources @ {:?}", xresources);
17 std::fs::read_to_string(xresources)
18}
19
20#[cfg(test)]
21use tests::read_xresources;
22
23static COLOR_REGEX: LazyLock<Regex> = LazyLock::new(|| {
24 Regex::new(r"^\s*\*(?<name>[^: ]+)\s*:\s*(?<color>#[a-f0-9]{6,8}).*$").unwrap()
25});
26
27static COLORS: LazyLock<Result<HashMap<String, String>, Error>> = LazyLock::new(|| {
28 let content = read_xresources().error("could not read .Xresources")?;
29 debug!(".Xresources content:\n{}", content);
30 Ok(HashMap::from_iter(content.lines().filter_map(|line| {
31 COLOR_REGEX
32 .captures(line)
33 .map(|caps| (caps["name"].to_string(), caps["color"].to_string()))
34 })))
35});
36
37pub fn get_color(name: &str) -> Result<Option<&String>, Error> {
38 COLORS
39 .as_ref()
40 .map(|cmap| cmap.get(name))
41 .map_err(Clone::clone)
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47 use std::io::Result;
48
49 #[allow(clippy::unnecessary_wraps)]
50 pub(crate) fn read_xresources() -> Result<String> {
51 static XRESOURCES: &str = "\
52 ! this is a comment\n\
53 \n\
54 *color4 : #feedda\n\
55 \n\
56 *background: #ee33aa99\n\
57 ";
58 Ok(XRESOURCES.to_string())
59 }
60
61 #[test]
62 fn test_reading_colors() {
63 let colors = COLORS.as_ref().unwrap();
64 assert_eq!(colors.get("color4"), Some(&"#feedda".to_string()));
65 assert_eq!(colors.get("background"), Some(&"#ee33aa99".to_string()));
66 assert_eq!(2, colors.len());
67 }
68
69 #[test]
70 fn test_deserializing_xcolors() {
71 use super::super::color::*;
72 let mut parsed_color = "x:color4".parse::<Color>().unwrap();
73 assert_eq!(
74 parsed_color,
75 Color::Rgba(Rgba {
76 r: 254,
77 g: 237,
78 b: 218,
79 a: 255
80 })
81 );
82 parsed_color = "x:background".parse::<Color>().unwrap();
83 assert_eq!(
84 parsed_color,
85 Color::Rgba(Rgba {
86 r: 238,
87 g: 51,
88 b: 170,
89 a: 153,
90 })
91 );
92 }
93}