1use anyhow::{Context, Result};
2use csscolorparser::Color;
3use derive_builder::Builder;
4use pango::FontDescription;
5
6use crate::{
7 background::Bg, parser, remove_color_from_config, remove_string_from_config,
8};
9
10#[derive(Builder, Clone, Default, Debug, PartialEq, PartialOrd)]
12#[builder_struct_attr(allow(missing_docs))]
13#[builder_impl_attr(allow(missing_docs))]
14pub struct Attrs {
15 #[builder(default, setter(strip_option))]
16 font: Option<FontDescription>,
17 #[builder(default, setter(strip_option))]
18 fg: Option<Color>,
19 #[builder(default, setter(strip_option))]
20 pub(crate) bg: Option<Bg>,
21}
22
23impl Attrs {
24 #[must_use]
29 pub const fn empty() -> Self {
30 Self {
31 font: None,
32 fg: None,
33 bg: None,
34 }
35 }
36
37 pub fn parse(name: impl AsRef<str>) -> Result<Self> {
53 let attrs_table = parser::ATTRS.get().unwrap();
54 let name = name.as_ref();
55 log::debug!("parsing {name} attrs");
56 let mut attr_table = attrs_table
57 .get(name)
58 .with_context(|| {
59 format!("couldn't find attrs table with name {name}")
60 })?
61 .clone()
62 .into_table()?;
63 log::trace!("got attr table");
64 let mut builder = AttrsBuilder::default();
65 if let Some(fg) = remove_color_from_config("fg", &mut attr_table) {
66 log::debug!("got fg: {fg}");
67 builder.fg(fg);
68 }
69 if let Some(bg) = remove_string_from_config("bg", &mut attr_table) {
70 if let Some(bg) = Bg::parse(bg.as_str()) {
71 log::debug!("got bg: {bg:?}");
72 builder.bg(bg);
73 }
74 }
75 if let Some(font) = remove_string_from_config("font", &mut attr_table) {
76 log::debug!("got font: {font}");
77 builder.font(FontDescription::from_string(font.as_str()));
78 }
79
80 Ok(builder.build()?)
81 }
82
83 pub fn parse_global(name: impl AsRef<str>) -> Self {
89 Self::parse(name).unwrap_or_default()
90 }
91
92 pub fn apply_font(&self, layout: &pango::Layout) {
94 if let Some(font) = &self.font {
95 layout.set_font_description(Some(font));
96 }
97 }
98
99 pub fn apply_fg(&self, cr: &cairo::Context) {
101 if let Some(fg) = &self.fg {
102 cr.set_source_rgba(
103 fg.r.into(),
104 fg.g.into(),
105 fg.b.into(),
106 fg.a.into(),
107 );
108 }
109 }
110
111 pub fn apply_to(&mut self, new: &Self) {
114 if self.font.is_none() {
115 self.font.clone_from(&new.font);
116 }
117 if self.fg.is_none() {
118 self.fg.clone_from(&new.fg);
119 }
120 if self.bg.is_none() {
121 self.bg.clone_from(&new.bg);
122 }
123 }
124}