1
0
mirror of https://github.com/jht5945/finding.git synced 2026-01-12 20:00:03 +08:00

Compare commits

..

12 Commits

Author SHA1 Message Date
6f274d9a46 is_skip_link_and_is_link 2020-05-02 00:34:54 +08:00
b42086b865 j -> i 2020-05-02 00:32:26 +08:00
1cd44f5cbb use is_skip_link 2020-05-02 00:31:03 +08:00
0fda440d02 ref parts 2020-05-02 00:24:18 +08:00
1cbeccfd9a ref for 2020-05-02 00:23:17 +08:00
e430e037bc ref print 2020-05-02 00:21:49 +08:00
5b78fa85bc use chars 2020-05-02 00:18:56 +08:00
e0a85b1368 use (line_no, ln) in lines.enumerate() 2020-05-02 00:16:39 +08:00
ca8a3fb848 move to local_util 2020-05-01 22:16:52 +08:00
204e82635a version verbose 2020-05-01 22:10:07 +08:00
713cbdc67f fix size 2020-05-01 22:04:18 +08:00
9818c25f15 use CountCell 2020-05-01 21:38:47 +08:00
2 changed files with 94 additions and 62 deletions

View File

@@ -1,10 +1,46 @@
use std::{ use std::{
cell::Cell,
fs::File, fs::File,
path::Path, path::Path,
io::prelude::*, io::prelude::*,
}; };
use rust_util::{ XResult, new_box_error, }; use rust_util::{ XResult, new_box_error, };
#[derive(Debug)]
pub struct MatchLine {
pub line_number: usize,
pub line_string: String,
}
impl MatchLine {
pub fn new(line_number: usize, line_string: String) -> MatchLine {
MatchLine { line_number, line_string, }
}
}
pub struct CountCell( Cell<u64> );
impl CountCell {
pub fn new() -> CountCell {
CountCell( Cell::new(0_u64) )
}
#[inline]
pub fn get(&self) -> u64 {
self.0.get()
}
#[inline]
pub fn add(&self, i: u64) {
self.0.set(self.0.get() + i);
}
#[inline]
pub fn add_one(&self) {
self.add(1);
}
}
pub fn read_file_content<P: AsRef<Path>>(p: P, len_of_large_file: u64) -> XResult<String> { pub fn read_file_content<P: AsRef<Path>>(p: P, len_of_large_file: u64) -> XResult<String> {
let file = p.as_ref(); let file = p.as_ref();
if !file.exists() { if !file.exists() {

View File

@@ -6,7 +6,10 @@ extern crate rust_util;
mod opt; mod opt;
mod local_util; mod local_util;
use std::{ cell::Cell, path::Path, time::SystemTime, }; use std::{
path::Path,
time::{ Duration, SystemTime,},
};
use opt::*; use opt::*;
use rust_util::{ use rust_util::{
iff, iff,
@@ -16,30 +19,26 @@ use rust_util::{
util_size::*, util_size::*,
util_msg::*, util_msg::*,
}; };
use local_util::read_file_content; use local_util::{
CountCell,
MatchLine,
read_file_content,
};
const EMPTY: &str = ""; const EMPTY: &str = "";
const VERSION: &str = env!("CARGO_PKG_VERSION"); const VERSION: &str = env!("CARGO_PKG_VERSION");
const GIT_HASH: &str = env!("GIT_HASH"); const GIT_HASH: &str = env!("GIT_HASH");
#[derive(Debug)] fn print_version(options: &Options) {
struct MatchLine {
line_number: usize,
line_string: String,
}
impl MatchLine {
fn new(line_number: usize, line_string: String) -> MatchLine {
MatchLine { line_number, line_string, }
}
}
fn print_version() {
println!(r#"finding {} - {} println!(r#"finding {} - {}
Copyright (C) 2019-2020 Hatter Jiang. Copyright (C) 2019-2020 Hatter Jiang.
License MIT <https://opensource.org/licenses/MIT> License MIT <https://opensource.org/licenses/MIT>
Written by Hatter Jiang"#, VERSION, &GIT_HASH[0..7]); Written by Hatter Jiang"#, VERSION, &GIT_HASH[0..7]);
if options.verbose {
print_message(MessageType::DEBUG, &format!("Version: {}", VERSION));
print_message(MessageType::DEBUG, &format!("Git hash: {}", GIT_HASH));
}
} }
fn clear_n_print_message(mt: MessageType, message: &str) { fn clear_n_print_message(mt: MessageType, message: &str) {
@@ -48,11 +47,11 @@ fn clear_n_print_message(mt: MessageType, message: &str) {
} }
fn find_huge_files(options: &Options, dir_path: &Path) { fn find_huge_files(options: &Options, dir_path: &Path) {
let total_file_count_cell = Cell::new(0_u64); let total_file_count = CountCell::new();
let huge_file_count_cell = Cell::new(0_u64); let huge_file_count = CountCell::new();
let huge_file_size_cell = Cell::new(0_u64); let huge_file_size = CountCell::new();
walk_dir(&dir_path, &|_, _| (/* do not process error */), &|p| { // process file walk_dir(&dir_path, &|_, _| (/* do not process error */), &|p| { // process file
total_file_count_cell.replace(total_file_count_cell.get() + 1); total_file_count.add_one();
let p_str = match p.to_str() { let p_str = match p.to_str() {
Some(s) => s, None => return, Some(s) => s, None => return,
}; };
@@ -63,8 +62,8 @@ fn find_huge_files(options: &Options, dir_path: &Path) {
Ok(metadata) => { Ok(metadata) => {
let len = metadata.len(); let len = metadata.len();
if len >= options.parsed_huge_file_size { if len >= options.parsed_huge_file_size {
huge_file_count_cell.replace(huge_file_count_cell.get() + 1); huge_file_count.add_one();
huge_file_size_cell.replace(huge_file_size_cell.get() + 1); huge_file_size.add(len);
clear_n_print_message(MessageType::OK, &format!("{} [{}]", p_str, get_display_size(len as i64))); clear_n_print_message(MessageType::OK, &format!("{} [{}]", p_str, get_display_size(len as i64)));
} }
}, },
@@ -73,31 +72,31 @@ fn find_huge_files(options: &Options, dir_path: &Path) {
let p_str = match p.to_str() { let p_str = match p.to_str() {
Some(s) => s, None => return false, Some(s) => s, None => return false,
}; };
if options.skip_link_dir && is_symlink(p) { let is_skip_link_and_is_link = options.skip_link_dir && is_symlink(p);
if is_skip_link_and_is_link {
if options.verbose { if options.verbose {
clear_n_print_message(MessageType::INFO, &format!("Skip link dir: {}", p_str)); clear_n_print_message(MessageType::DEBUG, &format!("Skip link dir: {}", p_str));
} }
return false; } else {
print_lastline(&get_term_width_message(&format!("Scanning: {}", p_str), 10));
} }
print_lastline(&get_term_width_message(&format!("Scanning: {}", p_str), 10)); !is_skip_link_and_is_link
true
}).ok(); }).ok();
clear_n_print_message(MessageType::OK, &format!("Total file count: {}, huge file count: {}, total huge file size: {}", clear_n_print_message(MessageType::OK, &format!("Total file count: {}, huge file count: {}, total huge file size: {}",
total_file_count_cell.into_inner(), total_file_count.get(),
huge_file_count_cell.into_inner(), huge_file_count.get(),
get_display_size(huge_file_size_cell.into_inner() as i64))); get_display_size(huge_file_size.get() as i64)));
} }
fn match_lines(tag: &str, content: &str, options: &Options) -> bool { fn match_lines(tag: &str, content: &str, options: &Options) -> bool {
let search_text = &options.search_text; let search_text = &options.search_text;
let lines = content.lines(); let lines = content.lines();
let mut match_lines_vec = vec![]; let mut match_lines_vec = vec![];
let mut line_no = 0_usize;
let the_search_text = &iff!(options.ignore_case, search_text.to_lowercase(), search_text.to_string()); let the_search_text = &iff!(options.ignore_case, search_text.to_lowercase(), search_text.to_string());
for ln in lines { for (line_no, ln) in lines.enumerate() {
if options.filter_large_line && ln.len() as u64 >= options.parsed_large_line_size { if options.filter_large_line && ln.len() as u64 >= options.parsed_large_line_size {
if options.verbose { if options.verbose {
clear_n_print_message(MessageType::INFO, &format!("Skip large line: {} bytes", ln.len())); clear_n_print_message(MessageType::DEBUG, &format!("Skip large line: {} chars", ln.len()));
} }
continue; continue;
} }
@@ -109,30 +108,27 @@ fn match_lines(tag: &str, content: &str, options: &Options) -> bool {
if matches && matches_line_content { if matches && matches_line_content {
match_lines_vec.push(MatchLine::new(line_no, ln.to_string())); match_lines_vec.push(MatchLine::new(line_no, ln.to_string()));
} }
line_no += 1;
} }
if match_lines_vec.is_empty() { if !match_lines_vec.is_empty() {
false
} else {
clear_n_print_message(MessageType::OK, &format!("Find in {}:", tag)); clear_n_print_message(MessageType::OK, &format!("Find in {}:", tag));
for match_line in &match_lines_vec { for match_line in &match_lines_vec {
print!("{}: ", match_line.line_number + 1); print!("{}: ", match_line.line_number + 1);
if options.ignore_case { if options.ignore_case {
println!("{}", match_line.line_string); println!("{}", match_line.line_string);
} else { } else {
let ss: Vec<&str> = match_line.line_string.split(search_text).collect(); let parts = match_line.line_string.split(search_text).collect::<Vec<_>>();
for j in 0..ss.len() { for (i, part) in parts.iter().enumerate() {
print!("{}", ss[j]); if i != 0 {
if j < ss.len() - 1 {
print_color(Some(term::color::RED), true, search_text); print_color(Some(term::color::RED), true, search_text);
} }
print!("{}", part);
} }
println!(); println!();
} }
} }
true
} }
!match_lines_vec.is_empty()
} }
fn find_text_files(options: &Options, dir_path: &Path) { fn find_text_files(options: &Options, dir_path: &Path) {
@@ -147,13 +143,13 @@ fn find_text_files(options: &Options, dir_path: &Path) {
ext if ext.is_empty() => vec![], ext if ext.is_empty() => vec![],
ext => ext.split(',').map(|s| s.trim()).filter(|s| !s.is_empty()).map(|s| ".".to_owned() + s).collect(), ext => ext.split(',').map(|s| s.trim()).filter(|s| !s.is_empty()).map(|s| ".".to_owned() + s).collect(),
}; };
let total_file_count_cell = Cell::new(0_u64); let total_file_count = CountCell::new();
let scaned_file_count_cell = Cell::new(0_u64); let scaned_file_count = CountCell::new();
let matched_file_count_cell = Cell::new(0_u64); let matched_file_count = CountCell::new();
let total_dir_count_cell = Cell::new(0_u64); let total_dir_count = CountCell::new();
let scaned_dir_count_cell = Cell::new(0_u64); let scaned_dir_count = CountCell::new();
walk_dir(&dir_path, &|_, _| (/* do not process error */), &|p| { // process file walk_dir(&dir_path, &|_, _| (/* do not process error */), &|p| { // process file
total_file_count_cell.replace(total_file_count_cell.get() + 1); total_file_count.add_one();
let p_str = match p.to_str() { let p_str = match p.to_str() {
Some(s) => s, None => return, Some(s) => s, None => return,
}; };
@@ -169,50 +165,50 @@ fn find_text_files(options: &Options, dir_path: &Path) {
return; return;
}, },
}; };
scaned_file_count_cell.replace(scaned_file_count_cell.get() + 1); scaned_file_count.add_one();
if match_lines(p_str, &file_content, &options) { if match_lines(p_str, &file_content, &options) {
matched_file_count_cell.replace(matched_file_count_cell.get() + 1); matched_file_count.add_one();
} }
}, &|p| { // process path }, &|p| { // process path
total_dir_count_cell.replace(total_dir_count_cell.get() + 1); total_dir_count.add_one();
let p_str = match p.to_str() { let p_str = match p.to_str() {
Some(s) => s, None => return false, Some(s) => s, None => return false,
}; };
if (!options.scan_dot_git_dir) && p_str.ends_with("/.git") { if (!options.scan_dot_git_dir) && p_str.ends_with("/.git") {
if options.verbose { clear_n_print_message(MessageType::INFO, &format!("Skip .git dir: {}", p_str)); } if options.verbose { clear_n_print_message(MessageType::DEBUG, &format!("Skip .git dir: {}", p_str)); }
return false; return false;
} }
if options.skip_target_dir && p_str.ends_with("/target") { if options.skip_target_dir && p_str.ends_with("/target") {
if options.verbose { clear_n_print_message(MessageType::INFO, &format!("Skip target dir: {}", p_str)); } if options.verbose { clear_n_print_message(MessageType::DEBUG, &format!("Skip target dir: {}", p_str)); }
return false; return false;
} }
if options.skip_dot_dir && p_str.contains("/.") { if options.skip_dot_dir && p_str.contains("/.") {
if options.verbose { clear_n_print_message(MessageType::INFO, &format!("Skip dot(.) dir: {}", p_str)); } if options.verbose { clear_n_print_message(MessageType::DEBUG, &format!("Skip dot(.) dir: {}", p_str)); }
return false; return false;
} }
if options.skip_link_dir && is_symlink(p) { if options.skip_link_dir && is_symlink(p) {
if options.verbose { clear_n_print_message(MessageType::INFO, &format!("Skip link dir: {}", p_str)); } if options.verbose { clear_n_print_message(MessageType::DEBUG, &format!("Skip link dir: {}", p_str)); }
return false; return false;
} }
scaned_dir_count_cell.replace(scaned_dir_count_cell.get() + 1); scaned_dir_count.add_one();
print_lastline(&get_term_width_message(&format!("Scanning: {}", p_str), 10)); print_lastline(&get_term_width_message(&format!("Scanning: {}", p_str), 10));
true true
}).ok(); }).ok();
print_lastline(EMPTY); print_lastline(EMPTY);
print_message(MessageType::OK, &format!("Total dir count: {}, scaned dir count: {}", print_message(MessageType::OK, &format!("Total dir count: {}, scaned dir count: {}",
total_dir_count_cell.into_inner(), total_dir_count.get(),
scaned_dir_count_cell.into_inner())); scaned_dir_count.get()));
print_message(MessageType::OK, &format!("Total file count: {}, scaned file count: {}, matched file count: {}", print_message(MessageType::OK, &format!("Total file count: {}, scaned file count: {}, matched file count: {}",
total_file_count_cell.into_inner(), total_file_count.get(),
scaned_file_count_cell.into_inner(), scaned_file_count.get(),
matched_file_count_cell.into_inner())); matched_file_count.get()));
} }
fn main() -> XResult<()> { fn main() -> XResult<()> {
let options = Options::new_and_parse_args()?; let options = Options::new_and_parse_args()?;
if options.version { if options.version {
print_version(); print_version(&options);
return Ok(()); return Ok(());
} }
@@ -226,7 +222,7 @@ fn main() -> XResult<()> {
"text" => find_text_files(&options, &dir_path), "text" => find_text_files(&options, &dir_path),
others => return Err(new_box_error(&format!("Unknown command: {}", others))), others => return Err(new_box_error(&format!("Unknown command: {}", others))),
} }
let cost_millis = SystemTime::now().duration_since(start.clone()).unwrap().as_millis(); let cost_millis = SystemTime::now().duration_since(start.clone()).unwrap_or(Duration::from_millis(0)).as_millis();
print_message(MessageType::OK, &format!("Finding finished, cost {} ms", cost_millis)); print_message(MessageType::OK, &format!("Finding finished, cost {} ms", cost_millis));
Ok(()) Ok(())
} }