bug fix:: Never reach readline_prompt() in nsh_initialize, moved it up to the top. Works now.

enhancement: TAB completion now works like Unix, it will autocomplete as much as possible for
multiple matches.
This commit is contained in:
Nghia Ho 2015-11-01 01:41:01 -07:00
parent 09add96e22
commit 211f8bf76d
2 changed files with 61 additions and 16 deletions

View File

@ -101,6 +101,18 @@ static const struct extmatch_vtable_s g_nsh_extmatch =
void nsh_initialize(void) void nsh_initialize(void)
{ {
#if defined(CONFIG_NSH_READLINE) && defined(CONFIG_READLINE_TABCOMPLETION)
/* Configure the NSH prompt */
(void)readline_prompt(g_nshprompt);
#ifdef CONFIG_READLINE_HAVE_EXTMATCH
/* Set up for tab completion on NSH commands */
(void)readline_extmatch(&g_nsh_extmatch);
#endif
#endif
/* Mount the /etc filesystem */ /* Mount the /etc filesystem */
(void)nsh_romfsetc(); (void)nsh_romfsetc();
@ -114,16 +126,4 @@ void nsh_initialize(void)
/* Bring up the network */ /* Bring up the network */
(void)nsh_netinit(); (void)nsh_netinit();
#if defined(CONFIG_NSH_READLINE) && defined(CONFIG_READLINE_TABCOMPLETION)
/* Configure the NSH prompt */
(void)readline_prompt(g_nshprompt);
#ifdef CONFIG_READLINE_HAVE_EXTMATCH
/* Set up for tab completion on NSH commands */
(void)readline_extmatch(&g_nsh_extmatch);
#endif
#endif
} }

View File

@ -147,6 +147,8 @@ static void tab_completion(FAR struct rl_common_s *vtbl, char *buf,
int len = *nch; int len = *nch;
int i; int i;
int j; int j;
int name_len;
char tmp_name[CONFIG_TASK_NAME_SIZE+1];
if (len >= 1) if (len >= 1)
{ {
@ -177,8 +179,6 @@ static void tab_completion(FAR struct rl_common_s *vtbl, char *buf,
if (nr_matches == 1) if (nr_matches == 1)
{ {
int name_len;
/* Yes... that that is the one we want. Was it a match with a /* Yes... that that is the one we want. Was it a match with a
* builtin command? Or with an external command. * builtin command? Or with an external command.
*/ */
@ -229,18 +229,40 @@ static void tab_completion(FAR struct rl_common_s *vtbl, char *buf,
{ {
RL_PUTC(vtbl, '\n'); RL_PUTC(vtbl, '\n');
/* See how many characters we can auto complete for the user
* For example, if we have the following commands:
* - prog1
* - prog2
* - prog3
* then it should automatically complete up to prog.
* We do this in one pass using a temp */
memset(tmp_name, 0, sizeof(tmp_name));
#ifdef CONFIG_READLINE_HAVE_EXTMATCH #ifdef CONFIG_READLINE_HAVE_EXTMATCH
/* Show the possible external completions */ /* Show the possible external completions */
for (i = 0; i < nr_ext_matches; i++) for (i = 0; i < nr_ext_matches; i++)
{ {
name = g_extmatch_vtbl->getname(ext_matches[i]); name = g_extmatch_vtbl->getname(ext_matches[i]);
/* initialize temp */
if (tmp_name[0] == '\0')
{
strcpy(tmp_name, name);
}
RL_PUTC(vtbl, ' '); RL_PUTC(vtbl, ' ');
RL_PUTC(vtbl, ' '); RL_PUTC(vtbl, ' ');
for (j = 0; j < strlen(name); j++) for (j = 0; j < strlen(name); j++)
{ {
/* removing characters that aren't common to all the
* matches */
if (name[j] != tmp_name[j])
{
tmp_name[j] = '\0';
}
RL_PUTC(vtbl, name[j]); RL_PUTC(vtbl, name[j]);
} }
@ -254,18 +276,34 @@ static void tab_completion(FAR struct rl_common_s *vtbl, char *buf,
for (i = 0; i < nr_builtin_matches; i++) for (i = 0; i < nr_builtin_matches; i++)
{ {
name = builtin_getname(builtin_matches[i]); name = builtin_getname(builtin_matches[i]);
/* initialize temp */
if (tmp_name[0] == '\0')
{
strcpy(tmp_name, name);
}
RL_PUTC(vtbl, ' '); RL_PUTC(vtbl, ' ');
RL_PUTC(vtbl, ' '); RL_PUTC(vtbl, ' ');
for (j = 0; j < strlen(name); j++) for (j = 0; j < strlen(name); j++)
{ {
/* removing characters that aren't common to all the
* matches */
if (name[j] != tmp_name[j])
{
tmp_name[j] = '\0';
}
RL_PUTC(vtbl, name[j]); RL_PUTC(vtbl, name[j]);
} }
RL_PUTC(vtbl, '\n'); RL_PUTC(vtbl, '\n');
} }
#endif #endif
strcpy(buf, tmp_name);
name_len = strlen(tmp_name);
/* Output the original prompt */ /* Output the original prompt */
@ -277,10 +315,17 @@ static void tab_completion(FAR struct rl_common_s *vtbl, char *buf,
} }
} }
for (i = 0; i < len; i++) for (i = 0; i < name_len; i++)
{ {
RL_PUTC(vtbl, buf[i]); RL_PUTC(vtbl, buf[i]);
} }
/* Don't remove extra characters after the completed word, if any. */
if (len < name_len)
{
*nch = name_len;
}
} }
} }
} }
@ -341,7 +386,7 @@ FAR const char *readline_prompt(FAR const char *prompt)
* Assumptions: * Assumptions:
* The vtbl string is statically allocated a global. readline() will * The vtbl string is statically allocated a global. readline() will
* simply remember the pointer to the structure. The structure must stay * simply remember the pointer to the structure. The structure must stay
* allocated and available. Only one instance of such a structure is * allocated and available. Only one instance of such a structure is
* supported. If there are multiple clients of readline(), they must all * supported. If there are multiple clients of readline(), they must all
* share the same tab-completion logic (with exceptions in the case of * share the same tab-completion logic (with exceptions in the case of
* the kernel build). * the kernel build).