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
When an executable with asynchronous commands is backdeployed,
the compiler chooses the synchronous `main()` unless a minimum
availability target is provided for the root command type. This
changes the error message provided when the incorrect `main()`
function is called to direct the tool's author to a correct
solution.
A generated fish script didn't complete an option after an argument.
The cause is the generated fish script doesn't accept an input text which already has arguments.
For example, when the input is `repeat -`, the script can complete `--count`, but when the text is `repeat foo -`, the script cannot complete `repeat foo --count`, because the input text already has the argument "foo".
To fix the issue, `FishCompletionsGenerator` got a capability that can accept a text which has arguments.
- 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.
- 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.
- Updates README.md and GettingStarted.md to reference
swift-argument-parser from: 1.2.0. Additionally, adds a minimum
supported swift version table to README.md to guide users on older
toolchains.
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
* Use existential CodingKey parameters consistently
Swift 5.7 supports implicit opening for existentials, so these
conversions from `CodingKey` parameters to pass to methods that
are generic over `CodingKey` work fine. Prior to Swift 5.7, however,
these don't compile, with the message that `CodingKey` doesn't conform
to itself.
* Bump the required Swift version for the count-lines test
The overload resolution for the `static func main()` in an `@main`
type still had issues in Swift 5.6, such that a package with a min.
platform below that which works for concurrency backdeployment doesn't
properly resolve the AsyncParsableCommand `main()` function. In
Swift 5.7, this is properly resolved, so just the availability on
the main type is sufficient.
This change just skips the test of `count-lines` prior to Swift 5.7,
so that we can maintain the open platform minimum for the package
as a whole.
There are references to functions from the Windows SDK rather than the C
library for the console handling. Explicitly import the necessary types
and functions from the WinSDK module so that Windows can build once more
with the changes to sequester the platform specific code.
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.
This change lets you provide a title for option groups, which is used
when generating the help screen. Titled option groups, when they exist,
are placed between the ARGUMENTS and OPTIONS section of the help.
Multiple option groups with the same title are coalesced into a single
group.
For example, this command declaration:
struct Extras: ParsableArguments {
@Flag(help: "Print extra output while processing.")
var verbose: Bool = false
@Flag(help: "Include details no one asked for.")
var oversharing: Bool = false
}
@main
struct Example: ParsableCommand {
@OptionGroup(title: "Extras")
var extras: Extras
@Argument var name: String?
@Option var title: String?
}
yields this help screen:
USAGE: example [--verbose] [--oversharing] [<name>] [--title <title>]
ARGUMENTS:
<name>
EXTRAS:
--verbose Print extra output while processing.
--oversharing Include details no one asked for.
OPTIONS:
--title <title>
-h, --help Show help information.
RawRepresentable types that have a non-String raw value are having
values displayed in the help screen by converting the RawRep value
into a string. However, these values are by default parsed by their
raw value, so we should use that for display instead.
This is accomplished by adding a defaultValueDescription
implementation for all ExpressibleByArgument-conforming RawValue
types, and then basing the allValues implementation on that.
This generalizes the existing overloads for String-based RawRep types,
while also allowing users who customize their ExpressibleByArgument
implementation to provide the correct help value for clients.
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.
If a ParsableArguments type doesn't implement init(from:) correctly,
it isn't decodable by the parser. This improves the validation
failure message for such types.
In addition to being useful, this allows us to drop the `@testable`
annotation for the ArgumentParser import in ArgumentParserTestHelpers,
which resolves#463.
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.
defaultValueDescription is always the enum case name, but that's not a
valid argument when the enum value differs from the case name. Extend
ExpressibleByArgument to use rawValue for defaultValueDescription for
string enums.
- Fixes a bug where built-in flags such as --help and --version were not
properly marked with isOptional which resulted in them appearing in
generated content (such as completion scripts and manuals) as required
arguments.
- Changes the generate-manual --single-page argument to --multi-page, so
generate-manual with create a single manual page with all subcommand
information by default instead of many distinct files.
* Fix array parsing as supplemental input
* Add test for `ExpressibleByArgument`
* Add options for `CaseIterable`
* Add test for `@Argument(transform:)`
- Adds a swift package manager command plugin called
GenerateManualPlugin. The plugin can be invoked from the command line
using `swift package experimental-generate-manual`. The plugin is
prefixed for now with "experimental-" to indicate it is not mature and
may see breaking changes to its CLI and output in the future. The
plugin can be can be used to generate a manual in MDoc syntax for any
swift-argument-parser tool that can be executed via
`tool --experimental-dump-info`.
- The plugin works by converting the `ToolInfoV0` structure from the
`ArgumentParserToolInfo` library into MDoc AST nodes using a custom
(SwiftUI-esk) result builder DSL. The MDoc AST is then lowered to a
string and written to disk.
- The MDoc AST included is not general purpose and doesn't represent the
true language exactly, so it is private to the underlying
`generate-manual` tool. In the future it would be interesting to
finish fleshing out this MDoc library and spin it out, however this is
not a priority.
- Next steps include:
- Improving the command line interface for the plugin.
- Adding support for "extended discussions" to Commands and exposing
this information in manuals.
- Further improve the escaping logic to properly escape MDoc macros
that might happen to appear in user's help strings.
- Ingesting external content a-la swift-docc so the entire tool
documentation does not need to be included in the binary itself.
- Bug fixes and addressing developer/user feedback.
Built with love,
@rauhul