summaryrefslogtreecommitdiffstats
path: root/src/parser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser.rs')
-rw-r--r--src/parser.rs292
1 files changed, 162 insertions, 130 deletions
diff --git a/src/parser.rs b/src/parser.rs
index 7e772d6..d75b39d 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -11,7 +11,7 @@ use std::io::prelude::*;
use std::{iter, str};
use config::Config;
-use errors::{GitJournalResult, error};
+use errors::*;
pub static TOML_DEFAULT_KEY: &'static str = "default";
pub static TOML_FOOTERS_KEY: &'static str = "footers";
@@ -37,12 +37,12 @@ pub trait Print {
c1: &F,
c2: &G,
c3: &H)
- -> GitJournalResult<Printed>
- where F: Fn(&mut T) -> GitJournalResult<()>,
- G: Fn(&mut T) -> GitJournalResult<()>,
- H: Fn(&mut T) -> GitJournalResult<()>;
+ -> Result<Printed>
+ where F: Fn(&mut T) -> Result<()>,
+ G: Fn(&mut T) -> Result<()>,
+ H: Fn(&mut T) -> Result<()>;
- fn print_default<T: Write>(&self, t: &mut T, config: &Config, tag: Option<&str>) -> GitJournalResult<()> {
+ fn print_default<T: Write>(&self, t: &mut T, config: &Config, tag: Option<&str>) -> Result<()> {
self.print(t, config, tag, &|_| Ok(()), &|_| Ok(()), &|_| Ok(()))?;
Ok(())
}
@@ -51,22 +51,22 @@ pub trait Print {
mut t: &mut Box<term::StdoutTerminal>,
config: &Config,
tag: Option<&str>)
- -> GitJournalResult<()> {
+ -> Result<()> {
self.print(&mut t,
config,
tag,
&|t| {
- t.fg(term::color::BRIGHT_BLUE)?;
- Ok(())
- },
+ t.fg(term::color::BRIGHT_BLUE)?;
+ Ok(())
+ },
&|t| {
- t.fg(term::color::WHITE)?;
- Ok(())
- },
+ t.fg(term::color::WHITE)?;
+ Ok(())
+ },
&|t| {
- t.reset()?;
- Ok(())
- })?;
+ t.reset()?;
+ Ok(())
+ })?;
Ok(())
}
@@ -90,7 +90,7 @@ pub trait Print {
mut vec: &mut Vec<u8>,
config: &Config,
tag: Option<&str>)
- -> GitJournalResult<()> {
+ -> Result<()> {
self.print_default_term(&mut term, config, tag)?;
self.print_default(&mut vec, config, tag)?;
Ok(())
@@ -121,10 +121,10 @@ pub struct ParsedTag {
}
impl ParsedTag {
- fn print<T: Write, F, G, H>(&self, t: &mut T, config: &Config, c1: &F, c2: &G, c3: &H) -> GitJournalResult<Printed>
- where F: Fn(&mut T) -> GitJournalResult<()>,
- G: Fn(&mut T) -> GitJournalResult<()>,
- H: Fn(&mut T) -> GitJournalResult<()>
+ fn print<T: Write, F, G, H>(&self, t: &mut T, config: &Config, c1: &F, c2: &G, c3: &H) -> Result<Printed>
+ where F: Fn(&mut T) -> Result<()>,
+ G: Fn(&mut T) -> Result<()>,
+ H: Fn(&mut T) -> Result<()>
{
if config.colored_output {
c1(t)?;
@@ -144,26 +144,26 @@ impl ParsedTag {
Ok(Printed::Something)
}
- fn print_default<T: Write>(&self, t: &mut T, config: &Config) -> GitJournalResult<()> {
+ fn print_default<T: Write>(&self, t: &mut T, config: &Config) -> Result<()> {
self.print(t, config, &|_| Ok(()), &|_| Ok(()), &|_| Ok(()))?;
Ok(())
}
- fn print_default_term(&self, mut t: &mut Box<term::StdoutTerminal>, config: &Config) -> GitJournalResult<()> {
+ fn print_default_term(&self, mut t: &mut Box<term::StdoutTerminal>, config: &Config) -> Result<()> {
self.print(&mut t,
config,
&|t| {
- t.fg(term::color::GREEN)?;
- Ok(())
- },
+ t.fg(term::color::GREEN)?;
+ Ok(())
+ },
&|t| {
- t.fg(term::color::YELLOW)?;
- Ok(())
- },
+ t.fg(term::color::YELLOW)?;
+ Ok(())
+ },
&|t| {
- t.reset()?;
- Ok(())
- })?;
+ t.reset()?;
+ Ok(())
+ })?;
Ok(())
}
@@ -174,7 +174,7 @@ impl ParsedTag {
config: &Config,
template: Option<&str>,
index_len: (usize, usize))
- -> GitJournalResult<()> {
+ -> Result<()> {
match template {
Some(template) => {
// Try to parse the template
@@ -249,7 +249,7 @@ impl ParsedTag {
level: &mut usize,
config: &Config,
compact: &bool)
- -> GitJournalResult<()> {
+ -> Result<()> {
for value in table {
if let Value::Array(ref array) = *value.1 {
for item in array {
@@ -273,14 +273,25 @@ impl ParsedTag {
};
if (*compact &&
- ((self.commits.iter().filter(|c| c.summary.contains_tag(Some(tag))).count() > 0 &&
- !config.excluded_commit_tags.contains(&tag.to_owned())) ||
+ ((self.commits
+ .iter()
+ .filter(|c| c.summary.contains_tag(Some(tag)))
+ .count() > 0 && !config.excluded_commit_tags.contains(&tag.to_owned())) ||
(tag == TOML_DEFAULT_KEY &&
- self.commits.iter().filter(|c| c.summary.contains_untagged_elements()).count() > 0))) ||
+ self.commits
+ .iter()
+ .filter(|c| c.summary.contains_untagged_elements())
+ .count() > 0))) ||
(!*compact &&
- ((self.commits.iter().filter(|c| c.contains_tag(Some(tag))).count() > 0 &&
- !config.excluded_commit_tags.contains(&tag.to_owned())) ||
- (tag == TOML_DEFAULT_KEY && self.commits.iter().filter(|c| c.contains_untagged_elements()).count() > 0))) {
+ ((self.commits
+ .iter()
+ .filter(|c| c.contains_tag(Some(tag)))
+ .count() > 0 && !config.excluded_commit_tags.contains(&tag.to_owned())) ||
+ (tag == TOML_DEFAULT_KEY &&
+ self.commits
+ .iter()
+ .filter(|c| c.contains_untagged_elements())
+ .count() > 0))) {
if config.colored_output {
@@ -294,8 +305,7 @@ impl ParsedTag {
// Print commits for this tag
for commit in &self.commits {
if *compact {
- commit.summary
- .print_to_term_and_write_to_vector(&mut term, &mut vec, config, Some(tag))?;
+ commit.summary.print_to_term_and_write_to_vector(&mut term, &mut vec, config, Some(tag))?;
} else {
commit.print_to_term_and_write_to_vector(&mut term, &mut vec, config, Some(tag))?;
}
@@ -322,7 +332,7 @@ impl ParsedTag {
mut vec: &mut Vec<u8>,
footer_keys: Option<&[Value]>,
config: &Config)
- -> GitJournalResult<()> {
+ -> Result<()> {
let mut footer_tree: BTreeMap<String, Vec<String>> = BTreeMap::new();
@@ -342,9 +352,9 @@ impl ParsedTag {
// Map the parsed results into a BTreeMap
for footer in self.commits
- .iter()
- .flat_map(|commit| commit.footer.clone())
- .collect::<Vec<FooterElement>>() {
+ .iter()
+ .flat_map(|commit| commit.footer.clone())
+ .collect::<Vec<FooterElement>>() {
if valid_footer_keys.is_empty() || valid_footer_keys.contains(&footer.key) {
let mut value = footer.value;
if config.show_commit_hash {
@@ -413,10 +423,10 @@ impl Print for ParsedCommit {
c1: &F,
c2: &G,
c3: &H)
- -> GitJournalResult<Printed>
- where F: Fn(&mut T) -> GitJournalResult<()>,
- G: Fn(&mut T) -> GitJournalResult<()>,
- H: Fn(&mut T) -> GitJournalResult<()>
+ -> Result<Printed>
+ where F: Fn(&mut T) -> Result<()>,
+ G: Fn(&mut T) -> Result<()>,
+ H: Fn(&mut T) -> Result<()>
{
// If summary is already filtered out then do not print at all
if self.summary.print(t, config, tag, c1, c2, c3)? == Printed::Nothing {
@@ -429,12 +439,19 @@ impl Print for ParsedCommit {
}
fn contains_tag(&self, tag: Option<&str>) -> bool {
- self.summary.contains_tag(tag) || self.body.iter().filter(|x| x.contains_tag(tag)).count() > 0
+ self.summary.contains_tag(tag) ||
+ self.body
+ .iter()
+ .filter(|x| x.contains_tag(tag))
+ .count() > 0
}
fn contains_untagged_elements(&self) -> bool {
self.summary.contains_untagged_elements() ||
- self.body.iter().filter(|x| x.contains_untagged_elements()).count() > 0
+ self.body
+ .iter()
+ .filter(|x| x.contains_untagged_elements())
+ .count() > 0
}
}
@@ -465,13 +482,16 @@ impl Print for SummaryElement {
c1: &F,
c2: &G,
c3: &H)
- -> GitJournalResult<Printed>
- where F: Fn(&mut T) -> GitJournalResult<()>,
- G: Fn(&mut T) -> GitJournalResult<()>,
- H: Fn(&mut T) -> GitJournalResult<()>
+ -> Result<Printed>
+ where F: Fn(&mut T) -> Result<()>,
+ G: Fn(&mut T) -> Result<()>,
+ H: Fn(&mut T) -> Result<()>
{
// Filter out excluded tags
- if self.tags.iter().filter(|x| config.excluded_commit_tags.contains(x)).count() > 0usize {
+ if self.tags
+ .iter()
+ .filter(|x| config.excluded_commit_tags.contains(x))
+ .count() > 0usize {
return Ok(Printed::Nothing);
}
@@ -544,10 +564,10 @@ impl Print for BodyElement {
c1: &F,
c2: &G,
c3: &H)
- -> GitJournalResult<Printed>
- where F: Fn(&mut T) -> GitJournalResult<()>,
- G: Fn(&mut T) -> GitJournalResult<()>,
- H: Fn(&mut T) -> GitJournalResult<()>
+ -> Result<Printed>
+ where F: Fn(&mut T) -> Result<()>,
+ G: Fn(&mut T) -> Result<()>,
+ H: Fn(&mut T) -> Result<()>
{
match *self {
BodyElement::List(ref vec) => {
@@ -599,13 +619,16 @@ impl Print for ListElement {
c1: &F,
c2: &G,
c3: &H)
- -> GitJournalResult<Printed>
- where F: Fn(&mut T) -> GitJournalResult<()>,
- G: Fn(&mut T) -> GitJournalResult<()>,
- H: Fn(&mut T) -> GitJournalResult<()>
+ -> Result<Printed>
+ where F: Fn(&mut T) -> Result<()>,
+ G: Fn(&mut T) -> Result<()>,
+ H: Fn(&mut T) -> Result<()>
{
// Check if list item contains excluded tag
- if self.tags.iter().filter(|x| config.excluded_commit_tags.contains(x)).count() > 0usize {
+ if self.tags
+ .iter()
+ .filter(|x| config.excluded_commit_tags.contains(x))
+ .count() > 0usize {
return Ok(Printed::Nothing);
}
@@ -668,26 +691,29 @@ impl Print for ParagraphElement {
_c1: &F,
_c2: &G,
_c3: &H)
- -> GitJournalResult<Printed>
- where F: Fn(&mut T) -> GitJournalResult<()>,
- G: Fn(&mut T) -> GitJournalResult<()>,
- H: Fn(&mut T) -> GitJournalResult<()>
+ -> Result<Printed>
+ where F: Fn(&mut T) -> Result<()>,
+ G: Fn(&mut T) -> Result<()>,
+ H: Fn(&mut T) -> Result<()>
{
// Check if paragraph contains excluded tag
- if self.tags.iter().filter(|x| config.excluded_commit_tags.contains(x)).count() > 0usize {
+ if self.tags
+ .iter()
+ .filter(|x| config.excluded_commit_tags.contains(x))
+ .count() > 0usize {
return Ok(Printed::Nothing);
}
if self.should_be_printed(tag) {
for (index, line) in self.text
- .lines()
- .map(|x| {
- let indent = if tag.is_none() { 4 } else { 2 };
- iter::repeat(' ').take(indent).collect::<String>()
- } + x)
- .collect::<Vec<String>>()
- .iter()
- .enumerate() {
+ .lines()
+ .map(|x| {
+ let indent = if tag.is_none() { 4 } else { 2 };
+ iter::repeat(' ').take(indent).collect::<String>()
+ } + x)
+ .collect::<Vec<String>>()
+ .iter()
+ .enumerate() {
if tag.is_some() && index == 0 {
// Paragraphs will be transformed into lists when using templates
write!(t, "\n{}", line.replace(" ", "- "))?;
@@ -794,17 +820,17 @@ impl Parser {
let mut tags = vec![];
for cap in RE_TAGS.captures_iter(string) {
tags.extend(cap.at(1)
- .unwrap_or("")
- .split(',')
- .filter_map(|x| {
- // Ignore tags containing dots.
- if !x.contains('.') {
- Some(x.trim().to_owned())
- } else {
- None
- }
- })
- .collect::<Vec<String>>());
+ .unwrap_or("")
+ .split(',')
+ .filter_map(|x| {
+ // Ignore tags containing dots.
+ if !x.contains('.') {
+ Some(x.trim().to_owned())
+ } else {
+ None
+ }
+ })
+ .collect::<Vec<String>>());
}
let mut text = RE_TAGS.replace_all(string, "");
if let Some('.') = text.chars().rev().nth(0) {
@@ -814,13 +840,14 @@ impl Parser {
}
/// Parses a single commit message and returns a changelog ready form
- pub fn parse_commit_message(&self, message: &str, oid: Option<Oid>) -> GitJournalResult<ParsedCommit> {
+ pub fn parse_commit_message(&self, message: &str, oid: Option<Oid>) -> Result<ParsedCommit> {
// Every block is split by two newlines
let mut commit_parts = message.split("\n\n");
// Parse the summary line
- let summary_line =
- commit_parts.nth(0).ok_or_else(|| error("Summary line", "Commit message length too small."))?.trim();
+ let summary_line = commit_parts.nth(0)
+ .ok_or_else(|| "Summar line parsing: Commit message length too small.")?
+ .trim();
let mut parsed_summary = match self.clone().parse_summary(summary_line.as_bytes()) {
(_, IResult::Done(_, parsed)) => parsed,
_ => bail!("Summary parsing failed: '{}'", summary_line),
@@ -842,10 +869,14 @@ impl Parser {
} else if RE_FOOTER.is_match(part) {
for cap in RE_FOOTER.captures_iter(part) {
parsed_footer.push(FooterElement {
- oid: oid,
- key: cap.at(1).ok_or_else(|| error("Footer parsing", part))?.to_owned(),
- value: cap.at(2).ok_or_else(|| error("Footer parsing", part))?.to_owned(),
- });
+ oid: oid,
+ key: cap.at(1)
+ .ok_or_else(|| part)?
+ .to_owned(),
+ value: cap.at(2)
+ .ok_or_else(|| part)?
+ .to_owned(),
+ });
}
// Parse all list items
@@ -863,10 +894,10 @@ impl Parser {
} else if RE_PARAGRAPH.is_match(part) {
let (parsed_tags, parsed_text) = Self::parse_and_consume_tags(part.as_bytes());
parsed_body.push(BodyElement::Paragraph(ParagraphElement {
- oid: oid,
- text: parsed_text.trim().to_owned(),
- tags: parsed_tags,
- }));
+ oid: oid,
+ text: parsed_text.trim().to_owned(),
+ tags: parsed_tags,
+ }));
// Nothing matched, this should not happen at all
} else {
@@ -875,16 +906,16 @@ impl Parser {
}
Ok(ParsedCommit {
- oid: oid,
- summary: parsed_summary,
- body: parsed_body,
- footer: parsed_footer,
- })
+ oid: oid,
+ summary: parsed_summary,
+ body: parsed_body,
+ footer: parsed_footer,
+ })
}
/// Prints the commits without any template
- pub fn print(&self, compact: &bool, template: Option<&str>) -> GitJournalResult<Vec<u8>> {
- let mut term = term::stdout().ok_or_else(|| error("Terminal", "Could not print to terminal"))?;
+ pub fn print(&self, compact: &bool, template: Option<&str>) -> Result<Vec<u8>> {
+ let mut term = term::stdout().ok_or_else(|| "Could not print to terminal")?;
let mut vec = vec![];
// Print every tag
@@ -955,10 +986,10 @@ mod tests {
assert_eq!(commit.body.len(), 1);
assert_eq!(commit.body[0],
BodyElement::Paragraph(ParagraphElement {
- text: "Some paragraph".to_owned(),
- tags: vec![],
- oid: None,
- }));
+ text: "Some paragraph".to_owned(),
+ tags: vec![],
+ oid: None,
+ }));
assert_eq!(commit.footer.len(), 0);
assert_eq!(commit.summary.prefix, "JIRA-1234");
assert_eq!(commit.summary.category, "Changed");
@@ -966,17 +997,16 @@ mod tests {
assert_eq!(commit.summary.tags.len(), 0);
let mut t = term::stdout().unwrap();
assert!(commit.print_to_term_and_write_to_vector(&mut t, &mut vec![], &config::Config::new(), None)
- .is_ok());
+ .is_ok());
assert!(commit.print_to_term_and_write_to_vector(&mut t, &mut vec![], &config::Config::new(), Some("tag"))
- .is_ok());
+ .is_ok());
}
}
#[test]
fn parse_commit_ok_2() {
- let commit = get_parser()
- .parse_commit_message("Changed my commit summary\n\n- List item 1\n- List item 2\n- List item 3",
- None);
+ let commit = get_parser().parse_commit_message("Changed my commit summary\n\n- List item 1\n- List item 2\n- List item 3",
+ None);
assert!(commit.is_ok());
if let Ok(commit) = commit {
assert_eq!(commit.body.len(), 1);
@@ -987,9 +1017,9 @@ mod tests {
assert_eq!(commit.summary.tags.len(), 0);
let mut t = term::stdout().unwrap();
assert!(commit.print_to_term_and_write_to_vector(&mut t, &mut vec![], &config::Config::new(), None)
- .is_ok());
+ .is_ok());
assert!(commit.print_to_term_and_write_to_vector(&mut t, &mut vec![], &config::Config::new(), Some("tag"))
- .is_ok());
+ .is_ok());
}
}
@@ -1010,19 +1040,21 @@ mod tests {
vec!["tag1".to_owned(), "tag2".to_owned(), "tag3".to_owned()]);
let mut t = term::stdout().unwrap();
assert!(commit.print_to_term_and_write_to_vector(&mut t, &mut vec![], &config::Config::new(), None)
- .is_ok());
- assert!(commit.print_to_term_and_write_to_vector(&mut t, &mut vec![], &config::Config::new(), Some("tag3"))
- .is_ok());
+ .is_ok());
+ assert!(commit.print_to_term_and_write_to_vector(&mut t,
+ &mut vec![],
+ &config::Config::new(),
+ Some("tag3"))
+ .is_ok());
}
}
#[test]
fn parse_commit_ok_4() {
- let commit = get_parser()
- .parse_commit_message("Added my :1234: commit 💖 summary :some tag:\n\nParagraph\n\n- List \
+ let commit = get_parser().parse_commit_message("Added my :1234: commit 💖 summary :some tag:\n\nParagraph\n\n- List \
Item\n\nReviewed-by: Me",
- None);
+ None);
assert!(commit.is_ok());
if let Ok(commit) = commit {
assert_eq!(commit.body.len(), 2);
@@ -1034,12 +1066,12 @@ mod tests {
vec!["1234".to_owned(), "some tag".to_owned()]);
let mut t = term::stdout().unwrap();
assert!(commit.print_to_term_and_write_to_vector(&mut t, &mut vec![], &config::Config::new(), None)
- .is_ok());
+ .is_ok());
assert!(commit.print_to_term_and_write_to_vector(&mut t,
- &mut vec![],
- &config::Config::new(),
- Some("some tag"))
- .is_ok());
+ &mut vec![],
+ &config::Config::new(),
+ Some("some tag"))
+ .is_ok());
}
}