blinddate/src/main.rs

107 lines
4.1 KiB
Rust

use chrono::{Date, Datelike, Duration, Local};
use enigo::*;
use std::env;
use std::process;
fn command_to_date(command: &str) -> Result<Date<Local>, ()> {
let today = Local::today();
calc_date(command, today)
}
fn calc_date(command: &str, today: Date<Local>) -> Result<Date<Local>, ()> {
let wday = today.weekday().num_days_from_monday() as i64;
if command == "today" {
return Ok(today);
} else if command == "tomorrow" {
return Ok(today + Duration::days(1));
} else if command == "yesterday" {
return Ok(today - Duration::days(1));
} else if command == "daybeforeyesterday" {
return Ok(today - Duration::days(2));
} else if command == "dayaftertomorrow" {
return Ok(today + Duration::days(2));
} else if command.starts_with("next") || command.starts_with("last") {
let target = match &command[4..] {
"monday" => Ok(0),
"tuesday" => Ok(1),
"wednesday" => Ok(2),
"thursday" => Ok(3),
"friday" => Ok(4),
"saturday" => Ok(5),
"sunday" => Ok(6),
_ => Err(()),
};
if let Ok(target) = target {
if command.starts_with("next") {
let offset = (target - wday + 7 - 1) % 7 + 1;
return Ok(today + Duration::days(offset));
}
let offset = (wday - target + 7 - 1) % 7 + 1;
return Ok(today - Duration::days(offset));
}
};
Err(())
}
fn type_date(date: Date<Local>) {
let date_str = format!("{}", date.format("%Y-%m-%d"));
let mut enigo = Enigo::new();
for c in date_str.chars() {
enigo.key_click(Key::Layout(c));
}
// enigo.key_click(Key::Return);
}
fn main() {
let command = env::args()
.nth(1)
.unwrap_or_else(|| "".to_string())
.to_lowercase();
if let Ok(date) = command_to_date(&command) {
type_date(date);
} else {
eprintln!("blinddate");
eprintln!("Calculates a date and types it. Use with a shell script to enter dates into files rapidly.");
eprintln!("Usage: blinddate <command>");
eprintln!("Supported commands:");
eprintln!(" today");
eprintln!(" tomorrow");
eprintln!(" yesterday");
eprintln!(" daybeforeyesterday");
eprintln!(" dayaftertomorrow");
eprintln!(" next<weekday> (e.g. nextmonday)");
eprintln!(" last<weekday> (e.g. lastsaturday)");
process::exit(1);
}
}
#[cfg(test)]
use chrono::prelude::*;
#[test]
fn test_calc_date() {
let today = Local.ymd(2020, 9, 1);
assert!(Local.ymd(2020, 9, 1) == calc_date("today", today).unwrap());
assert!(Local.ymd(2020, 9, 2) == calc_date("tomorrow", today).unwrap());
assert!(Local.ymd(2020, 8, 31) == calc_date("yesterday", today).unwrap());
assert!(Local.ymd(2020, 8, 30) == calc_date("daybeforeyesterday", today).unwrap());
assert!(Local.ymd(2020, 9, 3) == calc_date("dayaftertomorrow", today).unwrap());
assert!(Local.ymd(2020, 9, 7) == calc_date("nextmonday", today).unwrap());
assert!(Local.ymd(2020, 9, 8) == calc_date("nexttuesday", today).unwrap());
assert!(Local.ymd(2020, 9, 2) == calc_date("nextwednesday", today).unwrap());
assert!(Local.ymd(2020, 9, 3) == calc_date("nextthursday", today).unwrap());
assert!(Local.ymd(2020, 9, 4) == calc_date("nextfriday", today).unwrap());
assert!(Local.ymd(2020, 9, 5) == calc_date("nextsaturday", today).unwrap());
assert!(Local.ymd(2020, 9, 6) == calc_date("nextsunday", today).unwrap());
assert!(Local.ymd(2020, 8, 31) == calc_date("lastmonday", today).unwrap());
assert!(Local.ymd(2020, 8, 25) == calc_date("lasttuesday", today).unwrap());
assert!(Local.ymd(2020, 8, 26) == calc_date("lastwednesday", today).unwrap());
assert!(Local.ymd(2020, 8, 27) == calc_date("lastthursday", today).unwrap());
assert!(Local.ymd(2020, 8, 28) == calc_date("lastfriday", today).unwrap());
assert!(Local.ymd(2020, 8, 29) == calc_date("lastsaturday", today).unwrap());
assert!(Local.ymd(2020, 8, 30) == calc_date("lastsunday", today).unwrap());
assert!(calc_date("weirdbullshit", today).is_err());
}