hlctl/src/hlwm/and_or_command.rs

118 lines
3.1 KiB
Rust

use crate::hlwm::parser::ParseError;
use super::{
command::HlwmCommand,
parser::{ArgParser, FromCommandArgs, FromStringsHint},
Separator,
};
pub struct AndOrCommands(Vec<HlwmCommand>);
impl AndOrCommands {
pub fn commands(self) -> Vec<HlwmCommand> {
self.0
}
}
impl FromStringsHint<Separator> for AndOrCommands {
fn from_strings_hint<I: Iterator<Item = String>>(
s: I,
hint: Separator,
) -> Result<Self, ParseError> {
Ok(Self(
split_by_separator(s, hint)
.into_iter()
.map(|cmd_args| -> Result<HlwmCommand, ParseError> {
let mut parser = ArgParser::from_strings(cmd_args.into_iter());
HlwmCommand::from_command_args(
&parser.must_string("hlwmcommand(command)")?,
parser.collect::<Vec<String>>().into_iter(),
)
})
.collect::<Result<Vec<HlwmCommand>, ParseError>>()?,
))
}
}
fn split_by_separator<I: Iterator<Item = String>>(s: I, separator: Separator) -> Vec<Vec<String>> {
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);
}
}
}