CountLines.swift 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. //===----------------------------------------------------------------------===//
  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. import ArgumentParser
  12. import Foundation
  13. @main
  14. @available(macOS 12, iOS 15, visionOS 1, tvOS 15, watchOS 8, *)
  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? = nil
  20. @Option(help: "Only count lines with this prefix.")
  21. var prefix: String? = nil
  22. @Flag(help: "Include extra information in the output.")
  23. var verbose = false
  24. var fileHandle: FileHandle {
  25. get throws {
  26. guard let inputFile else {
  27. return .standardInput
  28. }
  29. return try FileHandle(forReadingFrom: inputFile)
  30. }
  31. }
  32. func printCount(_ count: Int) {
  33. guard verbose else {
  34. print(count)
  35. return
  36. }
  37. if let filename = inputFile?.lastPathComponent {
  38. print("Lines in '\(filename)'", terminator: "")
  39. } else {
  40. print("Lines from stdin", terminator: "")
  41. }
  42. if let prefix {
  43. print(", prefixed by '\(prefix)'", terminator: "")
  44. }
  45. print(": \(count)")
  46. }
  47. mutating func run() async throws {
  48. var lineCount = 0
  49. for try await line in try fileHandle.bytes.lines {
  50. if let prefix {
  51. lineCount += line.starts(with: prefix) ? 1 : 0
  52. } else {
  53. lineCount += 1
  54. }
  55. }
  56. printCount(lineCount)
  57. }
  58. }