use std::io::{self, IsTerminal};
use clap::{CommandFactory, Parser};
use zenops::config_files::ConfigFileDirs;
#[derive(Parser, Debug)]
#[command(
name = "zenops",
about = "ZenOps: your system’s calm overseer",
version
)]
pub struct Cli {
#[clap(flatten)]
args: zenops::Args,
#[clap(long, short, global = true, value_enum, default_value_t = OutputMode::Human)]
output: OutputMode,
#[command(subcommand)]
command: zenops::Cmd,
}
#[derive(Clone, Copy, Debug, clap::ValueEnum)]
#[clap(rename_all = "lower")]
pub enum OutputMode {
Human,
Json,
}
fn main() {
let Cli {
mut args,
output,
command,
} = Cli::parse();
args.stdin_is_terminal = io::stdin().is_terminal();
if let zenops::Cmd::Completions { shell } = &command {
let mut cmd = Cli::command();
clap_complete::generate(*shell, &mut cmd, "zenops", &mut std::io::stdout());
return;
}
env_logger::init();
let stdout = io::stdout();
let stdout_is_terminal = stdout.is_terminal();
let color = args.color.enabled(stdout_is_terminal);
let show_diffs = matches!(command, zenops::Cmd::Status { diff: true, .. });
let show_clean = matches!(command, zenops::Cmd::Status { all: true, .. });
let mut lock = stdout.lock();
let mut renderer: Box<dyn zenops::output::Output> = match output {
OutputMode::Human => Box::new(zenops::output::TerminalRenderer::new(
&mut lock, color, show_diffs, show_clean,
)),
OutputMode::Json => Box::new(zenops::output::JsonOutput::new(&mut lock)),
};
let home = match home::home_dir() {
Some(h) => h,
None => {
eprintln!("error: {}", zenops::error::Error::NoHomeDir);
std::process::exit(1);
}
};
let dirs = ConfigFileDirs::load(home);
let path = zenops::utils::which::SearchPath::from_env();
let host = zenops::HostInputs {
dirs: &dirs,
path: &path,
args: &args,
};
if let Err(e) = zenops::real_main(&command, &host, renderer.as_mut()) {
eprintln!("error: {e}");
std::process::exit(1);
}
if let Err(e) = renderer.finalize() {
eprintln!("error: {e}");
std::process::exit(1);
}
}