2024-03-06 19:49:15 +00:00
|
|
|
|
use std::{borrow::BorrowMut, str::FromStr};
|
2024-02-29 20:36:38 +00:00
|
|
|
|
|
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
use strum::IntoEnumIterator;
|
|
|
|
|
|
2024-03-06 19:49:15 +00:00
|
|
|
|
use super::{
|
|
|
|
|
parser::{ArgParser, FromCommandArgs, ParseError},
|
|
|
|
|
window::Window,
|
|
|
|
|
Monitor, TagSelect, ToCommandString,
|
|
|
|
|
};
|
2024-02-29 20:36:38 +00:00
|
|
|
|
|
|
|
|
|
#[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,
|
2024-03-02 21:18:21 +00:00
|
|
|
|
TagAdded(TagSelect),
|
2024-02-29 20:36:38 +00:00
|
|
|
|
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 reloaded — and tells them to quit.
|
|
|
|
|
/// This hook **should** be emitted in the first line of every autostart file.
|
|
|
|
|
Reload,
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-06 19:49:15 +00:00
|
|
|
|
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());
|
2024-02-29 20:36:38 +00:00
|
|
|
|
|
2024-03-06 19:49:15 +00:00
|
|
|
|
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")
|
2024-02-29 20:36:38 +00:00
|
|
|
|
}
|
2024-03-06 19:49:15 +00:00
|
|
|
|
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)")?;
|
2024-02-29 20:36:38 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-06 19:49:15 +00:00
|
|
|
|
Ok(command)
|
2024-02-29 20:36:38 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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")
|
|
|
|
|
}
|
|
|
|
|
}
|