Page MenuHomePhorge

No OneTemporary

diff --git a/.gitignore b/.gitignore
index 88eb5a1..e138ae8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
build
+target
.cache
compile_commands.json
.luacheckcache
\ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..6c62469
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,196 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "aho-corasick"
+version = "0.7.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "bstr"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "fuzzy-matcher"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54614a3312934d066701a80f20f15fa3b56d67ac7722b39eea5b4c9dd1d66c94"
+dependencies = [
+ "thread_local",
+]
+
+[[package]]
+name = "globset"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a"
+dependencies = [
+ "aho-corasick",
+ "bstr",
+ "fnv",
+ "log",
+ "regex",
+]
+
+[[package]]
+name = "ignore"
+version = "0.4.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "713f1b139373f96a2e0ce3ac931cd01ee973c3c5dd7c40c0c2efe96ad2b6751d"
+dependencies = [
+ "crossbeam-utils",
+ "globset",
+ "lazy_static",
+ "log",
+ "memchr",
+ "regex",
+ "same-file",
+ "thread_local",
+ "walkdir",
+ "winapi-util",
+]
+
+[[package]]
+name = "ivy"
+version = "0.0.1"
+dependencies = [
+ "fuzzy-matcher",
+ "ignore",
+ "lazy_static",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "log"
+version = "0.4.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "memchr"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+
+[[package]]
+name = "once_cell"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
+
+[[package]]
+name = "regex"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
+
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "thread_local"
+version = "1.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
+name = "walkdir"
+version = "2.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
+dependencies = [
+ "same-file",
+ "winapi",
+ "winapi-util",
+]
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..cd601b6
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+name = "ivy"
+version = "0.0.1"
+edition = "2021"
+
+[lib]
+name = "ivyrs"
+crate-type = ["cdylib"]
+path = "rust/lib.rs"
+
+[dependencies]
+ignore = "0.4"
+fuzzy-matcher = "0.3.7"
+lazy_static = "1.4.0"
+
+[profile.release]
+opt-level = 3
diff --git a/lua/ivy/libivy.lua b/lua/ivy/libivy.lua
index d6222fa..0b00c2f 100644
--- a/lua/ivy/libivy.lua
+++ b/lua/ivy/libivy.lua
@@ -1,29 +1,29 @@
local library_path = (function()
local dirname = string.sub(debug.getinfo(1).source, 2, #"/fzf_lib.lua" * -1)
- return dirname .. "/../../build/Release/lib/libivy.so"
+ 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*);
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_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/rust/finder.rs b/rust/finder.rs
new file mode 100644
index 0000000..4a3ccf5
--- /dev/null
+++ b/rust/finder.rs
@@ -0,0 +1,26 @@
+use ignore::WalkBuilder;
+use std::fs;
+
+pub struct Options {
+ pub directory: String,
+}
+
+pub fn find_files(options: Options) -> Vec<String> {
+ let mut files: Vec<String> = Vec::new();
+ let base_path = &fs::canonicalize(options.directory).unwrap();
+
+ let mut builder = WalkBuilder::new(base_path);
+ builder.ignore(true).hidden(true);
+
+ 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());
+ }
+
+ return files;
+}
diff --git a/rust/lib.rs b/rust/lib.rs
new file mode 100644
index 0000000..52b861d
--- /dev/null
+++ b/rust/lib.rs
@@ -0,0 +1,68 @@
+mod matcher;
+mod finder;
+mod sorter;
+mod thread_pool;
+
+use std::sync::Mutex;
+use std::collections::HashMap;
+use std::os::raw::{c_int, c_char};
+use std::ffi::CString;
+use std::ffi::CStr;
+
+#[macro_use]
+extern crate lazy_static;
+
+lazy_static! {
+ static ref GLOBAL_FILE_CACHE: Mutex<HashMap<String, Vec<String>>> = return Mutex::new(HashMap::new()) ;
+}
+
+fn to_string(input: *const c_char) -> String {
+ return unsafe { CStr::from_ptr(input) }.to_str().unwrap().to_string();
+}
+
+fn get_files(directory: &String) -> Vec<String> {
+ 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() {}
+
+#[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);
+
+ let m = matcher::Matcher{ pattern };
+ return m.score(text) 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);
+
+ // Bail out early if the pattern is empty its never going to find anything
+ if pattern.is_empty() {
+ return CString::new("").unwrap().into_raw()
+ }
+
+ let files = get_files(&directory);
+
+ let mut output = String::new();
+ let sorter_options = sorter::Options::new(pattern);
+
+ let files = sorter::sort_strings(sorter_options, files);
+ for file in files.lock().unwrap().iter() {
+ output.push_str(&file.content);
+ output.push('\n');
+ }
+
+ return CString::new(output).unwrap().into_raw()
+}
+
diff --git a/rust/matcher.rs b/rust/matcher.rs
new file mode 100644
index 0000000..43d364d
--- /dev/null
+++ b/rust/matcher.rs
@@ -0,0 +1,18 @@
+use fuzzy_matcher::FuzzyMatcher;
+use fuzzy_matcher::skim::SkimMatcherV2;
+
+pub struct Matcher {
+ /// The search pattern that we want to match against some text
+ pub pattern: String,
+}
+
+impl Matcher {
+ pub fn score(self: &Self, text: String) -> i64 {
+ let matcher = SkimMatcherV2::default();
+ if let Some((score, _indices)) = matcher.fuzzy_indices(&text, &self.pattern) {
+ return score;
+ }
+
+ return 0;
+ }
+}
diff --git a/rust/sorter.rs b/rust/sorter.rs
new file mode 100644
index 0000000..3bb5c47
--- /dev/null
+++ b/rust/sorter.rs
@@ -0,0 +1,48 @@
+use super::matcher;
+use super::thread_pool;
+
+
+use std::sync::Mutex;
+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 {
+ return Self { pattern, minimun_score: 20 };
+ }
+}
+
+pub fn sort_strings(options: Options, strings: Vec<String>) -> Arc<Mutex<Vec<Match>>> {
+ let matches: Arc<Mutex<Vec<Match>>> = Arc::new(Mutex::new(Vec::new()));
+ let matcher = Arc::new(Mutex::new(matcher::Matcher{ pattern: options.pattern }));
+
+ let pool = thread_pool::ThreadPool::new(std::thread::available_parallelism().unwrap().get());
+
+ for string in strings {
+ let thread_matcher = Arc::clone(&matcher);
+ let thread_matches = Arc::clone(&matches);
+ pool.execute(move || {
+ let score = thread_matcher.lock().unwrap().score(string.to_string());
+ if score > 25 {
+ let mut tmp = thread_matches.lock().unwrap();
+ let content = string.clone();
+ tmp.push(Match{ score, content });
+ }
+ })
+ }
+
+ drop(pool);
+
+ matches.lock().unwrap().sort_by(|a, b| a.score.cmp(&b.score));
+ return matches;
+}
+
diff --git a/rust/thread_pool.rs b/rust/thread_pool.rs
new file mode 100644
index 0000000..df49872
--- /dev/null
+++ b/rust/thread_pool.rs
@@ -0,0 +1,87 @@
+use std::sync::mpsc;
+use std::sync::Arc;
+use std::sync::Mutex;
+use std::thread;
+
+enum Message {
+ NewJob(Job),
+ Terminate,
+}
+
+pub struct ThreadPool {
+ jobs: mpsc::Sender<Message>,
+ threads: Vec<Worker>,
+}
+
+trait FnBox {
+ fn call_box(self: Box<Self>);
+}
+
+impl<F: FnOnce()> FnBox for F {
+ fn call_box(self: Box<F>) {
+ (*self)()
+ }
+}
+
+type Job = Box<dyn FnBox + Send + 'static>;
+
+impl ThreadPool {
+ pub fn new(thread_count: usize) -> Self {
+ let (jobs, receiver) = mpsc::channel();
+ let receiver = Arc::new(Mutex::new(receiver));
+
+ let mut threads: Vec<Worker> = Vec::new();
+ for id in 1..thread_count {
+ threads.push(Worker::new(id, Arc::clone(&receiver)));
+ }
+
+ return ThreadPool { jobs, threads };
+ }
+
+ pub fn execute<F>(&self, f: F)
+ where
+ F: FnOnce() + Send + 'static,
+ {
+ let job = Box::new(f);
+ self.jobs.send(Message::NewJob(job)).unwrap();
+ }
+}
+
+impl Drop for ThreadPool {
+ fn drop(&mut self) {
+ for _ in &mut self.threads {
+ self.jobs.send(Message::Terminate).unwrap();
+ }
+
+ for worker in &mut self.threads {
+ if let Some(thread) = worker.thread.take() {
+ thread.join().unwrap();
+ }
+ }
+ }
+}
+
+struct Worker {
+ id: usize,
+ thread: Option<thread::JoinHandle<()>>,
+}
+
+impl Worker {
+ fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Message>>>) -> Worker {
+ let thread = thread::spawn(move || loop {
+ let message = receiver.lock().unwrap().recv().unwrap();
+
+ match message {
+ Message::NewJob(job) => job.call_box(),
+ Message::Terminate => {
+ break;
+ }
+ }
+ });
+
+ return Worker {
+ id,
+ thread: Some(thread),
+ };
+ }
+}

File Metadata

Mime Type
text/x-diff
Expires
Fri, May 8, 9:59 PM (1 w, 7 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
9044
Default Alt Text
(13 KB)

Event Timeline