use std::fs::File; use std::env; use std::path::Path; use std::io::*; mod config; fn omit_line(line: String, in_comment_section: &mut bool, comment_tokens: &config::CommentTokens) -> bool { let s = line.trim(); let begin_comment_section = s.starts_with(comment_tokens.begin_comment_block.as_str()); let end_comment_section = s.starts_with(comment_tokens.end_comment_block.as_str()); if begin_comment_section { *in_comment_section = true; return true; } else if *in_comment_section && !end_comment_section { return true; } else if *in_comment_section && end_comment_section { *in_comment_section = false; return true; } s.starts_with(comment_tokens.single_line.as_str()) || s.is_empty() } fn get_config<'a>(config: &'a Vec, extension: &str) -> Option<&'a config::CommentTokens> { for conf in config.iter() { if conf.file_ending == extension { return Some(conf); } } None } fn count_lines(filename: &str, config: &mut Vec) -> Result{ let mut sum = 0; let mut in_comment_section = false; // do we have config for this type of file? let extension = match Path::new(filename).extension() { Some(ext) => ext.to_str().unwrap(), None => return Err(Error::new(std::io::ErrorKind::Other, "could not get extension")), }; let comment_tokens = match get_config(&config, extension) { Some(conf) => conf, None => return Err(Error::new(std::io::ErrorKind::NotFound, "config not found")), }; let bufread = BufReader::new(try!(File::open(filename))); for line in bufread.lines() { if omit_line(try!(line), &mut in_comment_section, &comment_tokens) { continue; } sum += 1; } Ok(sum) } fn main() { let mut config = match config::read_config() { Err(e) => panic!("error reading config file(s): {}", e), Ok(i) => i, }; let mut sum = 0; // TODO read files from standard input option // TODO read all file below this dictionary for argument in env::args().skip(1) { match count_lines(argument.as_str(), &mut config) { Ok(i) => { println!("{}\t: {}", i, argument); sum += i; }, Err(e) => println!("error for file {}: {}", argument, e), } } println!("{}\t: total", sum); }