made clippy and rustfmt happy

This commit is contained in:
Michael Bryan 2017-06-30 07:36:17 +08:00
parent 01bab56faf
commit 131a404064
3 changed files with 123 additions and 93 deletions

View File

@ -27,14 +27,15 @@ impl Loader {
/// Parse the summary file and use it to load a book from disk. /// Parse the summary file and use it to load a book from disk.
pub fn load(&self) -> Result<()> { pub fn load(&self) -> Result<()> {
let summary = self.parse_summary() let summary = self.parse_summary().chain_err(
.chain_err(|| "Couldn't parse `SUMMARY.md`")?; || "Couldn't parse `SUMMARY.md`",
)?;
unimplemented!() unimplemented!()
} }
/// Parse the `SUMMARY.md` file. /// Parse the `SUMMARY.md` file.
fn parse_summary(&self) -> Result<Summary> { pub fn parse_summary(&self) -> Result<Summary> {
let path = self.source_directory.join("SUMMARY.md"); let path = self.source_directory.join("SUMMARY.md");
let mut summary_content = String::new(); let mut summary_content = String::new();
@ -42,5 +43,4 @@ impl Loader {
summary::parse_summary(&summary_content) summary::parse_summary(&summary_content)
} }
} }

View File

@ -285,20 +285,58 @@ impl<'a> SummaryParser<'a> {
Ok(()) Ok(())
} }
/// Try to parse the title line. /// Parse the numbered chapters.
fn parse_title(&mut self) -> Option<String> { ///
if let Some(Event::Start(Tag::Header(1))) = self.stream.next() { /// If the event is the start of a list item, consume the entire item and
debug!("[*] Found a h1 in the SUMMARY"); /// add a new link to the summary with `push_numbered_section`.
///
/// If the event is the start of a new list, bump the nesting level.
///
/// If the event is the end of a list, decrement the nesting level. When
/// the nesting level would go negative, we've finished the numbered
/// section and need to parse the suffix section.
///
/// Otherwise, ignore the event.
fn step_numbered(&mut self, event: Event, nesting: u32) -> Result<()> {
match event {
Event::Start(Tag::Item) => {
let it = self.parse_item()
.chain_err(|| "List items should only contain links")?;
let tags = collect_events!(self.stream, Tag::Header(1)); debug!("[*] Found a chapter: {:?} ({})", it.name, it.location.display());
let section_number = self.push_numbered_section(SummaryItem::Link(it));
trace!("[*] Section number is {}", section_number);
},
Event::Start(Tag::List(_)) => {
match self.state {
State::NumberedChapters(n) => {
let new_nest = n + 1;
self.state = State::NumberedChapters(new_nest);
trace!("[*] Nesting level increased to {}", new_nest);
},
other => unreachable!(),
}
},
Event::End(Tag::List(_)) => {
match self.state {
State::NumberedChapters(n) => {
if n == 0 {
trace!("[*] Finished parsing the numbered chapters");
self.state = State::SuffixChapters;
} else {
trace!("[*] Nesting level decreased to {}", n - 1);
self.state = State::NumberedChapters(n - 1);
}
},
other => unreachable!(),
}
},
other => {
trace!("[*] skipping unexpected token: {:?}", other);
},
}
// TODO: How do we deal with headings like "# My **awesome** summary"? Ok(())
// for now, I'm just going to scan through and concatenate the
// Event::Text tags, skipping any styling.
Some(stringify_events(tags))
} else {
None
}
} }
fn step_suffix(&mut self, event: Event<'a>) -> Result<()> { fn step_suffix(&mut self, event: Event<'a>) -> Result<()> {
@ -348,70 +386,34 @@ impl<'a> SummaryParser<'a> {
} }
} }
/// Parse the numbered chapters. /// Try to parse the title line.
/// fn parse_title(&mut self) -> Option<String> {
/// If the event is the start of a list item, consume the entire item and if let Some(Event::Start(Tag::Header(1))) = self.stream.next() {
/// add a new link to the summary with `push_numbered_section`. debug!("[*] Found a h1 in the SUMMARY");
///
/// If the event is the start of a new list, bump the nesting level.
///
/// If the event is the end of a list, decrement the nesting level. When
/// the nesting level would go negative, we've finished the numbered
/// section and need to parse the suffix section.
///
/// Otherwise, ignore the event.
fn step_numbered(&mut self, event: Event, nesting: u32) -> Result<()> {
match event {
Event::Start(Tag::Item) => {
let it = self.parse_item()
.chain_err(|| "List items should only contain links")?;
debug!("[*] Found a chapter: {:?} ({})", it.name, it.location.display()); let tags = collect_events!(self.stream, Tag::Header(1));
let section_number = self.push_numbered_section(SummaryItem::Link(it));
trace!("[*] Section number is {}", section_number);
}
Event::Start(Tag::List(_)) => {
match self.state {
State::NumberedChapters(n) => {
let new_nest = n + 1;
self.state = State::NumberedChapters(new_nest);
trace!("[*] Nesting level increased to {}", new_nest);
}
other => unreachable!(),
}
} // TODO: How do we deal with headings like "# My **awesome** summary"?
Event::End(Tag::List(_)) => { // for now, I'm just going to scan through and concatenate the
match self.state { // Event::Text tags, skipping any styling.
State::NumberedChapters(n) => { Some(stringify_events(tags))
if n == 0 { } else {
trace!("[*] Finished parsing the numbered chapters"); None
self.state = State::SuffixChapters;
} else {
trace!("[*] Nesting level decreased to {}", n - 1);
self.state = State::NumberedChapters(n - 1);
}
}
other => unreachable!(),
}
}
other => {
trace!("[*] skipping unexpected token: {:?}", other);
}
} }
Ok(())
} }
/// Push a new section at the end of the current nesting level. /// Push a new section at the end of the current nesting level.
fn push_numbered_section(&mut self, item: SummaryItem) -> SectionNumber { fn push_numbered_section(&mut self, item: SummaryItem) -> SectionNumber {
if let State::NumberedChapters(level) = self.state { if let State::NumberedChapters(level) = self.state {
push_item_at_nesting_level(&mut self.summary.numbered_chapters, push_item_at_nesting_level(
&mut self.summary.numbered_chapters,
item, item,
level as usize, level as usize,
SectionNumber::default()) SectionNumber::default(),
.chain_err(|| format!("The parser should always ensure we add the next \ ).chain_err(|| {
item at the correct level ({}:{})", module_path!(), line!())) format!("The parser should always ensure we add the next \
item at the correct level ({}:{})", module_path!(), line!())
})
.unwrap() .unwrap()
} else { } else {
// this method should only ever be called when parsing a numbered // this method should only ever be called when parsing a numbered
@ -430,17 +432,14 @@ impl<'a> SummaryParser<'a> {
/// Given a particular level (e.g. 3), go that many levels down the `Link`'s /// Given a particular level (e.g. 3), go that many levels down the `Link`'s
/// nested items then append the provided item to the last `Link` in the /// nested items then append the provided item to the last `Link` in the
/// list. /// list.
fn push_item_at_nesting_level(links: &mut Vec<SummaryItem>, fn push_item_at_nesting_level(links: &mut Vec<SummaryItem>, mut item: SummaryItem, level: usize, mut section_number: SectionNumber)
mut item: SummaryItem, -> Result<SectionNumber> {
level: usize,
mut section_number: SectionNumber) -> Result<SectionNumber> {
if level == 0 { if level == 0 {
// set the section number, if applicable // set the section number, if applicable
section_number.push(links.len() as u32 + 1); section_number.push(links.len() as u32 + 1);
match &mut item { if let SummaryItem::Link(ref mut l) = item {
&mut SummaryItem::Link(ref mut l) => l.number = Some(section_number.clone()), l.number = Some(section_number.clone());
_ => {}
} }
links.push(item); links.push(item);
@ -451,12 +450,13 @@ fn push_item_at_nesting_level(links: &mut Vec<SummaryItem>,
// FIXME: This bit needs simplifying! // FIXME: This bit needs simplifying!
let (index, last_link) = let (index, last_link) =
links.iter_mut() links
.iter_mut()
.enumerate() .enumerate()
.filter_map(|(i, item)| item.maybe_link_mut().map(|l| (i, l))) .filter_map(|(i, item)| item.maybe_link_mut().map(|l| (i, l)))
.rev() .rev()
.next() .next()
.ok_or(format!("Can't recurse any further, summary needs to be {} more levels deep", level))?; .ok_or_else(|| format!("Can't recurse any further, summary needs to be {} more levels deep", level))?;
section_number.push(index as u32 + 1); section_number.push(index as u32 + 1);
push_item_at_nesting_level(&mut last_link.nested_items, item, level - 1, section_number) push_item_at_nesting_level(&mut last_link.nested_items, item, level - 1, section_number)
@ -466,7 +466,7 @@ fn push_item_at_nesting_level(links: &mut Vec<SummaryItem>,
/// Extracts the text from formatted markdown. /// Extracts the text from formatted markdown.
fn stringify_events<'a>(events: Vec<Event<'a>>) -> String { fn stringify_events(events: Vec<Event>) -> String {
events events
.into_iter() .into_iter()
.filter_map(|t| match t { .filter_map(|t| match t {
@ -680,7 +680,12 @@ mod tests {
.nested_items[0].maybe_link_mut() .nested_items[0].maybe_link_mut()
.unwrap() .unwrap()
.nested_items.len() , 0); .nested_items.len() , 0);
let got = push_item_at_nesting_level(&mut links, SummaryItem::Link(Link::new("Dummy", "")), 3, SectionNumber::default()).unwrap(); let got = push_item_at_nesting_level(
&mut links,
SummaryItem::Link(Link::new("Dummy", "")),
3,
SectionNumber::default(),
).unwrap();
assert_eq!(links[0].maybe_link_mut().unwrap() assert_eq!(links[0].maybe_link_mut().unwrap()
.nested_items[1].maybe_link_mut() .nested_items[1].maybe_link_mut()
.unwrap() .unwrap()

View File

@ -4,9 +4,14 @@
extern crate pretty_assertions; extern crate pretty_assertions;
extern crate mdbook; extern crate mdbook;
extern crate env_logger; extern crate env_logger;
extern crate tempdir;
use std::path::PathBuf; use std::path::PathBuf;
use mdbook::loader::{parse_summary, Link, SummaryItem, SectionNumber, Summary}; use std::fs::File;
use std::io::Write;
use mdbook::loader::{parse_summary, Link, SummaryItem, SectionNumber, Summary, Loader};
use tempdir::TempDir;
const SUMMARY: &'static str = " const SUMMARY: &'static str = "
@ -28,10 +33,35 @@ const SUMMARY: &'static str = "
#[test] #[test]
fn parse_summary_md() { fn parse_summary_md() {
env_logger::init().unwrap(); env_logger::init().ok();
// Hard-code the structure `SUMMARY` *should* be parsed into. let should_be = expected_summary();
let should_be = Summary { let got = parse_summary(SUMMARY).unwrap();
println!("{:#?}", got);
assert_eq!(got, should_be);
}
#[test]
fn parse_summary_using_loader() {
env_logger::init().ok();
let temp = TempDir::new("book").unwrap();
let summary_md = temp.path().join("SUMMARY.md");
File::create(&summary_md).unwrap().write_all(SUMMARY.as_bytes()).unwrap();
let loader = Loader::new(temp.path());
let got = loader.parse_summary().unwrap();
let should_be = expected_summary();
assert_eq!(got, should_be);
}
/// This is what the SUMMARY should be parsed as
fn expected_summary() -> Summary {
Summary {
title: Some(String::from("Summary")), title: Some(String::from("Summary")),
prefix_chapters: vec![ prefix_chapters: vec![
@ -68,17 +98,12 @@ fn parse_summary_md() {
suffix_chapters: vec![ suffix_chapters: vec![
SummaryItem::Separator, SummaryItem::Separator,
SummaryItem::Link( Link { SummaryItem::Link(Link {
name: String::from("Conclusion"), name: String::from("Conclusion"),
location: PathBuf::from("/conclusion.md"), location: PathBuf::from("/conclusion.md"),
number: None, number: None,
nested_items: vec![], nested_items: vec![],
}) }),
], ],
}; }
let got = parse_summary(SUMMARY).unwrap();
println!("{:#?}", got);
assert_eq!(got, should_be);
} }