Move app to its own module

Moved blocks into their own functions and made a small public api.
This commit is contained in:
Cameron Cordes
2021-02-13 22:45:24 -05:00
parent eaf9994cd4
commit 4ef70979bc

View File

@@ -1,14 +1,35 @@
use rack::config::Config; use crate::rack::Rack;
use rack::filematch::*;
extern crate term;
fn main() {
let rack = Rack::new();
rack.run();
}
mod rack {
use ::rack::config::Config;
use ::rack::filematch::*;
use std::fs::{self, DirEntry, File}; use std::fs::{self, DirEntry, File};
use std::io; use std::io;
use std::io::prelude::*; use std::io::prelude::*;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
extern crate term; pub struct Rack {
config: Config,
matches: Vec<FileMatch>,
}
fn main() { impl Rack {
let config = Config::from_args(); pub fn new() -> Self {
Rack {
config: Config::from_args(),
matches: Vec::new(),
}
}
pub fn run(mut self) {
let config = &self.config;
let search_path = &config.path; let search_path = &config.path;
let path = if search_path.starts_with('/') { let path = if search_path.starts_with('/') {
@@ -19,23 +40,18 @@ fn main() {
PathBuf::from(path) PathBuf::from(path)
}; };
let results = traverse_dir(&config, &path, Option::None, |config, path| { match self.traverse_dir(&path, Option::None) {
check_file(config, path) Result::Ok(_) if self.matches.is_empty() => println!("No matches :("),
}); Result::Ok(_) => self.print_report(),
match results {
Result::Ok(matches) if matches.is_empty() => println!("No matches :("),
Result::Ok(matches) => print_report(&config, &matches),
Result::Err(msg) => println!("Error while parsing: {}", msg), Result::Err(msg) => println!("Error while parsing: {}", msg),
} }
} }
fn traverse_dir( fn traverse_dir(
config: &Config, &mut self,
dir: &PathBuf, dir: &PathBuf,
gitignore_entries: Option<Vec<String>>, gitignore_entries: Option<Vec<String>>,
operation: fn(&Config, &Path) -> io::Result<FileMatch>, ) -> io::Result<()> {
) -> io::Result<Vec<FileMatch>> {
let mut matches: Vec<FileMatch> = Vec::new();
let entries = fs::read_dir(dir)?.collect::<Vec<io::Result<DirEntry>>>(); let entries = fs::read_dir(dir)?.collect::<Vec<io::Result<DirEntry>>>();
let gitignore: Option<&DirEntry> = entries let gitignore: Option<&DirEntry> = entries
@@ -57,50 +73,45 @@ fn traverse_dir(
for entry in entries { for entry in entries {
let entry = entry?; let entry = entry?;
let file_type = entry.file_type()?; let file_type = entry.file_type()?;
let path = entry.path().to_str().unwrap().to_owned(); let path = entry.path();
let path = path.to_str().unwrap();
if file_type.is_dir() { if file_type.is_dir() {
if config.use_gitignore { if self.should_ignore(&gitignore, path, &entry) {
let should_ignore = gitignore.iter().find(|&line| path.contains(&line.clone()));
if !should_ignore.unwrap_or(&String::from("")).is_empty()
|| entry.path().to_str().unwrap().contains("/.git")
{
continue; continue;
} }
}
// TODO: Should borrow gitignore instead of cloning.. // TODO: Should borrow gitignore instead of cloning..
let mut results = self.traverse_dir(&entry.path(), Some(gitignore.clone()))?;
traverse_dir(&config, &entry.path(), Some(gitignore.clone()), operation)?;
let has_results = results.iter().filter(|mat| !mat.matches.is_empty()).count() > 0;
if has_results {
matches.append(&mut results);
}
} else { } else {
if config.use_gitignore { if self.should_ignore(&gitignore, path, &entry) {
let should_ignore: Option<&String> =
gitignore.iter().find(|&line| path.contains(&line.clone()));
if !should_ignore.unwrap_or(&String::from("")).is_empty()
|| entry.path().to_str().unwrap().contains("/.git")
{
continue; continue;
} }
} let result = self.check_file(&entry.path());
let result = operation(&config, &entry.path());
match result { match result {
Result::Ok(result) if !result.matches.is_empty() => matches.push(result), Result::Ok(result) if !result.matches.is_empty() => self.matches.push(result),
_ => (), _ => (),
} }
} }
} }
Ok(matches) Ok(())
} }
fn check_file(config: &Config, path: &Path) -> io::Result<FileMatch> { fn should_ignore(&self, gitignore: &Vec<String>, path: &str, entry: &DirEntry) -> bool {
let mut pattern = config.pattern.clone(); if self.config.use_gitignore {
let should_ignore = gitignore.iter().find(|&line| path.contains(&line.clone()));
if !should_ignore.unwrap_or(&String::from("")).is_empty()
|| entry.path().to_str().unwrap().contains("/.git")
{
return true;
}
}
false
}
fn check_file(&self, path: &Path) -> io::Result<FileMatch> {
let mut pattern = self.config.pattern.clone();
let file = File::open(&path)?; let file = File::open(&path)?;
let file = io::BufReader::new(file); let file = io::BufReader::new(file);
@@ -109,7 +120,7 @@ fn check_file(config: &Config, path: &Path) -> io::Result<FileMatch> {
for (number, line) in file.lines().enumerate() { for (number, line) in file.lines().enumerate() {
let mut line = line?; let mut line = line?;
let orig_line = line.clone(); let orig_line = line.clone();
if config.ignore_case { if self.config.ignore_case {
line = line.to_lowercase(); line = line.to_lowercase();
pattern = pattern.to_lowercase(); pattern = pattern.to_lowercase();
} }
@@ -137,8 +148,10 @@ fn check_file(config: &Config, path: &Path) -> io::Result<FileMatch> {
}) })
} }
fn print_report(config: &Config, matches: &[FileMatch]) { fn print_report(&self) {
for file in matches { for file in &self.matches {
file.print(config) file.print(&self.config)
}
}
} }
} }