Not obvious how to provide multiple usage statements with `App::override_usage()`
Please complete the following tasks
- [X] I have searched the discussions
- [X] I have searched the open and rejected issues
Rust Version
rustc 1.58.1 (db9d1b20b 2022-01-20)
Clap Version
3.0.14
Minimal reproducible code
fn main() {
clap::App::new("myapp")
.override_usage(
"myapp -X [-a] [-b] <file>\n\
myapp -Y [-c] <file1> <file2>\n\
myapp -Z [-d|-e]"
)
.get_matches_from(["myapp", "-h"]);
}
Steps to reproduce the bug with the above code
Paste as examples/min-usage.rs.
cargo run --example=min-usage
Actual Behaviour
myapp
USAGE:
myapp -X [-a] [-b] <file>
myapp -Y [-c] <file1> <file2>
myapp -Z [-d|-e]
OPTIONS:
-h, --help Print help information
Expected Behaviour
myapp
USAGE:
myapp -X [-a] [-b] <file>
myapp -Y [-c] <file1> <file2>
myapp -Z [-d|-e]
OPTIONS:
-h, --help Print help information
Additional Context
This relates to issue #1068.
When providing multiple usage statements on multiple lines, the help output is mis-indented.
The canonical workaround is for the user to indent the lines within their usage string according to the following rules:
- Do not indent the first usage line.
- Indent all subsequent usage lines with four spaces.
- The last line must not end with a newline.
The workaround versions of the reproducing example above:
fn main() {
clap::App::new("myapp")
.override_usage(
"myapp -X [-a] [-b] <file>\n \
myapp -Y [-c] <file1> <file2>\n \
myapp -Z [-d|-e]"
)
.get_matches_from(["myapp", "-h"]);
}
or
fn main() {
clap::App::new("myapp")
.override_usage("\
myapp -X [-a] [-b] <file>
myapp -Y [-c] <file1> <file2>
myapp -Z [-d|-e]"
)
.get_matches_from(["myapp", "-h"]);
}
The above workaround works with the current DEFAULT_TEMPLATE and DEFAULT_NO_ARGS_TEMPLATE, but is sensitive to indentation changes in those default templates. Note that in the discussion for #2002, there is a stated goal to avoid making the details of the default templates an API contract. Requiring user-indented usage strings jeopardizes the flexibility to change the default templates to some degree.
N.B. the workaround for this issue changed when PR #2067 was merged. Prior to that, usage strings were tab-indented. #1068 illustrates the old-style workaround. It's perhaps worth noting that users upgrading from clap 2 --> 3 may bump into this issue if they have legacy multi-line usage strings with tab indentation.
Possible Solutions
Document/standardize the workaround
The least intrusive way to make multiple usage statements more obvious to users would be to document the required multi-line format (i.e. the above workaround) for custom usage strings. A couple additions to App::override_usage()'s docstring would be sufficient for this option.
Handle/comprehend non-indented multi-line usage strings
This approach was implemented in PR #3404. The idea was to accept user-provided usage strings where lines may or may not be indented by the user, and then use a new template tag ({usage-indented}) to normalize the user-provided usage lines to fit into clap's default help templates.
The benefits of this approach are that multi-line usage strings will Just Work(tm) both for simple newline separated usage statements as well as usage strings containing either the modern or legacy (see #1068) workarounds.
The key downside of this approach is the API change of adding the {usage-indented} template tag.
Debug Output
No response
This sounds contradictory to the purported change that closed #1068. I marked #1068 as closed based on a comment in the CHANGELOG
App::override_usageno longer implies a leading\t, allowing multi lined usages
This was copied over from before the changelog rewrite and was introduced in commit 8bd1f1a9d. This was released in v3.0.0-beta.1 on 2020-05-03. Looking back in the history, starting around that time, I am not finding any change to the usage code that sounds like this.
Looking back through src/output/help.rss history, for the entire time we used a template for default help (a87320ae8), we seem to always have the fixed number of leading spaces. We seem to have been inserting spaces between the header and the usage statement for quite a while.
Going to do some more digging into this.
FWIW, I also had a hard time reconciling the CHANGELOG message that prompted #1068 to be closed with any specific commit(s) that addressed #1068. AFAICT, the only difference between clap 2 and clap 3 for this issue is whether tab or space is used to indent the usage. It has always been one or the other hardwired indentation in either the procedural or templated help generation; and that change from tab to space indentation came with the template feature in a87320a (PR #2067).
I feel like we are hitting a cap in the number of subtle breaking changes for 4.0 and feel this should be pushed back to 5.0.
PR #4106 adds documentation for how to add multiple override usage lines. Regardless of whether we may want to do something more substantial with usage overrides in clap 5, this documentation will be helpful for anyone that wants multiple usage lines in clap 3 or 4.