use crate::{
core::layout::Layout,
pure::{geometry::Rect, Stack},
Result, Xid,
};
use std::{
io::Read,
process::{Command, Stdio},
};
use tracing::trace;
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) -> std::io::Result<String> {
let cmd = cmd.into();
trace!(?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()
};
trace!(?cmd, "reading output");
let mut child = result?;
let mut buff = String::new();
child
.stdout
.take()
.expect("to have output")
.read_to_string(&mut buff)
.map(|_| buff)
}
pub fn spawn_for_output_with_args<S: Into<String>>(
cmd: S,
args: &[&str],
) -> std::io::Result<String> {
let cmd = cmd.into();
trace!(?cmd, ?args, "spawning subprocess for output");
let mut child = Command::new(&cmd)
.stdout(Stdio::piped())
.args(args)
.spawn()?;
trace!(?cmd, ?args, "reading output");
let mut buff = String::new();
child
.stdout
.take()
.unwrap()
.read_to_string(&mut buff)
.map(|_| buff)
}
pub fn notify(msg: &str) -> std::io::Result<()> {
Command::new("notify-send").arg(msg).output().map(|_| ())
}
pub fn print_layout_result<L: Layout>(
l: &mut L,
n_clients: u32,
screen_width: u32,
screen_height: u32,
) {
let s: Stack<Xid> = Stack::try_from_iter((0..n_clients).map(Into::into)).expect("non-empty");
let (_, positions) = l.layout(&s, Rect::new(0, 0, screen_width, screen_height));
let mut screen = vec![vec![' '; (screen_width + 1) as usize]; (screen_height + 1) as usize];
for (_, Rect { x, y, w, h }) in positions.into_iter() {
for i in 0..=w {
screen[y as usize][(x as u32 + i) as usize] = '.';
screen[(y as u32 + h) as usize][(x as u32 + i) as usize] = '.';
}
for i in 0..=h {
screen[(y as u32 + i) as usize][x as usize] = '.';
screen[(y as u32 + i) as usize][(x as u32 + w) as usize] = '.';
}
}
for row in screen.into_iter() {
let chars: String = row.into_iter().collect();
println!("{chars}");
}
}