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.
105 lines
2.7 KiB
105 lines
2.7 KiB
pub mod decode; |
|
pub mod encode; |
|
pub mod import_dict; |
|
pub mod list_dicts; |
|
|
|
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::DecodeCmd), |
|
|
|
/// Encode a number using given system |
|
Encode(encode::EncodeCmd), |
|
|
|
/// Import dictionary |
|
ImportDict(import_dict::ImportDictCmd), |
|
|
|
/// List all dictionaries |
|
ListDicts(list_dicts::ListDictsCmd), |
|
} |
|
|
|
impl Command { |
|
pub fn into_app_command(self) -> Box<dyn AppCommand> { |
|
match self { |
|
Command::Decode(cmd) => Box::new(cmd), |
|
Command::Encode(cmd) => Box::new(cmd), |
|
Command::ImportDict(cmd) => Box::new(cmd), |
|
Command::ListDicts(cmd) => Box::new(cmd), |
|
} |
|
} |
|
} |
|
|
|
// pub fn resolve_command(command: &Command) -> &dyn AppCommand { |
|
// match command { |
|
// Command::Decode(app_cmd) => app_cmd, |
|
// Command::Encode(app_cmd) => app_cmd, |
|
// Command::ImportDict(app_cmd) => app_cmd, |
|
// } |
|
// } |
|
|
|
// pub fn resolve_command_box(command: Command) -> Box<dyn AppCommand> { |
|
// match command { |
|
// Command::Decode(cmd) => Box::new(cmd), |
|
// Command::Encode(cmd) => Box::new(cmd), |
|
// Command::ImportDict(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); |
|
}
|
|
|