diff --git a/build.rs b/build.rs index d3177444..25884ef3 100644 --- a/build.rs +++ b/build.rs @@ -20,7 +20,8 @@ fn main() { .arg(format!("{}", theme_dir.to_str().unwrap())) .arg("--use") .arg("nib") - .status().unwrap() + .status() + .unwrap() .success() { panic!("Stylus encoutered an error"); } diff --git a/rustfmt.toml b/rustfmt.toml index 78db360b..5ac9fa56 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -10,6 +10,7 @@ enum_trailing_comma = true match_block_trailing_comma = true struct_trailing_comma = "Always" wrap_comments = true +use_try_shorthand = true report_todo = "Always" report_fixme = "Always" diff --git a/src/bin/mdbook.rs b/src/bin/mdbook.rs index 3af3ada4..0b931457 100644 --- a/src/bin/mdbook.rs +++ b/src/bin/mdbook.rs @@ -121,7 +121,7 @@ fn init(args: &ArgMatches) -> Result<(), Box> { let mut book = MDBook::new(&book_dir); // Call the function that does the initialization - try!(book.init()); + book.init()?; // If flag `--theme` is present, copy theme to src if args.is_present("theme") { @@ -142,7 +142,7 @@ fn init(args: &ArgMatches) -> Result<(), Box> { } // Call the function that copies the theme - try!(book.copy_theme()); + book.copy_theme()?; println!("\nTheme copied."); } @@ -172,14 +172,14 @@ fn build(args: &ArgMatches) -> Result<(), Box> { let mut book = match args.value_of("dest-dir") { Some(dest_dir) => book.set_dest(Path::new(dest_dir)), - None => book + None => book, }; if args.is_present("no-create") { book.create_missing = false; } - try!(book.build()); + book.build()?; if args.is_present("open") { open(book.get_dest().join("index.html")); @@ -197,11 +197,11 @@ fn watch(args: &ArgMatches) -> Result<(), Box> { let mut book = match args.value_of("dest-dir") { Some(dest_dir) => book.set_dest(Path::new(dest_dir)), - None => book + None => book, }; if args.is_present("open") { - try!(book.build()); + book.build()?; open(book.get_dest().join("index.html")); } @@ -227,7 +227,7 @@ fn serve(args: &ArgMatches) -> Result<(), Box> { let mut book = match args.value_of("dest-dir") { Some(dest_dir) => book.set_dest(Path::new(dest_dir)), - None => book + None => book, }; let port = args.value_of("port").unwrap_or("3000"); @@ -253,25 +253,22 @@ fn serve(args: &ArgMatches) -> Result<(), Box> { socket.close(); }} - "#, public_address, ws_port, RELOAD_COMMAND).to_owned()); + "#, + public_address, + ws_port, + RELOAD_COMMAND)); - try!(book.build()); + book.build()?; let staticfile = staticfile::Static::new(book.get_dest()); let iron = iron::Iron::new(staticfile); let _iron = iron.http(&*address).unwrap(); - let ws_server = ws::WebSocket::new(|_| { - |_| { - Ok(()) - } - }).unwrap(); + let ws_server = ws::WebSocket::new(|_| |_| Ok(())).unwrap(); let broadcaster = ws_server.broadcaster(); - std::thread::spawn(move || { - ws_server.listen(&*ws_address).unwrap(); - }); + std::thread::spawn(move || { ws_server.listen(&*ws_address).unwrap(); }); println!("\nServing on {}", address); @@ -296,7 +293,7 @@ fn test(args: &ArgMatches) -> Result<(), Box> { let book_dir = get_book_dir(args); let mut book = MDBook::new(&book_dir).read_config(); - try!(book.test()); + book.test()?; Ok(()) } @@ -339,7 +336,7 @@ fn trigger_on_change(book: &mut MDBook, closure: F) -> () Err(e) => { println!("Error while trying to watch the files:\n\n\t{:?}", e); ::std::process::exit(0); - } + }, }; // Add the source directory to the watcher @@ -350,10 +347,14 @@ fn trigger_on_change(book: &mut MDBook, closure: F) -> () // Add the book.{json,toml} file to the watcher if it exists, because it's not // located in the source directory - if watcher.watch(book.get_root().join("book.json"), NonRecursive).is_err() { + if watcher + .watch(book.get_root().join("book.json"), NonRecursive) + .is_err() { // do nothing if book.json is not found } - if watcher.watch(book.get_root().join("book.toml"), NonRecursive).is_err() { + if watcher + .watch(book.get_root().join("book.toml"), NonRecursive) + .is_err() { // do nothing if book.toml is not found } @@ -361,16 +362,18 @@ fn trigger_on_change(book: &mut MDBook, closure: F) -> () loop { match rx.recv() { - Ok(event) => match event { - NoticeWrite(path) | - NoticeRemove(path) | - Create(path) | - Write(path) | - Remove(path) | - Rename(_, path) => { - closure(&path, book); + Ok(event) => { + match event { + NoticeWrite(path) | + NoticeRemove(path) | + Create(path) | + Write(path) | + Remove(path) | + Rename(_, path) => { + closure(&path, book); + }, + _ => {}, } - _ => {} }, Err(e) => { println!("An error occured: {:?}", e); diff --git a/src/book/bookconfig.rs b/src/book/bookconfig.rs index 9b1b33a5..ac1f0605 100644 --- a/src/book/bookconfig.rs +++ b/src/book/bookconfig.rs @@ -53,7 +53,7 @@ impl BookConfig { Err(_) => { error!("[*]: Failed to open {:?}", &path); exit(2); - } + }, }; if f.read_to_string(&mut data).is_err() { error!("[*]: Failed to read {:?}", &path); @@ -85,11 +85,11 @@ impl BookConfig { pub fn parse_from_toml_string(&mut self, data: &str) -> &mut Self { let config = match toml::from_str(data) { - Ok(x) => {x}, + Ok(x) => x, Err(e) => { error!("[*]: Toml parse errors in book.toml: {:?}", e); exit(2); - } + }, }; self.parse_from_btreemap(&config); @@ -97,7 +97,8 @@ impl BookConfig { self } - /// Parses the string to JSON and converts it to BTreeMap. + /// Parses the string to JSON and converts it + /// to BTreeMap. pub fn parse_from_json_string(&mut self, data: &str) -> &mut Self { let c: serde_json::Value = match serde_json::from_str(data) { @@ -105,7 +106,7 @@ impl BookConfig { Err(e) => { error!("[*]: JSON parse errors in book.json: {:?}", e); exit(2); - } + }, }; let config = json_object_to_btreemap(c.as_object().unwrap()); @@ -205,10 +206,7 @@ pub fn json_object_to_btreemap(json: &serde_json::Map let mut config: BTreeMap = BTreeMap::new(); for (key, value) in json.iter() { - config.insert( - String::from_str(key).unwrap(), - json_value_to_toml_value(value.to_owned()) - ); + config.insert(String::from_str(key).unwrap(), json_value_to_toml_value(value.to_owned())); } config @@ -223,10 +221,10 @@ pub fn json_value_to_toml_value(json: serde_json::Value) -> toml::Value { serde_json::Value::Number(x) => toml::Value::Float(x.as_f64().unwrap()), serde_json::Value::String(x) => toml::Value::String(x), serde_json::Value::Array(x) => { - toml::Value::Array(x.iter().map(|v| json_value_to_toml_value(v.to_owned())).collect()) - }, - serde_json::Value::Object(x) => { - toml::Value::Table(json_object_to_btreemap(&x)) + toml::Value::Array(x.iter() + .map(|v| json_value_to_toml_value(v.to_owned())) + .collect()) }, + serde_json::Value::Object(x) => toml::Value::Table(json_object_to_btreemap(&x)), } } diff --git a/src/book/bookitem.rs b/src/book/bookitem.rs index 51773371..e3e40225 100644 --- a/src/book/bookitem.rs +++ b/src/book/bookitem.rs @@ -37,10 +37,12 @@ impl Chapter { impl Serialize for Chapter { - fn serialize(&self, serializer: S) -> Result where S: Serializer { - let mut struct_ = try!(serializer.serialize_struct("Chapter", 2)); - try!(struct_.serialize_field("name", &self.name)); - try!(struct_.serialize_field("path", &self.path)); + fn serialize(&self, serializer: S) -> Result + where S: Serializer + { + let mut struct_ = serializer.serialize_struct("Chapter", 2)?; + struct_.serialize_field("name", &self.name)?; + struct_.serialize_field("path", &self.path)?; struct_.end() } } @@ -66,7 +68,8 @@ impl<'a> Iterator for BookItems<'a> { let cur = &self.items[self.current_index]; match *cur { - BookItem::Chapter(_, ref ch) | BookItem::Affix(ref ch) => { + BookItem::Chapter(_, ref ch) | + BookItem::Affix(ref ch) => { self.stack.push((self.items, self.current_index)); self.items = &ch.sub_items[..]; self.current_index = 0; diff --git a/src/book/mod.rs b/src/book/mod.rs index 5e413c87..0a0e1099 100644 --- a/src/book/mod.rs +++ b/src/book/mod.rs @@ -54,8 +54,10 @@ impl MDBook { /// # } /// ``` /// - /// In this example, `root_dir` will be the root directory of our book and is specified in function - /// of the current working directory by using a relative path instead of an absolute path. + /// In this example, `root_dir` will be the root directory of our book + /// and is specified in function of the current working directory + /// by using a relative path instead of an + /// absolute path. /// /// Default directory paths: /// @@ -63,7 +65,8 @@ impl MDBook { /// - output: `root/book` /// - theme: `root/theme` /// - /// They can both be changed by using [`set_src()`](#method.set_src) and [`set_dest()`](#method.set_dest) + /// They can both be changed by using [`set_src()`](#method.set_src) and + /// [`set_dest()`](#method.set_dest) pub fn new(root: &Path) -> MDBook { @@ -90,7 +93,8 @@ impl MDBook { } } - /// Returns a flat depth-first iterator over the elements of the book, it returns an [BookItem enum](bookitem.html): + /// Returns a flat depth-first iterator over the elements of the book, + /// it returns an [BookItem enum](bookitem.html): /// `(section: String, bookitem: &BookItem)` /// /// ```no_run @@ -126,7 +130,8 @@ impl MDBook { } } - /// `init()` creates some boilerplate files and directories to get you started with your book. + /// `init()` creates some boilerplate files and directories + /// to get you started with your book. /// /// ```text /// book-test/ @@ -136,7 +141,8 @@ impl MDBook { /// └── SUMMARY.md /// ``` /// - /// It uses the paths given as source and output directories and adds a `SUMMARY.md` and a + /// It uses the paths given as source and output directories + /// and adds a `SUMMARY.md` and a /// `chapter_1.md` to the source directory. pub fn init(&mut self) -> Result<(), Box> { @@ -152,12 +158,12 @@ impl MDBook { if !self.dest.exists() { debug!("[*]: {:?} does not exist, trying to create directory", self.dest); - try!(fs::create_dir_all(&self.dest)); + fs::create_dir_all(&self.dest)?; } if !self.src.exists() { debug!("[*]: {:?} does not exist, trying to create directory", self.src); - try!(fs::create_dir_all(&self.src)); + fs::create_dir_all(&self.src)?; } let summary = self.src.join("SUMMARY.md"); @@ -167,18 +173,18 @@ impl MDBook { // Summary does not exist, create it debug!("[*]: {:?} does not exist, trying to create SUMMARY.md", self.src.join("SUMMARY.md")); - let mut f = try!(File::create(&self.src.join("SUMMARY.md"))); + let mut f = File::create(&self.src.join("SUMMARY.md"))?; debug!("[*]: Writing to SUMMARY.md"); - try!(writeln!(f, "# Summary")); - try!(writeln!(f, "")); - try!(writeln!(f, "- [Chapter 1](./chapter_1.md)")); + writeln!(f, "# Summary")?; + writeln!(f, "")?; + writeln!(f, "- [Chapter 1](./chapter_1.md)")?; } } // parse SUMMARY.md, and create the missing item related file - try!(self.parse_summary()); + self.parse_summary()?; debug!("[*]: constructing paths for missing files"); for item in self.iter() { @@ -193,16 +199,15 @@ impl MDBook { if !path.exists() { if !self.create_missing { - return Err(format!( - "'{}' referenced from SUMMARY.md does not exist.", - path.to_string_lossy()).into()); + return Err(format!("'{}' referenced from SUMMARY.md does not exist.", path.to_string_lossy()) + .into()); } debug!("[*]: {:?} does not exist, trying to create file", path); - try!(::std::fs::create_dir_all(path.parent().unwrap())); - let mut f = try!(File::create(path)); + ::std::fs::create_dir_all(path.parent().unwrap())?; + let mut f = File::create(path)?; // debug!("[*]: Writing to {:?}", path); - try!(writeln!(f, "# {}", ch.name)); + writeln!(f, "# {}", ch.name)?; } } } @@ -217,17 +222,19 @@ impl MDBook { if !gitignore.exists() { // Gitignore does not exist, create it - // Because of `src/book/mdbook.rs#L37-L39`, `dest` will always start with `root`. If it - // is not, `strip_prefix` will return an Error. + // Because of `src/book/mdbook.rs#L37-L39`, + // `dest` will always start with `root`. + // If it is not, `strip_prefix` will return an Error. if !self.get_dest().starts_with(&self.root) { return; } let relative = self.get_dest() - .strip_prefix(&self.root) - .expect("Destination is not relative to root."); - let relative = relative.to_str() - .expect("Path could not be yielded into a string slice."); + .strip_prefix(&self.root) + .expect("Destination is not relative to root."); + let relative = relative + .to_str() + .expect("Path could not be yielded into a string slice."); debug!("[*]: {:?} does not exist, trying to create .gitignore", gitignore); @@ -239,20 +246,21 @@ impl MDBook { } } - /// The `build()` method is the one where everything happens. First it parses `SUMMARY.md` to - /// construct the book's structure in the form of a `Vec` and then calls `render()` + /// The `build()` method is the one where everything happens. + /// First it parses `SUMMARY.md` to construct the book's structure + /// in the form of a `Vec` and then calls `render()` /// method of the current renderer. /// /// It is the renderer who generates all the output files. pub fn build(&mut self) -> Result<(), Box> { debug!("[fn]: build"); - try!(self.init()); + self.init()?; // Clean output directory - try!(utils::fs::remove_dir_content(&self.dest)); + utils::fs::remove_dir_content(&self.dest)?; - try!(self.renderer.render(&self)); + self.renderer.render(&self)?; Ok(()) } @@ -269,55 +277,54 @@ impl MDBook { if !theme_dir.exists() { debug!("[*]: {:?} does not exist, trying to create directory", theme_dir); - try!(fs::create_dir(&theme_dir)); + fs::create_dir(&theme_dir)?; } // index.hbs - let mut index = try!(File::create(&theme_dir.join("index.hbs"))); - try!(index.write_all(theme::INDEX)); + let mut index = File::create(&theme_dir.join("index.hbs"))?; + index.write_all(theme::INDEX)?; // book.css - let mut css = try!(File::create(&theme_dir.join("book.css"))); - try!(css.write_all(theme::CSS)); + let mut css = File::create(&theme_dir.join("book.css"))?; + css.write_all(theme::CSS)?; // favicon.png - let mut favicon = try!(File::create(&theme_dir.join("favicon.png"))); - try!(favicon.write_all(theme::FAVICON)); + let mut favicon = File::create(&theme_dir.join("favicon.png"))?; + favicon.write_all(theme::FAVICON)?; // book.js - let mut js = try!(File::create(&theme_dir.join("book.js"))); - try!(js.write_all(theme::JS)); + let mut js = File::create(&theme_dir.join("book.js"))?; + js.write_all(theme::JS)?; // highlight.css - let mut highlight_css = try!(File::create(&theme_dir.join("highlight.css"))); - try!(highlight_css.write_all(theme::HIGHLIGHT_CSS)); + let mut highlight_css = File::create(&theme_dir.join("highlight.css"))?; + highlight_css.write_all(theme::HIGHLIGHT_CSS)?; // highlight.js - let mut highlight_js = try!(File::create(&theme_dir.join("highlight.js"))); - try!(highlight_js.write_all(theme::HIGHLIGHT_JS)); + let mut highlight_js = File::create(&theme_dir.join("highlight.js"))?; + highlight_js.write_all(theme::HIGHLIGHT_JS)?; Ok(()) } pub fn write_file>(&self, filename: P, content: &[u8]) -> Result<(), Box> { let path = self.get_dest().join(filename); - try!(utils::fs::create_file(&path).and_then(|mut file| { - file.write_all(content) - }).map_err(|e| { - io::Error::new(io::ErrorKind::Other, format!("Could not create {}: {}", path.display(), e)) - })); + utils::fs::create_file(&path) + .and_then(|mut file| file.write_all(content)) + .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("Could not create {}: {}", path.display(), e)))?; Ok(()) } - /// Parses the `book.json` file (if it exists) to extract the configuration parameters. + /// Parses the `book.json` file (if it exists) to extract + /// the configuration parameters. /// The `book.json` file should be in the root directory of the book. /// The root directory is the one specified when creating a new `MDBook` pub fn read_config(mut self) -> Self { let config = BookConfig::new(&self.root) - .read_config(&self.root) - .to_owned(); + .read_config(&self.root) + .to_owned(); self.title = config.title; self.description = config.description; @@ -330,8 +337,10 @@ impl MDBook { self } - /// You can change the default renderer to another one by using this method. The only requirement - /// is for your renderer to implement the [Renderer trait](../../renderer/renderer/trait.Renderer.html) + /// You can change the default renderer to another one + /// by using this method. The only requirement + /// is for your renderer to implement the + /// [Renderer trait](../../renderer/renderer/trait.Renderer.html) /// /// ```no_run /// extern crate mdbook; @@ -343,12 +352,14 @@ impl MDBook { /// let mut book = MDBook::new(Path::new("mybook")) /// .set_renderer(Box::new(HtmlHandlebars::new())); /// - /// // In this example we replace the default renderer by the default renderer... - /// // Don't forget to put your renderer in a Box + /// // In this example we replace the default renderer + /// // by the default renderer... + /// // Don't forget to put your renderer in a Box /// } /// ``` /// - /// **note:** Don't forget to put your renderer in a `Box` before passing it to `set_renderer()` + /// **note:** Don't forget to put your renderer in a `Box` + /// before passing it to `set_renderer()` pub fn set_renderer(mut self, renderer: Box) -> Self { self.renderer = renderer; @@ -357,7 +368,7 @@ impl MDBook { pub fn test(&mut self) -> Result<(), Box> { // read in the chapters - try!(self.parse_summary()); + self.parse_summary()?; for item in self.iter() { if let BookItem::Chapter(_, ref ch) = *item { @@ -367,17 +378,15 @@ impl MDBook { println!("[*]: Testing file: {:?}", path); - let output_result = Command::new("rustdoc") - .arg(&path) - .arg("--test") - .output(); - let output = try!(output_result); + let output_result = Command::new("rustdoc").arg(&path).arg("--test").output(); + let output = output_result?; if !output.status.success() { - return Err(Box::new(io::Error::new(ErrorKind::Other, format!( - "{}\n{}", - String::from_utf8_lossy(&output.stdout), - String::from_utf8_lossy(&output.stderr)))) as Box); + return Err(Box::new(io::Error::new(ErrorKind::Other, + format!("{}\n{}", + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr)))) as + Box); } } } @@ -480,7 +489,7 @@ impl MDBook { // Construct book fn parse_summary(&mut self) -> Result<(), Box> { // When append becomes stable, use self.content.append() ... - self.content = try!(parse::construct_bookitems(&self.src.join("SUMMARY.md"))); + self.content = parse::construct_bookitems(&self.src.join("SUMMARY.md"))?; Ok(()) } } diff --git a/src/lib.rs b/src/lib.rs index 49c56fac..303bb23b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -76,7 +76,8 @@ extern crate handlebars; extern crate pulldown_cmark; extern crate regex; -#[macro_use] extern crate log; +#[macro_use] +extern crate log; pub mod book; mod parse; pub mod renderer; diff --git a/src/parse/summary.rs b/src/parse/summary.rs index 3d966355..cc8452d4 100644 --- a/src/parse/summary.rs +++ b/src/parse/summary.rs @@ -6,10 +6,10 @@ use book::bookitem::{BookItem, Chapter}; pub fn construct_bookitems(path: &PathBuf) -> Result> { debug!("[fn]: construct_bookitems"); let mut summary = String::new(); - try!(try!(File::open(path)).read_to_string(&mut summary)); + File::open(path)?.read_to_string(&mut summary)?; debug!("[*]: Parse SUMMARY.md"); - let top_items = try!(parse_level(&mut summary.split('\n').collect(), 0, vec![0])); + let top_items = parse_level(&mut summary.split('\n').collect(), 0, vec![0])?; debug!("[*]: Done parsing SUMMARY.md"); Ok(top_items) } @@ -22,9 +22,10 @@ fn parse_level(summary: &mut Vec<&str>, current_level: i32, mut section: Vec, current_level: i32, mut section: Vec, current_level: i32, mut section: Vec 0 => { + BookItem::Affix(_) | + BookItem::Spacer if level > 0 => { return Err(Error::new(ErrorKind::Other, "Your summary.md is messed up\n\n \ @@ -98,7 +102,9 @@ fn parse_level(summary: &mut Vec<&str>, current_level: i32, mut section: Vec parsed_item, diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs index 6ecd9e17..cb452000 100644 --- a/src/renderer/html_handlebars/hbs_renderer.rs +++ b/src/renderer/html_handlebars/hbs_renderer.rs @@ -37,7 +37,8 @@ impl Renderer for HtmlHandlebars { // Register template debug!("[*]: Register handlebars template"); - try!(handlebars.register_template_string("index", try!(String::from_utf8(theme.index)))); + handlebars + .register_template_string("index", String::from_utf8(theme.index)?)?; // Register helpers debug!("[*]: Register handlebars helpers"); @@ -45,7 +46,7 @@ impl Renderer for HtmlHandlebars { handlebars.register_helper("previous", Box::new(helpers::navigation::previous)); handlebars.register_helper("next", Box::new(helpers::navigation::next)); - let mut data = try!(make_data(book)); + let mut data = make_data(book)?; // Print version let mut print_content: String = String::new(); @@ -69,11 +70,11 @@ impl Renderer for HtmlHandlebars { let path = book.get_src().join(&ch.path); debug!("[*]: Opening file: {:?}", path); - let mut f = try!(File::open(&path)); + let mut f = File::open(&path)?; let mut content: String = String::new(); debug!("[*]: Reading file"); - try!(f.read_to_string(&mut content)); + f.read_to_string(&mut content)?; // Parse for playpen links if let Some(p) = path.parent() { @@ -85,8 +86,10 @@ impl Renderer for HtmlHandlebars { print_content.push_str(&content); // Update the context with data for this file - let path = ch.path.to_str().ok_or_else(|| - io::Error::new(io::ErrorKind::Other, "Could not convert path to str"))?; + let path = + ch.path + .to_str() + .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Could not convert path to str"))?; data.insert("path".to_owned(), json!(path)); data.insert("content".to_owned(), json!(content)); data.insert("chapter_title".to_owned(), json!(ch.name)); @@ -94,7 +97,7 @@ impl Renderer for HtmlHandlebars { // Render the handlebars template with the data debug!("[*]: Render template"); - let rendered = try!(handlebars.render("index", &data)); + let rendered = handlebars.render("index", &data)?; let filename = Path::new(&ch.path).with_extension("html"); @@ -106,24 +109,26 @@ impl Renderer for HtmlHandlebars { // Write to file info!("[*] Creating {:?} ✓", filename.display()); - try!(book.write_file(filename, &rendered.into_bytes())); + book.write_file(filename, &rendered.into_bytes())?; // Create an index.html from the first element in SUMMARY.md if index { debug!("[*]: index.html"); let mut content = String::new(); - let _source = try!(File::open(book.get_dest().join(&ch.path.with_extension("html")))) + let _source = File::open(book.get_dest().join(&ch.path.with_extension("html")))? .read_to_string(&mut content); - // This could cause a problem when someone displays code containing + // This could cause a problem when someone displays + // code containing // on the front page, however this case should be very very rare... - content = content.lines() + content = content + .lines() .filter(|line| !line.contains(" Result match *item { BookItem::Affix(ref ch) => { chapter.insert("name".to_owned(), json!(ch.name)); - let path = ch.path.to_str().ok_or_else(|| - io::Error::new(io::ErrorKind::Other, "Could not convert path to str"))?; + let path = ch.path + .to_str() + .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Could not convert path to str"))?; chapter.insert("path".to_owned(), json!(path)); }, BookItem::Chapter(ref s, ref ch) => { chapter.insert("section".to_owned(), json!(s)); chapter.insert("name".to_owned(), json!(ch.name)); - let path = ch.path.to_str().ok_or_else(|| - io::Error::new(io::ErrorKind::Other, "Could not convert path to str"))?; + let path = ch.path + .to_str() + .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Could not convert path to str"))?; chapter.insert("path".to_owned(), json!(path)); }, BookItem::Spacer => { @@ -237,42 +244,55 @@ fn build_header_links(html: String, filename: &str) -> String { let regex = Regex::new(r"(.*?)").unwrap(); let mut id_counter = HashMap::new(); - regex.replace_all(&html, |caps: &Captures| { - let level = &caps[1]; - let text = &caps[2]; - let mut id = text.to_string(); - let repl_sub = vec!["", "", "", "", - "", "", - "<", ">", "&", "'", """]; - for sub in repl_sub { - id = id.replace(sub, ""); - } - let id = id.chars().filter_map(|c| { - if c.is_alphanumeric() || c == '-' || c == '_' { - if c.is_ascii() { - Some(c.to_ascii_lowercase()) - } else { - Some(c) - } - } else if c.is_whitespace() && c.is_ascii() { - Some('-') - } else { - None + regex + .replace_all(&html, |caps: &Captures| { + let level = &caps[1]; + let text = &caps[2]; + let mut id = text.to_string(); + let repl_sub = vec!["", + "", + "", + "", + "", + "", + "<", + ">", + "&", + "'", + """]; + for sub in repl_sub { + id = id.replace(sub, ""); } - }).collect::(); + let id = id.chars() + .filter_map(|c| if c.is_alphanumeric() || c == '-' || c == '_' { + if c.is_ascii() { + Some(c.to_ascii_lowercase()) + } else { + Some(c) + } + } else if c.is_whitespace() && c.is_ascii() { + Some('-') + } else { + None + }) + .collect::(); - let id_count = *id_counter.get(&id).unwrap_or(&0); - id_counter.insert(id.clone(), id_count + 1); + let id_count = *id_counter.get(&id).unwrap_or(&0); + id_counter.insert(id.clone(), id_count + 1); - let id = if id_count > 0 { - format!("{}-{}", id, id_count) - } else { - id - }; + let id = if id_count > 0 { + format!("{}-{}", id, id_count) + } else { + id + }; - format!("{text}", - level=level, id=id, text=text, filename=filename) - }).into_owned() + format!("{text}", + level = level, + id = id, + text = text, + filename = filename) + }) + .into_owned() } // anchors to the same page (href="#anchor") do not work because of @@ -280,18 +300,24 @@ fn build_header_links(html: String, filename: &str) -> String { // that in a very inelegant way fn fix_anchor_links(html: String, filename: &str) -> String { let regex = Regex::new(r##"]+)href="#([^"]+)"([^>]*)>"##).unwrap(); - regex.replace_all(&html, |caps: &Captures| { - let before = &caps[1]; - let anchor = &caps[2]; - let after = &caps[3]; + regex + .replace_all(&html, |caps: &Captures| { + let before = &caps[1]; + let anchor = &caps[2]; + let after = &caps[3]; - format!("", - before=before, filename=filename, anchor=anchor, after=after) - }).into_owned() + format!("", + before = before, + filename = filename, + anchor = anchor, + after = after) + }) + .into_owned() } -// The rust book uses annotations for rustdoc to test code snippets, like the following: +// The rust book uses annotations for rustdoc to test code snippets, +// like the following: // ```rust,should_panic // fn main() { // // Code here @@ -300,40 +326,48 @@ fn fix_anchor_links(html: String, filename: &str) -> String { // This function replaces all commas by spaces in the code block classes fn fix_code_blocks(html: String) -> String { let regex = Regex::new(r##"]+)class="([^"]+)"([^>]*)>"##).unwrap(); - regex.replace_all(&html, |caps: &Captures| { - let before = &caps[1]; - let classes = &caps[2].replace(",", " "); - let after = &caps[3]; + regex + .replace_all(&html, |caps: &Captures| { + let before = &caps[1]; + let classes = &caps[2].replace(",", " "); + let after = &caps[3]; - format!("", before=before, classes=classes, after=after) - }).into_owned() + format!("", before = before, classes = classes, after = after) + }) + .into_owned() } fn add_playpen_pre(html: String) -> String { let regex = Regex::new(r##"((?s)]?class="([^"]+)".*?>(.*?))"##).unwrap(); - regex.replace_all(&html, |caps: &Captures| { - let text = &caps[1]; - let classes = &caps[2]; - let code = &caps[3]; + regex + .replace_all(&html, |caps: &Captures| { + let text = &caps[1]; + let classes = &caps[2]; + let code = &caps[3]; - if classes.contains("language-rust") && !classes.contains("ignore") { - // wrap the contents in an external pre block + if classes.contains("language-rust") && !classes.contains("ignore") { + // wrap the contents in an external pre block - if text.contains("fn main") || text.contains("quick_main!") { - format!("
{}
", text) - } else { - // we need to inject our own main - let (attrs, code) = partition_source(code); - format!("
# #![allow(unused_variables)]
+                if text.contains("fn main") || text.contains("quick_main!") {
+                    format!("
{}
", text) + } else { + // we need to inject our own main + let (attrs, code) = partition_source(code); + format!("
# #![allow(unused_variables)]
 {}#fn main() {{
-{}
-#}}
", classes, attrs, code) +\ + {} +#}}
", + classes, + attrs, + code) + } + } else { + // not language-rust, so no-op + format!("{}", text) } - } else { - // not language-rust, so no-op - format!("{}", text) - } - }).into_owned() + }) + .into_owned() } fn partition_source(s: &str) -> (String, String) { @@ -343,8 +377,7 @@ fn partition_source(s: &str) -> (String, String) { for line in s.lines() { let trimline = line.trim(); - let header = trimline.chars().all(|c| c.is_whitespace()) || - trimline.starts_with("#!["); + let header = trimline.chars().all(|c| c.is_whitespace()) || trimline.starts_with("#!["); if !header || after_header { after_header = true; after.push_str(line); @@ -356,4 +389,4 @@ fn partition_source(s: &str) -> (String, String) { } (before, after) -} \ No newline at end of file +} diff --git a/src/renderer/html_handlebars/helpers/navigation.rs b/src/renderer/html_handlebars/helpers/navigation.rs index 50dd7a4a..ca37efdb 100644 --- a/src/renderer/html_handlebars/helpers/navigation.rs +++ b/src/renderer/html_handlebars/helpers/navigation.rs @@ -14,9 +14,12 @@ pub fn previous(_h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<( // get value from context data // rc.get_path() is current json parent path, you should always use it like this // param is the key of value you want to display - let chapters = rc.context().navigate(rc.get_path(), &VecDeque::new(), "chapters").to_owned(); + let chapters = rc.context() + .navigate(rc.get_path(), &VecDeque::new(), "chapters") + .to_owned(); - let current = rc.context().navigate(rc.get_path(), &VecDeque::new(), "path") + let current = rc.context() + .navigate(rc.get_path(), &VecDeque::new(), "path") .to_string() .replace("\"", ""); @@ -84,7 +87,7 @@ pub fn previous(_h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<( match _h.template() { Some(t) => { *rc.context_mut() = updated_context; - try!(t.render(r, rc)); + t.render(r, rc)?; }, None => return Err(RenderError::new("Error with the handlebars template")), } @@ -115,9 +118,12 @@ pub fn next(_h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), R // get value from context data // rc.get_path() is current json parent path, you should always use it like this // param is the key of value you want to display - let chapters = rc.context().navigate(rc.get_path(), &VecDeque::new(), "chapters").to_owned(); + let chapters = rc.context() + .navigate(rc.get_path(), &VecDeque::new(), "chapters") + .to_owned(); - let current = rc.context().navigate(rc.get_path(), &VecDeque::new(), "path") + let current = rc.context() + .navigate(rc.get_path(), &VecDeque::new(), "path") .to_string() .replace("\"", ""); @@ -181,7 +187,7 @@ pub fn next(_h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Result<(), R match _h.template() { Some(t) => { *rc.context_mut() = updated_context; - try!(t.render(r, rc)); + t.render(r, rc)?; }, None => return Err(RenderError::new("Error with the handlebars template")), } diff --git a/src/renderer/html_handlebars/helpers/playpen.rs b/src/renderer/html_handlebars/helpers/playpen.rs index c71a70a0..5e49811f 100644 --- a/src/renderer/html_handlebars/helpers/playpen.rs +++ b/src/renderer/html_handlebars/helpers/playpen.rs @@ -4,8 +4,9 @@ use std::io::Read; pub fn render_playpen(s: &str, path: &Path) -> String { - // When replacing one thing in a string by something with a different length, the indices - // after that will not correspond, we therefore have to store the difference to correct this + // When replacing one thing in a string by something with a different length, + // the indices after that will not correspond, + // we therefore have to store the difference to correct this let mut previous_end_index = 0; let mut replaced = String::new(); @@ -35,13 +36,13 @@ pub fn render_playpen(s: &str, path: &Path) -> String { continue; }; - let replacement = String::new() + "
" + &file_content +
-                          "
"; + let replacement = String::new() + "
" + &file_content + "
"; replaced.push_str(&s[previous_end_index..playpen.start_index]); replaced.push_str(&replacement); previous_end_index = playpen.end_index; - // println!("Playpen{{ {}, {}, {:?}, {} }}", playpen.start_index, playpen.end_index, playpen.rust_file, + // println!("Playpen{{ {}, {}, {:?}, {} }}", playpen.start_index, + // playpen.end_index, playpen.rust_file, // playpen.editable); } @@ -100,12 +101,12 @@ fn find_playpens(s: &str, base_path: &Path) -> Vec { .unwrap_or(false); playpens.push(Playpen { - start_index: i, - end_index: end_i, - rust_file: base_path.join(PathBuf::from(params[0])), - editable: editable, - escaped: escaped, - }) + start_index: i, + end_index: end_i, + rust_file: base_path.join(PathBuf::from(params[0])), + editable: editable, + escaped: escaped, + }) } playpens @@ -189,7 +190,11 @@ fn test_find_playpens_escaped_playpen() { println!("\nOUTPUT: {:?}\n", find_playpens(s, Path::new(""))); assert!(find_playpens(s, Path::new("")) == - vec![ - Playpen{start_index: 39, end_index: 68, rust_file: PathBuf::from("file.rs"), editable: true, escaped: true}, - ]); + vec![Playpen { + start_index: 39, + end_index: 68, + rust_file: PathBuf::from("file.rs"), + editable: true, + escaped: true, + }]); } diff --git a/src/renderer/html_handlebars/helpers/toc.rs b/src/renderer/html_handlebars/helpers/toc.rs index c7cc074a..bfc9513c 100644 --- a/src/renderer/html_handlebars/helpers/toc.rs +++ b/src/renderer/html_handlebars/helpers/toc.rs @@ -15,9 +15,14 @@ impl HelperDef for RenderToc { // get value from context data // rc.get_path() is current json parent path, you should always use it like this // param is the key of value you want to display - let chapters = rc.context().navigate(rc.get_path(), &VecDeque::new(), "chapters").to_owned(); - let current = rc.context().navigate(rc.get_path(), &VecDeque::new(), "path").to_string().replace("\"", ""); - try!(rc.writer.write_all("".as_bytes())?; + rc.writer.write_all("".as_bytes())?; current_level -= 1; } - try!(rc.writer.write_all("".as_bytes())); + rc.writer.write_all("".as_bytes())?; Ok(()) } } diff --git a/src/theme/mod.rs b/src/theme/mod.rs index 130dd115..6082ff51 100644 --- a/src/theme/mod.rs +++ b/src/theme/mod.rs @@ -19,11 +19,14 @@ pub static FONT_AWESOME_WOFF: &'static [u8] = include_bytes!("_FontAwesome/fonts pub static FONT_AWESOME_WOFF2: &'static [u8] = include_bytes!("_FontAwesome/fonts/fontawesome-webfont.woff2"); pub static FONT_AWESOME_OTF: &'static [u8] = include_bytes!("_FontAwesome/fonts/FontAwesome.otf"); -/// The `Theme` struct should be used instead of the static variables because the `new()` method -/// will look if the user has a theme directory in his source folder and use the users theme instead +/// The `Theme` struct should be used instead of the static variables because +/// the `new()` method +/// will look if the user has a theme directory in his source folder and use +/// the users theme instead /// of the default. /// -/// You should exceptionnaly use the static variables only if you need the default theme even if the +/// You should exceptionnaly use the static variables only if you need the +/// default theme even if the /// user has specified another theme. pub struct Theme { pub index: Vec, diff --git a/src/utils/fs.rs b/src/utils/fs.rs index d40e621b..c2d7fe80 100644 --- a/src/utils/fs.rs +++ b/src/utils/fs.rs @@ -24,10 +24,11 @@ pub fn file_to_string(path: &Path) -> Result> { Ok(content) } -/// Takes a path and returns a path containing just enough `../` to point to the root of the given path. +/// Takes a path and returns a path containing just enough `../` to point to +/// the root of the given path. /// -/// This is mostly interesting for a relative path to point back to the directory from where the -/// path starts. +/// This is mostly interesting for a relative path to point back to the +/// directory from where the path starts. /// /// ```ignore /// let mut path = Path::new("some/relative/path"); @@ -41,9 +42,10 @@ pub fn file_to_string(path: &Path) -> Result> { /// "../../" /// ``` /// -/// **note:** it's not very fool-proof, if you find a situation where it doesn't return the correct -/// path. Consider [submitting a new issue](https://github.com/azerupi/mdBook/issues) or a -/// [pull-request](https://github.com/azerupi/mdBook/pulls) to improve it. +/// **note:** it's not very fool-proof, if you find a situation where +/// it doesn't return the correct path. +/// Consider [submitting a new issue](https://github.com/azerupi/mdBook/issues) +/// or a [pull-request](https://github.com/azerupi/mdBook/pulls) to improve it. pub fn path_to_root(path: &Path) -> String { debug!("[fn]: path_to_root"); @@ -66,8 +68,9 @@ pub fn path_to_root(path: &Path) -> String { -/// This function creates a file and returns it. But before creating the file it checks every -/// directory in the path to see if it exists, and if it does not it will be created. +/// This function creates a file and returns it. But before creating the file +/// it checks every directory in the path to see if it exists, +/// and if it does not it will be created. pub fn create_file(path: &Path) -> io::Result { debug!("[fn]: create_file"); @@ -76,7 +79,7 @@ pub fn create_file(path: &Path) -> io::Result { if let Some(p) = path.parent() { debug!("Parent directory is: {:?}", p); - try!(fs::create_dir_all(p)); + fs::create_dir_all(p)?; } debug!("[*]: Create file: {:?}", path); @@ -86,13 +89,13 @@ pub fn create_file(path: &Path) -> io::Result { /// Removes all the content of a directory but not the directory itself pub fn remove_dir_content(dir: &Path) -> Result<(), Box> { - for item in try!(fs::read_dir(dir)) { + for item in fs::read_dir(dir)? { if let Ok(item) = item { let item = item.path(); if item.is_dir() { - try!(fs::remove_dir_all(item)); + fs::remove_dir_all(item)?; } else { - try!(fs::remove_file(item)); + fs::remove_file(item)?; } } } @@ -101,20 +104,21 @@ pub fn remove_dir_content(dir: &Path) -> Result<(), Box> { /// /// -/// Copies all files of a directory to another one except the files with the extensions given in the -/// `ext_blacklist` array +/// Copies all files of a directory to another one except the files +/// with the extensions given in the `ext_blacklist` array -pub fn copy_files_except_ext(from: &Path, to: &Path, recursive: bool, ext_blacklist: &[&str]) -> Result<(), Box> { +pub fn copy_files_except_ext(from: &Path, to: &Path, recursive: bool, ext_blacklist: &[&str]) + -> Result<(), Box> { debug!("[fn] copy_files_except_ext"); // Check that from and to are different if from == to { return Ok(()); } debug!("[*] Loop"); - for entry in try!(fs::read_dir(from)) { - let entry = try!(entry); + for entry in fs::read_dir(from)? { + let entry = entry?; debug!("[*] {:?}", entry.path()); - let metadata = try!(entry.metadata()); + let metadata = entry.metadata()?; // If the entry is a dir and the recursive option is enabled, call itself if metadata.is_dir() && recursive { @@ -125,13 +129,10 @@ pub fn copy_files_except_ext(from: &Path, to: &Path, recursive: bool, ext_blackl // check if output dir already exists if !to.join(entry.file_name()).exists() { - try!(fs::create_dir(&to.join(entry.file_name()))); + fs::create_dir(&to.join(entry.file_name()))?; } - try!(copy_files_except_ext(&from.join(entry.file_name()), - &to.join(entry.file_name()), - true, - ext_blacklist)); + copy_files_except_ext(&from.join(entry.file_name()), &to.join(entry.file_name()), true, ext_blacklist)?; } else if metadata.is_file() { // Check if it is in the blacklist @@ -141,13 +142,22 @@ pub fn copy_files_except_ext(from: &Path, to: &Path, recursive: bool, ext_blackl } } debug!("[*] creating path for file: {:?}", - &to.join(entry.path().file_name().expect("a file should have a file name..."))); + &to.join(entry + .path() + .file_name() + .expect("a file should have a file name..."))); info!("[*] Copying file: {:?}\n to {:?}", entry.path(), - &to.join(entry.path().file_name().expect("a file should have a file name..."))); - try!(fs::copy(entry.path(), - &to.join(entry.path().file_name().expect("a file should have a file name...")))); + &to.join(entry + .path() + .file_name() + .expect("a file should have a file name..."))); + fs::copy(entry.path(), + &to.join(entry + .path() + .file_name() + .expect("a file should have a file name...")))?; } } Ok(())