我想运行一个在stdin上阻塞的可执行文件,当按下一个键时,Enter不必按下即可立即打印相同的字符.
如何从stdin中读取一个字符而不必点击Enter?我从这个例子开始:
fn main() {
println!("Type something!");
let mut line = String::new();
let input = std::io::stdin().read_line(&mut line).expect("Failed to read line");
println!("{}", input);
}
Run Code Online (Sandbox Code Playgroud)
我通过API看起来并试图替换read_line()用bytes(),但一切我尝试需要我打Enter的读取发生之前.
这个问题被要求用于C/C++,但似乎没有标准的方法:从标准输入中捕获字符而不等待按下输入
考虑到它在C/C++中并不简单,它在Rust中可能不可行.
doj*_*uba 13
虽然@ Jon使用ncurses的解决方案可行,但ncurses会按设计清除屏幕.我想出了这个解决方案,使用termios crate为我的小项目学习Rust.想法是通过访问termios绑定来修改ECHO和ICANON标记tcsetattr.
extern crate termios;
use std::io;
use std::io::Read;
use std::io::Write;
use termios::{Termios, TCSANOW, ECHO, ICANON, tcsetattr};
fn main() {
let stdin = 0; // couldn't get std::os::unix::io::FromRawFd to work
// on /dev/stdin or /dev/tty
let termios = Termios::from_fd(stdin).unwrap();
let mut new_termios = termios.clone(); // make a mutable copy of termios
// that we will modify
new_termios.c_lflag &= !(ICANON | ECHO); // no echo and canonical mode
tcsetattr(stdin, TCSANOW, &mut new_termios).unwrap();
let stdout = io::stdout();
let mut reader = io::stdin();
let mut buffer = [0;1]; // read exactly one byte
print!("Hit a key! ");
stdout.lock().flush().unwrap();
reader.read_exact(&mut buffer).unwrap();
println!("You have hit: {:?}", buffer);
tcsetattr(stdin, TCSANOW, & termios).unwrap(); // reset the stdin to
// original termios data
}
Run Code Online (Sandbox Code Playgroud)
读取单个字节的一个优点是捕获箭头键,ctrl等.不捕获扩展的F键(尽管ncurses可以捕获这些).
此解决方案适用于类UNIX平台.我没有使用Windows的经验,但根据这个论坛,也许SetConsoleMode在Windows中可以实现类似的东西.
小智 12
使用现在可用的"ncurses"库之一,例如这个库.
在Cargo中添加依赖项
[dependencies]
ncurses = "5.86.0"
Run Code Online (Sandbox Code Playgroud)
并包含在main.rs中:
extern crate ncurses;
use ncurses::*; // watch for globs
Run Code Online (Sandbox Code Playgroud)
按照库中的示例初始化ncurses并等待单个字符输入,如下所示:
initscr();
/* Print to the back buffer. */
printw("Hello, world!");
/* Update the screen. */
refresh();
/* Wait for a key press. */
getch();
/* Terminate ncurses. */
endwin();
Run Code Online (Sandbox Code Playgroud)
您也可以使用termion,但您必须启用原始 TTY 模式,这也会改变其行为stdout。请参阅下面的示例(使用 Rust 1.34.0 测试)。请注意,在内部,它还包装了 termios UNIX API。
[dependencies]
termion = "1.5.2"
Run Code Online (Sandbox Code Playgroud)
[dependencies]
termion = "1.5.2"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8461 次 |
| 最近记录: |