Skip to content

Commit e3f818e

Browse files
committed
refactor: finding similar strings
1 parent 2c7b61c commit e3f818e

File tree

2 files changed

+81
-12
lines changed

2 files changed

+81
-12
lines changed

Diff for: src/commands.rs

+1-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use rayon::prelude::*;
2-
use similar_string;
32
use std::{env, fs, process};
43

54
use crate::models::*;
@@ -58,17 +57,7 @@ pub fn get(args: &GetArgs) {
5857
// Check if we need to search for similar environment variables
5958
if !args.no_similar_names {
6059
// Check for similar variables, if user made a mistake
61-
let similar_names = env::vars()
62-
.collect::<Vec<_>>()
63-
.into_par_iter()
64-
.map(|(name, _)| name)
65-
.filter(|name| {
66-
similar_string::compare_similarity(
67-
args.key.to_lowercase(),
68-
name.to_lowercase(),
69-
) > 0.6
70-
})
71-
.collect::<Vec<_>>();
60+
let similar_names = find_similar_string(args.key.clone(), env::vars().map(|(key, _)| key).collect(), 0.6);
7261
if !similar_names.is_empty() {
7362
eprintln!("Did you mean:");
7463
for name in similar_names {

Diff for: src/utils.rs

+80
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use colored::Colorize;
2+
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
23
use std::process;
34
use subprocess::Exec;
45

@@ -36,3 +37,82 @@ pub fn warning(text: &str, exit_on_warning: bool) {
3637
process::exit(1);
3738
}
3839
}
40+
41+
/// Returns vector of string that are similar by threshold to given string in given vector
42+
pub fn find_similar_string(string: String, strings: Vec<String>, threshold:f64) -> Vec<String> {
43+
strings.par_iter()
44+
.filter(|name| {
45+
similar_string::compare_similarity(
46+
string.to_lowercase(),
47+
name.to_lowercase(),
48+
) > threshold
49+
})
50+
.map(|name| name.to_string())
51+
.collect::<Vec<_>>()
52+
}
53+
54+
#[cfg(test)]
55+
mod tests {
56+
use super::*;
57+
58+
#[test]
59+
fn test_validate_var_name_valid() {
60+
let result = validate_var_name("VALID_NAME");
61+
assert!(result.is_ok());
62+
}
63+
64+
#[test]
65+
fn test_validate_var_name_with_space() {
66+
let result = validate_var_name("INVALID NAME");
67+
assert!(result.is_err());
68+
assert_eq!(result.unwrap_err(), "Variable name cannot contain spaces");
69+
}
70+
71+
#[test]
72+
fn test_find_similar_string_exact_match() {
73+
let strings = vec![
74+
"PATH".to_string(),
75+
"HOME".to_string(),
76+
"USER".to_string()
77+
];
78+
let result = find_similar_string("PATH".to_string(), strings, 0.8);
79+
assert_eq!(result, vec!["PATH"]);
80+
}
81+
82+
#[test]
83+
fn test_find_similar_string_case_insensitive() {
84+
let strings = vec![
85+
"PATH".to_string(),
86+
"HOME".to_string(),
87+
"USER".to_string()
88+
];
89+
let result = find_similar_string("path".to_string(), strings, 0.8);
90+
assert_eq!(result, vec!["PATH"]);
91+
}
92+
93+
#[test]
94+
fn test_find_similar_string_no_match() {
95+
let strings = vec![
96+
"PATH".to_string(),
97+
"HOME".to_string(),
98+
"USER".to_string()
99+
];
100+
let result = find_similar_string("XXXXXX".to_string(), strings, 0.8);
101+
assert!(result.is_empty());
102+
}
103+
104+
#[test]
105+
fn test_find_similar_string_multiple_matches() {
106+
let strings = vec![
107+
"TEST".to_string(),
108+
"TSET".to_string(),
109+
"TEXT".to_string(),
110+
"NONE".to_string()
111+
];
112+
let result = find_similar_string("TEST".to_string(), strings, 0.5);
113+
assert!(result.contains(&"TEST".to_string()));
114+
assert!(result.contains(&"TEXT".to_string()));
115+
assert!(result.contains(&"TSET".to_string()));
116+
assert!(!result.contains(&"NONE".to_string()));
117+
}
118+
}

0 commit comments

Comments
 (0)