在 Swift 中收听标准输入 [英] Listening to stdin in Swift

查看:61
本文介绍了在 Swift 中收听标准输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前我正在尝试从我的 swift 应用程序中的命令行收听用户输入.

Currently I am trying to listen to user input from the command line in my swift application.

我知道 readLine() 方法,但它并不真正适合我的需要.我想监听在命令行上插入的数据.就像用户在终端内按下向上键"一样.

I am aware of the readLine() method but it does not really fit my needs. I want to listen for data being inserted on the command line. Like when a user is pressing the ‘up key’ inside the terminal.

类似于在 Node.js 中可以完成的事情:

Something like what can be done in 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"有关,但也没有找到合适的解决方案.

I tried searching but I couldn’t find an equivalent to this in Swift. I thought maybe something with ‘Inputstream’ but didn’t a find a appropriate solution either.

如果有人能给我一些关于如何在 Swift 中做这样的事情的提示,我将不胜感激.

If someone could give me some hints on how to do something like this in Swift I would highly appreciate it.

推荐答案

通常标准输入会缓冲所有内容,直到输入换行符,这就是为什么典型的标准输入是按行读取的:

Normally standard input buffers everything until a newline is entered, that's why a typical standard input is read by lines:

while let line = readLine() {
   print(line)
}

(按CTRL+D发送EOF,即结束输入)

(press CTRL+D to send EOF, that is end the input)

要真正分别读取每个字符,您需要进入原始模式,这意味着使用低级终端功能:

To really read every character separately, you need to enter raw mode and that means use the low level terminal functions:

// 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

这篇关于在 Swift 中收听标准输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆