Skip to content

Commit

Permalink
fzf: refactors
Browse files Browse the repository at this point in the history
  • Loading branch information
noib3 committed Nov 3, 2023
1 parent bff2123 commit 4b92f90
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 167 deletions.
1 change: 0 additions & 1 deletion src/algos/fzf/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ mod v2;

pub use distance::FzfDistance;
pub use parser::FzfParser;
use parser::*;
pub use query::FzfQuery;
pub use scheme::FzfScheme;
#[doc(hidden)]
Expand Down
178 changes: 24 additions & 154 deletions src/algos/fzf/parser.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use core::fmt::Write;

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

/// TODO: docs
#[derive(Default, Clone)]
#[derive(Clone)]
pub struct FzfParser {
/// TODO: docs
chars: Vec<char>,
Expand All @@ -15,160 +13,41 @@ pub struct FzfParser {
conditions: Vec<Condition<'static>>,
}

/// TODO: docs
#[derive(Default, Clone, Copy)]
pub(super) struct Condition<'a> {
/// TODO: docs
pub(super) or_patterns: &'a [Pattern<'a>],
}

impl core::fmt::Debug for Condition<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match &self.or_patterns[..] {
[] => Ok(()),

[only] => only.to_string().fmt(f),

_ => {
f.write_char('(')?;

let len = self.or_patterns.len();

for (idx, pattern) in self.or_patterns().enumerate() {
let is_last = idx + 1 == len;

pattern.to_string().fmt(f)?;

if !is_last {
f.write_str(" || ")?;
}
}

f.write_char(')')
},
}
}
}

impl<'a> Condition<'a> {
#[inline]
fn new(or_patterns: &'a [Pattern<'a>]) -> Self {
Self { or_patterns }
}

#[inline]
pub(super) fn or_patterns(
&self,
) -> impl Iterator<Item = Pattern<'a>> + '_ {
self.or_patterns.iter().copied()
}
}

/// TODO: docs
#[derive(Default, Clone, Copy)]
pub(super) struct Pattern<'a> {
/// TODO: docs
text: &'a [char],

/// Whether any of the characters in [`Self::text`] are uppercase.
pub(super) has_uppercase: bool,

/// TODO: docs
pub(super) ty: PatternType,
}

impl core::fmt::Debug for Pattern<'_> {
#[inline]
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("Pattern").field(&self.to_string()).finish()
}
}

impl<'a> Pattern<'a> {
/// TODO: docs
#[inline(always)]
pub(super) fn char_len(&self) -> usize {
self.text.len()
}

/// TODO: docs
#[inline(always)]
pub(super) fn char(&self, idx: usize) -> char {
self.text[idx]
}

/// TODO: docs
#[inline]
pub(crate) fn chars(
&self,
) -> impl Iterator<Item = char> + DoubleEndedIterator + '_ {
self.text.iter().copied()
}

/// TODO: docs
impl Default for FzfParser {
#[inline]
pub(super) fn is_empty(&self) -> bool {
self.text.is_empty()
}

/// TODO: docs
#[inline]
pub(super) fn new(text: &'a [char], ty: PatternType) -> Self {
fn default() -> Self {
Self {
has_uppercase: text.iter().copied().any(char::is_uppercase),
text,
ty,
chars: vec![char::default(); 64],
patterns: vec![Pattern::default(); 64],
conditions: vec![Condition::default(); 64],
}
}

/// TODO: docs
#[inline]
fn to_string(&self) -> String {
self.text.iter().collect::<String>()
}
}

/// TODO: docs
#[derive(Default, Clone, Copy)]
pub(super) enum PatternType {
/// TODO: docs
#[default]
FuzzyMatch,

/// TODO: docs
ExactMatch,

/// TODO: docs
PrefixExactMatch,

/// TODO: docs
SuffixExactMatch,

/// TODO: docs
InverseExactMatch,

/// TODO: docs
InversePrefixExactMatch,

/// TODO: docs
InverseSuffixExactMatch,
}

impl FzfParser {
/// TODO: docs
#[inline]
pub fn parse<'a>(&'a mut self, query: &str) -> FzfQuery<'a> {
// When parsing, the `|` operator has precedence over the `space`
// operator.
let max_char_len = query.len();

if max_char_len > self.chars.len() {
self.chars.resize(max_char_len, char::default());
}

// The theoretical maximum number of conditions that could be included
// in the query.
//
// `|` acts like multiplication, and `space` acts like addition.
// The actual number of conditions (which we'll only know after
// parsing) matches this maximum on space-separated queries of
// multiple ascii characters, e.g. `a b c d`.
let max_conditions = query.len() / 2 + 1;

if query.len() > self.chars.len() {
self.chars.resize(query.len(), char::default());
if self.conditions.len() < max_conditions {
self.conditions.resize(max_conditions, Condition::default());
}

if query.is_empty() {
return FzfQuery::new(&[]);
if self.patterns.len() < max_conditions {
self.patterns.resize(max_conditions, Pattern::default());
}

let mut char_len = 0;
Expand All @@ -178,18 +57,13 @@ impl FzfParser {
char_len += 1;
}

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

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

if self.patterns.is_empty() {
self.patterns.resize(1, Pattern::default());
}

self.patterns[0] = pattern;

let patterns = &self.patterns[..1];
Expand All @@ -201,10 +75,6 @@ impl FzfParser {
core::mem::transmute::<Condition, Condition<'static>>(condition)
};

if self.conditions.is_empty() {
self.conditions.resize(1, Condition::default());
}

self.conditions[0] = condition;

let conditions = &self.conditions[..1];
Expand Down
135 changes: 134 additions & 1 deletion src/algos/fzf/query.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::Condition;
use core::fmt::Write;

/// TODO: docs.
#[derive(Clone, Copy)]
Expand Down Expand Up @@ -38,3 +38,136 @@ impl<'a> FzfQuery<'a> {
Self { conditions }
}
}

/// TODO: docs
#[derive(Default, Clone, Copy)]
pub(super) struct Condition<'a> {
/// TODO: docs
pub(super) or_patterns: &'a [Pattern<'a>],
}

impl core::fmt::Debug for Condition<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self.or_patterns {
[] => Ok(()),

[pattern] => pattern.into_string().fmt(f),

_ => {
f.write_char('(')?;

let len = self.or_patterns.len();

for (idx, pattern) in self.or_patterns().enumerate() {
let is_last = idx + 1 == len;

pattern.into_string().fmt(f)?;

if !is_last {
f.write_str(" || ")?;
}
}

f.write_char(')')
},
}
}
}

impl<'a> Condition<'a> {
#[inline]
pub(super) fn new(or_patterns: &'a [Pattern<'a>]) -> Self {
Self { or_patterns }
}

#[inline]
pub(super) fn or_patterns(
&self,
) -> impl Iterator<Item = Pattern<'a>> + '_ {
self.or_patterns.iter().copied()
}
}

/// TODO: docs
#[derive(Default, Clone, Copy)]
pub(super) struct Pattern<'a> {
/// TODO: docs
text: &'a [char],

/// Whether any of the characters in [`Self::text`] are uppercase.
pub(super) has_uppercase: bool,

/// TODO: docs
pub(super) match_type: MatchType,
}

impl core::fmt::Debug for Pattern<'_> {
#[inline]
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("Pattern").field(&self.into_string()).finish()
}
}

impl<'a> Pattern<'a> {
/// TODO: docs
#[inline(always)]
pub(super) fn char_len(&self) -> usize {
self.text.len()
}

/// TODO: docs
#[inline(always)]
pub(super) fn char(&self, idx: usize) -> char {
self.text[idx]
}

/// TODO: docs
#[inline]
pub(crate) fn chars(
&self,
) -> impl Iterator<Item = char> + DoubleEndedIterator + '_ {
self.text.iter().copied()
}

/// TODO: docs
#[inline]
pub(super) fn new(text: &'a [char], ty: MatchType) -> Self {
Self {
has_uppercase: text.iter().copied().any(char::is_uppercase),
text,
match_type: ty,
}
}

/// TODO: docs
#[inline]
fn into_string(self) -> String {
self.text.iter().collect::<String>()
}
}

/// TODO: docs
#[derive(Default, Clone, Copy)]
pub(super) enum MatchType {
/// TODO: docs
#[default]
Fuzzy,

/// TODO: docs
Exact,

/// TODO: docs
PrefixExact,

/// TODO: docs
SuffixExact,

/// TODO: docs
InverseExact,

/// TODO: docs
InversePrefixExact,

/// TODO: docs
InverseSuffixExact,
}
2 changes: 1 addition & 1 deletion src/algos/fzf/v1.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use core::ops::Range;

use super::*;
use super::{query::*, *};
use crate::*;

/// TODO: docs
Expand Down
Loading

0 comments on commit 4b92f90

Please sign in to comment.