Skip to content

Commit

Permalink
fzf-v2: move code around
Browse files Browse the repository at this point in the history
  • Loading branch information
noib3 committed Oct 27, 2023
1 parent f5f52d5 commit dc51250
Show file tree
Hide file tree
Showing 9 changed files with 737 additions and 732 deletions.
21 changes: 21 additions & 0 deletions src/algos/fzf/distance.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use super::{Distance, Score};

/// TODO: docs
#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq)]
pub struct FzfDistance(Distance);

impl FzfDistance {
/// TODO: docs
#[inline]
pub(super) fn from_score(score: Score) -> Self {
// The higher the score the lower the distance.
Self(Distance::MAX - score)
}

/// TODO: docs
#[cfg(feature = "tests")]
pub fn into_score(self) -> Score {
// The higher the score the lower the distance.
Distance::MAX - self.0
}
}
60 changes: 60 additions & 0 deletions src/algos/fzf/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//! TODO: docs
mod distance;
mod query;
mod scheme;
mod scoring;
mod slab;
#[cfg(feature = "fzf-v1")]
mod v1;
#[cfg(feature = "fzf-v1")]
mod v2;

pub use distance::FzfDistance;
pub use query::FzfQuery;
pub use scheme::FzfScheme;
use scheme::Scheme;
use scoring::*;
pub use slab::FzfSlab;
#[cfg(feature = "fzf-v1")]
pub use v1::FzfV1;
#[cfg(feature = "fzf-v1")]
pub use v2::FzfV2;

#[doc(hidden)]
pub mod bonus {
//! TODO: docs
use super::*;

/// TODO: docs
pub const MATCH: Score = 16;

/// TODO: docs
pub const BOUNDARY: Score = MATCH / 2;

/// TODO: docs
pub const NON_WORD: Score = MATCH / 2;

/// TODO: docs
pub const CAMEL_123: Score = BOUNDARY - penalty::GAP_EXTENSION;

/// TODO: docs
pub const CONSECUTIVE: Score = penalty::GAP_START + penalty::GAP_EXTENSION;

/// TODO: docs
pub const FIRST_QUERY_CHAR_MULTIPLIER: Score = 2;
}

#[doc(hidden)]
pub mod penalty {
//! TODO: docs
use super::*;

/// TODO: docs
pub const GAP_START: Score = 3;

/// TODO: docs
pub const GAP_EXTENSION: Score = 1;
}
20 changes: 20 additions & 0 deletions src/algos/fzf/query.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/// TODO: docs.
#[derive(Clone, Copy, Debug)]
pub struct FzfQuery<'a> {
/// TODO: docs.
raw: &'a str,
}

impl<'a> FzfQuery<'a> {
/// TODO: docs
#[inline]
pub fn new(s: &'a str) -> Self {
Self { raw: s }
}

/// TODO: docs
#[inline]
pub(super) fn raw(&self) -> &'a str {
self.raw
}
}
84 changes: 84 additions & 0 deletions src/algos/fzf/scheme.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
use super::{bonus, CharClass, Score};

/// TODO: docs
#[derive(Debug, Default, Clone, Copy, Ord, PartialOrd, Eq, PartialEq)]
pub enum FzfScheme {
/// TODO: docs
#[default]
Default,

/// TODO: docs
Path,

/// TODO: docs
History,
}

impl FzfScheme {
/// TODO: docs
#[inline]
pub(super) fn into_inner(self) -> Scheme {
match self {
Self::Default => DEFAULT,
Self::Path => PATH,
Self::History => HISTORY,
}
}
}

/// TODO: docs
#[derive(Clone)]
pub(super) struct Scheme {
pub bonus_boundary_white: Score,
pub bonus_boundary_delimiter: Score,
pub initial_char_class: CharClass,
pub is_delimiter: fn(char) -> bool,
}

impl Default for Scheme {
#[inline]
fn default() -> Self {
DEFAULT
}
}

/// TODO: docs
pub const DEFAULT: Scheme = Scheme {
bonus_boundary_white: bonus::BOUNDARY + 2,
bonus_boundary_delimiter: bonus::BOUNDARY + 1,
initial_char_class: CharClass::WhiteSpace,
is_delimiter: is_delimiter_default,
};

#[inline]
fn is_delimiter_default(ch: char) -> bool {
matches!(ch, '/' | ',' | ':' | ';' | '|')
}

/// TODO: docs
pub const PATH: Scheme = Scheme {
bonus_boundary_white: bonus::BOUNDARY,
bonus_boundary_delimiter: bonus::BOUNDARY + 1,
initial_char_class: CharClass::Delimiter,
is_delimiter: is_delimiter_path,
};

#[inline]
fn is_delimiter_path(ch: char) -> bool {
// Using `std::path::MAIN_SEPARATOR` would force us to depend on `std`
// instead of `core + alloc`, so we use a custom implementation.
#[cfg(windows)]
let os_path_separator = '\\';
#[cfg(not(windows))]
let os_path_separator = '/';

ch == '/' || ch == os_path_separator
}

/// TODO: docs
pub const HISTORY: Scheme = Scheme {
bonus_boundary_white: bonus::BOUNDARY,
bonus_boundary_delimiter: bonus::BOUNDARY,
initial_char_class: DEFAULT.initial_char_class,
is_delimiter: DEFAULT.is_delimiter,
};
110 changes: 110 additions & 0 deletions src/algos/fzf/scoring.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
use super::*;

pub(super) type Distance = u32;

pub(super) type Score = Distance;

/// TODO: docs
#[derive(Clone, Copy, PartialEq, Eq)]
pub(super) enum CharClass {
/// TODO: docs
WhiteSpace,

/// TODO: docs
NonWord,

/// TODO: docs
Delimiter,

/// TODO: docs
Lower,

/// TODO: docs
Upper,

/// TODO: docs
Letter,

/// TODO: docs
Number,
}

/// TODO: docs
#[inline]
pub(super) fn char_class(ch: char, scheme: &Scheme) -> CharClass {
if ch.is_ascii() {
ascii_char_class(ch, scheme)
} else {
non_ascii_char_class(ch, scheme)
}
}

/// TODO: docs
#[inline]
fn ascii_char_class(ch: char, scheme: &Scheme) -> CharClass {
if ch.is_ascii_lowercase() {
CharClass::Lower
} else if ch.is_ascii_uppercase() {
CharClass::Upper
} else if ch.is_ascii_digit() {
CharClass::Number
} else if ch.is_ascii_whitespace() {
CharClass::WhiteSpace
} else if (scheme.is_delimiter)(ch) {
CharClass::Delimiter
} else {
CharClass::NonWord
}
}

/// TODO: docs
#[inline]
fn non_ascii_char_class(ch: char, scheme: &Scheme) -> CharClass {
if ch.is_lowercase() {
CharClass::Lower
} else if ch.is_uppercase() {
CharClass::Upper
} else if ch.is_numeric() {
CharClass::Number
} else if ch.is_alphabetic() {
CharClass::Letter
} else if ch.is_whitespace() {
CharClass::WhiteSpace
} else if (scheme.is_delimiter)(ch) {
CharClass::Delimiter
} else {
CharClass::NonWord
}
}

/// TODO: docs
#[inline]
pub(super) fn bonus(
prev_class: CharClass,
next_class: CharClass,
scheme: &Scheme,
) -> Score {
use CharClass::*;

match next_class {
NonWord => bonus::NON_WORD,

WhiteSpace => scheme.bonus_boundary_white,

Upper if prev_class == Lower => bonus::CAMEL_123,

Number if prev_class != Number => bonus::CAMEL_123,

_ => {
if prev_class == WhiteSpace {
scheme.bonus_boundary_white
} else if prev_class == Delimiter {
scheme.bonus_boundary_delimiter
} else if prev_class == NonWord {
bonus::BOUNDARY
} else {
0
}
},
}
}
Loading

0 comments on commit dc51250

Please sign in to comment.