Skip to content

Commit

Permalink
Document changing file name when adding @main (apple#514)
Browse files Browse the repository at this point in the history
  • Loading branch information
natecook1000 authored Nov 1, 2022
1 parent 9033408 commit 4256f88
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ extension Math.Statistics {

Last but not least, we add the `@main` attribute to the root of our command tree, to tell the compiler to use that as the program's entry point. Upon execution, this parses the command-line arguments, determines whether a subcommand was selected, and then instantiates and calls the `run()` method on that particular subcommand.

> Note: The Swift compiler uses either the type marked with `@main` or a `main.swift` file as the entry point for an executable program. You can use either one, but not both — rename your `main.swift` file to the name of your command when you add `@main`. In this case, rename it to `Math.swift`.
```swift
@main
struct Math: ParsableCommand {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,11 @@ struct Count: ParsableCommand {

In the code above, the `inputFile` and `outputFile` properties use the `@Argument` property wrapper. `ArgumentParser` uses this wrapper to denote a positional command-line input — because `inputFile` is specified first in the `Count` type, it's the first value read from the command line, and `outputFile` is the second.

We've implemented the command's logic in its `run()` method. Here, we're printing out a message confirming the names of the files the user gave. (You can find a full implementation of the completed command at the end of this guide.)
The command's logic is implemented in its `run()` method. Here, it prints out a message confirming the names of the files the user gave. (You can find a full implementation of the completed command at the end of this guide.)

Finally, you designate the `Count` command as the program's entry point by applying the `@main` attribute. When running your command, the `ArgumentParser` library parses the command-line arguments, verifies that they match up with what we've defined in `Count`, and either calls the `run()` method or exits with a helpful message.
Finally, the `Count` command is designated as the program's entry point by applying the `@main` attribute. When running your command, the `ArgumentParser` library parses the command-line arguments, verifies that they match up with what we've defined in `Count`, and either calls the `run()` method or exits with a helpful message.

> Note: The Swift compiler uses either the type marked with `@main` or a `main.swift` file as the entry point for an executable program. You can use either one, but not both — rename your `main.swift` file to the name of the command when you add `@main`. In this case, rename the file to `Count.swift`.
## Working with Named Options

Expand All @@ -80,6 +81,7 @@ Counting words in 'readme.md' and writing the result into 'readme.counts'.
We do this by using the `@Option` property wrapper instead of `@Argument`:

```swift
@main
struct Count: ParsableCommand {
@Option var inputFile: String
@Option var outputFile: String
Expand Down Expand Up @@ -118,6 +120,7 @@ Counting words in 'readme.md' and writing the result into 'readme.counts'.
Let's change our `Count` type to look like this:

```swift
@main
struct Count: ParsableCommand {
@Option var inputFile: String
@Option var outputFile: String
Expand Down Expand Up @@ -155,6 +158,7 @@ Counting words in 'readme.md' and writing the result into 'readme.counts'.
Customize the input names by passing `name` parameters to the `@Option` and `@Flag` initializers:

```swift
@main
struct Count: ParsableCommand {
@Option(name: [.short, .customLong("input")])
var inputFile: String
Expand Down Expand Up @@ -189,6 +193,7 @@ OPTIONS:
This is a great start — you can see that all the custom names are visible, and the help shows that values are expected for the `--input` and `--output` options. However, our custom options and flag don't have any descriptive text. Let's add that now by passing string literals as the `help` parameter:

```swift
@main
struct Count: ParsableCommand {
@Option(name: [.short, .customLong("input")], help: "A file to read.")
var inputFile: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,30 @@

To use `async`/`await` code in your commands' `run()` method implementations, follow these steps:

1. For the root command in your command-line tool, declare conformance to `AsyncParsableCommand`, even if that command doesn't use asynchronous code.
1. For the root command in your command-line tool, declare conformance to `AsyncParsableCommand`, whether or not that command uses asynchronous code.
2. Apply the `@main` attribute to the root command. (Note: If your root command is in a `main.swift` file, rename the file to the name of the command.)
3. For any command that needs to use asynchronous code, declare conformance to `AsyncParsableCommand` and mark the `run()` method as `async`. No changes are needed for commands that don't use asynchronous code.
3. For any command that needs to use asynchronous code, declare conformance to `AsyncParsableCommand` and mark the `run()` method as `async`. No changes are needed for subcommands that don't use asynchronous code.

The following example declares a `CountLines` command that uses Foundation's asynchronous `FileHandle.AsyncBytes` to read the lines from a file:

```swift
import Foundation

@main
struct CountLines: AsyncParsableCommand {
@Argument(transform: URL.init(fileURLWithPath:))
var inputFile: URL

mutating func run() async throws {
let fileHandle = try FileHandle(forReadingFrom: inputFile)
let lineCount = try await fileHandle.bytes.lines.reduce(into: 0)
{ count, _ in count += 1 }
print(lineCount)
}
}
```

> Note: The Swift compiler uses either the type marked with `@main` or a `main.swift` file as the entry point for an executable program. You can use either one, but not both — rename your `main.swift` file to the name of the command when you add `@main`.
### Usage in Swift 5.5

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ struct Repeat: ParsableCommand {
}
```

> Note: The Swift compiler uses either the type marked with `@main` or a `main.swift` file as the entry point for an executable program. You can use either one, but not both — rename your `main.swift` file to the name of the command when you add `@main`.
## Topics

### Essentials
Expand Down

0 comments on commit 4256f88

Please sign in to comment.