diff --git a/examples/filename_search.rs b/examples/filename_search.rs index 0e91b96..68cba68 100644 --- a/examples/filename_search.rs +++ b/examples/filename_search.rs @@ -1,5 +1,7 @@ use ivyrs::inner_files; pub fn main() { - inner_files("file.go".to_owned(), "/tmp/ivy-trees/kubernetes".to_owned()); + let res = inner_files("file.go".to_owned(), "/tmp/ivy-trees/kubernetes".to_owned()); + + println!("{}", res); } diff --git a/rust/lib.rs b/rust/lib.rs index b1e6cf0..74bda52 100644 --- a/rust/lib.rs +++ b/rust/lib.rs @@ -1,87 +1,87 @@ mod finder; mod matcher; mod sorter; mod thread_pool; use std::collections::HashMap; use std::ffi::CStr; use std::ffi::CString; use std::os::raw::{c_char, c_int}; use std::sync::Mutex; #[macro_use] extern crate lazy_static; lazy_static! { static ref GLOBAL_FILE_CACHE: Mutex>> = Mutex::new(HashMap::new()); } fn to_string(input: *const c_char) -> String { unsafe { CStr::from_ptr(input) } .to_str() .unwrap() .to_string() } fn get_files(directory: &String) -> Vec { let mut cache = GLOBAL_FILE_CACHE.lock().unwrap(); if !cache.contains_key(directory) { let finder_options = finder::Options { directory: directory.clone(), }; cache.insert(directory.clone(), finder::find_files(finder_options)); } return cache.get(directory).unwrap().to_vec(); } #[no_mangle] pub extern "C" fn ivy_init(c_base_dir: *const c_char) { let directory = to_string(c_base_dir); get_files(&directory); } #[no_mangle] pub extern "C" fn ivy_match(c_pattern: *const c_char, c_text: *const c_char) -> c_int { let pattern = to_string(c_pattern); let text = to_string(c_text); inner_match(pattern, text) } pub fn inner_match(pattern: String, text: String) -> i32 { let m = matcher::Matcher::new(pattern); - m.score(text) as i32 + m.score(text.as_str()) as i32 } #[no_mangle] pub extern "C" fn ivy_files(c_pattern: *const c_char, c_base_dir: *const c_char) -> *const c_char { let pattern = to_string(c_pattern); let directory = to_string(c_base_dir); let output = inner_files(pattern, directory); CString::new(output).unwrap().into_raw() } pub fn inner_files(pattern: String, base_dir: String) -> String { let mut output = String::new(); // Bail out early if the pattern is empty; it's never going to find anything if pattern.is_empty() { return output; } let files = get_files(&base_dir); let sorter_options = sorter::Options::new(pattern); let files = sorter::sort_strings(sorter_options, files); for file in files.iter() { output.push_str(&file.content); output.push('\n'); } output } diff --git a/rust/matcher.rs b/rust/matcher.rs index 0560717..cbbf6d7 100644 --- a/rust/matcher.rs +++ b/rust/matcher.rs @@ -1,24 +1,24 @@ use fuzzy_matcher::skim::SkimMatcherV2; use fuzzy_matcher::FuzzyMatcher; pub struct Matcher { /// The search pattern that we want to match against some text pub pattern: String, matcher: SkimMatcherV2, } impl Matcher { pub fn new(pattern: String) -> Self { Self { pattern, matcher: SkimMatcherV2::default(), } } - pub fn score(&self, text: String) -> i64 { + pub fn score(&self, text: &str) -> i64 { self.matcher - .fuzzy_indices(&text, &self.pattern) + .fuzzy_indices(text, &self.pattern) .map(|(score, _indices)| score) .unwrap_or_default() } } diff --git a/rust/sorter.rs b/rust/sorter.rs index 83ba5b9..cc7c31b 100644 --- a/rust/sorter.rs +++ b/rust/sorter.rs @@ -1,59 +1,39 @@ use super::matcher; use super::thread_pool; use std::sync::mpsc; use std::sync::Arc; pub struct Match { pub score: i64, pub content: String, } pub struct Options { pub pattern: String, pub minimun_score: i64, } impl Options { pub fn new(pattern: String) -> Self { Self { pattern, minimun_score: 20, } } } pub fn sort_strings(options: Options, strings: Vec) -> Vec { - let mut matches = Vec::new(); - let matcher = Arc::new(matcher::Matcher::new(options.pattern)); + let matcher = matcher::Matcher::new(options.pattern); - let pool = thread_pool::ThreadPool::new(std::thread::available_parallelism().unwrap().get()); - - let (tx, rx) = mpsc::channel::(); - - for string in strings { - let thread_matcher = Arc::clone(&matcher); - let thread_transmitter = tx.clone(); - pool.execute(move || { - let score = thread_matcher.score(string.to_string()); - if score > 25 { - thread_transmitter - .send(Match { - score, - content: string, - }) - .expect("Failed to push data to channel"); - } + let mut matches = strings + .into_iter() + .map(|candidate| Match { + score: matcher.score(candidate.as_str()), + content: candidate, }) - } - - drop(pool); - drop(tx); - - while let Ok(result) = rx.recv() { - matches.push(result) - } - + .filter(|m| m.score > 25) + .collect::>(); matches.sort_by(|a, b| a.score.cmp(&b.score)); matches }