summaryrefslogtreecommitdiff
path: root/src/main.rs
blob: ea29cb75a8778b03c9a0a4d712c48d8de4bdc99d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use std::io::Write;
use std::fs::OpenOptions;
use std::env;
use chrono::{Local, Duration, Datelike};

mod task;
use task::*;
mod parse;
use parse::*;
mod html_calendar;
use html_calendar::*;
mod md_calendar;
use md_calendar::*;
mod dates;
use dates::*;
mod prune;
use prune::*;

// https://doc.rust-lang.org/std/fs/struct.File.html
// https://doc.rust-lang.org/book/ch12-01-accepting-command-line-arguments.html
fn main() {
    let args: Vec<String> = env::args().collect();
    let str_args: Vec<&str> = args.iter().map(String::as_str).collect();
    match str_args[..] {
        [_, "html"] => command_html(),
        [_, "describe", week] => command_describe(&week),
        [_, "generate", week] => command_generate(&week),
        [_, "validate"] => command_validate(),
        _ => panic!("Invalid command. Valid commands are: html, describe [week], generate [week], and validate.")
    }
}

fn command_html() {
    /* Pull tasks from:
     * - wtd.md (always, assuming exists)
     * - [week].md (assuming exists)
     * - weekly.md (only included for weeks without a week.md)
     */
    let n_days = 14;
    let first_date = Local::now().date().naive_local();
    let last_date = first_date + Duration::days(n_days - 1); // inclusive
    let paths = relevant_files(&first_date, &last_date);
    let mut tasks: Vec<Task> = vec![];
    for path in paths {
        tasks.append(&mut tasks_from_path(&path));
    }

    tasks_to_html_file(&tasks, first_date, last_date, CalendarPrivacy::Public, &"public.html");
    tasks_to_html_file(&tasks, first_date, last_date, CalendarPrivacy::Private, &"private.html");
}

fn command_describe(week: &str) {
    println!("{}", internal_describe(week));
}

fn command_generate(week: &str) {
    /* This command basically does two things:
     * 1) wtd describe [week] > [week].md
     * 2) Prune all tasks from this week from wtd.md
     */
    let new_week_file_contents = internal_describe(week);
    let first_date
        = parse_week_str(week).expect("Invalid week string provided. Should be, e.g., jan_24_2022");
    if first_date.weekday().number_from_monday() != 1 { // 1-based, for some reason.
        panic!("The provided week should start on a Monday.");
    }
    let new_wtd_contents = prune_week_from_file(first_date, "wtd.md");
    let week_file_name = first_date.format("%b_%d_%Y.md").to_string().to_lowercase();
    overwrite_file(&week_file_name, &new_week_file_contents);
    overwrite_file("wtd.md", &new_wtd_contents);
}

fn overwrite_file(name: &str, contents: &str) {
    let mut file = match OpenOptions::new().create(true).write(true).truncate(true).open(name) {
        Err(why) => panic!("Error opening {}: {}", name, why),
        Ok(file) => file,
    };

    match file.write_all(contents.as_bytes()) {
        Err(why) => panic!("Couldn't write to {}: {}", name, why),
        Ok(_) => {},
    };
}

fn command_validate() {
    let today = Local::now().date().naive_local();
    let paths = relevant_files_starting(&today);
    let mut tasks: Vec<Task> = vec![];
    for path in paths {
        for task in tasks_from_path(&path) {
            if task.date >= today && task.start_time.is_some() && task.end_time.is_some() {
                tasks.push(task);
            }
        }
    }
    tasks.sort_by(cmp_tasks);
    let n_tasks = tasks.len();
    for i in 0..n_tasks {
        let task_a = &tasks[i];
        for j in (i + 1)..n_tasks {
            let task_b = &tasks[j];
            if tasks_overlap(task_a, task_b) {
                println!("Overlap found: '{}' overlaps with '{}'",
                         task_a.raw.replace("\n", "").trim(),
                         task_b.raw.replace("\n", "").trim());
            } else {
                break;
            }
        }
    }
}

fn internal_describe(week: &str) -> String {
    let first_date
        = parse_week_str(week).expect("Invalid week string provided. Should be, e.g., jan_24_2022");
    if first_date.weekday().number_from_monday() != 1 { // 1-based, for some reason.
        panic!("The provided week should start on a Monday.");
    }
    let last_date = first_date + Duration::days(6); // inclusive

    let paths = relevant_files(&first_date, &last_date);
    let mut tasks: Vec<Task> = vec![];
    for path in paths {
        tasks.append(&mut tasks_from_path(&path));
    }

    return tasks_to_md(&tasks, first_date, last_date);
}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback