projectable/external_event/
run_cmd.rs1use std::{
2 sync::{
3 atomic::{AtomicBool, Ordering},
4 Arc,
5 },
6 thread,
7 time::Duration,
8};
9
10use anyhow::Result;
11use crossbeam_channel::Sender;
12use duct::Expression;
13
14use super::ExternalEvent;
15
16pub fn run_cmd(
17 cmd: Expression,
18 sender: Sender<ExternalEvent>,
19 refresh_time: Duration,
20 stop: Arc<AtomicBool>,
21) -> Result<()> {
22 let handle = cmd.start()?;
23 thread::spawn(move || loop {
24 if stop.load(Ordering::Acquire) {
25 if let Err(err) = handle.kill() {
26 sender
27 .send(ExternalEvent::Error(err.into()))
28 .expect("sender should not have deallocated");
29 }
30 return;
31 }
32 match handle.try_wait() {
33 Ok(Some(out)) => {
34 sender
35 .send(ExternalEvent::CommandOutput(
36 String::from_utf8_lossy(if out.stdout.is_empty() {
37 &out.stderr
38 } else {
39 &out.stdout
40 })
41 .to_string(),
42 ))
43 .expect("sender should not have deallocated");
44 return;
45 }
46 Ok(None) => {}
47 Err(err) => {
48 sender
49 .send(ExternalEvent::Error(err.into()))
50 .expect("sender should not have deallocated");
51 return;
52 }
53 };
54 thread::sleep(refresh_time);
55 });
56
57 Ok(())
58}