From 56ec11e143edc55beb27de4d7e4a04a0b88da7ed Mon Sep 17 00:00:00 2001 From: Schrottkatze Date: Mon, 19 Feb 2024 17:54:40 +0100 Subject: [PATCH] cli: add subcommand support --- crates/app/src/config.rs | 20 +++++------------ crates/app/src/config/cli.rs | 9 +++----- crates/app/src/main.rs | 42 +++++++++++++++++++++++++++++------- 3 files changed, 42 insertions(+), 29 deletions(-) diff --git a/crates/app/src/config.rs b/crates/app/src/config.rs index b4d1ed1..552a951 100644 --- a/crates/app/src/config.rs +++ b/crates/app/src/config.rs @@ -1,18 +1,11 @@ -use std::path::PathBuf; - -use clap::Parser; - -use self::{ - cli::Args, - config_file::{find_config_file, Configs}, -}; +use self::config_file::{find_config_file, Configs}; +pub(crate) use cli::CliConfigs; mod cli; mod config_file; /// this struct may hold all configuration pub struct Config { - pub source: PathBuf, pub evaluator: eval::Available, pub startup_msg: bool, @@ -20,10 +13,9 @@ pub struct Config { impl Config { /// Get the configs from all possible places (args, file, env...) - pub fn read() -> Self { - let args = Args::parse(); - let config = if let Some(config) = args.config_path { - Ok(config) + pub fn read(args: &CliConfigs) -> Self { + let config = if let Some(config) = &args.config_path { + Ok(config.clone()) } else { find_config_file() }; @@ -42,7 +34,6 @@ impl Config { if let Some(file) = config { Self { - source: args.source, evaluator: args.evaluator.and(file.evaluator).unwrap_or_default(), // this is negated because to an outward api, the negative is more intuitive, // while in the source the other way around is more intuitive @@ -50,7 +41,6 @@ impl Config { } } else { Self { - source: args.source, startup_msg: !args.no_startup_message, evaluator: args.evaluator.unwrap_or_default(), } diff --git a/crates/app/src/config/cli.rs b/crates/app/src/config/cli.rs index 1d9c57a..c0e6c4d 100644 --- a/crates/app/src/config/cli.rs +++ b/crates/app/src/config/cli.rs @@ -1,12 +1,9 @@ use std::path::PathBuf; -use clap::{builder::BoolishValueParser, ArgAction, Parser}; - -#[derive(Parser)] -pub(crate) struct Args { - /// What file contains the pipeline to evaluate. - pub source: PathBuf, +use clap::{builder::BoolishValueParser, ArgAction, Args}; +#[derive(Args)] +pub(crate) struct CliConfigs { /// How to actually run the pipeline. /// Overrides the config file. Defaults to the debug evaluator. #[arg(short, long)] diff --git a/crates/app/src/main.rs b/crates/app/src/main.rs index 58103a5..7d7eff2 100644 --- a/crates/app/src/main.rs +++ b/crates/app/src/main.rs @@ -1,6 +1,7 @@ -use std::fs; +use std::{fs, path::PathBuf}; -use config::Config; +use clap::{Parser, Subcommand}; +use config::{CliConfigs, Config}; use welcome_msg::print_startup_msg; mod config; @@ -9,19 +10,44 @@ mod config; mod error_reporting; mod welcome_msg; +#[derive(Parser)] +struct Args { + #[command(flatten)] + configs: CliConfigs, + #[command(subcommand)] + command: Commands, +} + +#[derive(Subcommand)] +enum Commands { + Run { + /// What file contains the pipeline to evaluate. + source: PathBuf, + }, + Dev, +} + fn main() { // TODO: proper error handling across the whole function // don't forget to also look inside `Config` - let cfg = Config::read(); + let args = Args::parse(); + let cfg = Config::read(&args.configs); if cfg.startup_msg { print_startup_msg(); } - let source = fs::read_to_string(cfg.source).expect("can't find source file"); - let ir = ir::from_ron(&source).expect("failed to parse source to graph ir"); + match args.command { + Commands::Run { source } => { + let source = fs::read_to_string(source).expect("can't find source file"); + let ir = ir::from_ron(&source).expect("failed to parse source to graph ir"); - let mut machine = cfg.evaluator.pick(); - machine.feed(ir); - machine.eval_full(); + let mut machine = cfg.evaluator.pick(); + machine.feed(ir); + machine.eval_full(); + } + Commands::Dev => { + println!("Hello world!"); + } + } }