1use std::{net::ToSocketAddrs, path::PathBuf, sync::Arc, sync::RwLock};
4use std::fmt::Write;
5
6use handlebars::{Handlebars, TemplateFileError};
7use hyper::server::Server;
8use notify::{Error as NotifyError, Event, EventFn, EventKind, RecommendedWatcher, RecursiveMode, Watcher};
9use Pencil;
10
11fn handle_modify(paths: &[PathBuf], registry: &RwLock<Handlebars<'_>>) {
12 for path in paths {
13 if let Some(fname) = path.file_name() {
14 let mut write_guard = registry.write().unwrap();
15 let fname = fname.to_str().unwrap();
16 let compile_result = write_guard.register_template_file(fname, &path);
17 if let Err(TemplateFileError::TemplateError(err)) = compile_result {
18 let mut msg = "Template syntax error:".to_owned();
19 if let Some(line_no) = err.line_no {
20 write!(msg, " line no: {}", line_no).unwrap();
21 }
22 if let Some(col_no) = err.column_no {
23 write!(msg, " col no: {}", col_no).unwrap();
24 }
25 write!(msg, " cause: {}", err.reason).unwrap();
26 warn!("{}", msg);
27 write_guard.register_template_string(fname, msg).unwrap();
28 } else {
29 info!("Registered template {}", fname);
30 }
31 }
32 }
33}
34
35fn watch_files(registry: Arc<RwLock<Handlebars<'static>>>) -> impl EventFn {
36 move |event: Result<Event, NotifyError>| match event {
37 Ok(Event { kind: EventKind::Create(_), paths, ..}) => handle_modify(&paths, ®istry),
38 Ok(Event { kind: EventKind::Modify(_), paths, ..}) => handle_modify(&paths, ®istry),
39 Err(e) => warn!("template watch error: {:?}", e),
40 _ => (),
41 }
42}
43
44
45pub fn run_server<A: ToSocketAddrs>(application: Pencil, addr: A, threads: usize) {
47
48 let mut watcher: RecommendedWatcher;
49 if application.template_debug {
50 let registry = application.handlebars_registry.clone();
51 let template_dir = application.template_folder.clone();
52 watcher = Watcher::new_immediate(watch_files(registry)).unwrap();
53 info!("Begin watching {}", &template_dir);
54 watcher.watch(&template_dir, RecursiveMode::Recursive).unwrap();
55 }
56
57 let server = Server::http(addr).unwrap();
58 let _guard = server.handle_threads(application, threads).unwrap();
59}