summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Sotoudeh <matthewsot@outlook.com>2022-01-24 08:19:57 -0800
committerMatthew Sotoudeh <matthewsot@outlook.com>2022-01-24 08:19:57 -0800
commitd9fac382c8d3b60f6ea641d175326d4e6bc678ff (patch)
tree1c620a129b04a995f8bd3485a2fa5eac6b31d675
parent0c64e06848292cf473b7d642cc02922ef9dcc2f4 (diff)
'wtd generate [week]' command builds
-rw-r--r--src/main.rs78
-rw-r--r--src/parse.rs2
-rw-r--r--src/prune.rs49
3 files changed, 105 insertions, 24 deletions
diff --git a/src/main.rs b/src/main.rs
index 06431e8..ea29cb7 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,3 +1,5 @@
+use std::io::Write;
+use std::fs::OpenOptions;
use std::env;
use chrono::{Local, Duration, Datelike};
@@ -11,6 +13,22 @@ 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:
@@ -32,25 +50,36 @@ fn command_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 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));
- }
-
- let md = tasks_to_md(&tasks, first_date, last_date);
- println!("{}", md);
+ 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 command_generate(week: &str) {
- // TODO
+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() {
@@ -81,16 +110,19 @@ fn command_validate() {
}
}
-// 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 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);
}
diff --git a/src/parse.rs b/src/parse.rs
index 876b861..6bed4d9 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -75,7 +75,7 @@ fn parse_file_str(file_str: &str, implicit_week: Option<NaiveDate>) -> Vec<Task>
return tasks;
}
-fn parse_date_line(l: &str) -> Option<NaiveDate> {
+pub fn parse_date_line(l: &str) -> Option<NaiveDate> {
for maybe_date_str in l.split(' ') {
if let Ok(date) = NaiveDate::parse_from_str(maybe_date_str, "%m/%d/%y") {
return Some(date);
diff --git a/src/prune.rs b/src/prune.rs
new file mode 100644
index 0000000..dd7a5fb
--- /dev/null
+++ b/src/prune.rs
@@ -0,0 +1,49 @@
+use std::path::Path;
+use std::fs::File;
+use std::io::prelude::*;
+use chrono::{NaiveDate, Duration};
+
+use crate::parse::*;
+
+pub fn prune_week_from_file(week: NaiveDate, file_str: &str) -> String {
+ let path = Path::new(file_str);
+ let display = path.display();
+
+ // Open the path in read-only mode, returns `io::Result<File>`
+ let mut file = match File::open(&path) {
+ Err(why) => panic!("Error opening {}: {}", display, why),
+ Ok(file) => file,
+ };
+
+ // Read the file contents into a string, returns `io::Result<usize>`
+ let mut s = String::new();
+ match file.read_to_string(&mut s) {
+ Err(why) => panic!("Couldn't read {}: {}", display, why),
+ Ok(_) => return prune_week_from_str(week, &s),
+ }
+}
+
+fn prune_week_from_str(week: NaiveDate, file_str: &str) -> String {
+ let mut new_contents = "\n".to_string();
+ let mut ghost = false;
+ let ghost_start = week - Duration::days(6);
+ let ghost_end = week + Duration::days(6);
+ for l in file_str.split('\n') {
+ if l.starts_with("# ") {
+ // '# 12/27/21', starts a new week block
+ let start_date = parse_date_line(l).expect("Couldn't parse '# ' header.");
+ ghost = ghost_start <= start_date && start_date <= ghost_end;
+ if ghost && start_date != week {
+ panic!("generate currently assumes `# ` headers always start on Mondays.");
+ }
+ }
+ if !ghost {
+ new_contents.push_str(l);
+ new_contents.push('\n');
+ }
+ }
+ // Remove leading & trailing newlines.
+ new_contents.remove(0);
+ new_contents.pop();
+ return new_contents;
+}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback