mirror of
https://github.com/storytold/deckcraft.git
synced 2026-10-27 20:16:50 -06:00
CLI: --help prints usage and unknown render flags are rejected (#163)
This commit is contained in:
@@ -54,6 +54,14 @@ fn main() -> ExitCode {
|
||||
Some("render") => report(render(rest)),
|
||||
Some("convert") => report(convert(rest)),
|
||||
Some("run") => report(run(rest)),
|
||||
Some("--help" | "-h" | "help") => {
|
||||
outln!("{USAGE}");
|
||||
ExitCode::SUCCESS
|
||||
}
|
||||
Some("commands") if rest.first().is_some_and(|a| is_help(a)) => {
|
||||
outln!("{USAGE}");
|
||||
ExitCode::SUCCESS
|
||||
}
|
||||
Some("commands") => {
|
||||
let s = Session::new();
|
||||
let f = rest.first().map(|x| x.to_lowercase());
|
||||
@@ -82,6 +90,10 @@ fn main() -> ExitCode {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_help(arg: &str) -> bool {
|
||||
matches!(arg, "--help" | "-h")
|
||||
}
|
||||
|
||||
fn report(r: Result<(), String>) -> ExitCode {
|
||||
match r {
|
||||
Ok(()) => ExitCode::SUCCESS,
|
||||
@@ -103,6 +115,10 @@ fn open(s: &mut Session, input: Option<&str>, sample: bool) -> Result<(), String
|
||||
}
|
||||
|
||||
fn info(args: &[String]) -> Result<(), String> {
|
||||
if args.first().is_some_and(|a| is_help(a)) {
|
||||
outln!("{USAGE}");
|
||||
return Ok(());
|
||||
}
|
||||
let path = args.first().ok_or("info needs a FILE")?;
|
||||
let mut s = Session::new();
|
||||
open(&mut s, Some(path), false)?;
|
||||
@@ -127,6 +143,11 @@ fn render(args: &[String]) -> Result<(), String> {
|
||||
"--all" => all = true,
|
||||
"--edit" => edit = true,
|
||||
"--scale" => scale = it.next().and_then(|v| v.parse().ok()).ok_or("--scale needs a number")?,
|
||||
"--help" | "-h" => {
|
||||
outln!("{USAGE}");
|
||||
return Ok(());
|
||||
}
|
||||
other if other.starts_with('-') => return Err(format!("unknown option `{other}`")),
|
||||
other
|
||||
if input.is_none()
|
||||
&& !sample
|
||||
@@ -162,6 +183,10 @@ fn render(args: &[String]) -> Result<(), String> {
|
||||
}
|
||||
|
||||
fn convert(args: &[String]) -> Result<(), String> {
|
||||
if args.first().is_some_and(|a| is_help(a)) {
|
||||
outln!("{USAGE}");
|
||||
return Ok(());
|
||||
}
|
||||
let (Some(input), Some(out)) = (args.first(), args.get(1)) else { return Err("convert needs IN and OUT".into()) };
|
||||
let mut s = Session::new();
|
||||
open(&mut s, Some(input), false)?;
|
||||
@@ -192,6 +217,10 @@ fn run(args: &[String]) -> Result<(), String> {
|
||||
"--save" => save = Some(it.next().cloned().ok_or("--save needs a path")?),
|
||||
"--export" => export = Some(it.next().cloned().ok_or("--export needs a path")?),
|
||||
"--print" => print = true,
|
||||
"--help" | "-h" => {
|
||||
outln!("{USAGE}");
|
||||
return Ok(());
|
||||
}
|
||||
other => return Err(format!("unknown option `{other}`")),
|
||||
}
|
||||
}
|
||||
@@ -217,6 +246,10 @@ fn run(args: &[String]) -> Result<(), String> {
|
||||
}
|
||||
|
||||
fn describe(id: Option<&str>) -> Result<(), String> {
|
||||
if id.is_some_and(is_help) {
|
||||
outln!("{USAGE}");
|
||||
return Ok(());
|
||||
}
|
||||
let id = id.ok_or("describe needs a command id")?;
|
||||
let c = deckcraft_engine::find_command(id).ok_or_else(|| format!("unknown command `{id}`"))?;
|
||||
outln!("{} — {}\n where: {}\n shortcut: {}\n params: {}", c.id, c.label, c.menu.join(" ▸ "), c.shortcut.unwrap_or("—"), c.params);
|
||||
@@ -233,6 +266,10 @@ fn app(args: &[String]) -> Result<(), String> {
|
||||
match a.as_str() {
|
||||
"--port" => port = it.next().cloned().ok_or("--port needs a value")?,
|
||||
"--method" => method = Some(it.next().cloned().ok_or("--method needs a name")?),
|
||||
"--help" | "-h" => {
|
||||
outln!("{USAGE}");
|
||||
return Ok(());
|
||||
}
|
||||
other => rest.push(other.to_string()),
|
||||
}
|
||||
}
|
||||
@@ -261,6 +298,10 @@ fn mcp(args: &[String]) -> Result<(), String> {
|
||||
match a.as_str() {
|
||||
"--connect" => connect = Some(it.next().cloned().ok_or("--connect needs a port or host:port")?),
|
||||
"--sample" => sample = true,
|
||||
"--help" | "-h" => {
|
||||
outln!("{USAGE}");
|
||||
return Ok(());
|
||||
}
|
||||
other => return Err(format!("unknown mcp option `{other}`")),
|
||||
}
|
||||
}
|
||||
@@ -278,3 +319,35 @@ fn mcp(args: &[String]) -> Result<(), String> {
|
||||
let stdin = std::io::stdin();
|
||||
server.serve(stdin.lock(), std::io::stdout()).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn args(a: &[&str]) -> Vec<String> {
|
||||
a.iter().map(|s| s.to_string()).collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn render_help_prints_usage_and_writes_nothing() {
|
||||
assert!(render(&args(&["--help"])).is_ok());
|
||||
assert!(render(&args(&["-h"])).is_ok());
|
||||
assert!(!std::path::Path::new("--help").exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn render_rejects_unknown_flag() {
|
||||
let err = render(&args(&["--sample", "--scael", "2", "out.png"])).unwrap_err();
|
||||
assert_eq!(err, "unknown option `--scael`");
|
||||
assert!(!std::path::Path::new("--scael").exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn other_subcommands_accept_help() {
|
||||
assert!(info(&args(&["--help"])).is_ok());
|
||||
assert!(convert(&args(&["-h"])).is_ok());
|
||||
assert!(run(&args(&["--help"])).is_ok());
|
||||
assert!(describe(Some("--help")).is_ok());
|
||||
assert!(mcp(&args(&["-h"])).is_ok());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user