[PATCH] ash,hush: allow builtins to be tab-completed, closes 7532

Ron Yorston rmy at pobox.com
Tue Jan 21 16:01:58 UTC 2020


function                                             old     new   delta
complete_cmd_dir_file                                768     861     +93
get_builtin_name                                       -      45     +45
new_line_input_t                                      31      42     +11
optschanged                                          112     117      +5
hush_main                                           1148    1153      +5
xc_vm_init                                           707     709      +2
read_line_input                                     2351    2353      +2
save_command_ps_at_cur_history                        87      86      -1
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 6/1 up/down: 163/-1)            Total: 162 bytes

Signed-off-by: Ron Yorston <rmy at pobox.com>
---
 include/libbb.h  | 10 ++++++++++
 libbb/lineedit.c | 47 +++++++++++++++++++++++++++++++++--------------
 miscutils/bc.c   |  2 +-
 shell/ash.c      | 16 +++++++++++++++-
 shell/hush.c     | 17 ++++++++++++++++-
 5 files changed, 75 insertions(+), 17 deletions(-)

diff --git a/include/libbb.h b/include/libbb.h
index 05a560977..68aff9f5c 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1818,10 +1818,15 @@ unsigned size_from_HISTFILESIZE(const char *hp) FAST_FUNC;
 # else
 #  define MAX_HISTORY 0
 # endif
+typedef const char *(*get_name_t)(int i);
 typedef struct line_input_t {
 	int flags;
 	int timeout;
 	const char *path_lookup;
+# if ENABLE_FEATURE_TAB_COMPLETION && (ENABLE_ASH || ENABLE_HUSH)
+	/* function to fetch additional application-specific names to match */
+	get_name_t get_name;
+#endif
 # if MAX_HISTORY
 	int cnt_history;
 	int cur_history;
@@ -1847,7 +1852,12 @@ enum {
 	WITH_PATH_LOOKUP = 0x10,
 	FOR_SHELL        = DO_HISTORY | TAB_COMPLETION | USERNAME_COMPLETION,
 };
+# if ENABLE_FEATURE_TAB_COMPLETION && (ENABLE_ASH || ENABLE_HUSH)
+line_input_t *new_line_input_t(int flags, get_name_t fn) FAST_FUNC;
+# else
 line_input_t *new_line_input_t(int flags) FAST_FUNC;
+#define new_line_input_t(fl, fn) new_line_input_t(fl)
+# endif
 void free_line_input_t(line_input_t *n) FAST_FUNC;
 /*
  * maxsize must be >= 2.
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index b1ec52b88..26d26b9da 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -826,6 +826,17 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
 	}
 # endif
 
+# if ENABLE_FEATURE_TAB_COMPLETION && (ENABLE_ASH || ENABLE_HUSH)
+	if (type == FIND_EXE_ONLY && !dirbuf) {
+		const char *p;
+
+		for (i = 0; state->get_name && (p=state->get_name(i)); i++) {
+			if (strncmp(pfind, p, pf_len) == 0)
+				add_match(xstrdup(p));
+		}
+	}
+# endif
+
 	for (i = 0; i < npaths; i++) {
 		DIR *dir;
 		struct dirent *next;
@@ -1300,18 +1311,6 @@ static NOINLINE void input_tab(smallint *lastWasTab)
 #endif  /* FEATURE_TAB_COMPLETION */
 
 
-line_input_t* FAST_FUNC new_line_input_t(int flags)
-{
-	line_input_t *n = xzalloc(sizeof(*n));
-	n->flags = flags;
-	n->timeout = -1;
-#if MAX_HISTORY > 0
-	n->max_history = MAX_HISTORY;
-#endif
-	return n;
-}
-
-
 #if MAX_HISTORY > 0
 
 unsigned FAST_FUNC size_from_HISTFILESIZE(const char *hp)
@@ -1486,7 +1485,7 @@ void save_history(line_input_t *st)
 
 		/* we may have concurrently written entries from others.
 		 * load them */
-		st_temp = new_line_input_t(st->flags);
+		st_temp = new_line_input_t(st->flags, NULL);
 		st_temp->hist_file = st->hist_file;
 		st_temp->max_history = st->max_history;
 		load_history(st_temp);
@@ -1535,7 +1534,7 @@ static void save_history(char *str)
 
 		/* we may have concurrently written entries from others.
 		 * load them */
-		st_temp = new_line_input_t(state->flags);
+		st_temp = new_line_input_t(state->flags, NULL);
 		st_temp->hist_file = state->hist_file;
 		st_temp->max_history = state->max_history;
 		load_history(st_temp);
@@ -1607,6 +1606,26 @@ static void remember_in_history(char *str)
 #endif /* MAX_HISTORY */
 
 
+#if ENABLE_FEATURE_TAB_COMPLETION && (ENABLE_ASH || ENABLE_HUSH)
+line_input_t* FAST_FUNC new_line_input_t(int flags, get_name_t fn)
+#else
+#undef new_line_input_t
+line_input_t* FAST_FUNC new_line_input_t(int flags)
+#endif
+{
+	line_input_t *n = xzalloc(sizeof(*n));
+	n->flags = flags;
+	n->timeout = -1;
+#if MAX_HISTORY > 0
+	n->max_history = MAX_HISTORY;
+#endif
+#if ENABLE_FEATURE_TAB_COMPLETION && (ENABLE_ASH || ENABLE_HUSH)
+	n->get_name = fn;
+#endif
+	return n;
+}
+
+
 #if ENABLE_FEATURE_EDITING_VI
 /*
  * vi mode implemented 2005 by Paul Fox <pgf at foxharp.boston.ma.us>
diff --git a/miscutils/bc.c b/miscutils/bc.c
index c7246ea1a..9c9d28eb5 100644
--- a/miscutils/bc.c
+++ b/miscutils/bc.c
@@ -7379,7 +7379,7 @@ static int xc_vm_init(const char *env_len)
 {
 	G.prog.len = xc_vm_envLen(env_len);
 #if ENABLE_FEATURE_EDITING
-	G.line_input_state = new_line_input_t(DO_HISTORY);
+	G.line_input_state = new_line_input_t(DO_HISTORY, NULL);
 #endif
 	bc_vec_init(&G.files, sizeof(char *), NULL);
 
diff --git a/shell/ash.c b/shell/ash.c
index 4b5eafa7c..a6b7a7b04 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -9523,6 +9523,11 @@ evalpipe(union node *n, int flags)
 	return status;
 }
 
+/* setinteractive needs this forward reference */
+#if ENABLE_FEATURE_TAB_COMPLETION
+static const char *get_builtin_name(int i);
+#endif
+
 /*
  * Controls whether the shell is interactive or not.
  */
@@ -9555,7 +9560,8 @@ setinteractive(int on)
 #endif
 #if ENABLE_FEATURE_EDITING
 		if (!line_input_state)
-			line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
+			line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP,
+								get_builtin_name);
 #endif
 	}
 }
@@ -10023,6 +10029,14 @@ find_builtin(const char *name)
 	return bp;
 }
 
+#if ENABLE_FEATURE_TAB_COMPLETION
+static const char *
+get_builtin_name(int i)
+{
+    return i >= 0 && i < ARRAY_SIZE(builtintab) ? builtintab[i].name+1 : NULL;
+}
+#endif
+
 /*
  * Execute a simple command.
  */
diff --git a/shell/hush.c b/shell/hush.c
index 97202b953..ea358cdb1 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -7889,6 +7889,21 @@ static const struct built_in_command *find_builtin(const char *name)
 	return find_builtin_helper(name, bltins2, &bltins2[ARRAY_SIZE(bltins2)]);
 }
 
+#if ENABLE_FEATURE_TAB_COMPLETION
+static const char *
+get_builtin_name(int i)
+{
+	if (i >= 0 && i < ARRAY_SIZE(bltins1)) {
+		return bltins1[i].b_cmd;
+	}
+	i -= ARRAY_SIZE(bltins1);
+	if (i >= 0 && i < ARRAY_SIZE(bltins2)) {
+		return bltins2[i].b_cmd;
+	}
+	return NULL;
+}
+#endif
+
 static void remove_nested_vars(void)
 {
 	struct variable *cur;
@@ -10267,7 +10282,7 @@ int hush_main(int argc, char **argv)
 		enable_restore_tty_pgrp_on_exit();
 
 # if ENABLE_FEATURE_EDITING
-		G.line_input_state = new_line_input_t(FOR_SHELL);
+		G.line_input_state = new_line_input_t(FOR_SHELL, get_builtin_name);
 # endif
 # if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0
 		{
-- 
2.24.1



More information about the busybox mailing list