[macOS/iOS] FileHandleをrawモードで読み出す方法
元記事は、StackOverflowの、Listening to stdin in Swiftです。特に、サンプルコードは丸写しです。
環境
- 作成日: 2019/11/03
- macOS 10.15
- Xcode 11.0
- Swift 5
課題
標準入力のFileHandleオブジェクトを、availableDataメソッドで呼び出した場合、改行キーが押されるまで、結果を返さない。キー入力ごとに値を取り出したい。
解決方法
標準入力のFileHandleを、rawモードで動作させる。下記のサンプルコードは、StackOverflowのListening to stdin in Swiftの丸写しです:
// see https://stackoverflow.com/a/24335355/669586
func initStruct<S>() -> S {
let struct_pointer = UnsafeMutablePointer<S>.allocate(capacity: 1)
let struct_memory = struct_pointer.pointee
struct_pointer.deallocate()
return struct_memory
}
func enableRawMode(fileHandle: FileHandle) -> termios {
var raw: termios = initStruct()
tcgetattr(fileHandle.fileDescriptor, &raw)
let original = raw
raw.c_lflag &= ~(UInt(ECHO | ICANON))
tcsetattr(fileHandle.fileDescriptor, TCSAFLUSH, &raw);
return original
}
func restoreRawMode(fileHandle: FileHandle, originalTerm: termios) {
var term = originalTerm
tcsetattr(fileHandle.fileDescriptor, TCSAFLUSH, &term);
}
let stdIn = FileHandle.standardInput
let originalTerm = enableRawMode(fileHandle: stdIn)
var char: UInt8 = 0
while read(stdIn.fileDescriptor, &char, 1) == 1 {
if char == 0x04 { // detect EOF (Ctrl+D)
break
}
print(char)
}
// It would be also nice to disable raw input when exiting the app.
restoreRawMode(fileHandle: stdIn, originalTerm: originalTerm)