Add helper for handling unknown subcommands
This commit is contained in:
parent
348389f745
commit
cb8b5a0cf6
1 changed files with 75 additions and 0 deletions
|
@ -502,6 +502,81 @@ impl<'a> Runtime<'a> {
|
||||||
Some(::std::io::stdin())
|
Some(::std::io::stdin())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper for handling subcommands which are not available.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// For example someone calls `imag foo bar`. If `imag-foo` is in the $PATH, but it has no
|
||||||
|
/// subcommand `bar`, the `imag-foo` binary is able to automatically forward the invokation to a
|
||||||
|
/// `imag-foo-bar` binary which might be in $PATH.
|
||||||
|
///
|
||||||
|
/// It needs to call `Runtime::handle_unknown_subcommand` with the following parameters:
|
||||||
|
///
|
||||||
|
/// 1. The "command" which was issued. In the example this would be `"imag-foo"`
|
||||||
|
/// 2. The "subcommand" which is missing: `"bar"` in the example
|
||||||
|
/// 3. The `ArgMatches` object from the call, so that this routine can forward all flags passed
|
||||||
|
/// to the `bar` subcommand.
|
||||||
|
///
|
||||||
|
/// # Return value
|
||||||
|
///
|
||||||
|
/// On success, the exit status object of the `Command` invocation is returned.
|
||||||
|
/// On Error, a RuntimeError object is returned.
|
||||||
|
///
|
||||||
|
/// # Details
|
||||||
|
///
|
||||||
|
/// The `IMAG_RTP` variable is set for the child process. It is set to the current runtime path.
|
||||||
|
///
|
||||||
|
/// Stdin, stdout and stderr are inherited to the child process.
|
||||||
|
///
|
||||||
|
/// This function **blocks** until the child returns.
|
||||||
|
///
|
||||||
|
pub fn handle_unknown_subcommand<S: AsRef<str>>(&self,
|
||||||
|
command: S,
|
||||||
|
subcommand: S,
|
||||||
|
args: &ArgMatches)
|
||||||
|
-> Result<::std::process::ExitStatus, RuntimeError>
|
||||||
|
{
|
||||||
|
use std::io::Write;
|
||||||
|
use std::io::ErrorKind;
|
||||||
|
|
||||||
|
let rtp_str = self.rtp()
|
||||||
|
.to_str()
|
||||||
|
.map(String::from)
|
||||||
|
.ok_or(RuntimeErrorKind::IOError)
|
||||||
|
.map_err(RuntimeError::from_kind)?;
|
||||||
|
|
||||||
|
let command = format!("{}-{}", command.as_ref(), subcommand.as_ref());
|
||||||
|
|
||||||
|
let subcommand_args = args.values_of("")
|
||||||
|
.map(|sx| sx.map(String::from).collect())
|
||||||
|
.unwrap_or_else(|| vec![]);
|
||||||
|
|
||||||
|
Command::new(&command)
|
||||||
|
.stdin(::std::process::Stdio::inherit())
|
||||||
|
.stdout(::std::process::Stdio::inherit())
|
||||||
|
.stderr(::std::process::Stdio::inherit())
|
||||||
|
.args(&subcommand_args[..])
|
||||||
|
.env("IMAG_RTP", rtp_str)
|
||||||
|
.spawn()
|
||||||
|
.and_then(|mut c| c.wait())
|
||||||
|
.map_err(|e| match e.kind() {
|
||||||
|
ErrorKind::NotFound => {
|
||||||
|
let mut out = self.stdout();
|
||||||
|
|
||||||
|
if let Err(e) = writeln!(out, "No such command: '{}'", command) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
if let Err(e) = writeln!(out, "See 'imag --help' for available subcommands") {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
e
|
||||||
|
},
|
||||||
|
_ => e,
|
||||||
|
})
|
||||||
|
.map_err(RuntimeError::from)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Exported for the `imag` command, you probably do not want to use that.
|
/// Exported for the `imag` command, you probably do not want to use that.
|
||||||
|
|
Loading…
Reference in a new issue