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