diff options
| author | David Lamparter <equinox@opensourcerouting.org> | 2016-11-19 11:57:08 +0100 |
|---|---|---|
| committer | Quentin Young <qlyoung@users.noreply.github.com> | 2017-05-15 10:27:43 -0400 |
| commit | 70d44c5cd4f28f9d08a24f519d859885d92e2a13 (patch) | |
| tree | c67e6c907a31487ca96b27e53a1f571c26f31bf9 /lib/command.c | |
| parent | c09c46ae3c2702b3553e558f723e6de4fea3e05d (diff) | |
lib: cli: autocomplete variables
Shows known values in the appropriate naming domain when the user hits
<?> or <Tab>. This patch only works in the telnet CLI, the next patch
adds vtysh support.
Included completions:
- interface names
- route-map names
- prefix-list names
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'lib/command.c')
| -rw-r--r-- | lib/command.c | 62 |
1 files changed, 58 insertions, 4 deletions
diff --git a/lib/command.c b/lib/command.c index 0e19a3dfee..5b4c63fa95 100644 --- a/lib/command.c +++ b/lib/command.c @@ -46,6 +46,7 @@ DEFINE_MTYPE( LIB, HOST, "Host config") DEFINE_MTYPE( LIB, STRVEC, "String vector") +DEFINE_MTYPE( LIB, COMPLETION, "Completion item") /* Command vector which includes some level of command lists. Normally each daemon maintains each own cmdvec. */ @@ -678,6 +679,54 @@ cmd_describe_command (vector vline, struct vty *vty, int *status) return cmd_complete_command_real (vline, vty, status); } +static struct list *varhandlers = NULL; + +void +cmd_variable_complete (struct cmd_token *token, const char *arg, vector comps) +{ + struct listnode *ln; + const struct cmd_variable_handler *cvh; + size_t i, argsz; + vector tmpcomps; + + tmpcomps = arg ? vector_init (VECTOR_MIN_SIZE) : comps; + + for (ALL_LIST_ELEMENTS_RO(varhandlers, ln, cvh)) + { + if (cvh->tokenname && strcmp(cvh->tokenname, token->text)) + continue; + if (cvh->varname && (!token->varname || strcmp(cvh->varname, token->varname))) + continue; + cvh->completions(tmpcomps, token); + break; + } + + if (!arg) + return; + + argsz = strlen(arg); + for (i = vector_active(tmpcomps); i; i--) + { + char *item = vector_slot(tmpcomps, i - 1); + if (strlen(item) >= argsz + && !strncmp(item, arg, argsz)) + vector_set(comps, item); + else + XFREE(MTYPE_COMPLETION, item); + } + vector_free(tmpcomps); +} + +void +cmd_variable_handler_register (const struct cmd_variable_handler *cvh) +{ + if (!varhandlers) + return; + + for (; cvh->completions; cvh++) + listnode_add(varhandlers, (void *)cvh); +} + /** * Generate possible tab-completions for the given input. This function only * returns results that would result in a valid command if used as Readline @@ -719,7 +768,12 @@ cmd_complete_command (vector vline, struct vty *vty, int *status) { struct cmd_token *token = vector_slot (initial_comps, i); if (token->type == WORD_TKN) - vector_set (comps, token); + vector_set (comps, XSTRDUP (MTYPE_COMPLETION, token->text)); + else if (IS_VARYING_TOKEN(token->type)) + { + const char *ref = vector_lookup(vline, vector_active (vline) - 1); + cmd_variable_complete (token, ref, comps); + } } vector_free (initial_comps); @@ -741,9 +795,7 @@ cmd_complete_command (vector vline, struct vty *vty, int *status) unsigned int i; for (i = 0; i < vector_active (comps); i++) { - struct cmd_token *token = vector_slot (comps, i); - ret[i] = XSTRDUP (MTYPE_TMP, token->text); - vector_unset (comps, i); + ret[i] = vector_slot (comps, i); } // set the last element to NULL, because this array is used in // a Readline completion_generator function which expects NULL @@ -2394,6 +2446,8 @@ cmd_init (int terminal) { qobj_init (); + varhandlers = list_new (); + /* Allocate initial top vector of commands. */ cmdvec = vector_init (VECTOR_MIN_SIZE); |
