hlctl/src/hlwm/hook.rs

152 lines
5.4 KiB
Rust
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use std::{borrow::BorrowMut, str::FromStr};
use serde::{Deserialize, Serialize};
use strum::IntoEnumIterator;
use super::{
parser::{ArgParser, FromCommandArgs, ParseError},
window::Window,
Monitor, TagSelect, ToCommandString,
};
#[derive(Debug, Clone, Serialize, Deserialize, strum::Display, strum::EnumIter, PartialEq)]
#[strum(serialize_all = "snake_case")]
pub enum Hook {
/// The attribute `path` was changed from `old` to `new`.
/// Requires that the attribute `path` has been passed to the [HlwmCommand::Watch] command before.
AttributeChanged {
path: String,
old: String,
new: String,
},
/// The fullscreen state of `window` was changed to [on|off].
Fullscreen {
on: bool,
window: Window,
},
/// The `tag` was selected on `monitor`.
TagChanged {
tag: String,
monitor: Monitor,
},
/// The `window` with title `title` was focused
FocusChanged {
window: Window,
title: String,
},
WindowTitleChanged {
window: Window,
title: String,
},
/// The flags (i.e. urgent or filled state) have been changed.
TagFlags,
TagAdded(TagSelect),
TagRenamed {
old: String,
new: String,
},
Urgent {
on: bool,
window: Window,
},
/// A `window` appeared which triggered a rule/hook.
Rule {
hook: String,
window: Window,
},
/// Tells a panel to quit. The default panel.sh quits on this hook. Many scripts are using this hook.
QuitPanel,
/// Tells all daemons that the autostart file is reloadedand tells them to quit.
/// This hook **should** be emitted in the first line of every autostart file.
Reload,
}
impl FromCommandArgs for Hook {
fn from_command_args<S: Into<String>, I: IntoIterator<Item = S>>(
cmd: &str,
args: I,
) -> Result<Self, super::parser::ParseError> {
let mut command = Self::iter()
.find(|c: &Hook| c.to_string() == cmd)
.ok_or(ParseError::InvalidCommand(cmd.to_string()))?;
let x = args.into_iter().map(|i| i.into()).collect::<Vec<String>>();
let mut parser = ArgParser::from_strings(x.into_iter());
match command.borrow_mut() {
Hook::QuitPanel | Hook::Reload | Hook::TagFlags => (),
Hook::AttributeChanged { path, old, new } => {
*path = parser.must_string("attribute_changed(path)")?;
*old = parser.must_string("attribute_changed(old)")?;
*new = parser.must_string("attribute_changed(new)")?;
}
Hook::Fullscreen { on, window } => {
*on = parser.next_from_str("fullscreen(on)")?;
*window = parser.next_from_str("fullscreen(window)")?;
}
Hook::TagChanged { tag, monitor } => {
*tag = parser.must_string("tag_changed(tag)")?;
*monitor = parser.next_from_str("tag_changed(monitor)")?;
}
Hook::FocusChanged { window, title } | Hook::WindowTitleChanged { window, title } => {
*window = parser.next_from_str(&format!("{cmd}(window)"))?;
*title = parser.must_string(&format!("{cmd}(title)"))?;
}
Hook::TagAdded(tag) => {
*tag = TagSelect::from_str(&parser.must_string(cmd)?).expect("infallible")
}
Hook::TagRenamed { old, new } => {
*old = parser.must_string("tag_renamed(old)")?;
*new = parser.must_string("tag_renamed(new)")?;
}
Hook::Urgent { on, window } => {
*on = parser.next_from_str("urgent(on)")?;
*window = parser.next_from_str("urgent(window)")?;
}
Hook::Rule { hook, window } => {
*hook = parser.must_string("rule(hook)")?;
*window = parser.next_from_str("rule(window)")?;
}
}
Ok(command)
}
}
impl Default for Hook {
fn default() -> Self {
Self::Reload
}
}
impl ToCommandString for Hook {
fn to_command_string(&self) -> String {
[self.to_string()]
.into_iter()
.chain(match self {
Hook::AttributeChanged { path, old, new } => {
vec![path.to_string(), old.to_string(), new.to_string()].into_iter()
}
Hook::Fullscreen { on, window } => {
vec![on.to_string(), window.to_string()].into_iter()
}
Hook::TagChanged { tag, monitor } => {
vec![tag.to_string(), monitor.to_string()].into_iter()
}
Hook::WindowTitleChanged { window, title }
| Hook::FocusChanged { window, title } => {
vec![window.to_string(), title.to_string()].into_iter()
}
Hook::QuitPanel | Hook::Reload | Hook::TagFlags => vec![].into_iter(),
Hook::TagAdded(tag) => vec![tag.to_string()].into_iter(),
Hook::TagRenamed { old, new } => vec![old.to_string(), new.to_string()].into_iter(),
Hook::Urgent { on, window } => vec![on.to_string(), window.to_string()].into_iter(),
Hook::Rule { hook, window } => {
vec![hook.to_string(), window.to_string()].into_iter()
}
})
.collect::<Vec<_>>()
.join("\t")
}
}