Skip to content

Commit 3964266

Browse files
Made mdbook watch and mdbook serve rebuild the book again (#508)
Made `mdbook watch` and `mdbook serve` rebuild the book again
1 parent d69bc9c commit 3964266

File tree

2 files changed

+36
-73
lines changed

2 files changed

+36
-73
lines changed

src/bin/serve.rs

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@ extern crate staticfile;
33
extern crate ws;
44

55
use std;
6-
use std::path::PathBuf;
76
use self::iron::{status, AfterMiddleware, Chain, Iron, IronError, IronResult, Request, Response,
87
Set};
98
use clap::{App, ArgMatches, SubCommand};
109
use mdbook::MDBook;
11-
use mdbook::errors::Result;
10+
use mdbook::errors::*;
1211
use {get_book_dir, open};
1312
#[cfg(feature = "watch")]
1413
use watch;
@@ -18,28 +17,21 @@ struct ErrorRecover;
1817
// Create clap subcommand arguments
1918
pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> {
2019
SubCommand::with_name("serve")
21-
.about(
22-
"Serve the book at http://localhost:3000. Rebuild and reload on change.",
23-
)
24-
.arg_from_usage(
25-
"[dir] 'A directory for your book{n}(Defaults to \
26-
Current Directory when omitted)'",
27-
)
20+
.about("Serve the book at http://localhost:3000. Rebuild and reload on change.")
2821
.arg_from_usage(
29-
"-d, --dest-dir=[dest-dir] 'The output directory for \
30-
your book{n}(Defaults to ./book when omitted)'",
22+
"[dir] 'A directory for your book{n}(Defaults to Current Directory when omitted)'",
3123
)
3224
.arg_from_usage("-p, --port=[port] 'Use another port{n}(Defaults to 3000)'")
3325
.arg_from_usage(
34-
"-w, --websocket-port=[ws-port] 'Use another port for the \
35-
websocket connection (livereload){n}(Defaults to 3001)'",
26+
"-w, --websocket-port=[ws-port] 'Use another port for the websocket connection \
27+
(livereload){n}(Defaults to 3001)'",
3628
)
3729
.arg_from_usage(
3830
"-i, --interface=[interface] 'Interface to listen on{n}(Defaults to localhost)'",
3931
)
4032
.arg_from_usage(
41-
"-a, --address=[address] 'Address that the browser can reach the \
42-
websocket server from{n}(Defaults to the interface address)'",
33+
"-a, --address=[address] 'Address that the browser can reach the websocket server \
34+
from{n}(Defaults to the interface address)'",
4335
)
4436
.arg_from_usage("-o, --open 'Open the book server in a web browser'")
4537
}
@@ -51,10 +43,6 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
5143
let book_dir = get_book_dir(args);
5244
let mut book = MDBook::load(&book_dir)?;
5345

54-
if let Some(dest_dir) = args.value_of("dest-dir") {
55-
book.config.build.build_dir = PathBuf::from(dest_dir);
56-
}
57-
5846
let port = args.value_of("port").unwrap_or("3000");
5947
let ws_port = args.value_of("websocket-port").unwrap_or("3001");
6048
let interface = args.value_of("interface").unwrap_or("localhost");
@@ -80,18 +68,19 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
8068
}}
8169
</script>
8270
"#,
83-
public_address,
84-
ws_port,
85-
RELOAD_COMMAND
71+
public_address, ws_port, RELOAD_COMMAND
8672
));
8773

8874
book.build()?;
8975

9076
let mut chain = Chain::new(staticfile::Static::new(book.get_destination()));
9177
chain.link_after(ErrorRecover);
92-
let _iron = Iron::new(chain).http(&*address).unwrap();
78+
let _iron = Iron::new(chain)
79+
.http(&*address)
80+
.chain_err(|| "Unable to launch the server")?;
9381

94-
let ws_server = ws::WebSocket::new(|_| |_| Ok(())).unwrap();
82+
let ws_server =
83+
ws::WebSocket::new(|_| |_| Ok(())).chain_err(|| "Unable to start the websocket")?;
9584

9685
let broadcaster = ws_server.broadcaster();
9786

@@ -107,9 +96,9 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
10796
}
10897

10998
#[cfg(feature = "watch")]
110-
watch::trigger_on_change(&mut book, move |path, book| {
99+
watch::trigger_on_change(&mut book, move |path, book_dir| {
111100
println!("File changed: {:?}\nBuilding book...\n", path);
112-
match book.build() {
101+
match MDBook::load(&book_dir).and_then(|mut b| b.build()) {
113102
Err(e) => println!("Error while building: {:?}", e),
114103
_ => broadcaster.send(RELOAD_COMMAND).unwrap(),
115104
}

src/bin/watch.rs

Lines changed: 21 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
extern crate notify;
22

3-
use std::path::{Path, PathBuf};
3+
use std::path::Path;
44
use self::notify::Watcher;
55
use std::time::Duration;
66
use std::sync::mpsc::channel;
@@ -15,12 +15,7 @@ pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> {
1515
.about("Watch the files for changes")
1616
.arg_from_usage("-o, --open 'Open the compiled book in a web browser'")
1717
.arg_from_usage(
18-
"-d, --dest-dir=[dest-dir] 'The output directory for \
19-
your book{n}(Defaults to ./book when omitted)'",
20-
)
21-
.arg_from_usage(
22-
"[dir] 'A directory for your book{n}(Defaults to \
23-
Current Directory when omitted)'",
18+
"[dir] 'A directory for your book{n}(Defaults to Current Directory when omitted)'",
2419
)
2520
}
2621

@@ -29,30 +24,28 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
2924
let book_dir = get_book_dir(args);
3025
let mut book = MDBook::load(&book_dir)?;
3126

32-
if let Some(dest_dir) = args.value_of("dest-dir") {
33-
book.config.build.build_dir = PathBuf::from(dest_dir);
34-
}
35-
3627
if args.is_present("open") {
3728
book.build()?;
3829
open(book.get_destination().join("index.html"));
3930
}
4031

41-
trigger_on_change(&mut book, |path, book| {
32+
trigger_on_change(&book, |path, book_dir| {
4233
println!("File changed: {:?}\nBuilding book...\n", path);
43-
if let Err(e) = book.build() {
44-
println!("Error while building: {:?}", e);
34+
let result = MDBook::load(&book_dir).and_then(|mut b| b.build());
35+
36+
if let Err(e) = result {
37+
println!("Error while building: {}", e);
4538
}
46-
println!("");
39+
println!();
4740
});
4841

4942
Ok(())
5043
}
5144

52-
// Calls the closure when a book source file is changed. This is blocking!
53-
pub fn trigger_on_change<F>(book: &mut MDBook, closure: F) -> ()
45+
/// Calls the closure when a book source file is changed, blocking indefinitely.
46+
pub fn trigger_on_change<F>(book: &MDBook, closure: F)
5447
where
55-
F: Fn(&Path, &mut MDBook) -> (),
48+
F: Fn(&Path, &Path),
5649
{
5750
use self::notify::RecursiveMode::*;
5851
use self::notify::DebouncedEvent::*;
@@ -64,48 +57,29 @@ where
6457
Ok(w) => w,
6558
Err(e) => {
6659
println!("Error while trying to watch the files:\n\n\t{:?}", e);
67-
::std::process::exit(0)
60+
::std::process::exit(1)
6861
}
6962
};
7063

7164
// Add the source directory to the watcher
7265
if let Err(e) = watcher.watch(book.source_dir(), Recursive) {
7366
println!("Error while watching {:?}:\n {:?}", book.source_dir(), e);
74-
::std::process::exit(0);
67+
::std::process::exit(1);
7568
};
7669

77-
// Add the theme directory to the watcher
78-
watcher.watch(book.theme_dir(), Recursive)
79-
.unwrap_or_default();
70+
let _ = watcher.watch(book.theme_dir(), Recursive);
8071

81-
// Add the book.{json,toml} file to the watcher if it exists, because it's not
82-
// located in the source directory
83-
if watcher.watch(book.root.join("book.json"), NonRecursive)
84-
.is_err()
85-
{
86-
// do nothing if book.json is not found
87-
}
88-
if watcher.watch(book.root.join("book.toml"), NonRecursive)
89-
.is_err()
90-
{
91-
// do nothing if book.toml is not found
92-
}
72+
// Add the book.toml file to the watcher if it exists
73+
let _ = watcher.watch(book.root.join("book.toml"), NonRecursive);
9374

9475
println!("\nListening for changes...\n");
9576

96-
loop {
97-
match rx.recv() {
98-
Ok(event) => {
99-
match event {
100-
Create(path) | Write(path) | Remove(path) | Rename(_, path) => {
101-
closure(&path, book);
102-
}
103-
_ => {}
104-
}
105-
}
106-
Err(e) => {
107-
println!("An error occured: {:?}", e);
77+
for event in rx.recv() {
78+
match event {
79+
Create(path) | Write(path) | Remove(path) | Rename(_, path) => {
80+
closure(&path, &book.root);
10881
}
82+
_ => {}
10983
}
11084
}
11185
}

0 commit comments

Comments
 (0)