33#[ macro_use]
44extern 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-
146use 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;
2611mod config;
2712mod domain;
2813mod merge;
@@ -33,111 +18,15 @@ mod parse_state;
3318mod pretty_print;
3419mod 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-
13221fn 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 ( ( ) )
0 commit comments