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
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
use std::marker::Send;
use log::{debug, error, warn};
use notify::{Watcher, RecursiveMode, DebouncedEvent, watcher};
use crate::input::Config;
use crate::markdown;
use crate::ui;
pub trait Sender {
fn send(&mut self, event: ui::Event) -> Result<(), mpsc::SendError<ui::Event>>;
}
impl Sender for glib::Sender<ui::Event> {
fn send(&mut self, event: ui::Event) -> Result<(), mpsc::SendError<ui::Event>> {
glib::Sender::<ui::Event>::send(self, event)
}
}
impl Sender for mpsc::Sender<ui::Event> {
fn send(&mut self, event: ui::Event) -> Result<(), mpsc::SendError<ui::Event>> {
mpsc::Sender::<ui::Event>::send(self, event)
}
}
pub fn init_update_loop<S>(renderer: markdown::Renderer, mut ui_sender: S)
where S: Sender + Send + 'static
{
thread::spawn(move || {
let (watcher_sender, watcher_receiver) = mpsc::channel();
let mut watcher = match watcher(watcher_sender, Duration::from_millis(200)) {
Ok(w) => w,
Err(e) => {
warn!("Couldn't initialize watcher: {}", e);
return;
}
};
let main_watch_path = renderer.canonical_md_path.parent().
unwrap_or(&renderer.canonical_md_path).
to_owned();
if let Err(e) = watcher.watch(&main_watch_path, RecursiveMode::NonRecursive) {
warn!("Couldn't initialize watcher: {}", e);
return;
}
let mut extra_watch_paths = vec![];
let custom_css_path = Config::css_path();
if watcher.watch(&custom_css_path, RecursiveMode::NonRecursive).is_ok() {
debug!("Watching {}", custom_css_path.display());
extra_watch_paths.push(custom_css_path);
}
loop {
match watcher_receiver.recv() {
Ok(DebouncedEvent::Write(file)) => {
debug!("File updated: {}", file.display());
if file == renderer.canonical_md_path {
match renderer.run() {
Ok(html) => {
let _ = ui_sender.send(ui::Event::LoadHtml(html));
},
Err(e) => {
error! {
"Error rendering markdown ({}): {:?}",
renderer.canonical_md_path.display(), e
};
}
}
} else if extra_watch_paths.contains(&file) {
let _ = ui_sender.send(ui::Event::Reload);
} else {
debug!("Ignored file update event: {:?}", file)
}
},
Ok(event) => debug!("Ignored watcher event: {:?}", event),
Err(e) => error!("Error watching file for changes: {:?}", e),
}
}
});
}