use std::sync::OnceLock;
use clap::Parser;
use repo::{Config, OutputFormat};
use super::{CliOutputMode, Commands};
#[derive(Parser)]
#[command(name = "heddle")]
#[command(author, version, about, long_about = None)]
#[command(disable_help_subcommand = true)]
pub struct Cli {
#[command(subcommand)]
pub command: Commands,
#[arg(long, global = true, value_enum)]
pub output: Option<CliOutputMode>,
#[arg(long, global = true)]
pub no_color: bool,
#[arg(short = 'C', long, global = true, value_name = "PATH")]
pub repo: Option<std::path::PathBuf>,
#[arg(short, long, global = true, action = clap::ArgAction::Count)]
pub verbose: u8,
#[arg(short, long, global = true)]
pub quiet: bool,
#[arg(long, global = true, env = "HEDDLE_OPERATION_ID", hide = true)]
pub op_id: Option<String>,
}
impl Cli {
pub fn user_config_or_exit() -> &'static cli_shared::UserConfig {
static USER_CONFIG: OnceLock<cli_shared::UserConfig> = OnceLock::new();
USER_CONFIG.get_or_init(|| cli_shared::UserConfig::load_default().unwrap_or_default())
}
pub fn output_mode(&self) -> Option<cli_shared::OutputMode> {
self.output.map(Into::into)
}
pub fn open_repo(&self) -> anyhow::Result<repo::Repository> {
use anyhow::Context as _;
let cwd;
let repo_path = match self.repo.as_ref() {
Some(path) => path,
None => {
cwd = std::env::current_dir().context("get current working directory")?;
&cwd
}
};
repo::Repository::open(repo_path).context("open Heddle repository")
}
}
impl weft_client_shim::CliContext for Cli {
fn repo_path(&self) -> Option<&std::path::Path> {
self.repo.as_deref()
}
fn operation_id_wire(&self) -> String {
self.op_id.clone().unwrap_or_default()
}
fn should_output_json(&self, repo_config: Option<&Config>) -> bool {
should_output_json(self, repo_config)
}
}
pub fn should_output_json(cli: &Cli, repo_config: Option<&Config>) -> bool {
let mut format = repo_config
.and_then(|config| config.output.format)
.unwrap_or(Cli::user_config_or_exit().output.format);
if let Some(output) = cli.output_mode() {
format = match output {
cli_shared::OutputMode::Json | cli_shared::OutputMode::JsonCompact => {
OutputFormat::Json
}
cli_shared::OutputMode::Text => OutputFormat::Text,
};
}
matches!(format, OutputFormat::Json)
}