编写打印任务的函数
我们需要定义的第三个也是最后一个操作是 list_tasks
函数。 此函数只需读取日志文件并打印任务列表(如果有):
pub fn list_tasks(journal_path: PathBuf) -> Result<()> {
// Open the file.
let file = OpenOptions::new().read(true).open(journal_path)?;
// Parse the file and collect the tasks.
let tasks = collect_tasks(&file)?;
// Enumerate and display tasks, if any.
if tasks.is_empty() {
println!("Task list is empty!");
} else {
let mut order: u32 = 1;
for task in tasks {
println!("{}: {}", order, task);
order += 1;
}
}
Ok(())
}
此函数比同级函数稍微简单一些,因为它不需要写入文件。 我们再次重用了 collect_tasks
helper 函数,这也证明了重构很有用。 然后,在尝试列出任务向量的内容之前,我们检查其是否为空。
打印列表时,我们使用一个从 1
开始的简单计数器来枚举任务。 这个数字与用户传递给 complete_task
操作的数字相同。
请注意,此代码将不会编译,因为 Task
结构尚未实现 Display
特征。 正如我们在其他模块中看到的那样,Display
特征用于向最终用户显示结构表示形式,这正是我们在此要执行的操作。
为类型实现 Display
特征非常简单。 我们只需实现 fmt
函数,如下所示:
use std::fmt;
impl fmt::Display for Task {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let created_at = self.created_at.with_timezone(&Local).format("%F %H:%M");
write!(f, "{:<50} [{}]", self.text, created_at)
}
}
在 Display::fmt
函数中,我们将 DateTime<Utc>
时间戳转换为 DateTime<Local>
结构,这样用户就可以查看以本地时间创建任务的日期和时间。
你可能想知道为什么我们一开始没有使用 DateTime<Local>
类型来定义 created_at
字段。 我们没有这样做是因为 chrono::serde::ts_seconds
模块需要在 Utc
类型上特殊化 DateTime
结构。
然后,使用 write!
宏将 Task
表示形式写入 Formatter
值 f
。 我们按如下所示表示 Task
类型:
{:<50}
:填充了 50 个空格的左对齐字符串。- 后跟
[{}]
:创建任务的日期和时间,并用括号括起。
总结
以上就是我们关于 tasks.rs
模块文件的探索。 如果你想要查看任务模块的完整代码,请在 Rust Playground 中进行查看。 我们应该执行的最后一步是将 cli::CommandLineArgs
捕获的用户输入与此模块中定义的三个函数绑定。
在下一节中,我们将连接 main.rs
文件中的这些端点并完成我们的应用程序。