在 Swift 中收听标准输入
Listening to stdin in Swift
目前我正尝试在我的 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 中找不到与此等效的内容。我想也许与“Inputstream”有关,但也没有找到合适的解决方案。
如果有人能给我一些关于如何在 Swift 中做这样的事情的提示,我将不胜感激。
你可能想要 FileHandle.standardInput
.
类似于:
let file = FileHandle.standardInput
while true {
let data = file.availableData
print("\(String(bytes: data, encoding: .utf8))")
}
将按照我认为您想要的方式回显输入。关于小心输入的标准免责声明,这可能是危险的 activity,清理您的输入等等。
我不确定您将如何匹配特定的控制键和箭头键,但这是一个开始。
通常标准输入会缓冲所有内容,直到输入换行符,这就是为什么典型的标准输入按行读取的原因:
while let line = readLine() {
print(line)
}
(按CTRL+D发送EOF,即结束输入)
要真正单独读取每个字符,您需要进入原始模式,这意味着使用低级终端功能:
// see
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
目前我正尝试在我的 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 中找不到与此等效的内容。我想也许与“Inputstream”有关,但也没有找到合适的解决方案。
如果有人能给我一些关于如何在 Swift 中做这样的事情的提示,我将不胜感激。
你可能想要 FileHandle.standardInput
.
类似于:
let file = FileHandle.standardInput
while true {
let data = file.availableData
print("\(String(bytes: data, encoding: .utf8))")
}
将按照我认为您想要的方式回显输入。关于小心输入的标准免责声明,这可能是危险的 activity,清理您的输入等等。
我不确定您将如何匹配特定的控制键和箭头键,但这是一个开始。
通常标准输入会缓冲所有内容,直到输入换行符,这就是为什么典型的标准输入按行读取的原因:
while let line = readLine() {
print(line)
}
(按CTRL+D发送EOF,即结束输入)
要真正单独读取每个字符,您需要进入原始模式,这意味着使用低级终端功能:
// see
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