summaryrefslogtreecommitdiffstats
path: root/atuin-client/src/ordering.rs
blob: 4e5ec84c91c6df3e2c8754582d9e117d3585bbc8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
use minspan::minspan;

use super::{history::History, settings::SearchMode};

pub fn reorder_fuzzy(mode: SearchMode, query: &str, res: Vec<History>) -> Vec<History> {
    match mode {
        SearchMode::Fuzzy => reorder(query, |x| &x.command, res),
        _ => res,
    }
}

fn reorder<F, A>(query: &str, f: F, res: Vec<A>) -> Vec<A>
where
    F: Fn(&A) -> &String,
    A: Clone,
{
    let mut r = res.clone();
    let qvec = &query.chars().collect();
    r.sort_by_cached_key(|h| {
        // TODO for fzf search we should sum up scores for each matched term
        let (from, to) = match minspan::span(qvec, &(f(h).chars().collect())) {
            Some(x) => x,
            // this is a little unfortunate: when we are asked to match a query that is found nowhere,
            // we don't want to return a None, as the comparison behaviour would put the worst matches
            // at the front. therefore, we'll return a set of indices that are one larger than the longest
            // possible legitimate match. This is meaningless except as a comparison.
            None => (0, res.len()),
        };
        1 + to - from
    });
    r
}