use abscissa_core::{Command, Configurable, FrameworkError, Runnable};
use clap::Parser;
use std::{ffi::OsString, path::PathBuf};
use crate::config::ZebradConfig;
use super::ZebradCmd;
#[derive(Debug, clap::Parser)]
#[clap(
version = clap::crate_version!(),
author="Zcash Foundation <zebra@zfnd.org>",
help_template = "\
{name} {version}\n
{author}\n
{usage-heading} {usage}\n
{all-args}\
"
)]
pub struct EntryPoint {
#[clap(subcommand)]
pub cmd: Option<ZebradCmd>,
#[clap(long, short, help = "path to configuration file")]
pub config: Option<PathBuf>,
#[clap(long, short, help = "be verbose")]
pub verbose: bool,
#[clap(long, help = "tracing filters which override the zebrad.toml config")]
filters: Vec<String>,
}
impl EntryPoint {
pub fn cmd(&self) -> &ZebradCmd {
self.cmd
.as_ref()
.expect("should default to start if not provided")
}
pub fn default_cmd_as_str() -> &'static str {
"start"
}
fn should_add_default_subcommand(&self) -> bool {
self.cmd.is_none()
}
pub fn process_cli_args(mut args: Vec<OsString>) -> clap::error::Result<Vec<OsString>> {
let entry_point = EntryPoint::try_parse_from(&args)?;
if entry_point.should_add_default_subcommand() {
args.push(EntryPoint::default_cmd_as_str().into());
for filter in entry_point.filters {
args.push(filter.into())
}
}
Ok(args)
}
}
impl Runnable for EntryPoint {
fn run(&self) {
self.cmd().run()
}
}
impl Command for EntryPoint {
fn name() -> &'static str {
ZebradCmd::name()
}
fn description() -> &'static str {
ZebradCmd::description()
}
fn authors() -> &'static str {
ZebradCmd::authors()
}
}
impl Configurable<ZebradConfig> for EntryPoint {
fn config_path(&self) -> Option<PathBuf> {
match &self.config {
Some(cfg) => Some(cfg.clone()),
None => self.cmd().config_path(),
}
}
fn process_config(&self, config: ZebradConfig) -> Result<ZebradConfig, FrameworkError> {
self.cmd().process_config(config)
}
}