Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 13 Apr 2022 19:01:50 GMT
From:      Piotr Pawel Stefaniak <pstef@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: c8f0a1c6d756 - stable/13 - sh: fix autocompletion for commands that share name with a directory
Message-ID:  <202204131901.23DJ1oQi048306@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by pstef:

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

commit c8f0a1c6d756a0c5cf2fb4deb0234b7863b46fd6
Author:     Piotr Pawel Stefaniak <pstef@FreeBSD.org>
AuthorDate: 2022-03-12 11:08:05 +0000
Commit:     Piotr Pawel Stefaniak <pstef@FreeBSD.org>
CommitDate: 2022-04-13 19:01:04 +0000

    sh: fix autocompletion for commands that share name with a directory
    
    (cherry picked from commit 68700941c7ad58d6fa8eda82f3f370d87670fa6a)
---
 bin/sh/histedit.c | 35 +++++++++++++++++++++++++++++++++--
 1 file changed, 33 insertions(+), 2 deletions(-)

diff --git a/bin/sh/histedit.c b/bin/sh/histedit.c
index f3100221d6ad..cf6bebad4c1a 100644
--- a/bin/sh/histedit.c
+++ b/bin/sh/histedit.c
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
 #include <dirent.h>
 #include <limits.h>
 #include <paths.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -70,12 +71,14 @@ History *hist;	/* history cookie */
 EditLine *el;	/* editline cookie */
 int displayhist;
 static FILE *el_in, *el_out;
+static bool in_command_completion;
 
 static char *fc_replace(const char *, char *, char *);
 static int not_fcnumber(const char *);
 static int str_to_event(const char *, int);
 static int comparator(const void *, const void *, void *);
 static char **sh_matches(const char *, int, int);
+static const char *append_char_function(const char *);
 static unsigned char sh_complete(EditLine *, int);
 
 /*
@@ -540,8 +543,10 @@ static char
 	size_t i = 0, size = 16, uniq;
 	size_t curpos = end - start, lcstring = -1;
 
+	in_command_completion = false;
 	if (start > 0 || memchr("/.~", text[0], 3) != NULL)
 		return (NULL);
+	in_command_completion = true;
 	if ((free_path = path = strdup(pathval())) == NULL)
 		goto out;
 	if ((matches = malloc(size * sizeof(matches[0]))) == NULL)
@@ -634,6 +639,32 @@ out:
 	return (matches);
 }
 
+/*
+ * If we don't specify this function as app_func in the call to fn_complete2,
+ * libedit will use the default one, which adds a " " to plain files and
+ * a "/" to directories regardless of whether it's a command name or a plain
+ * path (relative or absolute). We never want to add "/" to commands.
+ *
+ * For example, after I did "mkdir rmdir", "rmdi" would be autocompleted to
+ * "rmdir/" instead of "rmdir ".
+ */
+static const char *
+append_char_function(const char *name)
+{
+	struct stat stbuf;
+	char *expname = name[0] == '~' ? fn_tilde_expand(name) : NULL;
+	const char *rs;
+
+	if (!in_command_completion &&
+	    stat(expname ? expname : name, &stbuf) == 0 &&
+	    S_ISDIR(stbuf.st_mode))
+		rs = "/";
+	else
+		rs = " ";
+	free(expname);
+	return (rs);
+}
+
 /*
  * This is passed to el_set(el, EL_ADDFN, ...) so that it's possible to
  * bind a key (tab by default) to execute the function.
@@ -642,8 +673,8 @@ unsigned char
 sh_complete(EditLine *sel, int ch __unused)
 {
 	return (unsigned char)fn_complete2(sel, NULL, sh_matches,
-		L" \t\n\"\\'`@$><=;|&{(", NULL, NULL, (size_t)100,
-		NULL, &((int) {0}), NULL, NULL, FN_QUOTE_MATCH);
+		L" \t\n\"\\'`@$><=;|&{(", NULL, append_char_function,
+		(size_t)100, NULL, &((int) {0}), NULL, NULL, FN_QUOTE_MATCH);
 }
 
 #else



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202204131901.23DJ1oQi048306>