-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow unrecognized subcommands #372
Comments
This adds all the plumbing, and 3 of the 4 commands that I want to ship with the CLI for 0.4.0. This adds the ability to run, revert, and redo migrations. There's still a lot of things I'd like to improve about the CLI. We need to give better error output in cases where something unexpected happens, and I'd like to proxy unknown subcommands to `diesel-subcommand` (this last one appears to be [a limitation of clap](clap-rs/clap#372). I've opted to make `diesel_cli` be a separate crate, as cargo doesn't allow you to declare dependencies as only for executables. I don't want to add `clap` or `chrono` (which I'll be adding as a dependency in the follow up to this commit) to become hard dependencies of diesel itself. Another unrelated enhancement I'd like to eventually make is adding `dotenv` support. I think this should be optional, but if it doesn't become a hard dependency of diesel itself, maybe it doesn't matter?
This adds all the plumbing, and 3 of the 4 commands that I want to ship with the CLI for 0.4.0. This adds the ability to run, revert, and redo migrations. There's still a lot of things I'd like to improve about the CLI. We need to give better error output in cases where something unexpected happens, and I'd like to proxy unknown subcommands to `diesel-subcommand` (this last one appears to be [a limitation of clap](clap-rs/clap#372). I've opted to make `diesel_cli` be a separate crate, as cargo doesn't allow you to declare dependencies as only for executables. I don't want to add `clap` or `chrono` (which I'll be adding as a dependency in the follow up to this commit) to become hard dependencies of diesel itself. Another unrelated enhancement I'd like to eventually make is adding `dotenv` support. I think this should be optional, but if it doesn't become a hard dependency of diesel itself, maybe it doesn't matter?
This adds all the plumbing, and 3 of the 4 commands that I want to ship with the CLI for 0.4.0. This adds the ability to run, revert, and redo migrations. There's still a lot of things I'd like to improve about the CLI. We need to give better error output in cases where something unexpected happens, and I'd like to proxy unknown subcommands to `diesel-subcommand` (this last one appears to be [a limitation of clap](clap-rs/clap#372). I've opted to make `diesel_cli` be a separate crate, as cargo doesn't allow you to declare dependencies as only for executables. I don't want to add `clap` or `chrono` (which I'll be adding as a dependency in the follow up to this commit) to become hard dependencies of diesel itself. Another unrelated enhancement I'd like to eventually make is adding `dotenv` support. I think this should be optional, but if it doesn't become a hard dependency of diesel itself, maybe it doesn't matter?
This should be an easy addition. Thanks for suggesting it! 👍 I should be able to knock this out either later today or early tomorrow. I'll post back here with the updates. |
This adds all the plumbing, and 3 of the 4 commands that I want to ship with the CLI for 0.4.0. This adds the ability to run, revert, and redo migrations. There's still a lot of things I'd like to improve about the CLI. We need to give better error output in cases where something unexpected happens, and I'd like to proxy unknown subcommands to `diesel-subcommand` (this last one appears to be [a limitation of clap](clap-rs/clap#372). I've opted to make `diesel_cli` be a separate crate, as cargo doesn't allow you to declare dependencies as only for executables. I don't want to add `clap` or `chrono` (which I'll be adding as a dependency in the follow up to this commit) to become hard dependencies of diesel itself. Another unrelated enhancement I'd like to eventually make is adding `dotenv` support. I think this should be optional, but if it doesn't become a hard dependency of diesel itself, maybe it doesn't matter?
Rather than Now, it can get ambiguous when positional argument is also allowed. Should clap pass the argument as positional argument if it cannot find any subcommands? Or should it give the subcommand not found error message? |
I have a local branch of this and The issue that ended up making this take way longer than I'd hoped was in the details. What happens if that external subcommand isn't found (when The solutions I ended up going with (which I'm just ironing out, and hope to have done shortly), are you can either The second way of Once I finish the testing, I'll upload the branch and push the PR. |
@kbknapp 👍 |
I definitely like Does the proposed solution also work for |
@sgrif I'm glad you said that, because I already had some reservations about the So I'm going to pull the
Do you mean only for Status UpdateObviously this has taken much longer than I originally anticipated. Just to keep everyone in the loop, some of the changes required for this feature also melded nicely with some planned breaking changes for a 2x release. These breaking changes are minor, but big ergonomic wins. And as a bi-product, also making implementing this feature easier. So I'm trying to push out the base of the 2x (basically just breaking changes portion to speed up time to release), and this feature will be part of that. Now to quell any fears, 2x won't be a massive re-design like #259 proposes (that'll have to wait for a 3x). It's nearly complete, so it shouldn't be too much longer depending on my free time over the next few days. Here's what 2x looks like:
That's it. So you can see 2x isn't a massive change, but it's a chance to clean up some cruft. |
This adds all the plumbing, and 3 of the 4 commands that I want to ship with the CLI for 0.4.0. This adds the ability to run, revert, and redo migrations. There's still a lot of things I'd like to improve about the CLI. We need to give better error output in cases where something unexpected happens, and I'd like to proxy unknown subcommands to `diesel-subcommand` (this last one appears to be [a limitation of clap](clap-rs/clap#372). I've opted to make `diesel_cli` be a separate crate, as cargo doesn't allow you to declare dependencies as only for executables. I don't want to add `clap` or `chrono` (which I'll be adding as a dependency in the follow up to this commit) to become hard dependencies of diesel itself. Another unrelated enhancement I'd like to eventually make is adding `dotenv` support. I think this should be optional, but if it doesn't become a hard dependency of diesel itself, maybe it doesn't matter?
External subcommands are now supported via the following: ```rust extern crate clap; use clap::{App, AppSettings}; fn main() { // Assume there is a third party subcommand named myprog-subcmd let m = App::new("myprog") .setting(AppSettings::AllowExternalSubcommands) .get_matches_from(vec![ "myprog", "subcmd", "--option", "value", "-fff", "--flag" ]); // All trailing arguments will be stored under the subcommands sub-matches under a // value of their runtime name (in this case "subcmd") match m.subcommand() { (external, Some(ext_m)) => { let ext_args: Vec<&str> = ext_m.values_of(external).unwrap().collect(); assert_eq!(ext_args ,["--option", "value", "-fff", "--flag"]); }, _ => unreachable!() } } ``` Closes #372
External subcommands are now supported via the following: ```rust extern crate clap; use clap::{App, AppSettings}; fn main() { // Assume there is a third party subcommand named myprog-subcmd let m = App::new("myprog") .setting(AppSettings::AllowExternalSubcommands) .get_matches_from(vec![ "myprog", "subcmd", "--option", "value", "-fff", "--flag" ]); // All trailing arguments will be stored under the subcommands sub-matches under a // value of their runtime name (in this case "subcmd") match m.subcommand() { (external, Some(ext_m)) => { let ext_args: Vec<&str> = ext_m.values_of(external).unwrap().collect(); assert_eq!(ext_args ,["--option", "value", "-fff", "--flag"]); }, _ => unreachable!() } } ``` Closes #372
Closed with #391 and will be available shortly upon v2 release. Here's an example of using the new feature: Note, using extern crate clap;
use clap::{App, AppSettings};
fn main() {
// Assume there is a third party subcommand named myprog-subcmd
let m = App::new("myprog")
.setting(AppSettings::AllowExternalSubcommands)
.get_matches_from(vec!["myprog", "subcmd", "--option", "value", "-f"]);
// All trailing arguments will be stored under the subcommands sub-matches under a value
// of their runtime name (in this case "subcmd")
match m.subcommand() {
(external, Some(ext_m)) => {
let ext_args: Vec<&str> = ext_m.values_of(external).unwrap().collect();
assert_eq!(external, "subcmd");
assert_eq!(ext_args, ["--option", "value", "-f"]);
},
_ => unreachable!()
}
} |
External subcommands are now supported via the following: ```rust extern crate clap; use clap::{App, AppSettings}; fn main() { // Assume there is a third party subcommand named myprog-subcmd let m = App::new("myprog") .setting(AppSettings::AllowExternalSubcommands) .get_matches_from(vec![ "myprog", "subcmd", "--option", "value", "-fff", "--flag" ]); // All trailing arguments will be stored under the subcommands sub-matches under a // value of their runtime name (in this case "subcmd") match m.subcommand() { (external, Some(ext_m)) => { let ext_args: Vec<&str> = ext_m.values_of(external).unwrap().collect(); assert_eq!(ext_args ,["--option", "value", "-fff", "--flag"]); }, _ => unreachable!() } } ``` Closes #372
External subcommands are now supported via the following: ```rust extern crate clap; use clap::{App, AppSettings}; fn main() { // Assume there is a third party subcommand named myprog-subcmd let m = App::new("myprog") .setting(AppSettings::AllowExternalSubcommands) .get_matches_from(vec![ "myprog", "subcmd", "--option", "value", "-fff", "--flag" ]); // All trailing arguments will be stored under the subcommands sub-matches under a // value of their runtime name (in this case "subcmd") match m.subcommand() { (external, Some(ext_m)) => { let ext_args: Vec<&str> = ext_m.values_of(external).unwrap().collect(); assert_eq!(ext_args ,["--option", "value", "-fff", "--flag"]); }, _ => unreachable!() } } ``` Closes #372
It's a pretty common pattern for CLIs which take subcommands to attempt to subshell out to
appname-subcommand
if the command is unrecognized, to allow new commands to be easily added. This is impossible to do with clap today (at least not without writing the usage string by hand), as if you doappname foo
it'll complain that it did not expect an argumentfoo
.I propose adding
AppSettings::AllowUnrecognizedSubcommand
, and also improving the error message to specify that it's an unrecognized subcommand and list the possible subcommands, as it'll likely require the same code changesThe text was updated successfully, but these errors were encountered: