sh: also auto-complete built-ins

Reported in a comment in PR 261728.

Reported by:	Oleg
Reviewed by:	jilles (previous version), bapt
Differential Revision:	https://reviews.freebsd.org/D39839
This commit is contained in:
Piotr Pawel Stefaniak 2023-04-29 17:53:58 +02:00
parent 7a91ccd2fb
commit 14dd001235

View file

@ -594,6 +594,20 @@ comparator(const void *a, const void *b, void *thunk)
*(char *const *)b + curpos)); *(char *const *)b + curpos));
} }
static char
**add_match(char **matches, size_t i, size_t *size, char *match_copy)
{
if (match_copy == NULL)
return (NULL);
matches[i] = match_copy;
if (i >= *size - 1) {
*size *= 2;
matches = reallocarray(matches, *size, sizeof(matches[0]));
}
return (matches);
}
/* /*
* This function is passed to libedit's fn_complete2(). The library will use * This function is passed to libedit's fn_complete2(). The library will use
* it instead of its standard function that finds matching files in current * it instead of its standard function that finds matching files in current
@ -605,7 +619,7 @@ static char
{ {
char *free_path = NULL, *path; char *free_path = NULL, *path;
const char *dirname; const char *dirname;
char **matches = NULL; char **matches = NULL, **rmatches;
size_t i = 0, size = 16, uniq; size_t i = 0, size = 16, uniq;
size_t curpos = end - start, lcstring = -1; size_t curpos = end - start, lcstring = -1;
@ -631,7 +645,6 @@ static char
} }
while ((entry = readdir(dir)) != NULL) { while ((entry = readdir(dir)) != NULL) {
struct stat statb; struct stat statb;
char **rmatches;
if (strncmp(entry->d_name, text, curpos) != 0) if (strncmp(entry->d_name, text, curpos) != 0)
continue; continue;
@ -642,11 +655,8 @@ static char
continue; continue;
} else if (entry->d_type != DT_REG) } else if (entry->d_type != DT_REG)
continue; continue;
matches[++i] = strdup(entry->d_name); rmatches = add_match(matches, ++i, &size,
if (i < size - 1) strdup(entry->d_name));
continue;
size *= 2;
rmatches = reallocarray(matches, size, sizeof(matches[0]));
if (rmatches == NULL) { if (rmatches == NULL) {
closedir(dir); closedir(dir);
goto out; goto out;
@ -655,6 +665,14 @@ static char
} }
closedir(dir); closedir(dir);
} }
for (const unsigned char *bp = builtincmd; *bp != 0; bp += 2 + bp[0]) {
if (curpos > bp[0] || memcmp(bp + 2, text, curpos) != 0)
continue;
rmatches = add_match(matches, ++i, &size, strndup(bp + 2, bp[0]));
if (rmatches == NULL)
goto out;
matches = rmatches;
}
out: out:
free(free_path); free(free_path);
if (i == 0) { if (i == 0) {