use { crate::{ config::{ WindowMatch, WindowRule, context::Context, extractor::{Extractor, ExtractorError, bol, opt, recover, str, val}, parser::{DataType, ParseResult, Parser, UnexpectedDataType}, parsers::{ action::{ActionParser, ActionParserError}, tile_state::TileStateParser, window_match::{WindowMatchParser, WindowMatchParserError}, }, spanned::SpannedErrorExt, }, toml::{ toml_span::{DespanExt, Span, Spanned}, toml_value::Value, }, }, indexmap::IndexMap, thiserror::Error, }; #[derive(Debug, Error)] pub enum WindowRuleParserError { #[error(transparent)] Expected(#[from] UnexpectedDataType), #[error(transparent)] Extract(#[from] ExtractorError), #[error(transparent)] Match(#[from] WindowMatchParserError), #[error(transparent)] Action(ActionParserError), #[error(transparent)] Latch(ActionParserError), } pub struct WindowRuleParser<'a>(pub &'a Context<'a>); impl Parser for WindowRuleParser<'_> { type Value = WindowRule; type Error = WindowRuleParserError; const EXPECTED: &'static [DataType] = &[DataType::Table]; fn parse_table( &mut self, span: Span, table: &IndexMap, Spanned>, ) -> ParseResult { let mut ext = Extractor::new(self.0, span, table); let (name, match_val, action_val, latch_val, auto_focus, initial_tile_state_val) = ext .extract(( opt(str("name")), opt(val("match")), opt(val("action")), opt(val("latch")), recover(opt(bol("auto-focus"))), opt(val("initial-tile-state")), ))?; let mut action = None; if let Some(value) = action_val { action = Some( value .parse(&mut ActionParser(self.0)) .map_spanned_err(WindowRuleParserError::Action)?, ); } let mut latch = None; if let Some(value) = latch_val { latch = Some( value .parse(&mut ActionParser(self.0)) .map_spanned_err(WindowRuleParserError::Latch)?, ); } let mut initial_tile_state = None; if let Some(value) = initial_tile_state_val { match value.parse(&mut TileStateParser) { Ok(v) => initial_tile_state = Some(v), Err(e) => { log::warn!( "Could not parse the initial tile state: {}", self.0.error(e) ); } } } let match_ = match match_val { None => WindowMatch::default(), Some(m) => m.parse_map(&mut WindowMatchParser(self.0))?, }; Ok(WindowRule { name: name.despan_into(), match_, action, latch, auto_focus: auto_focus.despan(), initial_tile_state, }) } } pub struct WindowRulesParser<'a>(pub &'a Context<'a>); impl Parser for WindowRulesParser<'_> { type Value = Vec; type Error = WindowRuleParserError; const EXPECTED: &'static [DataType] = &[DataType::Array]; fn parse_array(&mut self, _span: Span, array: &[Spanned]) -> ParseResult { let mut res = vec![]; for el in array { match el.parse(&mut WindowRuleParser(self.0)) { Ok(o) => res.push(o), Err(e) => { log::warn!("Could not parse window rule: {}", self.0.error(e)); } } } Ok(res) } }