From 522eef9296b2291981faceed66a5fdde52a75c13 Mon Sep 17 00:00:00 2001 From: Mathieu David Date: Sun, 27 Sep 2015 14:38:37 +0200 Subject: [PATCH] first implementation of the watch sub-command. #61 Needs refining, bug in notify made me use recursion, afraid of hitting the max recursion limit... --- Cargo.toml | 10 +++++-- book-example/src/SUMMARY.md | 1 + src/bin/mdbook.rs | 58 +++++++++++++++++++++++++++++++++++-- 3 files changed, 65 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 56a9ab90..769873aa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mdbook" -version = "0.0.1" +version = "0.0.2" authors = ["Mathieu David "] description = "create books from markdown files (like Gitbook)" documentation = "http://azerupi.github.io/mdBook/index.html" @@ -11,6 +11,7 @@ readme = "README.md" build = "build.rs" exclude = [ "book-example/*", + "src/theme/stylus", ] [dependencies] @@ -22,11 +23,16 @@ pulldown-cmark = "*" [dev-dependencies] tempdir = "*" +[dependencies.notify] +notify = "*" +optional = true + [features] -default = ["output"] +default = ["output", "watch"] debug = [] output = [] regenerate-css = [] +watch = ["notify"] [[bin]] doc = false diff --git a/book-example/src/SUMMARY.md b/book-example/src/SUMMARY.md index a25059a7..18eb90e0 100644 --- a/book-example/src/SUMMARY.md +++ b/book-example/src/SUMMARY.md @@ -4,6 +4,7 @@ - [Command Line Tool](cli/cli-tool.md) - [init](cli/init.md) - [build](cli/build.md) + - [watch]() - [Format](format/format.md) - [SUMMARY.md](format/summary.md) - [Configuration](format/config.md) diff --git a/src/bin/mdbook.rs b/src/bin/mdbook.rs index 027fbb85..0e63b5f1 100644 --- a/src/bin/mdbook.rs +++ b/src/bin/mdbook.rs @@ -1,6 +1,8 @@ extern crate mdbook; #[macro_use] extern crate clap; +#[cfg(feature = "watch")] +extern crate notify; use std::env; use std::error::Error; @@ -9,6 +11,11 @@ use std::path::{Path, PathBuf}; use clap::{App, ArgMatches, SubCommand}; +#[cfg(feature = "watch")] +use notify::Watcher; +#[cfg(feature = "watch")] +use std::sync::mpsc::channel; + use mdbook::MDBook; const NAME: &'static str = "mdbook"; @@ -32,14 +39,16 @@ fn main() { .about("Build the book from the markdown files") .arg_from_usage("[dir] 'A directory for your book{n}(Defaults to Current Directory when ommitted)'")) .subcommand(SubCommand::with_name("watch") - .about("Watch the files for changes")) + .about("Watch the files for changes") + .arg_from_usage("[dir] 'A directory for your book{n}(Defaults to Current Directory when ommitted)'")) .get_matches(); // Check which subcomamnd the user ran... let res = match matches.subcommand() { ("init", Some(sub_matches)) => init(sub_matches), ("build", Some(sub_matches)) => build(sub_matches), - ("watch", _) => unimplemented!(), + #[cfg(feature = "watch")] + ("watch", Some(sub_matches)) => watch(sub_matches), (_, _) => unreachable!() }; @@ -104,6 +113,51 @@ fn build(args: &ArgMatches) -> Result<(), Box> { Ok(()) } +#[cfg(feature = "watch")] +fn watch(args: &ArgMatches) -> Result<(), Box> { + let book_dir = get_book_dir(args); + let book = MDBook::new(&book_dir).read_config(); + + // Create a channel to receive the events. + let (tx, rx) = channel(); + + let w: Result = notify::Watcher::new(tx); + + match w { + Ok(mut watcher) => { + + watcher.watch(book.get_src()).unwrap(); + + loop { + match rx.recv() { + Ok(event) => { + if let Some(path) = event.path { + println!("File changed: {:?}\nBuilding book...\n", path); + try!(build(args)); + println!(""); + // Hack to prevent receiving the event 4 times, probably a bug in notify + return watch(args); + } else { + continue; + } + }, + Err(e) => { + println!("An error occured: {:?}", e); + } + } + } + + }, + Err(e) => { + println!("Error while trying to watch the files:\n\n\t{:?}", e); + ::std::process::exit(0); + } + } + + Ok(()) +} + + fn get_book_dir(args: &ArgMatches) -> PathBuf { if let Some(dir) = args.value_of("dir") { // Check if path is relative from current dir, or absolute...