Skip to content

Commit

Permalink
progress
Browse files Browse the repository at this point in the history
  • Loading branch information
alexpasmantier committed Oct 6, 2024
1 parent 7081186 commit 941ed46
Show file tree
Hide file tree
Showing 12 changed files with 381 additions and 205 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,13 @@ tracing-error = "0.2.0"
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "serde"] }
unicode-width = "0.2.0"


[build-dependencies]
anyhow = "1.0.86"
vergen-gix = { version = "1.0.0", features = ["build", "cargo"] }



[profile.release]
opt-level = 3
debug = "none"
Expand All @@ -77,3 +80,4 @@ debug-assertions = false
overflow-checks = false
lto = "fat"
panic = "abort"

7 changes: 7 additions & 0 deletions src/components/finders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ impl Entry {
pub fn display_name(&self) -> &str {
self.display_name.as_ref().unwrap_or(&self.name)
}

pub fn stdout_repr(&self) -> String {
self.name.clone()
+ &self
.line_number
.map_or(String::new(), |n| format!(":{}", n))
}
}

pub const ENTRY_PLACEHOLDER: Entry = Entry {
Expand Down
76 changes: 49 additions & 27 deletions src/components/finders/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ impl EnvVarFinder {
let injector = matcher.injector();
for (name, value) in std::env::vars() {
let _ = injector.push(EnvVar { name, value }, |e, cols| {
cols[0] = e.name.clone().into();
cols[1] = e.value.clone().into();
cols[0] = (e.name.clone() + &e.value).into();
});
}
EnvVarFinder {
Expand Down Expand Up @@ -77,55 +76,46 @@ impl Finder for EnvVarFinder {
self.total_count
}

// FIXME: find a trick to match name + value but not orthogonally like nucleo does
fn results(&mut self, num_entries: u32, offset: u32) -> impl Iterator<Item = Entry> {
let status = self.matcher.tick(Self::MATCHER_TICK_TIMEOUT);
let snapshot = self.matcher.snapshot();
if status.changed {
self.result_count = snapshot.matched_item_count();
self.total_count = snapshot.item_count();
}
let mut name_indices = Vec::new();
let mut value_indices = Vec::new();
let mut col_indices = Vec::new();
let mut matcher = MATCHER.lock();
let icon = self.file_icon.clone();
let mut should_add_name_indices = false;
let mut should_add_value_indices = false;

snapshot
.matched_items(offset..(num_entries + offset).min(snapshot.matched_item_count()))
.map(move |item| {
snapshot.pattern().column_pattern(0).indices(
item.matcher_columns[0].slice(..),
&mut matcher,
&mut name_indices,
&mut col_indices,
);
name_indices.sort_unstable();
name_indices.dedup();
should_add_name_indices = !name_indices.is_empty();
let name_indices = name_indices.drain(..);
col_indices.sort_unstable();
col_indices.dedup();

snapshot.pattern().column_pattern(1).indices(
item.matcher_columns[1].slice(..),
&mut matcher,
&mut value_indices,
);
value_indices.sort_unstable();
value_indices.dedup();
should_add_value_indices = !value_indices.is_empty();
let value_indices = value_indices.drain(..);
let (
name_indices,
value_indices,
should_add_name_indices,
should_add_value_indices,
) = sep_name_and_value_indices(&mut col_indices, item.data.name.len() as u32);

Entry {
name: item.matcher_columns[0].to_string(),
name: item.data.name.clone(),
display_name: None,
preview: Some(item.matcher_columns[1].to_string()),
preview: Some(item.data.value.clone()),
name_match_ranges: if should_add_name_indices {
Some(name_indices.map(|i| (i, i + 1)).collect())
Some(name_indices.into_iter().map(|i| (i, i + 1)).collect())
} else {
None
},
preview_match_ranges: if should_add_value_indices {
Some(value_indices.map(|i| (i, i + 1)).collect())
Some(value_indices.into_iter().map(|i| (i, i + 1)).collect())
} else {
None
},
Expand All @@ -139,8 +129,8 @@ impl Finder for EnvVarFinder {
fn get_result(&self, index: u32) -> Option<Entry> {
let snapshot = self.matcher.snapshot();
snapshot.get_matched_item(index).and_then(|item| {
let name = item.matcher_columns[0].to_string();
let value = item.matcher_columns[1].to_string();
let name = item.data.name.clone();
let value = item.data.value.clone();
Some(Entry {
name,
display_name: None,
Expand All @@ -154,3 +144,35 @@ impl Finder for EnvVarFinder {
})
}
}

fn sep_name_and_value_indices(
indices: &mut Vec<u32>,
name_len: u32,
) -> (Vec<u32>, Vec<u32>, bool, bool) {
let mut name_indices = Vec::new();
let mut value_indices = Vec::new();
let mut should_add_name_indices = false;
let mut should_add_value_indices = false;

for i in indices.drain(..) {
if i < name_len {
name_indices.push(i);
should_add_name_indices = true;
} else {
value_indices.push(i - name_len);
should_add_value_indices = true;
}
}

name_indices.sort_unstable();
name_indices.dedup();
value_indices.sort_unstable();
value_indices.dedup();

(
name_indices,
value_indices,
should_add_name_indices,
should_add_value_indices,
)
}
4 changes: 2 additions & 2 deletions src/components/finders/grep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ impl Finder for GrepFinder {
snapshot.get_matched_item(index).and_then(|item| {
let display_path = item.data.path.to_string_lossy().to_string();
Some(Entry {
name: display_path.clone() + ":" + &item.data.line_number.to_string(),
display_name: Some(display_path),
name: display_path.clone(),
display_name: Some(display_path.clone() + ":" + &item.data.line_number.to_string()),
preview: None,
name_match_ranges: None,
preview_match_ranges: None,
Expand Down
11 changes: 3 additions & 8 deletions src/components/previewers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::sync::Arc;

use super::finders::Entry;

mod cache;
mod env;
mod files;

Expand Down Expand Up @@ -41,26 +42,20 @@ pub const FILE_TOO_LARGE_MSG: &str = "File too large";
pub struct Preview {
pub title: String,
pub content: PreviewContent,
pub target_line: Option<u16>,
}

impl Default for Preview {
fn default() -> Self {
Preview {
title: String::new(),
content: PreviewContent::Empty,
target_line: None,
}
}
}

impl Preview {
pub fn new(title: String, content: PreviewContent, target_line: Option<u16>) -> Self {
Preview {
title,
content,
target_line,
}
pub fn new(title: String, content: PreviewContent) -> Self {
Preview { title, content }
}

pub fn total_lines(&self) -> u16 {
Expand Down
98 changes: 98 additions & 0 deletions src/components/previewers/cache.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
use std::{
collections::{HashMap, HashSet, VecDeque},
sync::Arc,
};

use tracing::debug;

use crate::components::previewers::Preview;

/// A ring buffer that also keeps track of the keys it contains to avoid duplicates.
struct SetRingBuffer<T> {
ring_buffer: VecDeque<T>,
known_keys: HashSet<T>,
capacity: usize,
}

impl<T> SetRingBuffer<T>
where
T: Eq + std::hash::Hash + Clone + std::fmt::Debug,
{
pub fn with_capacity(capacity: usize) -> Self {
SetRingBuffer {
ring_buffer: VecDeque::with_capacity(capacity),
known_keys: HashSet::with_capacity(capacity),
capacity,
}
}

// TODO: finish this
pub fn push(&mut self, key: T) -> Option<T> {
// If the key is already in the buffer, do nothing
if self.contains(&key) {
debug!("Key already in ring buffer: {:?}", key);
return None;
}
// If the buffer is full, remove the oldest key
if self.ring_buffer.len() >= self.capacity {
self.pop();
}
// finally, push the new key
self.ring_buffer.push_back(key.clone());
self.known_keys.insert(key);
None
}

pub fn pop(&mut self) -> Option<T> {
if let Some(key) = self.ring_buffer.pop_front() {
debug!("Removing key from ring buffer: {:?}", key);
self.known_keys.remove(&key);
Some(key)
} else {
None
}
}

pub fn contains(&self, key: &T) -> bool {
self.known_keys.contains(key)
}
}

const DEFAULT_PREVIEW_CACHE_SIZE: usize = 100;

/// A cache for previews.
pub struct PreviewCache {
entries: HashMap<String, Arc<Preview>>,
set_ring_buffer: SetRingBuffer<String>,
}

impl PreviewCache {
pub fn new(max_size: usize) -> Self {
PreviewCache {
entries: HashMap::new(),
set_ring_buffer: SetRingBuffer::with_capacity(max_size),
}
}

pub fn get(&self, key: &str) -> Option<Arc<Preview>> {
self.entries.get(key).cloned()
}

pub fn insert(&mut self, key: String, preview: Arc<Preview>) {
debug!("Inserting preview into cache: {}", key);
self.entries.insert(key.clone(), preview.clone());
self.set_ring_buffer.push(key);
if self.entry_buffer.len() >= self.max_size {
if let Some(oldest_key) = self.entry_buffer.pop_front() {
debug!("Cache full, removing oldest entry: {}", oldest_key);
self.entries.remove(&oldest_key);
}
}
}
}

impl Default for PreviewCache {
fn default() -> Self {
PreviewCache::new(DEFAULT_PREVIEW_CACHE_SIZE)
}
}
1 change: 0 additions & 1 deletion src/components/previewers/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ impl EnvVarPreviewer {
} else {
PreviewContent::Empty
},
target_line: None,
});
self.cache.insert(entry.clone(), preview.clone());
preview
Expand Down
Loading

0 comments on commit 941ed46

Please sign in to comment.