Rust与许多编程语言一样,main 方法通常只是提供应用的入口点,仅起到启动作用,而不会做其他事情。我们的目标是将代码放置在逻辑上合理的位置,以便在后续开发过程中更容易找到和维护。这种方法还有很多其他好处,我会在遇到时指出来。
现在,我们的代码有点难以理解。要真正理解它的作用,你必须深入研究它的全部内容。简而言之,它会回显用户按下的每个键,并在按下“q”时退出。让我们简化一下,一举两得:我们将为我们的编辑器引入一个名为Editor 的结构体,它将放在一个单独的文件editor.rs中。这将使代码更容易理解,也更符合语言习惯。
现在我们可以把注意力放在editor.rs上,editor.rs的内容可以是这样的:
use std::io;
use std::io::Read;
use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
pub struct Editor{}
impl Editor {
pub fn default() -> Self {
Editor{}
}
pub fn run(&self) {
enable_raw_mode().unwrap();
for b in io::stdin().bytes() {
match b {
Ok(b) => {
let c = b as char;
if c.is_control() {
println!("Binary: {0:08b} ASCII: {0:#03} \r", b);
} else {
println!("Binary: {0:08b} ASCII: {0:#03} Character: {1:#?}\r", b, c);
}
if c == 'q' {
break;
}
}
Err(err) => println!("Error: {}", err),
}
}
disable_raw_mode().unwrap();
}
}
其实大体的逻辑就是把main.rs中的代码逻辑移动到了editor.rs中,然后我们修改main.rs的内容
use crate::editor::Editor;
mod editor;
fn main() {
let editor = Editor::default();
editor.run();
}
由于main.rs原来的代码逻辑迁移到了editor.rs中,所以现在新的main.rs代码很简洁
让我们通过解决关于错误处理的来总结一下惯用代码。我们的目标是:
本地处理:
如果我们能够在错误发生的地方解决它,我们就会处理它。
向上传递:
对于我们无法直接修复的错误,我们会将其传递到上级链以进行进一步处理。
顶级处理:
如果错误达到最高级别,我们将尽可能优雅地处理它。
作为其中的一部分,我们将错误处理逻辑与主循环分开,并打印出一条简单的再见消息。
use crossterm::event::{read, Event::Key, KeyCode::Char};
use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
pub struct Editor {}
impl Editor {
pub fn default() -> Self {
Editor {}
}
pub fn run(&self) {
if let Err(_err) = self.repl() {
panic!("{_err:#?}");
}
print!("Goodbye.\r\n");
}
fn repl(&self) -> Result<(), std::io::Error> {
enable_raw_mode()?;
loop {
if let Key(event) = read()? {
println!("{event:?} \r");
if let Char(c) = event.code {
if c == 'q' {
break;
}
}
}
}
disable_raw_mode()?;
Ok(())
}
}
目前,只要有人输入q,我们的文本编辑器就会退出,这不太理想。让我们来改变一下,让它只在你点击 时退出Ctrl-Q。
此外,随着代码越来越复杂,函数越来越多,我们需要一种更流畅的方法来关闭程序,而无需手动中断整个循环。
我们将通过调整Editor结构体来解决这个问题,使其包含一个名为 的布尔值should_quit。此修复还将消除 Clippy 的最终警告。