タスクを出力する関数を記述する
定義する必要がある 3 つ目かつ最後のアクションは 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
ヘルパー関数を再利用します。これで、リファクタリングが役に立つことがわかります。 次に、内容を一覧表示する前に、タスク ベクトルが空かどうかを確認します。
リストを出力するときは、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
フィールドを定義しなかったのはなぜか疑問に思われるかもしれません。 そうしなかったのは、DateTime
構造体が Utc
型に特殊化されていることが chrono::serde::ts_seconds
モジュールで想定されているためです。
次に、write!
マクロを使用して、Task
の表現を Formatter
値 f
に書き込みます。 Task
型を次のように表します。
{:<50}
: 50 個のスペースが埋め込まれた左揃えの文字列。- それに続く
[{}]
: タスクが作成された日時 (かっこ内)。
まとめ
tasks.rs
モジュール ファイルの探索は以上です。 タスク モジュールの完全なコードを確認するには、「Rust プレイグラウンド」をご覧ください。 実行する必要がある最後の手順は、cli::CommandLineArgs
によってキャプチャされたユーザー入力を、このモジュールで定義した 3 つの関数にバインドすることです。
次のセクションでは、その結果を main.rs
ファイルで接続し、アプリケーションを完成させます。