srctrait_note_cli/
run.rs

1use std::{fs, process::ExitCode};
2use clap::Parser;
3use crate::*;
4
5pub fn run() -> ExitCode {
6    match run_cli() {
7        Ok(_) => ExitCode::SUCCESS,
8        Err(e) => {
9            let source = e.source()
10                .map_or(String::new(), |s| format!("\n       {s}"));
11
12            eprintln!("{ERROR}error:{ERROR:#} {e}{source}");
13            ExitCode::FAILURE
14        }
15    }
16}
17
18fn run_cli() -> anyhow::Result<()> {
19    let cli = Cli::parse();
20    match &cli.command {
21        Command::Config => run_config(),
22        Command::Today(cmd) => match &cmd.from {
23            Some(TodaySubCommand::From{when}) => run_today_from(when),
24            None => run_today()
25        },
26        Command::Yesterday => run_yesterday(),
27        Command::Day{when} => run_day(when),
28        Command::Idea{topic} => run_idea(topic),
29        Command::Todo{topic} => run_todo(topic),
30        Command::Plan{topic} => run_plan(topic.as_deref()),
31    }
32}
33
34fn init_user() -> anyhow::Result<(lib::NoteConfig, lib::NotesDir)> {
35    let config = user_notes_config()?;
36    let dir = user_notes_dir(&config)?;
37    dir.init()?;
38    Ok((config, dir))
39}
40
41fn run_config() -> anyhow::Result<()> {
42    let (config, _notes_dir) = init_user()?;
43    let config_file = note_config_file()?;
44    let first_run = !config_file.is_file();
45
46    if first_run {
47        let content = config.to_toml()?
48            .lines()
49            .map(|l| format!("#{l}"))
50            .collect::<Vec<_>>()
51            .join("\n");
52
53        fs::write(&config_file, content)?;
54    }
55
56    run_editor(&config, &config_file)?;
57
58    if first_run {
59        let content = fs::read_to_string(&config_file)
60            .with_context(|| format!("Unable to read config file: {}", config_file.display()))?
61            .lines()
62            .filter(|l| !l.starts_with('#'))
63            .collect::<Vec<_>>()
64            .join("\n");
65
66        fs::write(config_file, content)?;
67    }
68
69    Ok(())
70}
71
72fn run_today() -> anyhow::Result<()> {
73    let (config, notes_dir) = init_user()?;
74    let today = lib::Date::now();
75    let note_file = lib::note_for_date(notes_dir, today, None)?;
76    run_editor(&config, &note_file)
77}
78
79fn run_today_from(when: &str) -> anyhow::Result<()> {
80    let (config, notes_dir) = init_user()?;
81    let today = lib::Date::now();
82    let when = today.from(when)?;
83    let note_file = lib::note_for_date(notes_dir, today, Some(when))?;
84    run_editor(&config, &note_file)
85}
86
87fn run_day(when: &str) -> anyhow::Result<()> {
88    let (config, notes_dir) = init_user()?;
89    let day = lib::Date::now().from(&when)?;
90    let note_file = lib::note_for_date(notes_dir, day, None)?;
91    run_editor(&config, &note_file)
92}
93
94fn run_yesterday() -> anyhow::Result<()> {
95    let (config, notes_dir) = init_user()?;
96    let day = lib::Date::now().from("yesterday")?;
97    let note_file = lib::note_for_date(notes_dir, day, None)?;
98    run_editor(&config, &note_file)
99}
100
101fn run_idea(topic: &str) -> anyhow::Result<()> {
102    let (config, notes_dir) = init_user()?;
103    let note_file = lib::note_for_topic(notes_dir, lib::NoteKind::Idea, topic)?;
104    run_editor(&config, &note_file)
105}
106
107fn run_todo(topic: &str) -> anyhow::Result<()> {
108    let (config, notes_dir) = init_user()?;
109    let note_file = lib::note_for_topic(notes_dir, lib::NoteKind::Todo, topic)?;
110    run_editor(&config, &note_file)
111}
112
113fn run_plan(topic: Option<&str>) -> anyhow::Result<()> {
114    let (config, notes_dir) = init_user()?;
115    let kind = match topic {
116        Some(_) => lib::NoteKind::PlanTopic,
117        None => lib::NoteKind::Plan,
118    };
119    
120    let note_file = lib::note_for_optional_topic(notes_dir, kind, topic)?;
121    run_editor(&config, &note_file)
122}