aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs43
1 files changed, 38 insertions, 5 deletions
diff --git a/src/main.rs b/src/main.rs
index e7a7d2f..c8b73dc 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -69,6 +69,10 @@ use std::io;
use std::process;
use std::str;
+use structopt::clap::ErrorKind;
+use structopt::clap::SubCommand;
+use structopt::StructOpt;
+
const NITROCLI_BINARY: &str = "NITROCLI_BINARY";
const NITROCLI_MODEL: &str = "NITROCLI_MODEL";
const NITROCLI_USB_PATH: &str = "NITROCLI_USB_PATH";
@@ -105,15 +109,44 @@ impl fmt::Display for DirectExitError {
impl error::Error for DirectExitError {}
/// Parse the command-line arguments and execute the selected command.
-fn handle_arguments(ctx: &mut Context<'_>, args: Vec<String>) -> anyhow::Result<()> {
- use structopt::StructOpt;
-
- match args::Args::from_iter_safe(args.iter()) {
+fn handle_arguments(ctx: &mut Context<'_>, argv: Vec<String>) -> anyhow::Result<()> {
+ match args::Args::from_iter_safe(argv.iter()) {
Ok(args) => {
ctx.config.update(&args);
args.cmd.execute(ctx)
}
- Err(err) => {
+ Err(mut err) => {
+ if err.kind == ErrorKind::HelpDisplayed {
+ // For the convenience of the user we'd like to list the
+ // available extensions in the help text. At the same time, we
+ // don't want to unconditionally iterate through PATH (which may
+ // contain directories with loads of files that need scanning)
+ // for every command invoked. So we do that listing only if a
+ // help text is actually displayed.
+ let path = ctx.path.clone().unwrap_or_else(ffi::OsString::new);
+ if let Ok(extensions) = commands::discover_extensions(&path) {
+ let mut clap = args::Args::clap();
+ for name in extensions {
+ // Because of clap's brain dead API, we see no other way
+ // but to leak the string we created here. That's okay,
+ // though, because we exit in a moment anyway.
+ let about = Box::leak(format!("Run the {} extension", name).into_boxed_str());
+ clap = clap.subcommand(
+ SubCommand::with_name(&name)
+ // Use some magic number here that causes all
+ // extensions to be listed after all other
+ // subcommands.
+ .display_order(1000)
+ .about(about as &'static str),
+ );
+ }
+ // At this point we are *pretty* sure that repeated invocation
+ // will result in another error. So should be fine to unwrap
+ // here.
+ err = clap.get_matches_from_safe(argv.iter()).unwrap_err();
+ }
+ }
+
if err.use_stderr() {
Err(err.into())
} else {