Skip to content

Commit abe6d4f

Browse files
committed
Add async command example
1 parent cacc0b6 commit abe6d4f

File tree

7 files changed

+145
-4
lines changed

7 files changed

+145
-4
lines changed

Examples/count-lines/CountLines.swift

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
//===----------------------------------------------------------*- swift -*-===//
2+
//
3+
// This source file is part of the Swift Argument Parser open source project
4+
//
5+
// Copyright (c) 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
//
10+
//===----------------------------------------------------------------------===//
11+
12+
import ArgumentParser
13+
import Foundation
14+
15+
struct CountLines: AsyncParsableCommand {
16+
@Argument(
17+
help: "A file to count lines in. If omitted, counts the lines of stdin.",
18+
completion: .file(), transform: URL.init(fileURLWithPath:))
19+
var inputFile: URL?
20+
21+
@Option(help: "Only count lines with this prefix.")
22+
var prefix: String?
23+
24+
@Flag(help: "Include extra information in the output.")
25+
var verbose = false
26+
}
27+
28+
extension CountLines {
29+
var fileHandle: FileHandle {
30+
get throws {
31+
guard let inputFile = inputFile else {
32+
return .standardInput
33+
}
34+
return try FileHandle(forReadingFrom: inputFile)
35+
}
36+
}
37+
38+
func printCount(_ count: Int) {
39+
guard verbose else {
40+
print(count)
41+
return
42+
}
43+
44+
if let filename = inputFile?.lastPathComponent {
45+
print("Lines in '\(filename)'", terminator: "")
46+
} else {
47+
print("Lines from stdin", terminator: "")
48+
}
49+
50+
if let prefix = prefix {
51+
print(", prefixed by '\(prefix)'", terminator: "")
52+
}
53+
54+
print(": \(count)")
55+
}
56+
57+
mutating func run() async throws {
58+
let countAllLines = prefix == nil
59+
60+
let lineCount = try await fileHandle.bytes.lines.reduce(0) { count, line in
61+
if countAllLines || line.starts(with: prefix!) {
62+
return count + 1
63+
} else {
64+
return count
65+
}
66+
}
67+
68+
printCount(lineCount)
69+
}
70+
}
71+
72+
#if swift(>=5.6)
73+
@main extension CountLines {}
74+
#else
75+
@main struct AsyncMain: AsyncMainProtocol {
76+
typealias Command = CountLines
77+
}
78+
#endif

Package.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ let package = Package(
4747
name: "repeat",
4848
dependencies: ["ArgumentParser"],
4949
path: "Examples/repeat"),
50+
.executableTarget(
51+
name: "count-lines",
52+
dependencies: ["ArgumentParser"],
53+
path: "Examples/count-lines"),
5054

5155
.executableTarget(
5256
name: "changelog-authors",
@@ -67,6 +71,7 @@ let package = Package(
6771
exclude: ["CMakeLists.txt"]),
6872
.testTarget(
6973
name: "ArgumentParserExampleTests",
70-
dependencies: ["ArgumentParserTestHelpers"]),
74+
dependencies: ["ArgumentParserTestHelpers"],
75+
resources: [.copy("CountLinesTest.txt")]),
7176
]
7277
)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//===----------------------------------------------------------*- swift -*-===//
2+
//
3+
// This source file is part of the Swift Argument Parser open source project
4+
//
5+
// Copyright (c) 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
//
10+
//===----------------------------------------------------------------------===//
11+
12+
#if os(macOS)
13+
14+
import XCTest
15+
import ArgumentParserTestHelpers
16+
17+
final class CountLinesExampleTests: XCTestCase {
18+
func testCountLines() throws {
19+
let testFile = try XCTUnwrap(Bundle.module.url(forResource: "CountLinesTest", withExtension: "txt"))
20+
try AssertExecuteCommand(command: "count-lines \(testFile.path)", expected: "20")
21+
try AssertExecuteCommand(command: "count-lines \(testFile.path) --prefix al", expected: "4")
22+
}
23+
24+
func testCountLinesHelp() throws {
25+
let helpText = """
26+
USAGE: count-lines <input-file> [--prefix <prefix>] [--verbose]
27+
28+
ARGUMENTS:
29+
<input-file> A file to count lines in. If omitted, counts the
30+
lines of stdin.
31+
32+
OPTIONS:
33+
--prefix <prefix> Only count lines with this prefix.
34+
--verbose Include extra information in the output.
35+
-h, --help Show help information.
36+
"""
37+
try AssertExecuteCommand(command: "count-lines -h", expected: helpText)
38+
}
39+
}
40+
41+
#endif
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
absinthe
2+
actuary
3+
adenoid
4+
affidavit
5+
affluent
6+
agnostic
7+
agoraphobia
8+
albatross
9+
algebra
10+
alkaline
11+
allocution
12+
ampule
13+
antimony
14+
argument
15+
artesian
16+
askance
17+
asterisk
18+
astonishment
19+
asynchronous
20+
axiomatic

Tests/ArgumentParserExampleTests/RepeatExampleTests.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
//===----------------------------------------------------------------------===//
1111

1212
import XCTest
13-
import ArgumentParser
1413
import ArgumentParserTestHelpers
1514

1615
final class RepeatExampleTests: XCTestCase {

Tests/ArgumentParserExampleTests/RollDiceExampleTests.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
//===----------------------------------------------------------------------===//
1111

1212
import XCTest
13-
import ArgumentParser
1413
import ArgumentParserTestHelpers
1514

1615
final class RollDiceExampleTests: XCTestCase {

Tests/ArgumentParserUnitTests/HelpGenerationTests.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,6 @@ extension HelpGenerationTests {
595595
}
596596

597597
func testIssue278() {
598-
print(ParserBug.helpMessage(for: ParserBug.Sub.self))
599598
AssertHelp(for: ParserBug.Sub.self, root: ParserBug.self, equals: """
600599
USAGE: parserBug sub [--example] [<argument>]
601600

0 commit comments

Comments
 (0)