diff --git a/include/readline.h b/include/readline.h index df0f38ed4..ed62bf67d 100644 --- a/include/readline.h +++ b/include/readline.h @@ -1,7 +1,7 @@ /**************************************************************************** * apps/include/readline.h * - * Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved. + * Copyright (C) 2011, 2013, 2015 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -63,6 +63,35 @@ extern "C" * Public Function Prototypes ****************************************************************************/ +/**************************************************************************** + * Name: readline_prompt + * + * If a prompt string is used by the application, then the application + * must provide the prompt string to readline by calling this function. + * This is needed only for tab completion in cases where is it necessary + * to reprint the prompt string. + * + * Input Parameters: + * prompt - The prompt string. + * + * Returned values: + * None + * + * Assumptions: + * The prompt string is statically allocated a global. readline will + * simply remember the pointer to the string. The string must stay + * allocated and available. Only one prompt string is supported. If + * there are multiple clients of readline, they must all share the same + * prompt string (with exceptions in the case of the kernel build). + * + **************************************************************************/ + +#ifdef CONFIG_READLINE_TABCOMPLETION +void readline_prompt(FAR const *prompt); +#else +# define readline_prompt(p) +#endif + /**************************************************************************** * Name: readline * diff --git a/nshlib/nsh_init.c b/nshlib/nsh_init.c index a59c5b323..a9a799926 100644 --- a/nshlib/nsh_init.c +++ b/nshlib/nsh_init.c @@ -1,7 +1,7 @@ /**************************************************************************** * apps/nshlib/nsh_init.c * - * Copyright (C) 2007-2012, 2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2012, 2014-2015 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -103,4 +103,10 @@ void nsh_initialize(void) /* Bring up the network */ (void)nsh_netinit(); + +#ifdef CONFIG_READLINE_TABCOMPLETION + /* Configure the NSH prompt */ + + readline_prompt(g_nshprompt); +#endif } diff --git a/system/readline/Kconfig b/system/readline/Kconfig index 021399262..be3777d8f 100644 --- a/system/readline/Kconfig +++ b/system/readline/Kconfig @@ -20,4 +20,12 @@ config READLINE_ECHO already has local echo support or you need to suppress the back-channel responses for any other reason. +config READLINE_TABCOMPLETION + bool "Tab completion" + default n + depends on BUILD_FLAT && BUILTIN + ---help--- + Build in support for Unix-style tab completion. This feature was + provided by Nghia. + endif diff --git a/system/readline/readline_common.c b/system/readline/readline_common.c index fc49f563b..a447745b5 100644 --- a/system/readline/readline_common.c +++ b/system/readline/readline_common.c @@ -48,27 +48,11 @@ #include #include +#include #include #include "readline.h" -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/**************************************************************************** - * Private Type Declarations - ****************************************************************************/ - -/**************************************************************************** - * Private Function Prototypes - ****************************************************************************/ - -/**************************************************************************** - * Public Data - ****************************************************************************/ -extern const char g_nshprompt[]; - /**************************************************************************** * Private Data ****************************************************************************/ @@ -76,18 +60,155 @@ extern const char g_nshprompt[]; static const char g_erasetoeol[] = VT100_CLEAREOL; +#ifdef CONFIG_READLINE_TABCOMPLETION +/* Prompt string to present at the beginning of the line */ + +static const *char g_readline_prompt = NULL; +#endif + /**************************************************************************** * Private Functions ****************************************************************************/ -static void tab_completion(FAR struct rl_common_s *vtbl, char *buf, int *len); + +/**************************************************************************** + * Name: tab_completion + * + * Description: + * Nghia - Unix like tab completion, only for builtin apps + * + * Input Parameters: + * vtbl - vtbl used to access implementation specific interface + * buf - The user allocated buffer to be filled. + * buflen - the size of the buffer. + * + * Returned Value: + * None. + * + **************************************************************************/ + +#ifdef CONFIG_READLINE_TABCOMPLETION +void tab_completion(FAR struct rl_common_s *vtbl, char *buf, int *nch) +{ + FAR const char *name = NULL; + int num_matches = 0; + int matches[128]; + int len = *nch; + int i; + int j; + + if (len >= 1) + { + for (i = 0; (name = builtin_getname(i)) != NULL; i++) + { + if (!strncmp(buf, name, len)) + { + matches[num_matches] = i; + num_matches++; + + if (num_matches >= sizeof(matches) / sizeof(int)) + { + break; + } + } + } + + if (num_matches == 1) + { + name = builtin_getname(matches[0]); + + int name_len = strlen(name); + + for (j = len; j < name_len; j++) + { + buf[j] = name[j]; + RL_PUTC(vtbl, name[j]); + } + + /* Don't remove extra characters after the completed word, if any */ + + if (len < name_len) + { + *nch = name_len; + } + } + else if (num_matches > 1) + { + RL_PUTC(vtbl, '\n'); + + /* possible completion */ + + for (i = 0; i < num_matches; i++) + { + name = builtin_getname(matches[i]); + + RL_PUTC(vtbl, ' '); + RL_PUTC(vtbl, ' '); + + for (j = 0; j < strlen(name); j++) + { + RL_PUTC(vtbl, name[j]); + } + + RL_PUTC(vtbl, '\n'); + } + + /* Output the original prompt */ + + if (g_readline_prompt != NULL) + { + for (i = 0; i < strlen(g_readline_prompt); i++) + { + RL_PUTC(vtbl, g_readline_prompt[i]); + } + } + + for (i = 0; i < len; i++) + { + RL_PUTC(vtbl, buf[i]); + } + } + } +} +#endif /**************************************************************************** * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: readline_prompt + * + * If a prompt string is used by the application, then the application + * must provide the prompt string to readline by calling this function. + * This is needed only for tab completion in cases where is it necessary + * to reprint the prompt string. + * + * Input Parameters: + * prompt - The prompt string. + * + * Returned values: + * None + * + * Assumptions: + * The prompt string is statically allocated a global. readline will + * simply remember the pointer to the string. The string must stay + * allocated and available. Only one prompt string is supported. If + * there are multiple clients of readline, they must all share the same + * prompt string (with exceptions in the case of the kernel build). + * + **************************************************************************/ + +#ifdef CONFIG_READLINE_TABCOMPLETION +void readline_prompt(FAR const *prompt) +{ + g_readline_prompt = prompt; +} +#endif + /**************************************************************************** * Name: readline_common * + * Description: * readline() reads in at most one less than 'buflen' characters from * 'instream' and stores them into the buffer pointed to by 'buf'. * Characters are echoed on 'outstream'. Reading stops after an EOF or a @@ -102,12 +223,11 @@ static void tab_completion(FAR struct rl_common_s *vtbl, char *buf, int *len); * different creature. * * Input Parameters: - * buf - The user allocated buffer to be filled. - * buflen - the size of the buffer. - * instream - The stream to read characters from - * outstream - The stream to each characters to. + * vtbl - vtbl used to access implementation specific interface + * buf - The user allocated buffer to be filled. + * buflen - the size of the buffer. * - * Returned values: + * Returned Value: * On success, the (positive) number of bytes transferred is returned. * EOF is returned to indicate either an end of file condition or a * failure. @@ -285,88 +405,11 @@ ssize_t readline_common(FAR struct rl_common_s *vtbl, FAR char *buf, int buflen) return nch; } } +#ifdef CONFIG_READLINE_TABCOMPLETION else if (ch == '\t') /* Nghia - TAB character */ { tab_completion(vtbl, buf, &nch); } - } -} - -/* - * Nghia - Unix like tab completion, only for builtin apps -*/ -void tab_completion(FAR struct rl_common_s *vtbl, char *buf, int *nch) -{ - int i, j; - int num_matches = 0; - int matches[128]; - FAR const char *name = NULL; - int len = *nch; - - if (len >= 1) - { - for (i = 0; (name = builtin_getname(i)) != NULL; i++) - { - if (!strncmp(buf, name, len)) - { - matches[num_matches] = i; - num_matches++; - - if (num_matches >= sizeof(matches) / sizeof(int)) - { - break; - } - } - } - - if (num_matches == 1) - { - name = builtin_getname(matches[0]); - - int name_len = strlen(name); - - for (j = len; j < name_len; j++) - { - buf[j] = name[j]; - RL_PUTC(vtbl, name[j]); - } - - // don't remove extra characters after the completed word, if any - if (len < name_len) - { - *nch = name_len; - } - } - else if (num_matches > 1) - { - RL_PUTC(vtbl, '\n'); - - // possible completion - for (i = 0; i < num_matches; i++) - { - name = builtin_getname(matches[i]); - - RL_PUTC(vtbl, ' '); - RL_PUTC(vtbl, ' '); - - for (j = 0; j < strlen(name); j++) - { - RL_PUTC(vtbl, name[j]); - } - - RL_PUTC(vtbl, '\n'); - } - - // output the original prompt - for (i = 0; i < strlen(g_nshprompt); i++) - { - RL_PUTC(vtbl, g_nshprompt[i]); - } - - for (i = 0; i < len; i++) - { - RL_PUTC(vtbl, buf[i]); - } - } +#endif } }