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);
}
|