目前我正在尝试在swift应用程序中从命令行监听用户输入。
我知道readLine()
方法但它并不真正符合我的需要。我想监听在命令行中插入的数据。就像用户按下终端内的“向上键”一样。
可以在Node.js中完成的任务:
stdin.on( 'data', function( key ){
if (key === '\u0003' ) {
process.exit();
} // write the key to stdout all normal like
process.stdout.write( key );
});
我试过搜索但是在Swift中找不到相同的东西。我想也许是“输入流”的东西,但也找不到合适的解决方案。
如果有人能给我一些关于如何在Swift中做这样的事情的提示,我会非常感激。
答案 0 :(得分:2)
您可能想要FileHandle.standardInput
。
类似的东西:
let file = FileHandle.standardInput
while true {
let data = file.availableData
print("\(String(bytes: data, encoding: .utf8))")
}
将按照我想要的方式回应输入。标准免责声明关于小心输入,这可能是一个危险的活动,消毒你的输入等等。
我不确定您是如何选择匹配特定控件和箭头键的,但这是一个开始。
答案 1 :(得分:2)
通常标准输入会缓冲所有内容,直到输入换行符,这就是为什么行读取典型标准输入的原因:
while let line = readLine() {
print(line)
}
(按CTRL + D发送EOF,即结束输入)
要真正分别读取每个字符,您需要进入原始模式,这意味着使用低级终端功能:
// 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)
参考https://viewsourcecode.org/snaptoken/kilo/02.enteringRawMode.html