Refactor read_line_input to accept a list of strings which are
added by 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

_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to