diff --git a/src/main.rs b/src/main.rs index 1c395a7..fdf62d9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,22 +1,24 @@ -extern crate term_painter; extern crate regex; +extern crate term_painter; mod parse; mod print; mod wrap; -use term_painter::ToStyle; -use term_painter::Color::*; - +use term_painter::{Color::*, ToStyle}; fn main() { - let mut op = parse::MessageIter::new(); + let mut op = parse::MessageIter::new(); - for i in &mut op { - for l in i { - l.print(); - } - } + for i in &mut op { + for l in i { + l.print(); + } + } - println!("\n~~~ {} : {} ~~~", Red.bold().paint(op.errors.to_string()), Yellow.bold().paint(op.warnings.to_string())); + println!( + "\n~~~ {} : {} ~~~", + Red.bold().paint(op.errors.to_string()), + Yellow.bold().paint(op.warnings.to_string()) + ); } diff --git a/src/parse.rs b/src/parse.rs index b7bbcab..a993050 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -1,127 +1,142 @@ -use std::io::stdin; -use std::io::prelude::*; -use std::iter::once; use regex::Regex; +use std::{ + io::{prelude::*, stdin}, + iter::once, +}; pub struct MessageIter { - buf: String, - terminated: bool, - pub errors: u16, - pub warnings: u16, + buf: String, + terminated: bool, + pub errors: u16, + pub warnings: u16, } pub enum Message { - Header(String, String), - Warning(String), - Note(String), - Error(String), - Help(String), - FollowUp(String), - Source(String, String), - Etc, - Marker(String), - NewLine, - Wat, - Aborting, + Header(String, String), + Warning(String), + Note(String), + Error(String), + Help(String), + FollowUp(String), + Source(String, String), + Etc, + Marker(String), + NewLine, + Wat, + Aborting, } impl<'a> Iterator for &'a mut MessageIter { - type Item = Vec; - - fn next(&mut self) -> Option> { - use self::Message::*; - - if self.terminated { - return None; - } - - let mut res = Vec::new(); - let mut file = String::new(); - let mut stop = false; - let si = stdin(); - let stdin = si.lock().lines().map(|x| x.expect("Stdin failed")); - - for l in once(self.buf.clone()).chain(stdin) { - let re_header = Regex::new(r"([0-9A-Za-z_\.\\/>< ]+):(\d+):\d+: .*(warning: |note: |error: |help: )(.*)").unwrap(); - let re_source = Regex::new(r"(\d+) (.*)").unwrap(); - if re_header.is_match(&l) { - - if !stop { - stop = true; - } else { - self.buf = l.to_string(); - return Some(res); - } - - res.push(NewLine); - - let caps = re_header.captures(&l).unwrap(); - file = caps.at(1).unwrap_or("?").to_string(); - - res.push(Header(file.clone(), caps.at(2).unwrap_or("?").to_string())); - - let msg = caps.at(4).unwrap_or("?").to_string(); - - // Warning, header or note? - match caps.at(3).unwrap_or("?") { - "warning: " => { - self.warnings += 1; - res.push(Warning(msg)); - }, - "note: " => res.push(Note(msg)), - "error: " => { - self.errors += 1; - res.push(Error(msg)); - }, - "help: " => res.push(Help(msg)), - _ => res.push(Wat), - } - - } else if l.len() > file.len() && re_source.is_match(&l[file.len()..]) && is_not_cmd(&l) { - let caps = re_source.captures(&l).unwrap(); - - res.push(Source(caps.at(1).unwrap_or("?").to_string(), caps.at(2).unwrap_or("????").to_string())); - } else if l.starts_with(' ') && l.contains("^") { - - let offset = file.len() - 4; //+ 5 - 5; - - if offset < l.len() { - res.push(Marker(l[offset..].to_string())); - } - } else if l.contains("aborting due to previous") || l.contains("Build failed") || l.contains("Could not compile") { - res.push(Aborting); - stop = true; - self.terminated = true; - } else if l.contains("Compilining ") || l.contains("file:///home/") || l.is_empty() { - // todo - } else if l.contains(" ...") { - res.push(Etc); - } else if is_not_cmd(&l){ - res.push(FollowUp(l.to_string())); - } - } - - self.terminated = true; - if stop { - Some(res) - } else { - None - } - } + type Item = Vec; + + fn next(&mut self) -> Option> { + use self::Message::*; + + if self.terminated { + return None; + } + + let mut res = Vec::new(); + let mut file = String::new(); + let mut stop = false; + let si = stdin(); + let stdin = si.lock().lines().map(|x| x.expect("Stdin failed")); + + for l in once(self.buf.clone()).chain(stdin) { + let re_header = Regex::new( + r"([0-9A-Za-z_\.\\/>< ]+):(\d+):\d+: .*(warning: |note: |error: |help: )(.*)", + ) + .unwrap(); + let re_source = Regex::new(r"(\d+) (.*)").unwrap(); + if re_header.is_match(&l) { + if !stop { + stop = true; + } else { + self.buf = l.to_string(); + return Some(res); + } + + res.push(NewLine); + + let caps = re_header.captures(&l).unwrap(); + file = caps.at(1).unwrap_or("?").to_string(); + + res.push(Header(file.clone(), caps.at(2).unwrap_or("?").to_string())); + + let msg = caps.at(4).unwrap_or("?").to_string(); + + // Warning, header or note? + match caps.at(3).unwrap_or("?") { + "warning: " => { + self.warnings += 1; + res.push(Warning(msg)); + } + "note: " => res.push(Note(msg)), + "error: " => { + self.errors += 1; + res.push(Error(msg)); + } + "help: " => res.push(Help(msg)), + _ => res.push(Wat), + } + } else if l.len() > file.len() && re_source.is_match(&l[file.len()..]) && is_not_cmd(&l) + { + let caps = re_source.captures(&l).unwrap(); + + res.push(Source( + caps.at(1).unwrap_or("?").to_string(), + caps.at(2).unwrap_or("????").to_string(), + )); + } else if l.starts_with(' ') && l.contains("^") { + let offset = file.len() - 4; //+ 5 - 5; + + if offset < l.len() { + res.push(Marker(l[offset..].to_string())); + } + } else if l.contains("aborting due to previous") + || l.contains("Build failed") + || l.contains("Could not compile") + { + res.push(Aborting); + stop = true; + self.terminated = true; + } else if l.contains("Compilining ") || l.contains("file:///home/") || l.is_empty() { + // todo + } else if l.contains(" ...") { + res.push(Etc); + } else if is_not_cmd(&l) { + res.push(FollowUp(l.to_string())); + } + } + + self.terminated = true; + if stop { + Some(res) + } else { + None + } + } } fn is_not_cmd(l: &str) -> bool { - l.len() < 30 || !(l.starts_with("rustc ") || l.starts_with("cargo ") || l.starts_with("make ") || l.contains(" --") || l.contains(" --target=") || l.contains(" -C ") || l.contains(" -L ") || l.contains(" -A ") || l.contains(" -Z ") || l.contains(" -o ") || l.starts_with("sed ") || l.starts_with("mkdir ") || l.starts_with("cd ")) + l.len() < 30 + || !(l.starts_with("rustc ") + || l.starts_with("cargo ") + || l.starts_with("make ") + || l.contains(" --") + || l.contains(" --target=") + || l.contains(" -C ") + || l.contains(" -L ") + || l.contains(" -A ") + || l.contains(" -Z ") + || l.contains(" -o ") + || l.starts_with("sed ") + || l.starts_with("mkdir ") + || l.starts_with("cd ")) } impl MessageIter { - pub fn new() -> Self { - MessageIter { - buf: String::new(), - terminated: false, - errors: 0, - warnings: 0, - } - } + pub fn new() -> Self { + MessageIter { buf: String::new(), terminated: false, errors: 0, warnings: 0 } + } } - diff --git a/src/print.rs b/src/print.rs index 1662788..25770f6 100644 --- a/src/print.rs +++ b/src/print.rs @@ -1,28 +1,41 @@ -use term_painter::ToStyle; -use term_painter::Color::*; -use term_painter::Attr::*; +use term_painter::{Attr::*, Color::*, ToStyle}; -use parse::Message; -use parse::Message::*; +use parse::{Message, Message::*}; use wrap::wrap_msg; impl Message { - - pub fn print(self) { - - match self { - Header(ref file, ref line) => println!("+---- {} : {} ----+", Blue.bold().paint(file), Blue.paint(line)), - Warning(warn) => println!(" =====> {}{}", Yellow.bold().paint("warning: "), Bold.paint(&wrap_msg(warn, 9))), - Note(note) => println!(" =====> {}{}", Green.bold().paint("note: "), Bold.paint(&wrap_msg(note, 6))), - Error(err) => println!(" =====> {}{}", Red.bold().paint("error: "), Bold.paint(&wrap_msg(err, 7))), - Help(err) => println!(" =====> {}{}", Green.bold().paint("help: "), Bold.paint(&wrap_msg(err, 6))), - FollowUp(msg) => println!(" > {}", Bold.paint(msg)), - Source(line, code) => println!(" {} {}", Magenta.paint(format!("{} |>", line)), code), - Etc => println!(" {}", Magenta.paint("...")), - Marker(ref mrk) => println!("{}", Yellow.paint(mrk)), - NewLine => println!("\n"), - Wat => println!("Dafuq?"), - Aborting => println!("\n{}", Red.paint("Aborting due to previous errors")), - } - } + pub fn print(self) { + match self { + Header(ref file, ref line) => { + println!("+---- {} : {} ----+", Blue.bold().paint(file), Blue.paint(line)) + } + Warning(warn) => println!( + " =====> {}{}", + Yellow.bold().paint("warning: "), + Bold.paint(&wrap_msg(warn, 9)) + ), + Note(note) => println!( + " =====> {}{}", + Green.bold().paint("note: "), + Bold.paint(&wrap_msg(note, 6)) + ), + Error(err) => println!( + " =====> {}{}", + Red.bold().paint("error: "), + Bold.paint(&wrap_msg(err, 7)) + ), + Help(err) => println!( + " =====> {}{}", + Green.bold().paint("help: "), + Bold.paint(&wrap_msg(err, 6)) + ), + FollowUp(msg) => println!(" > {}", Bold.paint(msg)), + Source(line, code) => println!(" {} {}", Magenta.paint(format!("{} |>", line)), code), + Etc => println!(" {}", Magenta.paint("...")), + Marker(ref mrk) => println!("{}", Yellow.paint(mrk)), + NewLine => println!("\n"), + Wat => println!("Dafuq?"), + Aborting => println!("\n{}", Red.paint("Aborting due to previous errors")), + } + } } diff --git a/src/wrap.rs b/src/wrap.rs index 96dd908..1bb8eca 100644 --- a/src/wrap.rs +++ b/src/wrap.rs @@ -1,14 +1,13 @@ use std::iter::repeat; pub fn wrap_msg(s: String, n: usize) -> String { - let split = s.split(' ').collect::>(); - let mut chunks = split.chunks(8).map(|x| x.join(" ")); - - chunks.next().unwrap_or("?".to_string()) + &chunks.map(|ref x| { + let split = s.split(' ').collect::>(); + let mut chunks = split.chunks(8).map(|x| x.join(" ")); - "\n > ".to_string() + &repeat(" ").take(n) - .collect::() - + x - - }).collect::() + chunks.next().unwrap_or("?".to_string()) + + &chunks + .map(|ref x| { + "\n > ".to_string() + &repeat(" ").take(n).collect::() + x + }) + .collect::() }