メイン モジュールを完成させる

完了

ユーザー操作 (cli モジュールを使用) とファイル処理 (tasks モジュールを使用) をプログラムで処理できるようになったので、次はすべてが期待どおりに動作するかどうかを試してみましょう。

既定のジャーナル ファイルを使用する、ユーザーにわかりやすいエラーを表示するなど、まだ必要な改善点はありますが、そのようなタスクについては後で取りかかりましょう。

メイン モジュールを完成させ、プログラムを実行する

次に必要な作業は、Actions 構造体を tasks モジュールで定義された 3 つのパブリック関数に接続することです。 main.rs ファイルを開き、次のようにします。

use structopt::StructOpt;
mod cli;
mod tasks;

use cli::{Action::*, CommandLineArgs};
use tasks::Task;

fn main() {
    // Get the command-line arguments.
    let CommandLineArgs {
        action,
        journal_file,
    } = CommandLineArgs::from_args();

    // Unpack the journal file.
    let journal_file = journal_file.expect("Failed to find journal file");

    // Perform the action.
    match action {
        Add { task } => tasks::add_task(journal_file, Task::new(task)),
        List => tasks::list_tasks(journal_file),
        Done { position } => tasks::complete_task(journal_file, position),
    }
    .expect("Failed to perform action")
}

main.rs のアウトラインは単純に見えます。

CommandLineArgs 構造体をそのフィールドに "非構造化" することから始めます。これにより、その値をタスク処理関数に個別に渡すことができるようになります。

journal_file の型は Option<PathBuf> であるため、ジャーナル ファイルのパスを抽出するか、panic を生成する必要があります。 この手順は、プログラムに既定のファイルを検索させる処理のために後でまた利用します。 今のところ、この .expect 命令は正常に機能します。

最後に、使用可能な各 Action をその関数に対応付け、列挙型から関数に必要なフィールドを渡します。 すべての関数から Result 型が返されため、match ブロックの末尾で .expect を呼び出します。これは失敗する可能性があります。 繰り返しになりますが、障害が発生した場合にユーザーに適切なエラー メッセージを表示できるように、後でこの機能を改善します。

試しに使ってみましょう。 ターミナルを開き、次のコマンドを入力します。

$ cargo run -- -j test-journal.json add "buy milk"

$ cargo run -- -j test-journal.json add "take the dog for a walk"

$ cargo run -- -j test-journal.json add "water the plants"

$ cargo run -- -j test-journal.json list
1: buy milk                                           [2021-01-08 16:39]
2: take the dog for a walk                            [2021-01-08 16:39]
3: water the plants                                   [2021-01-08 16:39]

$ cargo run -- -j test-journal.json done 2

$ cargo run -- -j test-journal.json list
1: buy milk                                           [2021-01-08 16:39]
2: water the plants                                   [2021-01-08 16:39]

プログラムは正常に実行されているようです。

まず cargo run -- を呼び出して、-- の後に渡されたすべての引数が cargo 自体ではなくプログラムに送信されることを確認しました。

次に、サブコマンド add とそれに続くタスク名の文字列を使用して、3 つのタスクを続けて追加しました。 次に、list サブコマンドにより、3 つのタスクが順に表示され、そのタイムスタンプが右端に表示されました。 次に、done 2 サブコマンドを呼び出して、2 つ目のタスクが完了したことをマークしました。 list をもう一度呼び出すと、そのタスクは削除されました。 すばらしいと思いませんか。

test-journal.json ファイルを見ると、次のような内容が表示されます。

[{"text":"buy milk","created_at":1610134741},{"text":"water the plants","created_at":1610134762}]

Task は JSON オブジェクトとして表され、各ファイルは 1 つのキーであることがわかります。 タスクの説明は文字列として保存され、タイムスタンプは epoch 以降の秒数として保持されます。

この JSON ファイルを整形して出力すると、次のようになります。

[
  {
    "text": "buy milk",
    "created_at": 1610134741
  },
  {
    "text": "water the plants",
    "created_at": 1610134762
  }
]

次の 2 つのセクションでは、既定のジャーナル ファイルを使用するようにプログラムを構成し、より見やすいエラー メッセージを表示することで、プログラムの使いやすさを向上させます。