use crate::hlwm::parser::ParseError; use super::{ command::HlwmCommand, parser::{ArgParser, FromCommandArgs, FromStringsHint}, Separator, }; pub struct AndOrCommands(Vec); impl AndOrCommands { pub fn commands(self) -> Vec { self.0 } } impl FromStringsHint for AndOrCommands { fn from_strings_hint>( s: I, hint: Separator, ) -> Result { Ok(Self( split_by_separator(s, hint) .into_iter() .map(|cmd_args| -> Result { let mut parser = ArgParser::from_strings(cmd_args.into_iter()); HlwmCommand::from_command_args( &parser.must_string("hlwmcommand(command)")?, parser.collect::>().into_iter(), ) }) .collect::, ParseError>>()?, )) } } fn split_by_separator>(s: I, separator: Separator) -> Vec> { let separator = separator.to_string(); let mut commands = Vec::new(); let mut working = Vec::new(); for itm in s { if itm.len() == 1 && itm == separator { if !working.is_empty() { commands.push(working); working = Vec::new(); } continue; } working.push(itm); } if !working.is_empty() { commands.push(working); } commands } #[cfg(test)] mod test { use crate::hlwm::Separator; use super::split_by_separator; use pretty_assertions::assert_eq; #[test] fn test_split_by_separator() { let cases = [( [ "or", ",", "and", ".", "compare", "tags.focus.curframe_wcount", "=", "2", ".", "cycle_layout", "+1", "vertical", "horizontal", "max", "vertical", "grid", ",", "cycle_layout", "+1", ] .into_iter(), Separator::Comma, vec![ vec!["or"], vec![ "and", ".", "compare", "tags.focus.curframe_wcount", "=", "2", ".", "cycle_layout", "+1", "vertical", "horizontal", "max", "vertical", "grid", ], vec!["cycle_layout", "+1"], ], )]; for (input, separator, expected) in cases { let input = input.map(|i| i.to_string()); let actual = split_by_separator(input, separator); assert_eq!(expected, actual); } } }