I'm trying to write a Swift program that
- Accepts either a single argument or piped data from standard input, and prints it
- Prints a usage message if both are missing.
Assuming the code is contained in main.swift, we have four cases:
swift main.swiftshould output "Please provide some input"swift main.swift argumentshould output "argument"echo | swift main.swiftshould output "Please provide some input"echo argument | swift main.swiftshould output "argument"
In the case of a compound echo argument1 | swift main.swift argument2, argument2 takes precedence.
Satisfying 1-3 is simple:
import Foundation
var input: String? = nil
if CommandLine.arguments.count > 1 {
input = CommandLine.arguments[1]
}
guard let input = input else {
print("Please provide some input")
exit(0)
}
print(input)
However, echo argument | swift main.swift obviously prints the usage message, as there are no arguments. Adding some code,
import Foundation
var input: String? = nil
if CommandLine.arguments.count > 1 {
input = CommandLine.arguments[1]
} else {
while let line = readLine() {
if input == nil {
if line.isEmpty { break }
input = line
} else {
input! += "\n" + line
}
}
}
guard let input = input else {
print("Please provide some input")
exit(0)
}
print(input)
Now cases 2-4 work as expected, but case 1 is problematic. The readLine() causes execution to pause, waiting for input. If you press return without input, the proper message is returned, but I'd like to avoid the necessity to manually enter a blank line.
How can I read enable reading from stdin, while not causing a pause when stdin is blank and there are no arguments?
