ncalendar

Reimplementation of the BSD calendar(1) program in Rust

git clone https://git.8pit.net/ncalendar.git

 1extern crate ncalendar;
 2extern crate structopt;
 3
 4mod timespan;
 5mod util;
 6
 7use crate::timespan::TimeSpan;
 8use crate::util::*;
 9
10use std::path;
11use structopt::StructOpt;
12use time::format_description;
13
14#[derive(StructOpt, Debug)]
15#[structopt(name = "basic")]
16struct Opt {
17    // XXX: Should this use try_from_os_str?!
18    /// Use the given file as the default calendar file.
19    #[structopt(short = "f", default_value = "", parse(try_from_str = parse_file))]
20    file: path::PathBuf,
21
22    /// Amount of next days to consider.
23    #[structopt(short = "A", parse(try_from_str = parse_days))]
24    forward: Option<time::Duration>,
25
26    /// Amount of past days to consider.
27    #[structopt(short = "B", parse(try_from_str = parse_days))]
28    back: Option<time::Duration>,
29
30    /// Act like the specified value is today.
31    #[structopt(short = "t", default_value = "today", parse(try_from_str = parse_today))]
32    today: time::Date,
33
34    /// Print day of the week name in front of each event.
35    #[structopt(short = "w")]
36    week: bool,
37}
38
39// For Fridays (if neither -A nor -B was provided) look
40// three days into the future by default (next monday).
41fn forward_default(opt: &Opt) -> impl FnOnce() -> time::Duration {
42    let fri: bool = opt.today.weekday() == time::Weekday::Friday && opt.back.is_none();
43    move || -> time::Duration { time::Duration::days(if fri { 3 } else { 1 }) }
44}
45
46fn main() {
47    let opt = Opt::from_args();
48    let span = TimeSpan::new(
49        opt.today,
50        opt.back.unwrap_or(time::Duration::days(0)),
51        opt.forward.unwrap_or_else(forward_default(&opt)),
52    )
53    .unwrap();
54
55    let out_fmt = format_description::parse("[month repr:short] [day]").unwrap();
56    let entries = ncalendar::parse_file(opt.file.as_path()).unwrap();
57
58    for date in span.iter() {
59        let matched = entries.iter().filter(|e| e.day.matches(date));
60
61        matched.for_each(|entry| {
62            let postfix = if entry.is_fixed() { ' ' } else { '*' };
63
64            if opt.week {
65                print!("{} ", weekday_short(date));
66            }
67            println!(
68                "{}{}\t{}",
69                date.format(&out_fmt).unwrap(),
70                postfix,
71                entry.desc
72            );
73        });
74    }
75}