commit
This commit is contained in:
parent
2fce4312eb
commit
2059555174
5 changed files with 142 additions and 1 deletions
13
Cargo.lock
generated
13
Cargo.lock
generated
|
@ -624,6 +624,19 @@ dependencies = [
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "execute"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"clap",
|
||||||
|
"color-eyre",
|
||||||
|
"deckster_mode",
|
||||||
|
"env_logger",
|
||||||
|
"log",
|
||||||
|
"serde",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "eyre"
|
name = "eyre"
|
||||||
version = "0.6.11"
|
version = "0.6.11"
|
||||||
|
|
|
@ -58,4 +58,11 @@ config.mode = "toggle"
|
||||||
config.entity_id = "light.moritz_zimmer_stehlampe"
|
config.entity_id = "light.moritz_zimmer_stehlampe"
|
||||||
config.style.on.icon = "@ph/computer-tower[color=#58fc11]"
|
config.style.on.icon = "@ph/computer-tower[color=#58fc11]"
|
||||||
config.style.disconnected.icon = "@ph/computer-tower[alpha=0.2]"
|
config.style.disconnected.icon = "@ph/computer-tower[alpha=0.2]"
|
||||||
config.disconnected_state = "disconnected"
|
config.disconnected_state = "disconnected"
|
||||||
|
|
||||||
|
[keys.4x1]
|
||||||
|
label = "9"
|
||||||
|
|
||||||
|
handler = "execute"
|
||||||
|
config.program = "wtype"
|
||||||
|
config.args = ["9"]
|
13
handlers/execute/Cargo.toml
Normal file
13
handlers/execute/Cargo.toml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
[package]
|
||||||
|
name = "execute"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
deckster_mode = { path = "../../crates/deckster_mode" }
|
||||||
|
clap = { version = "4.4.18", features = ["derive"] }
|
||||||
|
color-eyre = "0.6.2"
|
||||||
|
serde = { version = "1.0.196", features = ["derive"] }
|
||||||
|
env_logger = "0.11.1"
|
||||||
|
log = "0.4.20"
|
||||||
|
tokio = { version = "1.35.1", features = ["macros", "parking_lot", "rt", "process", "sync"] }
|
82
handlers/execute/src/handler.rs
Normal file
82
handlers/execute/src/handler.rs
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
use deckster_mode::shared::handler_communication::{HandlerEvent, HandlerInitializationError, InitialHandlerMessage, KeyEvent};
|
||||||
|
use deckster_mode::shared::path::KeyPath;
|
||||||
|
use deckster_mode::DecksterHandler;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use std::thread;
|
||||||
|
use tokio::process::Command;
|
||||||
|
use tokio::sync::broadcast;
|
||||||
|
use tokio::task::LocalSet;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct KeyConfig {
|
||||||
|
program: Box<str>,
|
||||||
|
#[serde(default)]
|
||||||
|
args: Box<[String]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Handler {
|
||||||
|
events_sender: broadcast::Sender<(KeyPath, KeyEvent)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Handler {
|
||||||
|
pub fn new(data: InitialHandlerMessage<(), KeyConfig, ()>) -> Result<Self, HandlerInitializationError> {
|
||||||
|
let (events_sender, _) = broadcast::channel::<(KeyPath, KeyEvent)>(5);
|
||||||
|
|
||||||
|
thread::spawn({
|
||||||
|
let events_sender = events_sender.clone();
|
||||||
|
|
||||||
|
move || {
|
||||||
|
let runtime = tokio::runtime::Builder::new_current_thread().enable_io().build().unwrap();
|
||||||
|
let task_set = LocalSet::new();
|
||||||
|
|
||||||
|
for (path, config) in data.key_configs {
|
||||||
|
task_set.spawn_local(manage_key(events_sender.subscribe(), path, config));
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime.block_on(task_set)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(Handler { events_sender })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DecksterHandler for Handler {
|
||||||
|
fn handle(&mut self, event: HandlerEvent) {
|
||||||
|
if let HandlerEvent::Key { path, event } = event {
|
||||||
|
self.events_sender.send((path, event)).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn manage_key(mut events: broadcast::Receiver<(KeyPath, KeyEvent)>, path: KeyPath, config: KeyConfig) {
|
||||||
|
let mut command = Command::new(config.program.as_ref());
|
||||||
|
let command = command.args(config.args.clone().iter());
|
||||||
|
|
||||||
|
while let Ok((p, event)) = events.recv().await {
|
||||||
|
if p != path {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if event == KeyEvent::Press {
|
||||||
|
tokio::spawn({
|
||||||
|
let future = command.status();
|
||||||
|
let path = path.clone();
|
||||||
|
|
||||||
|
async move {
|
||||||
|
let result = future.await;
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Ok(status) => {
|
||||||
|
if !status.success() {
|
||||||
|
log::error!("Process failed with status (key at {}): {}", &path, status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(error) => log::error!("Failed to spawn process (key at {}): {}", &path, error),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
handlers/execute/src/main.rs
Normal file
26
handlers/execute/src/main.rs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
use clap::Parser;
|
||||||
|
use color_eyre::Result;
|
||||||
|
|
||||||
|
use crate::handler::Handler;
|
||||||
|
|
||||||
|
mod handler;
|
||||||
|
|
||||||
|
#[derive(Debug, Parser)]
|
||||||
|
#[command(name = "execute")]
|
||||||
|
enum CliCommand {
|
||||||
|
#[command(name = "deckster-run", hide = true)]
|
||||||
|
Run,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
env_logger::init();
|
||||||
|
let command = CliCommand::parse();
|
||||||
|
|
||||||
|
match command {
|
||||||
|
CliCommand::Run => {
|
||||||
|
deckster_mode::run(Handler::new)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue