git: b2b7eb9e23dc - stable/13 - sh: improve command completion
Piotr Pawel Stefaniak
pstef at FreeBSD.org
Sat Sep 25 08:41:26 UTC 2021
The branch stable/13 has been updated by pstef:
URL: https://cgit.FreeBSD.org/src/commit/?id=b2b7eb9e23dcb4381780590fb7393b17d19100f5
commit b2b7eb9e23dcb4381780590fb7393b17d19100f5
Author: Piotr Pawel Stefaniak <pstef at FreeBSD.org>
AuthorDate: 2021-09-18 11:26:51 +0000
Commit: Piotr Pawel Stefaniak <pstef at FreeBSD.org>
CommitDate: 2021-09-25 08:34:38 +0000
sh: improve command completion
When multiple matches are found, we keep the provided string on the
input line and print unique matches as suggestions.
But the multiple matches might be the same command found in different
directories, so we should deduplicate the matches first and then decide
whether to autocomplete the command or not, based on the number of
unique matches.
(cherry picked from commit b8ff849cbddfee3404d6550cf98f53d6bb617707)
---
bin/sh/histedit.c | 40 +++++++++++++++++++---------------------
1 file changed, 19 insertions(+), 21 deletions(-)
diff --git a/bin/sh/histedit.c b/bin/sh/histedit.c
index 8d9e9fc64db3..488a0b355f80 100644
--- a/bin/sh/histedit.c
+++ b/bin/sh/histedit.c
@@ -530,7 +530,7 @@ static char
char *free_path = NULL, *path;
const char *dirname;
char **matches = NULL;
- size_t i = 0, size = 16, j, k;
+ size_t i = 0, size = 16, uniq;
size_t curpos = end - start;
if (start > 0 || memchr("/.~", text[0], 3) != NULL)
@@ -579,6 +579,21 @@ static char
}
out:
free(free_path);
+ if (i == 0) {
+ free(matches);
+ return (NULL);
+ }
+ uniq = 1;
+ if (i > 1) {
+ qsort_s(matches + 1, i, sizeof(matches[0]), comparator,
+ (void *)(intptr_t)curpos);
+ for (size_t k = 2; k <= i; k++)
+ if (strcmp(matches[uniq] + curpos, matches[k] + curpos) == 0)
+ free(matches[k]);
+ else
+ matches[++uniq] = matches[k];
+ }
+ matches[uniq + 1] = NULL;
/*
* matches[0] is special: it's not a real matching file name but a common
* prefix for all matching names. It can't be null, unlike any other
@@ -588,30 +603,13 @@ out:
* string in matches[0] which is the reason to copy the full name of the
* only match.
*/
- if (i == 0) {
- free(matches);
- return (NULL);
- } else if (i == 1) {
- matches[0] = strdup(matches[1]);
- matches[2] = NULL;
- if (matches[0] != NULL)
- return (matches);
- } else
- matches[0] = strdup(text);
+ matches[0] = strdup(uniq == 1 ? matches[1] : text);
if (matches[0] == NULL) {
- for (j = 1; j <= i; j++)
- free(matches[j]);
+ for (size_t k = 1; k <= uniq; k++)
+ free(matches[k]);
free(matches);
return (NULL);
}
- qsort_s(matches + 1, i, sizeof(matches[0]), comparator,
- (void *)(intptr_t)curpos);
- for (j = 1, k = 2; k <= i; k++)
- if (strcmp(matches[j] + curpos, matches[k] + curpos) == 0)
- free(matches[k]);
- else
- matches[++j] = matches[k];
- matches[j + 1] = NULL;
return (matches);
}
More information about the dev-commits-src-all
mailing list