use std::path::PathBuf;
use clap::{
Parser, Subcommand,
builder::styling::{AnsiColor, Styles},
};
use super::{completions::CompletionShell, run::RunArgs};
use crate::{constants::APP_NAME, domain::process::AgentTool};
const HELP_STYLES: Styles = Styles::styled()
.header(AnsiColor::Cyan.on_default().bold())
.usage(AnsiColor::Cyan.on_default().bold())
.literal(AnsiColor::Green.on_default())
.placeholder(AnsiColor::Yellow.on_default());
#[derive(Parser)]
#[command(
name = APP_NAME,
bin_name = APP_NAME,
about = "A terminal workspace for running CLI agents and dev processes",
styles = HELP_STYLES
)]
pub struct Args {
#[arg(short, long, global = true)]
pub config: Option<PathBuf>,
#[command(subcommand)]
pub command: Option<Command>,
}
#[derive(Subcommand)]
pub enum Command {
Init,
Check,
Run(RunArgs),
Projects {
#[command(subcommand)]
command: Option<ProjectsCommand>,
},
Hooks {
#[command(subcommand)]
command: HooksCommand,
},
Doctor,
Completions {
#[arg(value_enum)]
shell: CompletionShell,
},
#[command(hide = true)]
Hook {
#[command(subcommand)]
command: InternalHookCommand,
},
}
#[derive(Subcommand)]
pub enum ProjectsCommand {
Add {
path: Option<PathBuf>,
},
Remove {
name: String,
},
}
#[derive(Subcommand)]
pub enum HooksCommand {
Setup,
}
#[derive(Subcommand)]
pub enum InternalHookCommand {
Capture {
#[arg(long)]
provider: AgentTool,
#[arg(long)]
process_id: u32,
#[arg(long)]
parent_process_id: Option<u32>,
},
Launch {
#[arg(long)]
session: String,
#[arg(last = true, allow_hyphen_values = true)]
command: String,
},
}
#[cfg(test)]
mod tests {
use clap::Parser;
use super::*;
#[test]
fn the_command_is_named_after_the_binary() {
use clap::CommandFactory;
assert_eq!(Args::command().get_name(), APP_NAME);
assert_eq!(Args::command().get_bin_name(), Some(APP_NAME));
}
#[test]
fn global_config_flag_parses_anywhere() {
let before = Args::try_parse_from(["muster", "-c", "x.yml", "run", "--", "ls"]).unwrap();
assert_eq!(
before.config.as_deref(),
Some(std::path::Path::new("x.yml"))
);
let bare = Args::try_parse_from(["muster"]).unwrap();
assert!(bare.command.is_none());
}
}