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.
82 lines
2.1 KiB
82 lines
2.1 KiB
pub mod decode; |
|
pub mod encode; |
|
pub mod import_dict; |
|
|
|
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 |
|
Decode(decode::DecodeArgs), |
|
|
|
/// Encode a number using given system |
|
Encode(encode::EncodeArgs), |
|
|
|
/// Import dictionary |
|
ImportDict(import_dict::ImportDictArgs), |
|
} |
|
|
|
pub fn resolve_command(command: &Command) -> &dyn AppCommand { |
|
match command { |
|
Command::Decode(args) => args, |
|
Command::Encode(args) => args, |
|
Command::ImportDict(args) => args, |
|
} |
|
} |
|
|
|
#[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 ConfigurableCommand { |
|
fn apply_defaults( |
|
&self, |
|
builder: ConfigBuilder<DefaultState>, |
|
) -> Result<ConfigBuilder<DefaultState>>; |
|
fn apply_overrides( |
|
&self, |
|
builder: ConfigBuilder<DefaultState>, |
|
) -> Result<ConfigBuilder<DefaultState>>; |
|
} |
|
|
|
#[async_trait] |
|
pub trait CommandExecutor { |
|
async fn execute(&self, config: &AppConfig, container: &Container) -> Result<()>; |
|
} |
|
|
|
// AppCommand must be dyn-compatible. ConfigurableCommand is already dyn-compatible. |
|
// CommandExecutor is dyn-compatible because of #[async_trait]. |
|
pub trait AppCommand: ConfigurableCommand + CommandExecutor {} |
|
|
|
impl<T: ConfigurableCommand + CommandExecutor> 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); |
|
}
|
|
|