extern crate levtree; use levtree::{CaseInsensitiveKeyChecker, CaseSensitiveKeyChecker}; use levtree::{ DamerauLevenshteinDistanceCalculator, DistanceCalculator, KeyChecker, LcsDistanceCalculator, LevTrie, LevenshteinDistanceCalculator, LevenshteinNoSubDistanceCalculator, }; use std::io::BufRead; use std::io::BufReader; use clap::{Parser, ValueEnum}; #[derive(Debug, Clone, ValueEnum)] enum Algorithm { Lcs, Levenshtein, LevenshteinNoSub, DamerauLevenshtein, } /// Encrypt/decrypt files using catenaccio cipher #[derive(Parser, Debug)] #[command(version, about, long_about = None)] struct CliArgs { /// Word to look up #[arg(short, long)] wordkey: String, /// Number of results returned #[arg(short, long, default_value_t = 10)] result_size: usize, //Specify distance algorithm #[arg(short, long, required = false, default_value = "damerau-levenshtein")] distance: Algorithm, //Toggle case sensitivity #[arg(short, long, required = false, default_value_t = false)] case_sensitive: bool, } impl CliArgs {} fn run, DC: DistanceCalculator>(args: &CliArgs) { let mut trie = LevTrie::::new(); let bytes = include_bytes!("words.txt"); let reader = BufReader::new(&bytes[..]); reader .lines() .map(|line| line.unwrap()) .for_each(|word: String| { trie.add(word.chars()); }); let word = args.wordkey.chars().collect::>(); let results = trie.fuzzy_search::(&word, args.result_size); for result in results { let word: String = trie.lineal_descendant(result.word).into_iter().collect(); println!("distance: {}, wordkey: {}", result.distance, word); } } fn main() { let args = CliArgs::parse(); if args.case_sensitive { match args.distance { Algorithm::Lcs => { run::(&args); } Algorithm::Levenshtein => { run::(&args); } Algorithm::LevenshteinNoSub => { run::(&args); } Algorithm::DamerauLevenshtein => { run::(&args); } } } else { match args.distance { Algorithm::Lcs => { run::(&args); } Algorithm::Levenshtein => { run::(&args); } Algorithm::LevenshteinNoSub => { run::(&args); } Algorithm::DamerauLevenshtein => { run::(&args); } } } }