Big clean-up, reduced the unwrap's to 2 in the library part! Closes #36 The unwraps where replaced with more diverse error messages #14

This commit is contained in:
Mathieu David 2015-08-11 22:55:51 +02:00
parent b6034e8fbe
commit 0932bfd576
6 changed files with 161 additions and 70 deletions

View File

@ -36,7 +36,7 @@ by appending a path to the command:
mdbook init path/to/book
```
#### --theme
## --theme
When you use the `--theme` argument, the default theme will be copied into a directory
called `theme` in your source directory so that you can modify it.

View File

@ -8,6 +8,7 @@ use std::path::{Path, PathBuf};
pub struct BookConfig {
pub title: String,
pub author: String,
root: PathBuf,
dest: PathBuf,
src: PathBuf,
pub indent_spaces: i32,
@ -16,10 +17,11 @@ pub struct BookConfig {
impl BookConfig {
pub fn new() -> Self {
pub fn new(root: &Path) -> Self {
BookConfig {
title: String::new(),
author: String::new(),
root: root.to_owned(),
dest: PathBuf::from("book"),
src: PathBuf::from("src"),
indent_spaces: 4, // indentation used for SUMMARY.md
@ -42,32 +44,50 @@ impl BookConfig {
debug!("[*]: Reading config");
let mut data = String::new();
config_file.read_to_string(&mut data).unwrap();
// Just return if an error occured.
// I would like to propagate the error, but I have to return `&self`
match config_file.read_to_string(&mut data) {
Err(_) => return self,
_ => {},
}
// Convert to JSON
let config = Json::from_str(&data).unwrap();
if let Ok(config) = Json::from_str(&data) {
// Extract data
// Extract data
debug!("[*]: Extracting data from config");
// Title & author
if let Some(a) = config.find_path(&["title"]) { self.title = a.to_string().replace("\"", "") }
if let Some(a) = config.find_path(&["author"]) { self.author = a.to_string().replace("\"", "") }
debug!("[*]: Extracting data from config");
// Title & author
if let Some(a) = config.find_path(&["title"]) { self.title = a.to_string().replace("\"", "") }
if let Some(a) = config.find_path(&["author"]) { self.author = a.to_string().replace("\"", "") }
// Destination
if let Some(a) = config.find_path(&["dest"]) {
let dest = PathBuf::from(&a.to_string().replace("\"", ""));
// Destination
if let Some(a) = config.find_path(&["dest"]) {
let dest = PathBuf::from(&a.to_string().replace("\"", ""));
// If path is relative make it absolute from the parent directory of src
if dest.is_relative() {
let dest = &self.get_src().parent().unwrap().join(&dest);
self.set_dest(dest);
// If path is relative make it absolute from the parent directory of src
match dest.is_relative() {
true => {
let dest = self.get_root().join(&dest).to_owned();
self.set_dest(&dest);
},
false => { self.set_dest(&dest); },
}
}
}
self
}
pub fn get_root(&self) -> &Path {
&self.root
}
pub fn set_root(&mut self, root: &Path) -> &mut Self {
self.root = root.to_owned();
self
}
pub fn get_dest(&self) -> &Path {
&self.dest
}

View File

@ -1,4 +1,4 @@
use std::path::{Path, PathBuf};
use std::path::Path;
use std::fs::{self, File, metadata};
use std::io::Write;
use std::error::Error;
@ -12,7 +12,6 @@ use renderer::HtmlHandlebars;
pub struct MDBook {
config: BookConfig,
pub root: PathBuf,
pub content: Vec<BookItem>,
renderer: Box<Renderer>,
}
@ -39,9 +38,8 @@ impl MDBook {
}
MDBook {
root: root.to_path_buf(),
content: vec![],
config: BookConfig::new()
config: BookConfig::new(root)
.set_src(&root.join("src"))
.set_dest(&root.join("book"))
.to_owned(),
@ -106,7 +104,7 @@ impl MDBook {
// There is a very high chance that the error is due to the fact that
// the directory / file does not exist
debug!("[*]: {:?} does not exist, trying to create directory", dest);
fs::create_dir(&dest).unwrap();
try!(fs::create_dir(&dest));
},
Ok(_) => { /* If there is no error, the directory / file does exist */ }
}
@ -117,7 +115,7 @@ impl MDBook {
// There is a very high chance that the error is due to the fact that
// the directory / file does not exist
debug!("[*]: {:?} does not exist, trying to create directory", src);
fs::create_dir(&src).unwrap();
try!(fs::create_dir(&src));
},
Ok(_) => { /* If there is no error, the directory / file does exist */ }
}
@ -128,7 +126,7 @@ impl MDBook {
// There is a very high chance that the error is due to the fact that
// the directory / file does not exist
debug!("[*]: {:?} does not exist, trying to create SUMMARY.md", src.join("SUMMARY.md"));
Ok(File::create(&src.join("SUMMARY.md")).unwrap())
Ok(try!(File::create(&src.join("SUMMARY.md"))))
},
Ok(_) => {
/* If there is no error, the directory / file does exist */
@ -143,7 +141,7 @@ impl MDBook {
try!(writeln!(f, ""));
try!(writeln!(f, "- [Chapter 1](./chapter_1.md)"));
let mut chapter_1 = File::create(&src.join("chapter_1.md")).unwrap();
let mut chapter_1 = try!(File::create(&src.join("chapter_1.md")));
try!(writeln!(chapter_1, "# Chapter 1"));
}
@ -181,7 +179,7 @@ impl MDBook {
// There is a very high chance that the error is due to the fact that
// the directory / file does not exist
debug!("[*]: {:?} does not exist, trying to create directory", theme_dir);
fs::create_dir(&theme_dir).unwrap();
try!(fs::create_dir(&theme_dir));
},
Ok(_) => { /* If there is no error, the directory / file does exist */ }
}
@ -226,7 +224,8 @@ impl MDBook {
/// of the current working directory by using a relative path instead of an absolute path.
pub fn read_config(mut self) -> Self {
self.config.read_config(&self.root);
let root = self.config.get_root().to_owned();
self.config.read_config(&root);
self
}
@ -256,7 +255,16 @@ impl MDBook {
}
pub fn set_dest(mut self, dest: &Path) -> Self {
self.config.set_dest(&self.root.join(dest));
// Handle absolute and relative paths
match dest.is_absolute() {
true => { self.config.set_dest(dest); },
false => {
let dest = self.config.get_root().join(dest).to_owned();
self.config.set_dest(&dest);
}
}
self
}
@ -265,7 +273,16 @@ impl MDBook {
}
pub fn set_src(mut self, src: &Path) -> Self {
self.config.set_src(&self.root.join(src));
// Handle absolute and relative paths
match src.is_absolute() {
true => { self.config.set_src(src); },
false => {
let src = self.config.get_root().join(src).to_owned();
self.config.set_src(&src);
}
}
self
}

View File

@ -72,7 +72,11 @@ impl Renderer for HtmlHandlebars {
// Remove content from previous file and render content for this one
data.remove("path");
data.insert("path".to_string(), item.path.to_str().unwrap().to_json());
match item.path.to_str() {
Some(p) => { data.insert("path".to_string(), p.to_json()); },
None => return Err(Box::new(io::Error::new(io::ErrorKind::Other, "Could not convert path to str"))),
}
// Remove content from previous file and render content for this one
data.remove("content");
@ -144,7 +148,10 @@ fn make_data(book: BookItems, config: &BookConfig) -> Result<BTreeMap<String,Jso
let mut chapter = BTreeMap::new();
chapter.insert("section".to_string(), section.to_json());
chapter.insert("name".to_string(), item.name.to_json());
chapter.insert("path".to_string(), item.path.to_str().unwrap().to_json());
match item.path.to_str() {
Some(p) => { chapter.insert("path".to_string(), p.to_json()); },
None => return Err(Box::new(io::Error::new(io::ErrorKind::Other, "Could not convert path to str"))),
}
chapters.push(chapter);
}

View File

@ -30,9 +30,13 @@ pub fn previous(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext
debug!("[*]: Decode chapters from JSON");
// Decode json format
let decoded: Vec<BTreeMap<String, String>> = json::decode(&chapters.to_string()).unwrap();
let decoded: Vec<BTreeMap<String, String>> = match json::decode(&chapters.to_string()) {
Ok(data) => data,
Err(_) => return Err(RenderError{ desc: "Could not decode the JSON data"}),
};
let mut previous: Option<BTreeMap<String, String>> = None;
debug!("[*]: Search for current Chapter");
// Search for current chapter and return previous entry
for item in decoded {
@ -48,22 +52,32 @@ pub fn previous(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext
// Create new BTreeMap to extend the context: 'title' and 'link'
let mut previous_chapter = BTreeMap::new();
debug!("[*]: Inserting title: {}", previous.get("name").unwrap());
previous_chapter.insert("title".to_string(), previous.get("name").unwrap().to_json());
// Chapter title
match previous.get("name") {
Some(n) => {
debug!("[*]: Inserting title: {}", n);
previous_chapter.insert("title".to_string(), n.to_json())
},
None => {
debug!("[*]: No title found for chapter");
return Err(RenderError{ desc: "No title found for chapter in JSON data" })
}
};
debug!("[*]: Inserting link: {}",
path_to_root.join(
Path::new(previous.get("path").unwrap())
.with_extension("html")
).to_str().unwrap());
// Chapter link
previous_chapter.insert(
"link".to_string(),
path_to_root.join(
Path::new(previous.get("path").unwrap())
.with_extension("html")
).to_str().unwrap().to_json()
);
match previous.get("path") {
Some(p) => {
let path = path_to_root.join(Path::new(p).with_extension("html"));
debug!("[*]: Inserting link: {:?}", path);
match path.to_str() {
Some(p) => { previous_chapter.insert("link".to_string(), p.to_json()); },
None => return Err(RenderError{ desc: "Link could not be converted to str" })
}
},
None => return Err(RenderError{ desc: "No path found for chapter in JSON data" })
}
debug!("[*]: Inject in context");
// Inject in current context
@ -71,7 +85,13 @@ pub fn previous(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext
debug!("[*]: Render template");
// Render template
_h.template().unwrap().render(&updated_context, r, rc).unwrap();
match _h.template() {
Some(t) => {
try!(t.render(&updated_context, r, rc));
},
None => return Err(RenderError{ desc: "Error with the handlebars template" })
}
}
break;
@ -81,8 +101,11 @@ pub fn previous(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext
}
},
_ => continue,
}
}
Ok(())
}
@ -110,7 +133,10 @@ pub fn next(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext) ->
debug!("[*]: Decode chapters from JSON");
// Decode json format
let decoded: Vec<BTreeMap<String, String>> = json::decode(&chapters.to_string()).unwrap();
let decoded: Vec<BTreeMap<String, String>> = match json::decode(&chapters.to_string()) {
Ok(data) => data,
Err(_) => return Err(RenderError{ desc: "Could not decode the JSON data"}),
};
let mut previous: Option<BTreeMap<String, String>> = None;
debug!("[*]: Search for current Chapter");
@ -122,37 +148,48 @@ pub fn next(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext) ->
Some(path) if path.len() > 0 => {
if let Some(previous) = previous {
if previous.get("path").unwrap() == &current {
let path = match previous.get("path") {
Some(p) => p,
None => return Err(RenderError{ desc: "No path found for chapter in JSON data"})
};
if path == &current {
debug!("[*]: Found current chapter");
debug!("[*]: Creating BTreeMap to inject in context");
// Create new BTreeMap to extend the context: 'title' and 'link'
let mut next_chapter = BTreeMap::new();
debug!("[*]: Inserting title: {}", item.get("name").unwrap());
next_chapter.insert("title".to_string(), item.get("name").unwrap().to_json());
match item.get("name") {
Some(n) => {
debug!("[*]: Inserting title: {}", n);
next_chapter.insert("title".to_string(), n.to_json());
}
None => return Err(RenderError{ desc: "No title found for chapter in JSON data"})
}
debug!("[*]: Inserting link: {}",
path_to_root.join(
Path::new(item.get("path").unwrap())
.with_extension("html")
).to_str().unwrap());
let link = path_to_root.join(Path::new(path).with_extension("html"));
debug!("[*]: Inserting link: {:?}", link);
next_chapter.insert(
"link".to_string(),
path_to_root.join(
Path::new(item.get("path").unwrap())
.with_extension("html")
).to_str().unwrap().to_json()
);
match link.to_str() {
Some(l) => { next_chapter.insert("link".to_string(), l.to_json()); },
None => return Err(RenderError{ desc: "Link could not converted to str"})
}
debug!("[*]: Inject in context");
// Inject in current context
let updated_context = c.extend(&next_chapter);
debug!("[*]: Render template");
// Render template
_h.template().unwrap().render(&updated_context, r, rc).unwrap();
match _h.template() {
Some(t) => {
try!(t.render(&updated_context, r, rc));
},
None => return Err(RenderError{ desc: "Error with the handlebars template" })
}
break
}
@ -160,7 +197,7 @@ pub fn next(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext) ->
previous = Some(item.clone());
},
_ => continue,
}
}

View File

@ -63,7 +63,9 @@ impl Theme {
match File::open(&src.join("index.hbs")) {
Ok(mut f) => {
theme.index.clear(); // Reset the value, because read_to_string appends...
f.read_to_end(&mut theme.index).unwrap();
match f.read_to_end(&mut theme.index) {
_ => {}
};
},
_ => {},
}
@ -72,7 +74,9 @@ impl Theme {
match File::open(&src.join("book.js")) {
Ok(mut f) => {
theme.js.clear();
f.read_to_end(&mut theme.js).unwrap();
match f.read_to_end(&mut theme.js){
_ => {}
}
},
_ => {},
}
@ -81,7 +85,9 @@ impl Theme {
match File::open(&src.join("book.css")) {
Ok(mut f) => {
theme.css.clear();
f.read_to_end(&mut theme.css).unwrap();
match f.read_to_end(&mut theme.css) {
_ => {}
}
},
_ => {},
}
@ -90,7 +96,9 @@ impl Theme {
match File::open(&src.join("highlight.js")) {
Ok(mut f) => {
theme.highlight_js.clear();
f.read_to_end(&mut theme.highlight_js).unwrap();
match f.read_to_end(&mut theme.highlight_js) {
_ => {}
}
},
_ => {},
}
@ -99,7 +107,9 @@ impl Theme {
match File::open(&src.join("highlight.css")) {
Ok(mut f) => {
theme.highlight_css.clear();
f.read_to_end(&mut theme.highlight_css).unwrap();
match f.read_to_end(&mut theme.highlight_css) {
_ => {}
}
},
_ => {},
}