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()
我是一个新手 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()