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
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.
- Fixes#466.
- Adds initializers to ArgumentDefinition generic over a Container type.
The Container type must conform to a new internal protocol
ArgumentDefinitionContainer which describes functionality like default
set of help options for the argument defined by the property wrapper,
etc.
- Adds overloads for Optional @Arguments and @Options with default
values which emit deprecation warning to guide users towards using the
non-Optional versions.
- Make ArgumentSet(_:visibility:) filter correctly
The ArgumentSet initializer was previously only filtering out option
groups with visibility lower than requested. With this change, the
resulting ArgumentSet only includes values that are valid for display.
In addition, this moves the visibility parameter out of
UsageGenerator.synopsis(); that type needs to have the correct
visibility level at initialization.
- Mark non-parsed properties as private
This applies to properties that are defined without a property
wrapper. This kind of property should never be included in the help,
since they aren't included in the command-line tool's UI.
* 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.
- Adds an overload of ArgumentDefinition.init with a generic constraint
on ExpressibleByArgument that propogates the conformance to the
construction of ArgumentDefinition.Help. This allows the
allValueStrings of the type conforming to ExpressibleByArgument to
become the allValues property of the help object.
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.
- Removes unused codepaths.
- Simplifies synopsis string codepaths by removing optionality. This
complexity is moved to the caller who is now responsible for filtering
out hidden arguments and options. This change is desirable as it
allows the caller to determine if the argument should be hidden. For
example, while it makes sense to hide arguments in help text, it may
not make sense to hide them when dumping the arguments for another
tool to consume.
- Removes one layer of help properties by directly including the members
of ArgumentHelp in ArgumentDefinition.Help. This also results in the
discussion field which previously existed in both structures, now
having a single source of truth. Adds helper method for setting each
of these members using an instance of ArgumentHelp. Makes previously
optional Strings into plain Strings and updates points of use to check
for the empty string case.
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>
Fixes an issue where the inversion of a flag would not be hidden whe the ArgumentHelp shouldDisplay value is false.
Added a unit test to check for this behavior.
This removes the nesting inside the ArgumentSet data structure, which
had semantic meaning in an earlier version. This flattening, plus a
switch to using dictionary lookup instead of linear scanning, provides
another performance boost.
* 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
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
This pushes any errors indicated by unexpected arguments after parsing
out to the same late position. We were previously stopping immediately
when the command is a leaf node; that isn't necessary and created an
awkward second error path.
* 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
* 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 `PositionalArgumentsValidator`
* Update tests for PositionalArgumentsValidator
* Use argument property names in PositionalArgumentsValidator.Error
* Add a catch-all argument parsing strategy
We don't currently have a way for `@Argument` arrays to capture
command-line inputs that look like options. This capability is
important for tools like SwiftPM that need to forward input to
another command.
This introduces an `ArgumentArrayParsingStrategy` enum with a
`remaining` case that matches the current behavior, as well as an
`unconditionalRemaining` case that captures all remaining input. The
two array-based `@Argument` initializers gain defaulted parameters for
the parsing strategy.
* Address feedback from @danieleggert
- Added a bit of a warning for the unconditional parsing strategy
- Switched to a better way of getting the original input
- Changed to pulling the "earliest" element when combining positional and
unused values, rather than combining and sorting. This felt more
efficient than reconstructing a SplitArguments instance or combining
and sorting.
* Add parameter docs for argument parsing strategy
* Expand documentation and tests to cover `--` terminator
* Fix case name in API documentation
* Corrected grammatical and spelling errors in files in Documentation.
* Correct various spelling, grammar, and formatting mistakes in code documentation.