Arguments declared with the `.allUnrecognized` parsing strategy
currently capture built-in flags, which isn't intended. This
fixes that issue by looking for built-in flags in the captured
portion of the input before decoding.
Fixes rdar://104990388
When a property wrapper is applied to a property, the property's
storage is given a name with a prefixed underscore. That is,
for a property named `x`, the actual storage is named `_x`.
That prefixed storage is what is visible through reflection, so
when building an ArgumentSet from a command type's Mirror, we
need to remove the leading underscore. This is done when creating
an InputKey for each property.
However, InputKeys are also created from CodingKeys during
decoding of a ParsableCommand. These CodingKeys _do not_ have
the leading underscore that is visible, so any underscores
that appear are actually from the declaration of the property
with an underscored name. Removing leading underscores from
CodingKey names results in a mismatch when trying to find
the decoded value.
This change simplifies the InputKey type to use an array
path instead of an indirect enum and removes the leading
underscore dropping when creating an InputKey from a CodingKey.
rdar://104928743
- Renames AssertEqualStringsIgnoringTrailingWhitespace to
AssertEqualStrings and updates the implementation to require matching
trailing whitespace.
- Updates AssertEqualStrings to include much easier to read diff output
when CollectionDifference is available. This should add developers
when tests fail by providing more clear errors.
This change is to make sure that the non-optional generic parameter
type is chosen for @Argument and @Option properties that provide a
default value. Previously, an optional type might be chosen depending
on how the `help` parameter was spelled, due to strange overload resolution.
In particular, using the `.init` caused selection of the deprecated
optional overload:
// Unexpected:
// Infers `Value` as `Optional<AbsolutePath>`
@Argument(help: .init("The path"))
var path = AbsolutePath("/")
// Expected:
// Infers `Value` as `AbsolutePath`
@Argument(help: "The path")
var path = AbsolutePath("/")
This addresses the issue by marking the deprecated overloads as
disfavored. rdar://102383455
This adds two new parsing options for argument arrays, and renames
`.unconditionalRemaining` to `.captureForPassthrough`.
- `.allUnrecognized` collects all the inputs that weren't used during
parsing. This essentially suppresses all "unrecognized flag/option"
and "unexpected argument" errors, and makes those extra inputs
available to the client.
- `.postTerminator` collects all inputs that follow the `--`
terminator, before trying to parse any other positional arguments.
This is a non-standard, but sometimes useful parsing strategy.
In the help for flags like --prefix/--no-prefix, use the name of the
default flag instead of true/false. When EnumerableFlag types
have separate help strings, show the correct default flag name
on the default flag in the help.
This adds underscored initializers that let library users add `= nil` to
declarations of optional `@Option` and `@Argument` properties. Previously,
default values have been available for properties of non-optional types
only.
These new initializers use `_OptionalNilComparisonType` as the wrapped
value parameter, so only a `nil` literal is acceptable in the default
value position. This avoids the problem of declaring an optional property
with a non-`nil` default, which ends up negating the purpose of an optional.
* Propagate unconditional remaining arguments to higher commands
This changes the behavior of parsing when a subcommand includes an
argument array with an unconditionalRemaining parsing strategy, such
that parsing options stops when the subcommand is encountered, so
that the subcommand can pick up those additional options.
* Correctly track used input origins for single-dash options
When capturing the values for an option with a single-dash with the .upToNextOption
parsing strategy, the parser was stopping its search for values when it encountered
the "unpacked" short option candidates. This change removes the single-dash option
before looking for values, which strips those short options (e.g. -h) from
consideration. Fixes#327.
If a command defines an @Argument property with the .unconditionalRemaining
parsing strategy, we need to stop parsing input when we encounter either a
positional argument or an unrecognized option/flag label. Note that this is
a change in behavior, as seen in the modified test.
This fixes a bug where an @Option array defined with the .upToNextOption
parsing strategy would only capture the last "group" of elements. e.g. in:
example --test one two --test three four
the `--test` property would only have the value `["three", "four"]`.
Fixes rdar://73908471
Fixes “Internal error. Invalid state while parsing command-line arguments.” that is encountered when an unparsed value is optional.
Root causes:
- `ParsedArgumentsContainer.decodeNil` returns false for optional values because it only does a `!contains(key)` check. This should instead return nil if the value of the element is nil.
- The decoder did not know about unparsed input origins that and would result in unexpected behavior when decoding nil default values.
- The `value` of `Mirror.Child` is defined as `Any` but this is confusing because the value could be `Optional<Any>` which is not equal to `nil` even when the `Optional` case is `.none`.
Co-authored-by: Mike <mike.wermuth@icloud.com>
We're newly able to decode actual optional types due to allowing
unparsed variable properties. "Normal" optional values are still
wrapped in non-optional property wrappers, so ArgumentDecoder didn't
need to handle optional values until now. Fixes#285
* Allow variable properties in parsable types
This captures the default value for non-parsable properties
when building the ArgumentSet, which in turn get set as initial
values before decoding.
* Convert some linear operations to constant time
* Temporary test command for performance testing
* Improve SplitArguments docs
* Re-enable split arguments unit test
* Restore repeat example
* Allow required arrays in `Option`s
Un-deprecates (but changes the semantics of) an initializer for an array value type without a default, forcing the user to specify at least one value from the command line.
* Allow required arrays in `Argument`s
Extends the parent commit to arguments, still un-deprecating and changing the semantics of the previous initializer to force users to provide a value on the command line.
* Allow required arrays in `Flag`s
Extends the previous commits to flags, still un-deprecating and changing the semantics of the previous initializer to force users to provide a value on the command line.
* Add default-value section to documentation
Support for generating shell completion scripts for `ParsableCommand`
types, with customization points for `ExpressibleByArgument` types and
individual arguments and options. Zsh and Bash are supported in this
initial release.
* Use type inference for flags / options
* Use default value syntax for arg/option arrays
* Allow a default for flag arrays
* Fix some whitespace
* Allow arguments validations to warn instead of fail
* Move nonsense flag warning to argument validation
* Update guides/readme with default literal syntax
* Allow normal Swift default property initialization syntax
This change allows the normal `var foo = "blah"` default initialization
syntax for `Option`s, as a parallel initialization method as using the
`default` parameter.
* Add simple tests for default property initialization
* Centralize some constructor logic into a private `init`
Preparing for another no-initial value `init` to be added and the existing one with a `default` parameter to be deprecated
* Deprecate previous `Option.init` with `default` parameter
It's replaced with an `init` containing no default value parameter, which will be used when the user does not provide any value.
Also add a (most likely unnecessary) sanity test to make sure initializations without a default value still work.
Also copy out documentation to allow clean removal of the older `init` when the time comes.
* Document added test cases
* Correct punctuation
* Extend standard default initialization syntax to `Option`s with `transform` parameters
* Actually replace previous `init` with private version
This mirrors the non-transform variants, and should have been included in the previous commits
* Clean up usage of default parameter values
Private `init` doesn't need defaults, and the deprecated public ones shouldn't have it to avoid confusion with the new methods
* Clean up documentation
Treat new initializers as the originally intended way to allow for clean removal of the deprecated methods
Also add some additional documentation to the deprecated methods to help point users in the right direction
* Extend standard default initialization to `Argument`s
* Extend standard default initialization to `Flag`s
* Default flags with inversions to nil/required
* Extend standard default initialization to no-inversion boolean `Flags`
Prints a warning when that default value is `true` instead of `false`, as the flag value will be pinned regardless of user input
* Eliminate deprecation spam from default value initialization
All examples and unit tests have been transitioned to the new syntax, with the exception of `SourceCompatEndToEndTests`, which should not have the old style removed until it is no longer valid source.
* Add source compatibility tests for new default syntax and associated changes
* Update top-level documentation
* Remove ExpressibleByArgument conformance for Optional
It turns out that the conditional conformance for Optional was a bad idea, and
it should be handled more like Array, with specific initializers for the Optional
case. Primarily, this is because providing a default value for an optional property
doesn't make sense -- the default is already nil, and a non-nil default means that
the property will never be nil and therefore shouldn't be optional.
* Drop duplicated argument definitions
d1 and d6 are duplicates of c2 and c, respectively.
* Correctly mark optional args/options as optional
* Correct documentation for Option/Argument
* Use the correct parameter name in the documentation
* Eliminate #file warnings
* Test source compatibility for property wrappers
This adds compilation tests for all the property wrappers, including
all the various permutations of their default parameter values.
* Add 'see help' messages to usage messages and the help screen
* Update tests for new help messages.
* Update guide examples with additional help messages
If an argument has a single dash and single character, followed by a value, treat it as a short name.
`-c=1` -> `Name.short("c")`
Otherwise, treat it as a long name with single dash.
`-count=1` -> `Name.longWithSingleDash("count")`
If a command cannot successfully run with zero arguments, print the error and the full help message instead of the short usage message.
This closes#134.
* Add EnumerableFlag protocol
This addresses the need for providing name specifications for enum
flags, since property wrappers can't be used for enum cases.
* Incorporate updated flag-handling logic
* Include test of multiple names for enumerable flags
* Add documentation for EnumerableFlag protocol
* Add `static func help(for:)` to EnumerableFlag
* Update docs to cover `EnumerableFlag`
* Update default value documentation
* Revise the Flag type docs
* Update Documentation/02 Arguments, Options, and Flags.md
Co-authored-by: Kyle Macomber <kmacomber@apple.com>
Co-authored-by: Kyle Macomber <kmacomber@apple.com>
* Add a test for @Option transfrom
* Updated `testValidation_Fail()` transform test
It now checks for the validation error text thrown from a `transform` closure.
* Improved transform `@Option` tests
Added a test for the defaut error message and renamed object to imply the tests are for `@Options` only
* Added a `CustomParserErrorConvertible` protocol
Opting in an error types to this will prevent automatic error messages from being generated.
* Add associated value to `.unableToParseValue`
Added a `customMessage` (`String?`) associated value to `ParseError.unableToParseValue(…)`. Setting this will by-pass any automatic error generation.
* Convert transform throws into `unableToParseValue`
Errors thrown by the `transform` closure are caught and convered into a `ParserError.unableToParseValue(…)` error. If the thrown error also confirms to `CustomParserErrorConvertible` the `customMessage` associated value is of `.unableToParseValue` is set, otherwise it is nil.
Implemented for `@Option` and `@Argument`.
* Added transform tests
Added `ParsableArguments` and `ParsableCommand` tests for single values and arrays.
Testing for correctly parsing and transforming values. Throwing a custom error and improved default error messages.
* Add default value to `unableToParseValue`
`customMessage` now has a default value of `nil`
* Removed `CustomParserErrorConvertible`
Updated `unableToParseValue` to take an optional `Error` assocated value. If this error is not nil `unableToParseValueMessage(…)` makes best-efforts to create a custom error message.
* Updated tests to new error mssages format
* Reverted public access of ValidationError.message
* Improved coding standards
`catch` brases on the same line and 2 space indents.
* Simplified `unableToParseValueMessage(…)` logic
Append custom error message to all “unableToParse” errors if it is not nil
* Added a “Handling Transform Errors” section
* Improved switch/case statements
* Added docs link to Handling Transform Errors
* Update Documentation/05 Validation and Errors.md
Co-Authored-By: Xiaodi Wu <13952+xwu@users.noreply.github.com>
* Update Documentation/05 Validation and Errors.md
Co-Authored-By: Xiaodi Wu <13952+xwu@users.noreply.github.com>
* Update Documentation/05 Validation and Errors.md
Co-Authored-By: Xiaodi Wu <13952+xwu@users.noreply.github.com>
* Update Documentation/05 Validation and Errors.md
Co-Authored-By: Xiaodi Wu <13952+xwu@users.noreply.github.com>
* Fixed comment and docs typos
Co-Authored-By: Xiaodi Wu <13952+xwu@users.noreply.github.com>
* Fixed minor code formatting etc.
Co-Authored-By: Nate Cook <natecook@apple.com>
* Improved Documentation
Reduced the code used in the transform closure. Also fixed typing and formatting.
* Added error examples
* Doc edits via code review
Co-Authored-By: Nate Cook <natecook@apple.com>
* Converted TransformEndToEndTests.swift to
2-space indentation
Co-authored-by: Xiaodi Wu <13952+xwu@users.noreply.github.com>
Co-authored-by: Nate Cook <natecook@apple.com>
* Add built-in support for --version flag
* Test that command-defined --version overrides the built-in.
* Document the `version:` parameter in CommandConfiguration
* Include --version in the generated help.
We were incorrectly skipping over dash-prefixed inputs when looking for the next
subcommand. This means that input like `command sub1 --foo sub2` would match the
sub1 and sub2 subcommands, even if `--foo` wasn't defined by sub1. This manifested
in issues where a value expected by `--foo` would be eaten by the subcommand matcher.
Fixes#92.
Previously, we were only storing full-decoded ParsableCommand instances
for subcommands to pick up with the @OptionGroup() wrapper. This change
stores all decoded @OptionGroup() values as well, so that they can be
shared from super- to subcommand.