如何使用 Rust 中的 Termion 获取键盘输入?

问题描述

我正在试用 Rust,到目前为止我真的很喜欢它。我正在开发一种需要从用户那里获取箭头键输入的工具。到目前为止,我已经做了一些工作:如果我按住一个键一段时间,相关的函数就会被调用。然而,这远非一蹴而就。

到目前为止我得到了什么:

let mut stdout = io::stdout().into_raw_mode();
let mut stdin = termion::async_stdin();
// let mut stdin = io::stdin();
let mut it = stdin.keys(); //iterator object

loop {
    //copied straight from GitLab: https://gitlab.redox-os.org/redox-os/termion/-/issues/168
    let b = it.next(); 
    match b {
        Some(x) => match x {
            Ok(k) => {
                match k {
                    Key::Left => move_cursor(&mut cursor_char,-1,&enc_chars,&mpt,&status),Key::Right => move_cursor(&mut cursor_char,1,Key::Ctrl('c') => break,_ => {}
                }
            },_ => {}
        },None => {}
    }
    //this loop might do nothing if no recognized key was pressed.
}

我自己也不太明白。我正在使用终端原始模式,如果这与它有关的话。我看过 the rustyline crate,但这真的不好,因为它更像是一个交互式 shell,我只想检测按键。

解决方法

如果您使用原始输入模式并逐键读取,则需要使用您已有的相同类型的匹配循环手动缓冲字符键。 Key::Char(ch) 枚举变体可用于匹配常规字符。然后,您可以使用可变 String 或类似 [u8; MAX_SIZE] 的数组来存储字符数据并在键入时附加字符。如果用户移动光标,您需要跟踪输入缓冲区中的当前位置,并确保将新输入的字符插入正确的位置,如果需要移动现有字符。这是很多工作,这就是为什么有板条箱可以为你做这件事,但你将没有机会控制输入的行为方式。如果您想使用现有的 crate,那么 tui-rs 可能是查看完整解决方案的好方法,或者 linefeed 更简单的方法。

至于延迟,我认为可能是因为您使用的是 AsyncReader,根据文档,它使用辅助线程进行阻塞读取