Generate command line interface #3575
Closed
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Hi! So I've finally got to try the thing we have briefly discussed at RustConf: removing duplication of docopt options in different commands. This PR is a rough proof of concept to gather feedback and decide if we need this at all.
The approach here is to use hand-rolled code generation: all commands are specified in options.txt file, from which options.rs with docopt usage strings and options strutcs is generated. In options.txt, we can defined option groups and then use them to assemble full docopt description of the command.
I've decided to go with code generation and not with runtime string concatenation for the following reasons:
In some sense, it is simpler: to understand the end result, you need to look only at
options.rs, which contains usual self-describing docopt usages and structs. You don't need to understand the tricky string concatenation stuff.We can generate not only the usage strings, but also the structs with options. I think this can be extended to also generate bash completions.
This can be extended to generate structs for different option groups, so instead of
config.configure(options.flag_verbose, options.flag_quiet, &options.flag_color, options.flag_frozen, options.flag_locked)?;one can writeconfig.configure(options.color_options(), options.lockfile_options()).So that's the plan :)
Current implementation applies it only to
buildandpublishcommands, to show what's possible without creating a huge diff. Generation is done with a separate binarygenerate-options.rsand not viabuild.rsjust because it was easier to debug. However I think it maybe better to avoidbuild.rsand just to commit the generatedoptions.rstogether withoptions.txt: the generated code is supposed to be very readable, and you might want to inspect it to see if the help message is wrapped properly, for example.generate-options.rsis very rough: lots of unwraps and does not handle multiline flag descriptions :)