Separate filtering from running, and actually invoke interpret to run the scores

This commit is contained in:
tahahawa 2025-04-14 15:50:14 -04:00 committed by taha
parent 0a5d3b531a
commit e845544035
2 changed files with 32 additions and 29 deletions

View File

@ -14,13 +14,14 @@ This is the harmony CLI, a minimal implementation
The current help text: The current help text:
``` ````
Usage: example-cli [OPTIONS] Usage: harmony_cli [OPTIONS]
Options: Options:
-r, --run <RUN> Name of score to run -r, --run Run score(s) or not
-i, --interactive Run interactive or not -f, --filter <FILTER> Filter query
-a, --all Run all or nth -i, --interactive Run interactive TUI or not
-a, --all Run all or nth, defaults to all
-n, --number <NUMBER> Run nth matching, zero indexed [default: 0] -n, --number <NUMBER> Run nth matching, zero indexed [default: 0]
-l, --list list scores, will also be affected by run filter -l, --list list scores, will also be affected by run filter
-h, --help Print help -h, --help Print help
@ -30,3 +31,4 @@ Options:
## Core architecture ## Core architecture
![Harmony Core Architecture](docs/diagrams/Harmony_Core_Architecture.drawio.svg) ![Harmony Core Architecture](docs/diagrams/Harmony_Core_Architecture.drawio.svg)
````

View File

@ -1,3 +1,5 @@
use std::error::Error;
use clap::builder::ArgPredicate; use clap::builder::ArgPredicate;
use clap::{Arg, CommandFactory, Parser}; use clap::{Arg, CommandFactory, Parser};
use harmony; use harmony;
@ -9,26 +11,20 @@ use harmony_tui;
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[command(version, about, long_about = None)] #[command(version, about, long_about = None)]
struct Args { struct Args {
/// Name of score to run /// Run score(s) or not
#[cfg(feature = "tui")] #[arg(short, long, default_value_t = false)]
#[arg( run: bool,
short,
long,
default_value_if("interactive", ArgPredicate::IsPresent, Some(""))
)]
run: Option<String>,
/// Name of score to run /// Filter query
#[cfg(not(feature = "tui"))]
#[arg(short, long)] #[arg(short, long)]
run: String, filter: Option<String>,
/// Run interactive or not /// Run interactive TUI or not
#[arg(short, long, default_value_t = false)] #[arg(short, long, default_value_t = false)]
interactive: bool, interactive: bool,
/// Run all or nth /// Run all or nth, defaults to all
#[arg(short, long, default_value_t = false)] #[arg(short, long, default_value_t = true)]
all: bool, all: bool,
/// Run nth matching, zero indexed /// Run nth matching, zero indexed
@ -56,41 +52,46 @@ pub async fn init<T: Topology + std::fmt::Debug + Send + Sync + 'static>(
} }
// if no score to run provided, and list isn't specified, print help // if no score to run provided, and list isn't specified, print help
if args.run.is_none() && !args.list { if !args.run && !args.list {
println!("Please include at least --run or --list");
Args::command().print_help(); Args::command().print_help();
return Ok(()); return Ok(());
} }
let scores = maestro.scores(); let scores = maestro.scores();
let scores_read = scores.read().expect("Should be able to read scores"); let scores_read = scores.read().expect("Should be able to read scores");
let scores_vec: Vec<Box<dyn Score<T>>> = match args.run.clone() { let scores_vec: Vec<Box<dyn Score<T>>> = match args.filter.clone() {
Some(filter) => scores_read Some(f) => scores_read
.iter() .iter()
.map(|s| s.clone_box()) .map(|s| s.clone_box())
.filter(|s| s.name().contains(&filter)) .filter(|s| s.name().contains(&f))
.collect(), .collect(),
None => scores_read.iter().map(|s| s.clone_box()).collect(), None => scores_read.iter().map(|s| s.clone_box()).collect(),
}; };
if scores_vec.len() == 0 {
return Err("No score found".into());
}
// if list option is specified, print filtered list and exit // if list option is specified, print filtered list and exit
if args.list { if args.list {
println!("Available scores: {:#?}", scores_vec); println!("Available scores: {:#?}", scores_vec);
return Ok(()); return Ok(());
} }
if scores_vec.len() == 0 {
return Err("No score containing query found".into());
}
// if all is specified, run all. Otherwise, run the first match or specified index // if all is specified, run all. Otherwise, run the first match or specified index
if args.all { if args.all {
for s in scores_vec { for s in scores_vec {
println!("Running: {}", s.clone_box().name()); println!("Running: {}", s.name());
maestro.interpret(s).await?;
} }
} else { } else {
let score = scores_vec.get(args.number as usize); let score = scores_vec.get(args.number as usize);
match score { match score {
Some(s) => println!("Running: {}", s.clone_box().name()), Some(s) => {
println!("Running: {}", s.name());
maestro.interpret(s.clone_box()).await?;
}
None => return Err("Invalid index given".into()), None => return Err("Invalid index given".into()),
} }
} }