git: 14dd001235f9 - main - sh: also auto-complete built-ins

From: Piotr Pawel Stefaniak <pstef_at_FreeBSD.org>
Date: Mon, 19 Jun 2023 17:28:21 UTC
The branch main has been updated by pstef:

URL: https://cgit.FreeBSD.org/src/commit/?id=14dd001235f993f2c58d8ceddb5b0ac23db02367

commit 14dd001235f993f2c58d8ceddb5b0ac23db02367
Author:     Piotr Pawel Stefaniak <pstef@FreeBSD.org>
AuthorDate: 2023-04-29 15:53:58 +0000
Commit:     Piotr Pawel Stefaniak <pstef@FreeBSD.org>
CommitDate: 2023-06-19 17:27:20 +0000

    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
---
 bin/sh/histedit.c | 32 +++++++++++++++++++++++++-------
 1 file changed, 25 insertions(+), 7 deletions(-)

diff --git a/bin/sh/histedit.c b/bin/sh/histedit.c
index 07a344ebd17b..e13f38548a40 100644
--- a/bin/sh/histedit.c
+++ b/bin/sh/histedit.c
@@ -594,6 +594,20 @@ comparator(const void *a, const void *b, void *thunk)
 		*(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
  * it instead of its standard function that finds matching files in current
@@ -605,7 +619,7 @@ static char
 {
 	char *free_path = NULL, *path;
 	const char *dirname;
-	char **matches = NULL;
+	char **matches = NULL, **rmatches;
 	size_t i = 0, size = 16, uniq;
 	size_t curpos = end - start, lcstring = -1;
 
@@ -631,7 +645,6 @@ static char
 		}
 		while ((entry = readdir(dir)) != NULL) {
 			struct stat statb;
-			char **rmatches;
 
 			if (strncmp(entry->d_name, text, curpos) != 0)
 				continue;
@@ -642,11 +655,8 @@ static char
 					continue;
 			} else if (entry->d_type != DT_REG)
 				continue;
-			matches[++i] = strdup(entry->d_name);
-			if (i < size - 1)
-				continue;
-			size *= 2;
-			rmatches = reallocarray(matches, size, sizeof(matches[0]));
+			rmatches = add_match(matches, ++i, &size,
+				strdup(entry->d_name));
 			if (rmatches == NULL) {
 				closedir(dir);
 				goto out;
@@ -655,6 +665,14 @@ static char
 		}
 		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:
 	free(free_path);
 	if (i == 0) {