Add support for flags and options (issue #476)
Implementation for #476. See below for the design decisions I took in the implementation.
Example
# excerpt from `examples/kitchen-sink.just`
flags --flag --option="foo" positional:
@echo "flag: " {{ flag }}
@echo "option: " {{ option }}
@echo "positional:" {{ positional}}
Invocations
$ cargo run -q -- --justfile ./examples/kitchen-sink.just flags bar
flag:
option: foo
positional: bar
$ cargo run -q -- --justfile ./examples/kitchen-sink.just flags --option 42 bar
flag:
option: 42
positional: bar
cargo run -q -- --justfile ./examples/kitchen-sink.just flags --flag bar
flag: flag
option: foo
positional: bar
$ cargo run -q -- --justfile ./examples/kitchen-sink.just flags --option 42 --flag bar
flag: flag
option: 42
positional: bar
# out of order
$ cargo run -q -- --justfile ./examples/kitchen-sink.just flags bar --option test --flag
flag: flag
option: test
positional: bar
# special cases
$ cargo run -q -- --justfile ./examples/kitchen-sink.just flags -- --flag
flag:
option: foo
positional: --flag
$ cargo run -q -- --justfile ./examples/kitchen-sink.just flags --option --flag bar
flag:
option: --flag
positional: bar
Design
- Flags are defined by
---parameterwithout default value - Options are defined by
--parameter=default - Flags and options must be defined before positional parameters. Positional arguments are handled as before (including
*and+modifiers) - Flags evaluate to their name when passed. When not passed, they evaluate to the empty string . This way
flag != ""checks for the flag - Options consume the next parameter and evaluate to it when passed. When not passed, they evaluate to their default value
- Options and flags can be passed in any order and mixed with positional arguments
-
--forces all following arguments to interpreted as positional for the given recipe. When specifying multiple recipes, the parser resets for each new recipe - Recipes without flag parameters accept flags or options as positional arguments. This behavior ensure backwards compatibility (see for example the
trailing_flagstest) -
--$flagor--$option=defaultdefining environment variables
Open questions:
- Support
--options-with-hyphens? At the moment underscores must be used as in--options_with_underscores - How to update the Chinese readme?
Merge casey:master to keep PR up to date
Need this a lot
Small observation from my own use of this feature: the definition of flags plays quite nicely with the unstable && operator.
For example, this justfile
set unstable
test --full:
cargo test {{ full && "--all-targets --all-features" }}
allows to use
-
just testto runcargo test, and -
just test --fullto runcargo test "--all-targets --all-features"
Related example:
set unstable
run --port="" path="example":
RUST_LOG="debug" cargo run -p server -- {{ port && ("--port " + port) }} {{ path }}
hey @casey I just tipped you $20 via GitHub sponsors. Could you please take a look quick at this PR?
I suggest other folks in this thread to tip, too.
Flags are an essential features for CLIs but they are not currently available in Just :(
Merged master to keep the PR up to date