Skip to content

Commit f22ca47

Browse files
committed
Move most code out of main.rs
1 parent 3a3b05c commit f22ca47

File tree

3 files changed

+115
-116
lines changed

3 files changed

+115
-116
lines changed

src/app.rs

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
use std::collections::VecDeque;
2+
use std::io::Write;
3+
use std::sync::mpsc::{channel, Sender};
4+
use std::thread::JoinHandle;
5+
use std::time::Duration as StdDuration;
6+
7+
use notify::{watcher, RecursiveMode, Watcher};
8+
9+
use crate::config::Config;
10+
use crate::domain::TimedLifeChunk;
11+
use crate::notification::spawn_notification_thread;
12+
use crate::output::{
13+
delay, get_all_lines, get_writers, write_global_summary, write_plan, write_summary, Writers,
14+
};
15+
use crate::parse::get_all_life_lapses;
16+
use crate::summary::{compute_all_summaries, merge_summaries_on_same_date};
17+
18+
pub fn main_loop(config: &Config) -> anyhow::Result<(Sender<()>, Option<JoinHandle<()>>)> {
19+
// START PARSE
20+
let file_paths = config.get_file_paths();
21+
let all_activities_line = get_all_lines(Box::new(file_paths.into_iter()))?;
22+
23+
let (start_time, all_life_lapses) = get_all_life_lapses(all_activities_line, config);
24+
// END PARSE
25+
26+
// COMPUTE SUMMARIES
27+
let all_summaries = compute_all_summaries(&all_life_lapses);
28+
let all_summaries = merge_summaries_on_same_date(all_summaries);
29+
30+
// WRITE
31+
let Writers {
32+
plan_writers,
33+
summary_writers,
34+
global_summary_writers,
35+
} = get_writers(start_time, config);
36+
37+
write_plan(&all_life_lapses, plan_writers)?;
38+
write_summary(&all_summaries, summary_writers)?;
39+
write_global_summary(&all_summaries, global_summary_writers)?;
40+
// END WRITE
41+
42+
// WATCHING
43+
let (tx, rx) = channel();
44+
let handle = if config.notify {
45+
// XXX: should exit early if lifelapses are incompatible, otherwise this will be buggy
46+
let mut q: Vec<TimedLifeChunk> = vec![];
47+
for ll in all_life_lapses {
48+
q.extend(ll.tokens());
49+
}
50+
q.sort_by_key(|tlc| tlc.start);
51+
Some(spawn_notification_thread(VecDeque::from(q), rx))
52+
} else {
53+
None
54+
};
55+
Ok((tx, handle))
56+
}
57+
58+
/// Should be allowed to fail, after some timeouts or number of attempts.
59+
pub fn watch_main_loop(config: &Config) -> anyhow::Result<()> {
60+
let (tx, rx) = channel();
61+
62+
// XXX: infinite loop, causes problems, how to make it reasonable?
63+
64+
let mut watcher_var = loop {
65+
// clone also use in watcher method anyway
66+
if let Ok(r) = watcher(tx.clone(), StdDuration::from_secs(0)) {
67+
break r;
68+
}
69+
delay();
70+
};
71+
72+
let mut notification_tx;
73+
let mut handle;
74+
let paths = config.get_file_paths();
75+
'big_loop: loop {
76+
loop {
77+
if let Ok((n, h)) = main_loop(config) {
78+
notification_tx = n;
79+
handle = h;
80+
break;
81+
}
82+
delay();
83+
}
84+
85+
for filepath in &paths {
86+
let w = watcher_var.watch(filepath, RecursiveMode::Recursive);
87+
if w.is_err() {
88+
delay();
89+
continue 'big_loop;
90+
}
91+
}
92+
match rx.recv() {
93+
Ok(_event) => {
94+
// XXX: ugly, matches all around the place
95+
if !config.quiet {
96+
print!("{}[H", 27 as char);
97+
print!("{}[J", 27 as char);
98+
}
99+
// kill notification thread
100+
if let Some(h) = handle {
101+
// should we care and do all this cleaning?
102+
if notification_tx.send(()).is_err() || h.join().is_err() {
103+
// XXX: ignoring errors, especially in case where notifications are disabled. Better way?
104+
}
105+
}
106+
}
107+
Err(e) => println!("watch error: {:?}", e),
108+
}
109+
}
110+
}

src/main.rs

Lines changed: 4 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,11 @@
33
#[macro_use]
44
extern crate clap;
55

6-
use std::collections::VecDeque;
7-
use std::fmt;
8-
use std::io::Write;
9-
use std::sync::mpsc;
10-
use std::sync::mpsc::{channel, Sender};
11-
use std::thread::JoinHandle;
12-
use std::time::Duration as StdDuration;
13-
146
use clap::App;
15-
use notify::{watcher, RecursiveMode, Watcher};
167

17-
use crate::config::{load_config_from_matches, Config};
18-
use crate::domain::TimedLifeChunk;
19-
use crate::notification::spawn_notification_thread;
20-
use crate::output::{
21-
delay, get_all_lines, get_writers, write_global_summary, write_plan, write_summary, Writers,
22-
};
23-
use crate::parse::get_all_life_lapses;
24-
use crate::summary::{compute_all_summaries, merge_summaries_on_same_date};
8+
use crate::config::load_config_from_matches;
259

10+
mod app;
2611
mod config;
2712
mod domain;
2813
mod merge;
@@ -33,111 +18,15 @@ mod parse_state;
3318
mod pretty_print;
3419
mod summary;
3520

36-
type Writer = (Box<dyn Write>, bool);
37-
38-
fn main_loop(config: &Config) -> anyhow::Result<(Sender<()>, Option<JoinHandle<()>>)> {
39-
// START PARSE
40-
let file_paths = config.get_file_paths();
41-
let all_activities_line = get_all_lines(Box::new(file_paths.into_iter()))?;
42-
43-
let (start_time, all_life_lapses) = get_all_life_lapses(all_activities_line, config);
44-
// END PARSE
45-
46-
// COMPUTE SUMMARIES
47-
let all_summaries = compute_all_summaries(&all_life_lapses);
48-
let all_summaries = merge_summaries_on_same_date(all_summaries);
49-
50-
// WRITE
51-
let Writers {
52-
plan_writers,
53-
summary_writers,
54-
global_summary_writers,
55-
} = get_writers(start_time, config);
56-
57-
write_plan(&all_life_lapses, plan_writers)?;
58-
write_summary(&all_summaries, summary_writers)?;
59-
write_global_summary(&all_summaries, global_summary_writers)?;
60-
// END WRITE
61-
62-
// WATCHING
63-
let (tx, rx) = channel();
64-
let handle = if config.notify {
65-
// XXX: should exit early if lifelapses are incompatible, otherwise this will be buggy
66-
let mut q: Vec<TimedLifeChunk> = vec![];
67-
for ll in all_life_lapses {
68-
q.extend(ll.tokens());
69-
}
70-
q.sort_by_key(|tlc| tlc.start);
71-
Some(spawn_notification_thread(VecDeque::from(q), rx))
72-
} else {
73-
None
74-
};
75-
Ok((tx, handle))
76-
}
77-
78-
/// Should be allowed to fail, after some timeouts or number of attempts.
79-
fn watch_main_loop(config: &Config) -> anyhow::Result<()> {
80-
let (tx, rx) = channel();
81-
82-
// XXX: infinite loop, causes problems, how to make it reasonable?
83-
84-
let mut watcher_var = loop {
85-
// clone also use in watcher method anyway
86-
if let Ok(r) = watcher(tx.clone(), StdDuration::from_secs(0)) {
87-
break r;
88-
}
89-
delay();
90-
};
91-
92-
let mut notification_tx;
93-
let mut handle;
94-
let paths = config.get_file_paths();
95-
'big_loop: loop {
96-
loop {
97-
if let Ok((n, h)) = main_loop(config) {
98-
notification_tx = n;
99-
handle = h;
100-
break;
101-
}
102-
delay();
103-
}
104-
105-
for filepath in &paths {
106-
let w = watcher_var.watch(filepath, RecursiveMode::Recursive);
107-
if w.is_err() {
108-
delay();
109-
continue 'big_loop;
110-
}
111-
}
112-
match rx.recv() {
113-
Ok(_event) => {
114-
// XXX: ugly, matches all around the place
115-
if !config.quiet {
116-
print!("{}[H", 27 as char);
117-
print!("{}[J", 27 as char);
118-
}
119-
// kill notification thread
120-
if let Some(h) = handle {
121-
// should we care and do all this cleaning?
122-
if notification_tx.send(()).is_err() || h.join().is_err() {
123-
// XXX: ignoring errors, especially in case where notifications are disabled. Better way?
124-
}
125-
}
126-
}
127-
Err(e) => println!("watch error: {:?}", e),
128-
}
129-
}
130-
}
131-
13221
fn main() -> anyhow::Result<()> {
13322
let yaml = load_yaml!("cli.yml");
13423
let matches = App::from_yaml(yaml).version(crate_version!()).get_matches();
13524

13625
let config = load_config_from_matches(&matches);
13726
if config.watch {
138-
watch_main_loop(&config)?;
27+
app::watch_main_loop(&config)?;
13928
} else {
140-
main_loop(&config)?;
29+
app::main_loop(&config)?;
14130
}
14231

14332
Ok(())

src/output.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::summary::{
1313
compute_context_summary, format_category_summary, format_category_summary_with_note,
1414
merge_all_summaries, Summary, Timestamp,
1515
};
16-
use crate::Writer;
16+
pub type Writer = (Box<dyn Write>, bool);
1717
use anyhow::Result;
1818

1919
pub struct Writers {

0 commit comments

Comments
 (0)