use crate::{
core::{bindings::CodeMap, ring::Selector},
ErrorHandler, PenroseError, Result,
};
use std::{
io::Read,
process::{Command, Stdio},
};
pub fn spawn<S: Into<String>>(cmd: S) -> Result<()> {
let s = cmd.into();
let parts: Vec<&str> = s.split_whitespace().collect();
let result = if parts.len() > 1 {
Command::new(parts[0])
.args(&parts[1..])
.stdout(Stdio::null())
.stderr(Stdio::null())
.spawn()
} else {
Command::new(parts[0])
.stdout(Stdio::null())
.stderr(Stdio::null())
.spawn()
};
match result {
Ok(_) => Ok(()),
Err(e) => Err(e.into()),
}
}
pub fn spawn_with_args<S: Into<String>>(cmd: S, args: &[&str]) -> Result<()> {
let result = Command::new(cmd.into())
.args(args)
.stdout(Stdio::null())
.stderr(Stdio::null())
.spawn();
match result {
Ok(_) => Ok(()),
Err(e) => Err(e.into()),
}
}
pub fn spawn_for_output<S: Into<String>>(cmd: S) -> Result<String> {
let cmd = cmd.into();
info!(?cmd, "spawning subprocess for output");
let parts: Vec<&str> = cmd.split_whitespace().collect();
let result = if parts.len() > 1 {
Command::new(parts[0])
.stdout(Stdio::piped())
.args(&parts[1..])
.spawn()
} else {
Command::new(parts[0]).stdout(Stdio::piped()).spawn()
};
let child = result?;
let mut buff = String::new();
Ok(child
.stdout
.ok_or(PenroseError::SpawnProc(cmd))?
.read_to_string(&mut buff)
.map(|_| buff)?)
}
pub fn spawn_for_output_with_args<S: Into<String>>(cmd: S, args: &[&str]) -> Result<String> {
let cmd = cmd.into();
info!(?cmd, ?args, "spawning subprocess for output");
let child = Command::new(&cmd)
.stdout(Stdio::piped())
.args(args)
.spawn()?;
info!(?cmd, ?args, "reading output");
let mut buff = String::new();
Ok(child
.stdout
.ok_or(PenroseError::SpawnProc(cmd))?
.read_to_string(&mut buff)
.map(|_| buff)?)
}
pub fn keycodes_from_xmodmap() -> CodeMap {
match Command::new("xmodmap").arg("-pke").output() {
Err(e) => panic!("unable to fetch keycodes via xmodmap: {}", e),
Ok(o) => match String::from_utf8(o.stdout) {
Err(e) => panic!("invalid utf8 from xmodmap: {}", e),
Ok(s) => s
.lines()
.flat_map(|l| {
let mut words = l.split_whitespace(); let key_code: u8 = match words.nth(1) {
Some(word) => match word.parse() {
Ok(val) => val,
Err(e) => panic!("{}", e),
},
None => panic!("unexpected output format from xmodmap -pke"),
};
words.skip(1).map(move |name| (name.into(), key_code))
})
.collect::<CodeMap>(),
},
}
}
pub fn index_selectors<'a, T>(len: usize) -> Vec<Selector<'a, T>> {
(0..len).map(Selector::Index).collect()
}
pub fn logging_error_handler() -> ErrorHandler {
Box::new(|e: PenroseError| error!("{}", e))
}