diff --git a/lua/ivy/libivy.lua b/lua/ivy/libivy.lua index 0b00c2f..0377b2e 100644 --- a/lua/ivy/libivy.lua +++ b/lua/ivy/libivy.lua @@ -1,29 +1,34 @@ local library_path = (function() local dirname = string.sub(debug.getinfo(1).source, 2, #"/fzf_lib.lua" * -1) return dirname .. "/../../target/release/libivyrs.so" end)() local ffi = require "ffi" local ivy_c = ffi.load(library_path) ffi.cdef [[ void ivy_init(const char*); + char* ivy_cwd(); int ivy_match(const char*, const char*); char* ivy_files(const char*, const char*); ]] local libivy = {} libivy.ivy_init = function(dir) ivy_c.ivy_init(dir) end +libivy.ivy_cwd = function () + return ffi.string(ivy_c.ivy_cwd()) +end + libivy.ivy_match = function(pattern, text) return ivy_c.ivy_match(pattern, text) end libivy.ivy_files = function(pattern, base_dir) return ffi.string(ivy_c.ivy_files(pattern, base_dir)) end return libivy diff --git a/lua/ivy/libivy_test.lua b/lua/ivy/libivy_test.lua index 28fb527..519361a 100644 --- a/lua/ivy/libivy_test.lua +++ b/lua/ivy/libivy_test.lua @@ -1,9 +1,18 @@ local libivy = require "ivy.libivy" it("should run a simple match", function(t) local score = libivy.ivy_match("term", "I am a serch term") if score <= 0 then t.error("Score should not be less than 0 found " .. score) end end) + +it("should find a dot file", function (t) + local current_dir = libivy.ivy_cwd() + local matches = libivy.ivy_files("ci.yml", current_dir); + + if matches ~= ".github/workflows/ci.yml\n" then + t.error("Invalid matches: " .. matches) + end +end); diff --git a/rust/finder.rs b/rust/finder.rs index 3a4dd31..f77d55d 100644 --- a/rust/finder.rs +++ b/rust/finder.rs @@ -1,26 +1,34 @@ -use ignore::WalkBuilder; +use ignore::{overrides::OverrideBuilder, WalkBuilder}; use std::fs; pub struct Options { pub directory: String, } pub fn find_files(options: Options) -> Vec { let mut files: Vec = Vec::new(); let base_path = &fs::canonicalize(options.directory).unwrap(); let mut builder = WalkBuilder::new(base_path); - builder.ignore(true).hidden(true); + builder.hidden(false); + + // TODO(ade): Remove unwraps and find a good way to get the errors into the UI. Currently there + // is no way to handel errors in the rust library + let mut override_builder = OverrideBuilder::new(""); + override_builder.add("!.git").unwrap(); + + let overrides = override_builder.build().unwrap(); + builder.overrides(overrides); for result in builder.build() { let absolute_candidate = result.unwrap(); let candidate_path = absolute_candidate.path().strip_prefix(base_path).unwrap(); if candidate_path.is_dir() { continue; } files.push(candidate_path.to_str().unwrap().to_string()); } files } diff --git a/rust/lib.rs b/rust/lib.rs index e2aca28..3a0848d 100644 --- a/rust/lib.rs +++ b/rust/lib.rs @@ -1,86 +1,93 @@ mod finder; mod matcher; mod sorter; 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_cwd() -> *const c_char { + return CString::new(std::env::current_dir().unwrap().to_str().unwrap()) + .unwrap() + .into_raw(); +} + #[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_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 }