You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

74 lines
1.8 KiB

pub mod listen;
use crate::config::AppConfig;
use crate::container::Container;
use anyhow::Result;
use async_trait::async_trait;
use clap::Subcommand;
use clap::{Args as ClapArgs, Parser};
use config::ConfigBuilder;
use config::builder::DefaultState;
use std::path::PathBuf;
#[derive(Subcommand, Debug, Clone)]
pub enum Command {
/// Decode a word using given system
Listen(listen::ListenCmd),
}
impl Command {
pub fn into_app_command(self) -> Box<dyn AppCommand> {
match self {
Command::Listen(cmd) => Box::new(cmd),
}
}
}
#[derive(Parser, Debug)]
#[command(author, version, about)]
pub struct CliArgs {
#[command(flatten)]
pub global: GlobalArgs,
#[command(subcommand)]
pub command: Command,
}
#[derive(ClapArgs, Debug)]
pub struct GlobalArgs {
/// Path to config file
#[arg(short, long, default_value = "config.toml")]
pub config: PathBuf,
#[arg(long, help = defaults::HELP_LOG)]
pub log_level: Option<String>,
}
pub trait Configurable {
fn apply_defaults(
&self,
builder: ConfigBuilder<DefaultState>,
) -> Result<ConfigBuilder<DefaultState>>;
fn apply_overrides(
&self,
builder: ConfigBuilder<DefaultState>,
) -> Result<ConfigBuilder<DefaultState>>;
}
#[async_trait]
pub trait Executable {
async fn execute(&self, config: &AppConfig, container: &Container) -> Result<()>;
}
// AppCommand must be dyn-compatible. Configurable is already dyn-compatible.
// Executable is dyn-compatible because of #[async_trait].
pub trait AppCommand: Configurable + Executable {}
impl<T: Configurable + Executable> AppCommand for T {}
mod defaults {
use const_format::formatcp;
pub const LOG_LEVEL: &str = "info";
pub const HELP_LOG: &str = formatcp!("Override Log Level [default: {}]", LOG_LEVEL);
}