chore: better ffi
This commit is contained in:
parent
39febd82e2
commit
75bd90ab4a
5 changed files with 50 additions and 27 deletions
|
|
@ -7,9 +7,12 @@ local ffi = require "ffi"
|
|||
local ivy_c = ffi.load(library_path)
|
||||
|
||||
ffi.cdef [[
|
||||
typedef struct { int score; const char* content; } match;
|
||||
typedef struct { int len; match* matches; } match_list;
|
||||
|
||||
void ivy_init(const char*);
|
||||
int ivy_match(const char*, const char*);
|
||||
char* ivy_files(const char*, const char*);
|
||||
match_list* ivy_files(const char*, const char*);
|
||||
]]
|
||||
|
||||
local libivy = {}
|
||||
|
|
@ -23,7 +26,7 @@ libivy.ivy_match = function(pattern, text)
|
|||
end
|
||||
|
||||
libivy.ivy_files = function(pattern, base_dir)
|
||||
return ffi.string(ivy_c.ivy_files(pattern, base_dir))
|
||||
return ivy_c.ivy_files(pattern, base_dir)
|
||||
end
|
||||
|
||||
return libivy
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
local libivy = require "ivy.libivy"
|
||||
local ffi = require "ffi"
|
||||
|
||||
it("should run a simple match", function(t)
|
||||
local score = libivy.ivy_match("term", "I am a serch term")
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
local ffi = require "ffi"
|
||||
|
||||
-- Constent options that will be used for the keymaps
|
||||
local opts = { noremap = true, silent = true, nowait = true }
|
||||
|
||||
|
|
@ -22,12 +24,12 @@ local function string_to_table(lines)
|
|||
end
|
||||
|
||||
local function set_items_string(buffer, lines)
|
||||
vim.api.nvim_buf_set_lines(buffer, 0, 9999, false, string_to_table(lines))
|
||||
vim.api.nvim_buf_set_lines(buffer, 0, -1, false, string_to_table(lines))
|
||||
end
|
||||
|
||||
local function set_items_array(buffer, lines)
|
||||
if type(lines[1]) == "string" then
|
||||
vim.api.nvim_buf_set_lines(buffer, 0, 9999, false, lines)
|
||||
vim.api.nvim_buf_set_lines(buffer, 0, -1, false, lines)
|
||||
else
|
||||
for i = 1, #lines do
|
||||
vim.api.nvim_buf_set_lines(buffer, i - 1, 9999, false, { lines[i][2] })
|
||||
|
|
@ -112,7 +114,13 @@ window.update = function()
|
|||
end
|
||||
|
||||
window.set_items = function(items)
|
||||
if #items == 0 then
|
||||
vim.api.nvim_buf_set_lines(window.get_buffer(), 0, -1, false, {})
|
||||
|
||||
if items.len ~= nil then
|
||||
for i = 0, items.len - 1 do
|
||||
vim.api.nvim_buf_set_lines(window.get_buffer(), i - 1, -1, false, { ffi.string(items.matches[i].content) })
|
||||
end
|
||||
elseif #items == 0 then
|
||||
vim.api.nvim_buf_set_lines(window.get_buffer(), 0, 9999, false, { "-- No Items --" })
|
||||
elseif type(items) == "string" then
|
||||
set_items_string(window.get_buffer(), items)
|
||||
|
|
|
|||
38
rust/lib.rs
38
rust/lib.rs
|
|
@ -4,9 +4,15 @@ 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;
|
||||
use std::mem;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct FFiMatchList {
|
||||
len: c_int,
|
||||
matches: *mut sorter::Match
|
||||
}
|
||||
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
|
@ -22,6 +28,15 @@ fn to_string(input: *const c_char) -> String {
|
|||
.to_string()
|
||||
}
|
||||
|
||||
fn to_ffi_match_list(mut list: Vec<sorter::Match>) -> *const FFiMatchList {
|
||||
list.shrink_to_fit();
|
||||
let matches = list.as_mut_ptr();
|
||||
let len: c_int = list.len().try_into().unwrap();
|
||||
mem::forget(list);
|
||||
|
||||
return Box::into_raw(Box::new(FFiMatchList { len, matches }))
|
||||
}
|
||||
|
||||
fn get_files(directory: &String) -> Vec<String> {
|
||||
let mut cache = GLOBAL_FILE_CACHE.lock().unwrap();
|
||||
if !cache.contains_key(directory) {
|
||||
|
|
@ -55,32 +70,21 @@ pub fn inner_match(pattern: String, text: String) -> i32 {
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn ivy_files(c_pattern: *const c_char, c_base_dir: *const c_char) -> *const c_char {
|
||||
pub extern "C" fn ivy_files(c_pattern: *const c_char, c_base_dir: *const c_char) -> *const FFiMatchList {
|
||||
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()
|
||||
return inner_files(pattern, directory);
|
||||
}
|
||||
|
||||
pub fn inner_files(pattern: String, base_dir: String) -> String {
|
||||
let mut output = String::new();
|
||||
|
||||
pub fn inner_files(pattern: String, base_dir: String) -> *const FFiMatchList {
|
||||
// Bail out early if the pattern is empty; it's never going to find anything
|
||||
if pattern.is_empty() {
|
||||
return output;
|
||||
return to_ffi_match_list(Vec::new());
|
||||
}
|
||||
|
||||
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
|
||||
to_ffi_match_list(sorter::sort_strings(sorter_options, files))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,18 @@
|
|||
use super::matcher;
|
||||
use rayon::prelude::*;
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use std::ffi::CString;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Match {
|
||||
pub score: i64,
|
||||
pub content: String,
|
||||
pub score: c_int,
|
||||
pub content: *const c_char
|
||||
// pub score: i64,
|
||||
// pub content: String,
|
||||
}
|
||||
|
||||
unsafe impl Send for Match {}
|
||||
|
||||
pub struct Options {
|
||||
pub pattern: String,
|
||||
pub minimum_score: i64,
|
||||
|
|
@ -26,10 +33,10 @@ pub fn sort_strings(options: Options, strings: Vec<String>) -> Vec<Match> {
|
|||
let mut matches = strings
|
||||
.into_par_iter()
|
||||
.map(|candidate| Match {
|
||||
score: matcher.score(candidate.as_str()),
|
||||
content: candidate,
|
||||
score: matcher.score(candidate.as_str()) as i32,
|
||||
content: CString::new(candidate.clone().to_string()).unwrap().into_raw(),
|
||||
})
|
||||
.filter(|m| m.score > options.minimum_score)
|
||||
.filter(|m| m.score > options.minimum_score as i32)
|
||||
.collect::<Vec<Match>>();
|
||||
matches.par_sort_unstable_by(|a, b| a.score.cmp(&b.score));
|
||||
matches
|
||||
|
|
|
|||
Loading…
Reference in a new issue