rust 为用户输入设置光标位置

rust set cursor position for user input

我是一个新手 rust 程序员,我正在编写一个打印 table 的程序,并使用循环从用户那里获取数值,每次用户输入该值时, table 得到更新并再次打印,直到收到所有值。

            class1      class2      class3      class4      class5
Sensor      0           0           0           0           0
visual      0           0           0           0           0

我想将光标放在用户要为其输入值的所需单元格(如果可能的话闪烁)。这意味着在第一次迭代时,光标应位于单元格 sensor-class1,第二次迭代应位于 sensor-class2,依此类推。

我搜索了一会儿,似乎 termion 是解决方案,但是 print!("{}", termion::cursor::Goto((10 * i).try_into().unwrap(), j)); 在每次迭代中移动打印的 table 而不是用户输入光标:

extern crate termion;
use std::io;

fn main() {
    let mut sensor_data = [0; 5];
    let mut visual_data = [0; 5];

    for j in 1..3 {
        for i in 1..6 {
            print!("{}", termion::clear::All);
            print!("{}", termion::cursor::Goto(1, 1));

            println!(
                "{0: <10}  {1: <10}  {2: <10}  {3: <10}  {4: <10}  {5: <10}",
                "", "class1", "class2", "class3", "class4", "class5"
            );
            println!(
                "{0: <10}  {1: <10}  {2: <10}  {3: <10}  {4: <10}  {5: <10}",
                "Sensor",
                sensor_data[0],
                sensor_data[1],
                sensor_data[2],
                sensor_data[3],
                sensor_data[4]
            );
            println!(
                "{0: <10}  {1: <10}  {2: <10}  {3: <10}  {4: <10}  {5: <10}",
                "visual",
                visual_data[0],
                visual_data[1],
                visual_data[2],
                visual_data[3],
                visual_data[4]
            );

            //update the cursor position for user input

            let mut input = String::new();
            io::stdin()
                .read_line(&mut input)
                .expect("Failed to read line");
            if j == 1 {sensor_data[i - 1] = input.trim().parse().expect("Please type a number!");}
            else {visual_data[i - 1] = input.trim().parse().expect("Please type a number!");}
        }
    }
// print the complete table and go on
}


我认为主要是您缺少 stdout().flush()

print!(),与println!()相反,写换行符。在大多数系统上,换行符会导致刷新,但由于没有换行符,Goto 会卡在写入缓冲区中。

一个简单的解决方法是手动 flush(),如下面的代码示例所示。

不过,更正确的方法是以 raw 模式访问终端,首先禁用缓冲区。

use std::io::{self, Write};

fn main() {
    let mut sensor_data = [0; 5];
    let mut visual_data = [0; 5];

    for j in 1..3 {
        for i in 1..6 {
            print!("{}", termion::clear::All);
            print!("{}", termion::cursor::Goto(1, 1));

            println!(
                "{0: <10}  {1: <10}  {2: <10}  {3: <10}  {4: <10}  {5: <10}",
                "", "class1", "class2", "class3", "class4", "class5"
            );
            println!(
                "{0: <10}  {1: <10}  {2: <10}  {3: <10}  {4: <10}  {5: <10}",
                "Sensor",
                sensor_data[0],
                sensor_data[1],
                sensor_data[2],
                sensor_data[3],
                sensor_data[4]
            );
            println!(
                "{0: <10}  {1: <10}  {2: <10}  {3: <10}  {4: <10}  {5: <10}",
                "visual",
                visual_data[0],
                visual_data[1],
                visual_data[2],
                visual_data[3],
                visual_data[4]
            );

            //update the cursor position for user input
            print!("{}", termion::cursor::Goto(12 * i + 1, j + 1));
            io::stdout().flush().unwrap();

            let mut input = String::new();
            io::stdin()
                .read_line(&mut input)
                .expect("Failed to read line");
            if j == 1 {
                sensor_data[i as usize - 1] = input.trim().parse().expect("Please type a number!");
            } else {
                visual_data[i as usize - 1] = input.trim().parse().expect("Please type a number!");
            }
        }
    }
    // print the complete table and go on
}

我添加的其他小修复:

  • 删除 extern crate,因为不再需要或建议使用它
  • i 的类型更改为 u16 并转换为 usize 而不是相反,以避免 unwrap()