Skip to content

Commit 245dfa1

Browse files
committed
[update] unknown_with_suggestions to prune candidates that are shorter in length than the argument being checked
1 parent d00056e commit 245dfa1

1 file changed

Lines changed: 31 additions & 0 deletions

File tree

  • crates/lambda-rs-args/src

crates/lambda-rs-args/src/lib.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,6 +1307,28 @@ mod tests {
13071307
}
13081308
}
13091309

1310+
#[test]
1311+
fn unknown_argument_suggests_with_many_unrelated_keys() {
1312+
let mut parser = ArgumentParser::new("app")
1313+
.with_argument(Argument::new("--port").with_type(ArgumentType::Integer));
1314+
for i in 0..500 {
1315+
let long_name = Box::leak(
1316+
format!("--very-long-unrelated-argument-name-{}", i).into_boxed_str(),
1317+
);
1318+
parser = parser.with_argument(
1319+
Argument::new(long_name).with_type(ArgumentType::String),
1320+
);
1321+
}
1322+
1323+
let err = parser.parse(&argv(&["--portt", "1"])).unwrap_err();
1324+
match err {
1325+
ArgsError::UnknownArgument(msg) => {
1326+
assert!(msg.contains("did you mean '--port'"))
1327+
}
1328+
_ => panic!(),
1329+
}
1330+
}
1331+
13101332
#[test]
13111333
fn missing_value_error() {
13121334
let parser = ArgumentParser::new("app")
@@ -1512,7 +1534,16 @@ fn read_config_file(
15121534

15131535
fn unknown_with_suggestion(arg: &str, parser: &ArgumentParser) -> String {
15141536
let mut best: Option<(usize, String)> = None;
1537+
let arg_len = arg.chars().count();
15151538
for key in parser.args.keys() {
1539+
// Levenshtein distance has a hard lower bound of the character-length gap.
1540+
// If that bound cannot beat the current best score, skip this candidate.
1541+
if let Some((best_distance, _)) = best.as_ref() {
1542+
let key_len = key.chars().count();
1543+
if key_len.abs_diff(arg_len) >= *best_distance {
1544+
continue;
1545+
}
1546+
}
15161547
let d = levenshtein(arg, key);
15171548
if best.as_ref().map(|(bd, _)| d < *bd).unwrap_or(true) {
15181549
best = Some((d, key.clone()));

0 commit comments

Comments
 (0)