Processってなに?
ちょっと前までNSTaskと呼ばれていた、主にコマンドラインツールを実行してデータのやり取りを行うためのクラスです。
SwiftでできることはSwiftでやってしまってもいいのですが、swiftcを呼びたいとかそういう時に使います。
の3回目。
振り返り
前回出力を表す型を追加して下のようになりました。
swift;Output.swift
struct Output {
private let fileHandle: FileHandle
init(fileHandle: FileHandle) {
self.fileHandle = fileHandle
}
var data: Data {
return fileHandle.readDataToEndOfFile()
}
var string: String? {
return String(data: data, encoding: .utf8)
}
var lines: [String] {
return string?.components(separatedBy: "\n") ?? []
}
}
Operations.swift
precedencegroup ArgumentPrecedence {
associativity: left
higherThan: AdditionPrecedence
}
func <<< (lhs: Process, rhs: String) -> Process {
lhs.executableURL = URL(fileURLWithPath: rhs)
return lhs
}
func <<< (lhs: Process, rhs: [String]) -> Process {
lhs.arguments = rhs
return lhs
}
let echo = Process() <<< "/bin/echo" <<< ["Hello, World."]
let pipe = Pipe()
echo.standardOutput = pipe
echo.launch()
let output = Output(pipe.fileHandleForReading)
if let string = output.string {
print(string)
}
まだ長いわ――!!!!
Pipe
とかいう途中経過にしか使わない何かがあるし、launch()
を使う位置を気をつけなくてはならないし、面倒です。
もっと出力の取得を簡単に
出力を得るカスタムオペレーションを追加します。
precedencegroup RedirectPrecedence {
associativity: left
lowerThan: LogicalDisjunctionPrecedence
}
infix operator >>> : RedirectPrecedence
func >>> <T>(lhs: Process, rhs: (Output) -> T) -> T {
let pipe = Pipe()
lhs.standardOutput = pipe
lhs.launch()
return rhs(Output(fileHandle: pipe.fileHandleForReading))
}
Process
と関数を結合して関数で値を得ます。
launch()
をこのオペレータで行いますのでlaunch()
の位置を気にする必要がなくなりました。
使用法
Process() <<< "/bin/echo" <<< ["Hello, World."] >>> { output in
output.string.map { print($0) }
}
あるいは
let outputString = Process() <<< "/bin/echo" <<< ["Hello, World."] >>> { $0.string }
outputString.map { print($0) }
短い! わかりやすい!