aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
blob: 03eab2e3e9264636d7f980d2fd0095997c926f38 (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
extern crate almanac;
extern crate itertools;
extern crate colored;

use std::env;
use std::io::BufReader;
use std::fs::File;
use itertools::Itertools;
use colored::*;

use almanac::Calendar;
use almanac::Date;
use almanac::Duration;
use almanac::Event;

fn main() {
    let mut args = env::args().skip(1);
    let (first, last) = period(&args.next().unwrap());

    let calendars: Vec<_> = args.map(|arg| ics_calendar(&arg)).collect();
    let events = calendars
        .iter()
        .map(|c| c.iter())
        .kmerge()
        .skip_while(|e| e.end_date() < first)
        .take_while(|e| e.start <= last);
    print_events(events)
}

fn period(arg: &str) -> (Date, Date) {
    let days = match arg {
        "day" => 1,
        "week" => 7,
        "month" => 30,
        _ => panic!("Invalid time frame, try: day, week or month"),
    };
    let first = Date::now();
    let last = first + Duration::days(days);
    (first, last)
}

fn ics_calendar(file_path: &str) -> Calendar {
    let file = File::open(file_path).unwrap();
    let buf = BufReader::new(file);
    Calendar::parse(buf).unwrap()
}

fn print_events(events: impl Iterator<Item = Event>) {
    let mut day = Date::new();
    let mut unfinish = vec![];

    for event in events {
        if !day.same_day(&event.start) {
            if !unfinish.is_empty() {
                while !day.same_day(&event.start) {
                    day = day + Duration::days(1);
                    print_day(day);
                    for (i, event) in unfinish.clone().iter().enumerate() {
                        print_event(event);
                        if event.end_date() <= day + Duration::days(1) {
                            unfinish.remove(i);
                        }
                    }
                }
            } else {
                day = event.start.clone();
                print_day(day);
            }
        }

        print_event(&event);
        if event.end_date() > event.start + Duration::days(1) {
            unfinish.push(event);
        }
    }

    while !unfinish.is_empty() {
        day = day + Duration::days(1);
        print_day(day);
        for (i, event) in unfinish.clone().iter().enumerate() {
            print_event(event);
            if event.end_date() <= day + Duration::days(1) {
                unfinish.remove(i);
            }
        }
    }
}

fn print_day(date: Date) {
    println!("\n{}", date.format("%a %b %e %Y").green().bold())
}

fn print_event(event: &Event) {
    let start = match event.start {
        Date::Time(_) => event.start.format("%R"),
        Date::AllDay(_) => "-----".to_string(),
    };
    let end = match event.end_date() {
        Date::Time(_) => event.end_date().format("%R"),
        Date::AllDay(_) => "-----".to_string(),
    };

    println!(
        "    {}-{} {} {}",
        start.yellow(),
        end.yellow(),
        event.summary,
        event.location.purple()
    );

    if !event.description.is_empty() {
        println!("    {} {}", " ".repeat(11), event.description.cyan());
    }
}