既定のジャーナル ファイルを使用してタスクを格納する

完了

一部のコマンドライン アプリケーションでは、ドットファイルや構成ファイルなどのユーザー所有のファイルをホーム ディレクトリに配置するのが一般的です。 そのため、既定のジャーナル ファイルもそこに配置することをお勧めします。

ホーム ディレクトリはユーザーのオペレーティング システムによって異なるため、ディレクトリを判断するために home というサードパーティ製クレートを利用します。

まず、それを Cargo.toml ファイルに追加します。

[dependencies]
home = "0.5" # <--- Add `home` to our project dependencies.
serde_json = "1.0"
structopt = "0.3"

[dependencies.chrono]
features = ["serde"]
version = "0.4"

[dependencies.serde]
features = ["derive"]
version = "1.0"

これで、home::home_dir() 関数を使用するように main.rs ファイルを更新できるようになりました。 この関数により、ユーザーのホーム ディレクトリが検索され、CommandLineArgs 型の journal_file フィールドと同じように、Option<PathBuf> 型で返されます。

// ...
use std::path::PathBuf;


fn find_default_journal_file() -> Option<PathBuf> {
    home::home_dir().map(|mut path| {
        path.push(".rusty-journal.json");
        path
    })
}

fn main() {

    let CommandLineArgs {
        action,
        journal_file,
    } = CommandLineArgs::from_args();

    let journal_file = journal_file
        .or_else(find_default_journal_file)
        .expect("Failed to find journal file.");

    // ...
}

ここでは find_default_journal_file という新しい関数を作成しました。 入力引数を受け取らず、Option<PathBuf> が返されます。

この関数内では、既定のジャーナル ファイルの完全なパスを作成する処理が試行されています。 パスを作成するために、home::home_dir 関数の出力から Option 型を取得し、文字列 ".rusty-journal.json" をパスにプッシュする匿名関数を使用して、その map メソッドを呼び出しています。 home::home_dir の出力が None の場合、mapSome バリアントでのみ機能するため、アクションは実行されません。

次に、main 関数で、元の値が None の場合にのみ、find_default_journal_file の呼び出しで更新されるように、journal_file 変数を "シャドウ" します。 .or_else メソッドでは、map メソッドと逆の処理を行います。バリアントが None の場合にのみ保持する関数が呼び出されます。

ユーザーが対象のジャーナル ファイルを指定しておらず、find_default_journal_file によって適切なファイルが見つけられない場合、ジャーナル ファイルなしでは何も実行できないため、プログラムはパニックに陥ります。