Commit Graph
41 Commits
Author SHA1 Message Date
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
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
Rauhul Varma 607021b737 Unify @Argument and @Option initialization paths (#477)
- 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.
2022-09-10 18:40:31 -05:00
Kth dd6efd05cb Fix error message for @Option array without values (#435) 2022-04-03 23:58:31 -05:00
Nate Cook c959b3a5d2 Hide optional flags when a command has too many options (#416)
The usage string feature that only shows positional args and required
options/flags was incorrectly allowing through flags with type
`Bool?`.
2022-03-07 18:40:34 -06:00
Nate Cook 4de228195c Show hidden args/opts/flags with --help-hidden (#412)
- 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.
2022-02-15 14:57:43 -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
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
Rauhul Varma d4d1879c9d Propogate ExpressibleByArgument conformance (#341)
- 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.
2021-07-29 13:23:50 -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
Rauhul Varma f4353dbe3a Simplify synopsis string generation (#316)
- 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.
2021-05-22 10:59:37 -05:00
Rauhul Varma 860afdad31 Clean up internal property nesting (#315)
- 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.
2021-05-20 19:03:19 -05:00
Nate Cook 992a7451d5 Convert all public enums to structs (#299) 2021-05-15 10:30:48 -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
Nate Cook 267f707294 Use custom help flags in completion scripts (#308)
* Standardize the help and version flag generation
* Simplify some help generation code
* Support custom help flags in completion scripts
2021-05-14 10:27:05 -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
Mike Wermuth 080372b7cd Hide flag inversion when help is hidden (#289)
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.
2021-03-12 01:07:12 -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
Nate Cook 344537137b Flatten the ArgumentSet storage into a single array (#235)
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.
2020-09-01 21:07:35 -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
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
Nate Cook 1fa25574f8 Show option-based errors before unexpected positional errors (#187)
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.
2020-06-15 14:32:36 -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 8883f06b4e Don't consume the terminator during parsing. (#168)
Fixes #130.
2020-05-28 01:13:15 -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
Yu Ao 023730bdda Add PositionalArgumentsValidator (#101)
* Add `PositionalArgumentsValidator`

* Update tests for PositionalArgumentsValidator

* Use argument property names in PositionalArgumentsValidator.Error
2020-03-29 14:57:50 -05:00
Nate Cook d875544e96 Remove usage of 5.2-only syntax.
Fixes #97.
2020-03-23 13:38:29 -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
Šimon Javora 28b51d4945 Don't show Optional(x) when displaying default values in help. (#48) 2020-03-12 11:37:02 -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
Nate Cook 1e05511552 Add a catch-all argument parsing strategy (#29)
* 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
2020-03-09 17:12:42 -05:00
Guillaume Lessard 7f5984a29b make FlagExclusivity.chooseFirst work (#67) 2020-03-06 16:33:53 -06:00
Guillaume Lessard 3af071f566 add control of exclusivity for Bool Flags when inversion is enabled (#62) 2020-03-06 12:37:47 -06:00
Wildchild9 6f58e68a6a Fixed Various Grammar & Spelling Mistakes (#17)
* Corrected grammatical and spelling errors in files in Documentation.

* Correct various spelling, grammar, and formatting mistakes in code documentation.
2020-03-02 10:54:10 -06:00
Alexander Cyon d131c47155 Fixing 12 typos across 6 files. (#13) 2020-02-28 13:33:57 -06:00
Nate Cook f6ac7b8118 Initial import of ArgumentParser 2020-02-27 15:45:22 -06:00