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
- Changes uses of import Foundation in ArgumentParser to only expose the
symbols needed to avoid growing unintentional dependencies.
- Replaces direct usage of EXIT_FAILURE in MessageInfo with ExitCode,
exposed as a result of the above change.
- 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.
- Changes ArgumentVisibility from an enum to a struct. This will allow
ArgumentParser to add cases in the future without breaking clients
that could have been exhaustively switching across all cases. It also
allows us to implement protocol conformances on the internal type and
avoid exposing them on the public type.
- Replaces `ArgumentSet.init(_:creatingHelp:includeHidden:)` with
`ArgumentSet.init(_:visibility:)`. `visibility` intentionally does not
have a default value to ensure that callers only have the correct
arguments. As part of this change `includeHidden` has been replaced
throughout the codebase with `visibility`. This change also fixes a
bug where arguments with hidden `visibility` were being displayed in the
generated command usage string.
- Renames ArgumentHelp.Visibility to ArgumentVisibility.
- Replaces ArgumentDefinition.shouldDisplay with a visibility property
whose value is derived from ArgumentHelp.visibility.
Swift Package Manager adopted _hiddenFromHelp, the resulting help is
much more approachable for basic usage, but leaves no way to view
all the advanced options it accepts. This takes from swiftc's + clang's
playbook and adds a hidden `--help-hidden` flag that prints all help,
including those using `_hiddenFromHelp`
When an option value fails to parse, no custom error message is
provided, and a list of valid candidate values is available, include the
list as part of the error message.
Addresses #344.
- 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.
ArgumentParser is configured not to emit detailed synopsis when it would contain more than a dozen entries. This makes sense; however, eliding all information makes the synopsis rather useless.
While commands may have dozens of options, in most cases, only a few of them are required — so we can keep the synopsis short but still useful by only displaying the required parts.
* Include all positional arguments in shortened synopsis
* 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.
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.
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 the first long name in usage (#167)
Sorting names for option has been changed.
* Usage will choose the first long name, if available, or otherwise the first short name
* Help screen will show short names, then long names, in the order of their declaration.
Solves (#167)
* Fix adding same name more than once.
Checkin long names in sort caused single dash long names to be treated as a short name.
Fixed sort to check “short” instead of “long”
Update current test to cover more cases.
* Add isShort control to Name
*Replace sortedNames with partitionedNames
*Extract uniquifying logic into SequenceExtensions.swift
* Refactor short test with computed property
* Use pattern-matching instead of equality comparison
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 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.
* Add String#editDistance(to:)
Uses levenshtein distance to determine how much two strings differ.
See: https://en.wikipedia.org/wiki/Levenshtein_distance
* Simplify unknownOptionMessage
The logic of Name#synopsisString was repeated in unknownOptionMessage.
This change sit so that unknownOptionMessage defer to Name's
implementation instead.
* Provide suggestions for unknown options
* Corrected grammatical and spelling errors in files in Documentation.
* Correct various spelling, grammar, and formatting mistakes in code documentation.