[PATCH] ash: perform autocompletion on builtin commands
Matteo Croce
matteo at openwrt.org
Fri Oct 24 14:54:21 UTC 2014
Refactor read_line_input to accept a list of strings which are
added byt the autocompletion suggestions.
Let ash pass the builtin command list to read_line_input to enable
completion of builtin commands as echo, printf, history, exec, etc.
---
editors/ed.c | 6 +++---
include/libbb.h | 2 +-
libbb/lineedit.c | 17 ++++++++++++-----
shell/ash.c | 8 +++++++-
shell/hush.c | 2 +-
util-linux/fdisk.c | 2 +-
6 files changed, 25 insertions(+), 12 deletions(-)
diff --git a/editors/ed.c b/editors/ed.c
index 3087fb0..812580f 100644
--- a/editors/ed.c
+++ b/editors/ed.c
@@ -144,7 +144,7 @@ static void doCommands(void)
* 0 on ctrl-C,
* >0 length of input string, including terminating '\n'
*/
- len = read_line_input(NULL, ": ", buf, sizeof(buf), /*timeout*/ -1);
+ len = read_line_input(NULL, ": ", buf, sizeof(buf), /*timeout*/ -1, NULL);
if (len <= 0)
return;
endbuf = &buf[len - 1];
@@ -242,7 +242,7 @@ static void doCommands(void)
}
if (!dirty)
return;
- len = read_line_input(NULL, "Really quit? ", buf, 16, /*timeout*/ -1);
+ len = read_line_input(NULL, "Really quit? ", buf, 16, /*timeout*/ -1, NULL);
/* read error/EOF - no way to continue */
if (len < 0)
return;
@@ -556,7 +556,7 @@ static void addLines(int num)
* 0 on ctrl-C,
* >0 length of input string, including terminating '\n'
*/
- len = read_line_input(NULL, "", buf, sizeof(buf), /*timeout*/ -1);
+ len = read_line_input(NULL, "", buf, sizeof(buf), /*timeout*/ -1, NULL);
if (len <= 0) {
/* Previously, ctrl-C was exiting to shell.
* Now we exit to ed prompt. Is in important? */
diff --git a/include/libbb.h b/include/libbb.h
index d57f00e..c384f11 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1505,7 +1505,7 @@ line_input_t *new_line_input_t(int flags) FAST_FUNC;
* 0 on ctrl-C (the line entered is still returned in 'command'),
* >0 length of input string, including terminating '\n'
*/
-int read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout) FAST_FUNC;
+int read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout, char *completions[]) FAST_FUNC;
void show_history(const line_input_t *st) FAST_FUNC;
# if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
void save_history(line_input_t *st);
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 8564307..270445a 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -746,7 +746,7 @@ static int path_parse(char ***p)
/* Complete command, directory or file name.
* Return the length of the prefix used for matching.
*/
-static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
+static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type, char **completions)
{
char *path1[1];
char **paths = path1;
@@ -828,6 +828,13 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
closedir(dir);
} /* for every path */
+ if (completions && type == FIND_EXE_ONLY) {
+ int len = strlen(command);
+ for(i = 0; completions[i]; i++)
+ if(!strncmp(command, completions[i], len))
+ add_match(xstrdup(completions[i]));
+ }
+
if (paths != path1) {
free(paths[0]); /* allocated memory is only in first member */
free(paths);
@@ -1070,7 +1077,7 @@ static char *quote_special_chars(char *found)
}
/* Do TAB completion */
-static NOINLINE void input_tab(smallint *lastWasTab)
+static NOINLINE void input_tab(smallint *lastWasTab, char **completions)
{
char *chosen_match;
char *match_buf;
@@ -1134,7 +1141,7 @@ static NOINLINE void input_tab(smallint *lastWasTab)
/* If complete_username() did not match,
* try to match a command in $PATH, or a directory, or a file */
if (!matches)
- match_pfx_len = complete_cmd_dir_file(match_buf, find_type);
+ match_pfx_len = complete_cmd_dir_file(match_buf, find_type, completions);
/* Account for backslashes which will be inserted
* by quote_special_chars() later */
@@ -2239,7 +2246,7 @@ static int32_t reverse_i_search(void)
* 0 on ctrl-C (the line entered is still returned in 'command'),
* >0 length of input string, including terminating '\n'
*/
-int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout)
+int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout, char **completions)
{
int len;
#if ENABLE_FEATURE_TAB_COMPLETION
@@ -2412,7 +2419,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
break;
#if ENABLE_FEATURE_TAB_COMPLETION
case '\t':
- input_tab(&lastWasTab);
+ input_tab(&lastWasTab, completions);
break;
#endif
case CTRL('K'):
diff --git a/shell/ash.c b/shell/ash.c
index 705fe9f..e3d2354 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -9674,7 +9674,9 @@ preadfd(void)
if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1, /*loop_on_EINTR:*/ 1);
else {
+ int i;
int timeout = -1;
+ char *builtins[(ARRAY_SIZE(builtintab) + 1) * sizeof(char *)];
# if ENABLE_ASH_IDLE_TIMEOUT
if (iflag) {
const char *tmout_var = lookupvar("TMOUT");
@@ -9687,9 +9689,13 @@ preadfd(void)
# endif
# if ENABLE_FEATURE_TAB_COMPLETION
line_input_state->path_lookup = pathval();
+ for (i = 0; i < ARRAY_SIZE(builtintab); i++)
+ builtins[i] = builtintab[i].name + 1;
+ builtins[i] = 0;
# endif
reinit_unicode_for_ash();
- nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
+ nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout, builtins);
+
if (nr == 0) {
/* Ctrl+C pressed */
if (trap[SIGINT]) {
diff --git a/shell/hush.c b/shell/hush.c
index 92d7901..603ae17 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -2066,7 +2066,7 @@ static void get_user_input(struct in_str *i)
G.flag_SIGINT = 0;
/* buglet: SIGINT will not make new prompt to appear _at once_,
* only after <Enter>. (^C will work) */
- r = read_line_input(G.line_input_state, prompt_str, G.user_input_buf, CONFIG_FEATURE_EDITING_MAX_LEN-1, /*timeout*/ -1);
+ r = read_line_input(G.line_input_state, prompt_str, G.user_input_buf, CONFIG_FEATURE_EDITING_MAX_LEN-1, /*timeout*/ -1, NULL);
/* catch *SIGINT* etc (^C is handled by read_line_input) */
check_and_run_traps();
} while (r == 0 || G.flag_SIGINT); /* repeat if ^C or SIGINT */
diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c
index 39eb27b..bdf98ea 100644
--- a/util-linux/fdisk.c
+++ b/util-linux/fdisk.c
@@ -569,7 +569,7 @@ read_line(const char *prompt)
{
int sz;
- sz = read_line_input(NULL, prompt, line_buffer, sizeof(line_buffer), /*timeout*/ -1);
+ sz = read_line_input(NULL, prompt, line_buffer, sizeof(line_buffer), /*timeout*/ -1, NULL);
if (sz <= 0)
exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */
--
1.9.1
More information about the busybox
mailing list