From 9c516604f258d1e316caa937af893036b033168e Mon Sep 17 00:00:00 2001 From: Chris Wanstrath Date: Thu, 2 Apr 2026 14:05:45 -0700 Subject: [PATCH] Improve help text and error handling --- shout-rs/.gitignore | 1 + shout-rs/src/main.rs | 50 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 shout-rs/.gitignore diff --git a/shout-rs/.gitignore b/shout-rs/.gitignore new file mode 100644 index 0000000..2f7896d --- /dev/null +++ b/shout-rs/.gitignore @@ -0,0 +1 @@ +target/ diff --git a/shout-rs/src/main.rs b/shout-rs/src/main.rs index ea016a4..f85e958 100644 --- a/shout-rs/src/main.rs +++ b/shout-rs/src/main.rs @@ -37,18 +37,55 @@ struct TestOpts { parallel: bool, } +fn print_usage() { + eprintln!("Usage: shout [options] [command]"); + eprintln!(); + eprintln!("$ shell output tester"); + eprintln!(); + eprintln!("Options:"); + eprintln!(" -V, --version output the version number"); + eprintln!(" -h, --help display help for command"); + eprintln!(); + eprintln!("Commands:"); + eprintln!(" test [options] [files...] Run .shout test files"); + eprintln!(" version Print the version"); + eprintln!(" example Print an example .shout file"); + eprintln!(" help [command] display help for command"); +} + +fn print_test_help() { + eprintln!("Usage: shout test [options] [files...]"); + eprintln!(); + eprintln!("Run .shout test files"); + eprintln!(); + eprintln!("Arguments:"); + eprintln!(" files Files or directories to test"); + eprintln!(); + eprintln!("Options:"); + eprintln!(" -u, --update Rewrite expected output in-place with actual output"); + eprintln!(" -k, --keep Keep temp directories after run"); + eprintln!(" --clean-env Start with empty environment"); + eprintln!(" --path Prepend to PATH (repeatable)"); + eprintln!(" --timeout Per-command timeout (default: 10s)"); + eprintln!(" -v, --verbose Print each command as it runs"); + eprintln!(" --port-from Auto-assign $PORT starting from (default: 5400)"); + eprintln!(" -t, --filter Only run files matching (substring match)"); + eprintln!(" --parallel Run files in parallel"); + eprintln!(" -h, --help display help for command"); +} + fn parse_args() -> Option<(&'static str, TestOpts)> { let args: Vec = std::env::args().skip(1).collect(); - if args.is_empty() { - eprintln!("Usage: shout [options]"); - process::exit(1); + if args.is_empty() || args[0] == "-h" || args[0] == "--help" || args[0] == "help" { + print_usage(); + process::exit(if args.is_empty() { 1 } else { 0 }); } let subcommand = args[0].as_str(); match subcommand { - "version" => { + "-V" | "--version" | "version" => { println!("{VERSION}"); process::exit(0); } @@ -59,6 +96,7 @@ fn parse_args() -> Option<(&'static str, TestOpts)> { "test" => {} other => { eprintln!("Unknown command: {other}"); + eprintln!("Run 'shout --help' for usage"); process::exit(1); } } @@ -79,6 +117,10 @@ fn parse_args() -> Option<(&'static str, TestOpts)> { let mut i = 1; while i < args.len() { match args[i].as_str() { + "-h" | "--help" => { + print_test_help(); + process::exit(0); + } "-u" | "--update" => opts.update = true, "-k" | "--keep" => opts.keep = true, "--clean-env" => opts.clean_env = true,