use serde_derive::{Deserialize, Serialize};
use std::fmt;
#[derive(Default, Debug, Clone, Deserialize, Serialize, PartialEq)]
pub struct CommandLine {
cmd: Vec<String>,
#[serde(default)]
privileged: bool,
#[serde(default)]
interactive: bool,
}
impl CommandLine {
pub fn new<S: Clone + Into<String>>(cmd: &[S]) -> Self {
debug_assert!(!cmd.is_empty(), "commandline mustn't be empty");
let as_vec = cmd
.iter()
.map(|s| Into::<String>::into(s.clone()))
.collect::<Vec<String>>();
Self {
cmd: as_vec,
privileged: false,
interactive: false,
}
}
pub fn is_empty(&self) -> bool {
self.cmd.is_empty()
}
pub fn privileged(mut self) -> Self {
self.needs_privileges(true);
self
}
pub fn needs_privileges(&mut self, yesno: bool) {
self.privileged = yesno;
}
pub fn get_privileged(&self) -> bool {
self.privileged
}
pub fn is_interactive(&mut self, yesno: bool) {
self.interactive = yesno;
}
pub fn get_interactive(&self) -> bool {
self.interactive
}
pub fn append<S: Clone + Into<String>>(&mut self, args: &[S]) {
args.iter()
.for_each(|arg| self.cmd.push(Into::<String>::into(arg.clone())))
}
pub fn command(&self) -> String {
self.cmd[0].clone()
}
pub fn args(&self) -> &[String] {
self.cmd.get(1..).unwrap_or(&[])
}
}
impl fmt::Display for CommandLine {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} {}", self.command(), self.args().join(" "))
}
}
impl<S: Clone + Into<String>> From<Vec<S>> for CommandLine {
fn from(value: Vec<S>) -> Self {
Self::new(&value)
}
}
#[macro_export]
macro_rules! cmd {
( $( $text:expr ),+ ) => {
CommandLine::new( &[ $( $text ),+ ] )
};
}
pub use cmd;