Skip to content

Commit

Permalink
fzf: implement Pattern::parse
Browse files Browse the repository at this point in the history
  • Loading branch information
noib3 committed Nov 5, 2023
1 parent 9d247e2 commit b6f63bc
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 113 deletions.
142 changes: 31 additions & 111 deletions src/algos/fzf/parser.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use alloc::borrow::Cow;

use super::query::{Condition, FzfQuery, MatchType, Pattern};
use super::query::{Condition, FzfQuery, Pattern};

/// TODO: docs
#[derive(Clone)]
Expand Down Expand Up @@ -52,36 +52,26 @@ impl FzfParser {
self.patterns.resize(max_conditions, Pattern::default());
}

let mut char_len = 0;

for ch in query.chars() {
self.chars[char_len] = ch;
char_len += 1;
}

let pattern = Pattern::new(&self.chars[..char_len], MatchType::Fuzzy);

// SAFETY: todo.
let pattern = unsafe {
core::mem::transmute::<Pattern, Pattern<'static>>(pattern)
};

self.patterns[0] = pattern;

let patterns = &self.patterns[..1];

let condition = Condition::new(patterns);

// SAFETY: todo.
let condition = unsafe {
core::mem::transmute::<Condition, Condition<'static>>(condition)
};

self.conditions[0] = condition;
// let mut char_len = 0;
//
// for ch in query.chars() {
// self.chars[char_len] = ch;
// char_len += 1;
// }

// // SAFETY: todo.
// let pattern = unsafe {
// core::mem::transmute::<Pattern, Pattern<'static>>(pattern)
// };
//
// // SAFETY: todo.
// let condition = unsafe {
// core::mem::transmute::<Condition, Condition<'static>>(condition)
// };

let conditions = &self.conditions[..1];
let conditions = parse(query);

FzfQuery::new(conditions)
FzfQuery::new(conditions.leak())
}

/// TODO: docs
Expand All @@ -94,88 +84,17 @@ impl FzfParser {
/// TODO: docs
#[inline]
fn parse(query: &str) -> Vec<Condition<'static>> {
let mut conditions = Vec::new();

for word in Words::new(query) {
let mut word = word.as_ref();

let pattern_start;

let mut match_type;

match query.as_bytes()[0] {
b'\'' => {
pattern_start = 1;
match_type = MatchType::Exact;
},

b'^' => {
pattern_start = 1;
match_type = MatchType::PrefixExact;
},

b'!' => {
match query.as_bytes().get(1) {
Some(b'\'') => {
pattern_start = 2;
match_type = MatchType::InverseFuzzy;
},

Some(b'^') => {
pattern_start = 2;
match_type = MatchType::InversePrefixExact;
},

_ => {
pattern_start = 1;
match_type = MatchType::InverseExact;
},
};
},

_ => {
pattern_start = 0;
match_type = MatchType::Fuzzy;
},
};

word = &word[pattern_start..];

let pattern_end;

match memchr::memchr2(b' ', b'\\', word.as_bytes()) {
Some(idx) if query.as_bytes()[idx] == b' ' => {
todo!();
},

Some(idx) if query.as_bytes()[idx] == b'\\' => {
todo!();
},

Some(_) => {
unreachable!();
},

None => {
pattern_end = query.len();
},
};

let pattern_text = &query[..pattern_end];

let pattern = {
let pattern_text = pattern_text.chars().collect::<Vec<_>>().leak();
Pattern::new(pattern_text, match_type)
};

{
let or_patterns = vec![pattern].leak();
let condition = Condition::new(or_patterns);
conditions.push(condition);
}
}

conditions
OrBlocks::new(query)
.map(|or_block| {
or_block
.into_iter()
.map(|pattern| pattern.chars().collect::<Vec<_>>().leak() as _)
.map(Pattern::parse)
.collect::<Vec<_>>()
.leak() as _
})
.map(Condition::new)
.collect::<Vec<_>>()
}

const OR_BLOCK_SEPARATOR: &str = "|";
Expand Down Expand Up @@ -371,6 +290,7 @@ fn strip_spaces(s: &str) -> &str {

#[cfg(test)]
mod parse_tests {
use super::super::query::MatchType;
use super::*;

#[test]
Expand Down
53 changes: 51 additions & 2 deletions src/algos/fzf/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,60 @@ impl<'a> Pattern<'a> {

/// TODO: docs
#[inline]
pub(super) fn new(text: &'a [char], ty: MatchType) -> Self {
pub(super) fn parse(mut text: &'a [char]) -> Self {
debug_assert!(!text.is_empty());

let first_char = text[0];

let last_char = text[text.len() - 1];

let match_type;

match first_char {
'\'' => {
text = &text[1..];
match_type = MatchType::Exact;
},

'^' => {
text = &text[1..];
match_type = MatchType::PrefixExact;
},

'!' if text.get(1).copied() == Some('\'') => {
text = &text[2..];
match_type = MatchType::InverseFuzzy;
},

'!' if text.get(1).copied() == Some('^') => {
text = &text[2..];
match_type = MatchType::InversePrefixExact;
},

'!' if last_char == '$' => {
text = &text[1..text.len() - 1];
match_type = MatchType::InverseSuffixExact;
},

'!' => {
text = &text[1..];
match_type = MatchType::InverseExact;
},

_ if last_char == '$' => {
text = &text[..text.len() - 1];
match_type = MatchType::SuffixExact;
},

_ => {
match_type = MatchType::Fuzzy;
},
}

Self {
has_uppercase: text.iter().copied().any(char::is_uppercase),
text,
match_type: ty,
match_type,
}
}

Expand Down

0 comments on commit b6f63bc

Please sign in to comment.