File: fz.rs

package info (click to toggle)
rust-fuzzy-matcher 0.3.7-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 172 kB
  • sloc: makefile: 2
file content (65 lines) | stat: -rw-r--r-- 1,943 bytes parent folder | download
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use fuzzy_matcher::clangd::ClangdMatcher;
use fuzzy_matcher::skim::SkimMatcherV2;
use fuzzy_matcher::FuzzyMatcher;
use std::env;
use std::io::{self, BufRead};
use std::process::exit;
use termion::style::{Invert, Reset};

#[cfg(not(feature = "compact"))]
type IndexType = usize;
#[cfg(feature = "compact")]
type IndexType = u32;

pub fn main() {
    let args: Vec<String> = env::args().collect();

    // arg parsing (manually)
    let mut arg_iter = args.iter().skip(1);
    let mut pattern = "".to_string();
    let mut algorithm = Some("skim");

    while let Some(arg) = arg_iter.next() {
        if arg == "--algo" {
            algorithm = arg_iter.next().map(String::as_ref);
        } else {
            pattern = arg.to_string();
        }
    }

    if &pattern == "" {
        eprintln!("Usage: echo <piped_input> | fz --algo [skim|clangd] <pattern>");
        exit(1);
    }

    let matcher: Box<dyn FuzzyMatcher> = match algorithm {
        Some("skim") | Some("skim_v2") => Box::new(SkimMatcherV2::default()),
        Some("clangd") => Box::new(ClangdMatcher::default()),
        _ => panic!("Algorithm not supported: {:?}", algorithm),
    };

    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        if let Ok(line) = line {
            if let Some((score, indices)) = matcher.fuzzy_indices(&line, &pattern) {
                println!("{:8}: {}", score, wrap_matches(&line, &indices));
            }
        }
    }
}

fn wrap_matches(line: &str, indices: &[IndexType]) -> String {
    let mut ret = String::new();
    let mut peekable = indices.iter().peekable();
    for (idx, ch) in line.chars().enumerate() {
        let next_id = **peekable.peek().unwrap_or(&&(line.len() as IndexType));
        if next_id == (idx as IndexType) {
            ret.push_str(format!("{}{}{}", Invert, ch, Reset).as_str());
            peekable.next();
        } else {
            ret.push(ch);
        }
    }

    ret
}