Commit Graph
50 Commits
Author SHA1 Message Date
Gwynne Raskind c5050aa63e Handle unparsed non-optional complex property types (#554)
* Implement correct handling of unparsed property types which perform non-optional nested decoding.
2023-02-23 14:00:14 -06:00
Nate Cook f674173291 Don't let .allUnrecognized consume built-in flags (#550)
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
2023-02-08 21:02:46 -08:00
Nate Cook a9b9644153 Stop removing underscores from CodingKey names in InputKey (#548)
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
2023-02-02 08:33:51 -06:00
Rauhul Varma bc29743b72 Update tests with easier to read diff output (#529)
- 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.
2022-11-21 22:29:52 -08:00
Nate Cook f94e4b9951 Disfavor deprecated property wrapper inits (#522)
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
2022-11-16 09:30:27 -06:00
Nate Cook a8b48bc389 Add two new ArgumentArrayParsingStrategy options (#496)
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.
2022-10-07 16:18:52 -05:00
David Peterson 587d26a2aa Fixes incorrect value copying when ParseArguments has the same field name+type as the ParseCommand (Issue #322) (#495)
* Contains fixes and test cases for #322
2022-09-22 09:43:48 -05:00
Nate Cook 7506042c65 Fix default display in help for EnumerableFlag and other types (#486)
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.
2022-09-14 11:16:15 -05:00
Nate Cook 0bac2cc0f1 Allow default nil values for optional properties (#480)
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.
2022-08-30 22:23:15 -05:00
Nate Cook 6f30db08e6 Don't trigger help for unconditional remaining commands (#417) 2022-03-12 12:33:19 -06:00
Nate Cook 1a5b1b3c03 Fix issue with unconditional remaining properties in subcommands (#397)
* 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.
2022-01-31 14:55:19 -06:00
Adam McNight 2b352c08c2 Deprecate Option initializer and add a new one with parameters in order (#391) 2022-01-25 10:43:44 -06:00
Matt Zanchelli 9e14482156 Correct Typos (#388) 2022-01-11 16:47:13 -06:00
Nate Cook b77ea81c44 Fix parsing for single-dash names with .upToNextOption parsing (#353)
* 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.
2021-09-10 17:54:35 -05:00
Nate Cook 23f7265cd6 Stop parsing earlier when a catch-all argument is present (#333)
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.
2021-07-02 17:39:30 -05:00
Nate Cook c002f406ac Capture values across multiple .upToNextOption option uses (#304)
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
2021-05-14 21:39:51 -05:00
Mike WermuthandMike bafa74a9e4 Fix invalid state error when decoding an unparsed optional value (#290)
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>
2021-04-15 01:07:24 -05:00
Nate Cook 380eb72378 Don't error when decoding optional unparsed values (#286)
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
2021-03-06 19:02:45 -06:00
Alfredo Delli Bovi 4793b0f4b9 Include help text in error message when validation fails (#283) 2021-03-06 13:11:58 -06:00
Nate Cook e99a8ef488 Allow variable properties in parsable types (#268)
* 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.
2021-02-15 15:28:13 -06:00
Nate Cook 9fe9374a1f Remove deprecated property wrapper initializers (#262) 2021-01-16 00:47:11 -06:00
Nate Cook 2a4664a40b Add support for joined short options (#240)
This supports joined arguments, like '-Ddebug' or '-v4'. Joined arguments
need to be explicitly declared as `.customShort("D", allowingJoined: true)`.
2021-01-16 00:18:23 -06:00
Elliott Williams c17e00a3bf Store mutations made by validate() (#239) 2020-09-18 11:55:07 -05:00
Nate Cook c34703022c Re-enable a short option pack test (#236) 2020-09-02 10:29:21 -05:00
Nate Cook db24cb1275 Improve parsing performance (#234)
* 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
2020-09-01 09:31:42 -05:00
Mike Lewis 8dfa177102 Allow required array arguments, options, and flags (#196)
* 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
2020-08-14 15:00:07 -05:00
Nate Cook 280700d361 Add completion script generation (#123)
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.
2020-07-29 17:58:44 -05:00
Nate Cook 35ceb59427 Nate/continue default initialization (#193)
* 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
2020-06-23 10:43:50 -05:00
Mike Lewis c0f9a5feee Allow normal Swift default property initialization syntax (#170)
* 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
2020-06-22 23:12:51 -05:00
John Mueller f07d2fb107 Enable default for option and argument arrays (#186)
* Enable default for option and argument arrays

* Moved array reset to ParsedValues
2020-06-22 13:53:31 -05:00
Nate Cook ef76d22b8b Convert deprecations from pre-0.1.0 to unavailable (#177) 2020-06-03 11:18:42 -05:00
Nate CookandErik Little aad1ac085b Make ParsableCommand.run() a mutating method (#163)
Co-authored-by: Erik Little <nuclear.ace@gmail.com>
2020-06-02 14:07:16 -05:00
Nate Cook c87d0d0dde Remove ExpressibleByArgument conformance from Optional (#173)
* 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
2020-06-01 21:47:22 -05:00
Nate Cook 6c6b77c713 Test source compatibility for property wrappers (#172)
* 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.
2020-06-01 16:14:15 -05:00
Nate Cook 8883f06b4e Don't consume the terminator during parsing. (#168)
Fixes #130.
2020-05-28 01:13:15 -05:00
Nate Cook 85196ee1d8 Additional help messages (#165)
* Add 'see help' messages to usage messages and the help screen

* Update tests for new help messages.

* Update guide examples with additional help messages
2020-05-22 17:04:14 -05:00
John Mueller afeb2009f8 Fix short names with equals sign (#141)
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")`
2020-05-14 10:09:30 -05:00
John Mueller 501bf60536 Display help when no arguments results in error (#140)
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.
2020-05-14 09:08:19 -05:00
Nate CookandKyle Macomber e870503c45 Add an EnumerableFlag protocol (#65)
* 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>
2020-05-10 17:08:44 -05:00
1081d08b1d Improve errors messages thrown from a transform closure (#115)
* 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>
2020-04-21 09:31:57 -05:00
Nate Cook ac24dc6caf Fix test failures on Linux 2020-04-09 13:28:59 -05:00
Kenny YorkandKenny York 42c9d4a02c Call validate on the entire command stack, instead of just the final subcommand (#104)
Co-authored-by: Kenny York <kenny_york@apple.com>
2020-04-08 13:00:57 -05:00
Nate Cook 31799bc1b4 Add built-in support for --version flag (#102)
* 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.
2020-03-30 12:36:21 -05:00
Nate Cook 72fb0b168c Enforce that options must be used by command before matching a subcommand (#96)
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.
2020-03-22 13:27:13 -05:00
Nate Cook 9e77589d85 Don't repeat single-dash arguments with unconditionalRemaining arrays (#95)
This fixes #88.
2020-03-20 13:23:49 -05:00
Nate Cook 4ac7d890e5 Fix tests so that they build with Linux test discovery 2020-03-17 11:15:26 -05:00
Nate Cook ebb9a45751 Fix ParsableArguments sharing between cmds & subcommands (#78)
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.
2020-03-12 11:33:25 -05:00
griffin-stewieandNate Cook 747d6e5748 Add support for default Argument value (#75)
* Add support for default Argument value

* Add test code

* Fix documentation

Now `argument` have default parameter as well.

* Add missing comma

Co-Authored-By: Nate Cook <natecook@apple.com>

* Add missing colon

Co-Authored-By: Nate Cook <natecook@apple.com>

* Add UsageGenerationTests

Co-authored-by: Nate Cook <natecook@apple.com>
2020-03-12 00:28:33 -05:00
Guillaume Lessard bbe4ec142b accept repeated values from mutually-exclusive flag sets (#71)
- this is equivalent to saying the same thing twice, as opposed
  to contradicting oneself.
2020-03-10 22:34:00 -05:00
Elliott Williams 34300696f5 Prefix test target names with "ArgumentParser" (#74)
* Prefix testing and test helper targets with ArgumentParser

* Replace SAP with ArgumentParser in imports and CMakeLists
2020-03-10 12:44:07 -05:00