complete: reuse string fuzzy match when completing ~$USER

If we get to this code path, we'll only get completions for user
names, so technically the full StringFuzzyMatch with its ranking of
samecase/smartcase/icase (only showing the best) might be overkill,
but it seems like a good idea to treat this the same way as other
completions.

The occasion for this commit is to correct a wrong
StringFuzzyMatch::exact_match() in the icase branch; which will be
important for a following commit.  Add a test for that.
This commit is contained in:
Johannes Altmanninger
2026-04-16 23:13:09 +08:00
parent 413246a93d
commit fee4288122
2 changed files with 18 additions and 19 deletions

View File

@@ -1823,30 +1823,23 @@ fn getpwent_name() -> Option<WString> {
break;
}
if string_prefixes_string(user_name, &pw_name) {
if let Some(r#match) = StringFuzzyMatch::try_create(user_name, &pw_name, true) {
let desc = wgettext_fmt!(COMPLETE_USER_DESC, &pw_name);
// Append a user name.
// TODO: propagate overflow?
let mut flags = CompleteFlags::NO_SPACE;
if r#match.requires_full_replacement() {
flags |= CompleteFlags::REPLACES_TOKEN | CompleteFlags::DONT_ESCAPE;
}
let _ = self.completions.add(Completion::new(
pw_name.slice_from(name_len).to_owned(),
if r#match.requires_full_replacement() {
sprintf!("~%s", &pw_name)
} else {
pw_name.slice_from(name_len).to_owned()
},
desc,
StringFuzzyMatch::exact_match(),
CompleteFlags::NO_SPACE,
));
result = true;
} else if string_prefixes_string_case_insensitive(user_name, &pw_name) {
let name = sprintf!("~%s", &pw_name);
let desc = wgettext_fmt!(COMPLETE_USER_DESC, &pw_name);
// Append a user name
// TODO: propagate overflow?
let _ = self.completions.add(Completion::new(
name,
desc,
StringFuzzyMatch::exact_match(),
CompleteFlags::REPLACES_TOKEN
| CompleteFlags::DONT_ESCAPE
| CompleteFlags::NO_SPACE,
r#match,
flags,
));
result = true;
}

View File

@@ -727,3 +727,9 @@ complete -c foo -a "foo\\"
complete -C
# CHECKERR: complete: Can not get commandline in non-interactive mode
if string match -rq -- '^[a-z]+$' $USER
set -l first_letter_wrong_case (string sub -l 1 -- $USER | string upper)
string match -rq -- "$USER\t.*" (complete -C "echo ~$first_letter_wrong_case")
or echo "`complete -C'echo ~$first_letter_wrong_case'` did not yield $USER"
end