From 21bc3d47c8d8d705e58ce3b4ae120f5f4a77111c Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Sun, 1 Jan 2017 09:42:47 -0800 Subject: [PATCH] Add a CLI option to open a web browser --- Cargo.toml | 1 + book-example/src/cli/build.md | 5 +++++ book-example/src/cli/serve.md | 5 +++++ book-example/src/cli/watch.md | 4 ++++ src/bin/mdbook.rs | 27 ++++++++++++++++++++++++++- 5 files changed, 41 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b203f8fc..f44b31d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ pulldown-cmark = "0.0.8" log = "0.3" env_logger = "0.3" toml = { version = "0.2", features = ["serde"] } +open = "1.1" # Watch feature notify = { version = "2.5.5", optional = true } diff --git a/book-example/src/cli/build.md b/book-example/src/cli/build.md index 0d17e60d..9fe42be3 100644 --- a/book-example/src/cli/build.md +++ b/book-example/src/cli/build.md @@ -21,6 +21,11 @@ current working directory. mdbook build path/to/book ``` +#### --open + +When you use the `--open` (`-o`) option, mdbook will open the rendered book in +your default web browser after building it. + ------------------- ***note:*** *make sure to run the build command in the root directory and not in the source directory* diff --git a/book-example/src/cli/serve.md b/book-example/src/cli/serve.md index 2357dc89..39f1c6b8 100644 --- a/book-example/src/cli/serve.md +++ b/book-example/src/cli/serve.md @@ -26,6 +26,11 @@ mdbook server path/to/book -p 8000 -i 127.0.0.1 -a 192.168.1.100 If you were to want live reloading for this you would need to proxy the websocket calls through nginx as well from `192.168.1.100:` to `127.0.0.1:`. The `-w` flag allows for the websocket port to be configured. +#### --open + +When you use the `--open` (`-o`) option, mdbook will open the book in your +your default web browser after starting the server. + ----- ***note:*** *the `serve` command has not gotten a lot of testing yet, there could be some rough edges. If you discover a problem, please report it [on Github](https://github.com/azerupi/mdBook/issues)* diff --git a/book-example/src/cli/watch.md b/book-example/src/cli/watch.md index ad130c78..79117b3f 100644 --- a/book-example/src/cli/watch.md +++ b/book-example/src/cli/watch.md @@ -12,6 +12,10 @@ current working directory. mdbook watch path/to/book ``` +#### --open + +When you use the `--open` (`-o`) option, mdbook will open the rendered book in +your default web browser. ----- diff --git a/src/bin/mdbook.rs b/src/bin/mdbook.rs index 2d2bb0b0..3a82bf3e 100644 --- a/src/bin/mdbook.rs +++ b/src/bin/mdbook.rs @@ -5,6 +5,7 @@ extern crate clap; #[macro_use] extern crate log; extern crate env_logger; +extern crate open; // Dependencies for the Watch feature #[cfg(feature = "watch")] @@ -24,6 +25,7 @@ extern crate ws; use std::env; use std::error::Error; +use std::ffi::OsStr; use std::io::{self, Write}; use std::path::{Path, PathBuf}; @@ -59,9 +61,11 @@ fn main() { .arg_from_usage("--force 'skip confirmation prompts'")) .subcommand(SubCommand::with_name("build") .about("Build the book from the markdown files") + .arg_from_usage("-o, --open 'Open the compiled book in a web browser'") .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") + .arg_from_usage("-o, --open 'Open the compiled book in a web browser'") .arg_from_usage("[dir] 'A directory for your book{n}(Defaults to Current Directory when ommitted)'")) .subcommand(SubCommand::with_name("serve") .about("Serve the book at http://localhost:3000. Rebuild and reload on change.") @@ -69,7 +73,8 @@ fn main() { .arg_from_usage("-p, --port=[port] 'Use another port{n}(Defaults to 3000)'") .arg_from_usage("-w, --websocket-port=[ws-port] 'Use another port for the websocket connection (livereload){n}(Defaults to 3001)'") .arg_from_usage("-i, --interface=[interface] 'Interface to listen on{n}(Defaults to localhost)'") - .arg_from_usage("-a, --address=[address] 'Address that the browser can reach the websocket server from{n}(Defaults to the interface addres)'")) + .arg_from_usage("-a, --address=[address] 'Address that the browser can reach the websocket server from{n}(Defaults to the interface address)'") + .arg_from_usage("-o, --open 'Open the book server in a web browser'")) .subcommand(SubCommand::with_name("test") .about("Test that code samples compile")) .get_matches(); @@ -163,6 +168,10 @@ fn build(args: &ArgMatches) -> Result<(), Box> { try!(book.build()); + if args.is_present("open") { + open(book.get_dest().join("index.html")); + } + Ok(()) } @@ -173,6 +182,11 @@ fn watch(args: &ArgMatches) -> Result<(), Box> { let book_dir = get_book_dir(args); let mut book = MDBook::new(&book_dir).read_config(); + if args.is_present("open") { + try!(book.build()); + open(book.get_dest().join("index.html")); + } + trigger_on_change(&mut book, |event, book| { if let Some(path) = event.path { println!("File changed: {:?}\nBuilding book...\n", path); @@ -199,6 +213,7 @@ fn serve(args: &ArgMatches) -> Result<(), Box> { let ws_port = args.value_of("ws-port").unwrap_or("3001"); let interface = args.value_of("interface").unwrap_or("localhost"); let public_address = args.value_of("address").unwrap_or(interface); + let open_browser = args.is_present("open"); let address = format!("{}:{}", interface, port); let ws_address = format!("{}:{}", interface, ws_port); @@ -239,6 +254,10 @@ fn serve(args: &ArgMatches) -> Result<(), Box> { println!("\nServing on {}", address); + if open_browser { + open(format!("http://{}", address)); + } + trigger_on_change(&mut book, move |event, book| { if let Some(path) = event.path { println!("File changed: {:?}\nBuilding book...\n", path); @@ -278,6 +297,12 @@ fn get_book_dir(args: &ArgMatches) -> PathBuf { } } +fn open>(path: P) { + if let Err(e) = open::that(path) { + println!("Error opening web browser: {}", e); + } +} + // Calls the closure when a book source file is changed. This is blocking! #[cfg(feature = "watch")]