Match highlighting and better colors in report
This commit is contained in:
121
src/main.rs
121
src/main.rs
@@ -1,31 +1,130 @@
|
||||
use std::env;
|
||||
use std::io;
|
||||
use std::fs::{self};
|
||||
use std::path::Path;
|
||||
|
||||
extern crate term;
|
||||
|
||||
mod config;
|
||||
|
||||
fn main() {
|
||||
let config = config::Config::from_args();
|
||||
println!("{:?}", config);
|
||||
|
||||
let path = Path::new(".");
|
||||
|
||||
traverse_dir(path);
|
||||
let results = traverse_dir(&config, path, |config, path| check_file(config, path));
|
||||
match results {
|
||||
Result::Ok(matches) if matches.len() == 0 => println!("No matches :("),
|
||||
Result::Ok(matches) => print_report(&matches),
|
||||
Result::Err(msg) => println!("Error while parsing: {}", msg)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_args() {
|
||||
fn traverse_dir(config: &config::Config, dir: &Path, operation: fn(&config::Config, &Path) -> io::Result<FileMatch>)
|
||||
-> io::Result<Vec<FileMatch>> {
|
||||
|
||||
let mut matches: Vec<FileMatch> = Vec::new();
|
||||
for entry in fs::read_dir(dir)? {
|
||||
let entry = entry?;
|
||||
let file_type = entry.file_type()?;
|
||||
|
||||
if file_type.is_dir() {
|
||||
let results = traverse_dir(&config, &entry.path(), operation)?;
|
||||
for mat in results.as_slice() {
|
||||
if mat.matches.len() > 0 {
|
||||
matches.append(&mut results.clone());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let result = operation(&config, &entry.path());
|
||||
match result {
|
||||
Result::Ok(result) if result.matches.len() > 0 => matches.push(result),
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(matches)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct FileMatch {
|
||||
file_name: String,
|
||||
matches: Vec<Match>
|
||||
}
|
||||
|
||||
fn traverse_dir(dir: &Path) -> io::Result<()> {
|
||||
for entry in fs::read_dir(dir)? {
|
||||
let entry = entry?;
|
||||
let file_type = entry.file_type()?;
|
||||
impl FileMatch {
|
||||
fn print(&self) {
|
||||
let mut term = term::stdout().unwrap();
|
||||
term.fg(term::color::YELLOW).unwrap();
|
||||
term.attr(term::Attr::Bold).unwrap();
|
||||
println!("{}:", self.file_name);
|
||||
term.reset().unwrap();
|
||||
|
||||
if file_type.is_dir() {
|
||||
traverse_dir(&entry.path());
|
||||
for mat in &self.matches {
|
||||
term.attr(term::Attr::Bold).unwrap();
|
||||
print!("{}: ", mat.line_number);
|
||||
term.reset().unwrap();
|
||||
|
||||
let mut last_position = 0;
|
||||
for (idx, match_index) in mat.match_indexes.iter().enumerate() {
|
||||
print!("{}", mat.text.get(last_position..match_index.start).unwrap());
|
||||
term.fg(term::color::BRIGHT_RED).unwrap();
|
||||
print!("{}", mat.text.get(match_index.start..match_index.end).unwrap());
|
||||
term.reset().unwrap();
|
||||
|
||||
if idx == mat.match_indexes.len() -1 {
|
||||
println!("{}", mat.text.get(match_index.end..mat.text.len()).unwrap());
|
||||
last_position = 0;
|
||||
} else {
|
||||
last_position = match_index.end;
|
||||
}
|
||||
}
|
||||
}
|
||||
println!();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct Match {
|
||||
line_number: usize,
|
||||
match_indexes: Vec<MatchIndex>,
|
||||
text: String
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct MatchIndex {
|
||||
start: usize,
|
||||
end: usize
|
||||
}
|
||||
|
||||
fn check_file(config: &config::Config, path: &Path) -> io::Result<FileMatch> {
|
||||
let pattern = &config.pattern;
|
||||
|
||||
// TODO: Use BufRead and read_line instead of reading the entire file into memory.
|
||||
let content = fs::read_to_string(&path)?;
|
||||
let mut matches = Vec::new();
|
||||
for (number, line) in content.lines().enumerate() {
|
||||
if line.contains(pattern) {
|
||||
let mut indexes = Vec::<MatchIndex>::new();
|
||||
for m in line.trim().match_indices(pattern) {
|
||||
indexes.push(MatchIndex { start: m.0, end: m.0 + pattern.len() });
|
||||
}
|
||||
|
||||
matches.push(Match { line_number: number + 1, text: line.trim().to_string(), match_indexes: indexes });
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Ok(FileMatch { file_name: path.to_str().unwrap().to_string(), matches: matches })
|
||||
}
|
||||
|
||||
fn print_report(matches: &Vec<FileMatch>) {
|
||||
for file in matches {
|
||||
file.print()
|
||||
// println!("{}:", file.file_name);
|
||||
// for mat in &file.matches {
|
||||
// println!("{}", mat.text);
|
||||
// }
|
||||
// println!();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user