mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 12:41:21 +00:00
lib: Move string completions out of command_match.c
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
This commit is contained in:
parent
ee551f4827
commit
ee761cc086
@ -335,55 +335,6 @@ command_complete (struct graph *graph,
|
|||||||
return matcher_rv;
|
return matcher_rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: move this logic to command.c
|
|
||||||
* Compare two completions. Tightly coupled to vector.
|
|
||||||
*
|
|
||||||
* @param[in] fst pointer to first item pointer in vector->index
|
|
||||||
* @param[in] snd pointer to second item poitner in vector->index
|
|
||||||
* @return integer compare code as determined by strcmp
|
|
||||||
int
|
|
||||||
compare_completions (const void *fst, const void *snd)
|
|
||||||
{
|
|
||||||
const char *first = *((char **) fst);
|
|
||||||
const char *secnd = *((char **) snd);
|
|
||||||
return strcmp (first, secnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum matcher_rv
|
|
||||||
command_complete_str (struct graph_node *start,
|
|
||||||
vector vline,
|
|
||||||
vector completions)
|
|
||||||
{
|
|
||||||
struct list *comps;
|
|
||||||
enum matcher_rv rv = command_complete (start, vline, &comps);
|
|
||||||
|
|
||||||
// quick n' dirty deduplication fn here, prolly like O(n^n)
|
|
||||||
struct listnode *ln;
|
|
||||||
struct graph_node *gn;
|
|
||||||
unsigned int i;
|
|
||||||
for (ALL_LIST_ELEMENTS_RO(comps,ln,gn))
|
|
||||||
{
|
|
||||||
// linear search for node text in completions vector
|
|
||||||
int exists = 0;
|
|
||||||
for (i = 0; i < vector_active (completions) && !exists; i++)
|
|
||||||
exists = !strcmp (gn->text, vector_slot (completions, i));
|
|
||||||
|
|
||||||
if (!exists)
|
|
||||||
vector_set (completions, XSTRDUP(MTYPE_TMP, gn->text));
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort completions
|
|
||||||
qsort (completions->index,
|
|
||||||
vector_active (completions),
|
|
||||||
sizeof (void *),
|
|
||||||
&compare_completions);
|
|
||||||
|
|
||||||
list_delete (comps);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds all children that are reachable by one parser hop to the given list.
|
* Adds all children that are reachable by one parser hop to the given list.
|
||||||
* NUL_TKN, SELECTOR_TKN, and OPTION_TKN nodes are treated as transparent.
|
* NUL_TKN, SELECTOR_TKN, and OPTION_TKN nodes are treated as transparent.
|
||||||
|
@ -92,18 +92,4 @@ command_complete (struct graph *cmdgraph,
|
|||||||
vector vline,
|
vector vline,
|
||||||
struct list **completions);
|
struct list **completions);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compiles possible completions for a given line of user input.
|
|
||||||
*
|
|
||||||
* @param[in] start the start node of the DFA to match against
|
|
||||||
* @param[in] vline vectorized input string
|
|
||||||
* @param[in] completions vector to fill with string completions
|
|
||||||
* @return matcher status
|
|
||||||
enum matcher_rv
|
|
||||||
command_complete_str (struct graph *cmdgraph,
|
|
||||||
vector vline,
|
|
||||||
vector completions);
|
|
||||||
|
|
||||||
*/
|
|
||||||
#endif /* _ZEBRA_COMMAND_MATCH_H */
|
#endif /* _ZEBRA_COMMAND_MATCH_H */
|
||||||
|
@ -43,6 +43,10 @@ void
|
|||||||
pretty_print_graph (struct graph_node *, int);
|
pretty_print_graph (struct graph_node *, int);
|
||||||
void
|
void
|
||||||
init_cmdgraph (struct graph **);
|
init_cmdgraph (struct graph **);
|
||||||
|
vector
|
||||||
|
completions_to_vec (struct list *);
|
||||||
|
int
|
||||||
|
compare_completions (const void *, const void *);
|
||||||
|
|
||||||
/** shim interface commands **/
|
/** shim interface commands **/
|
||||||
struct graph *nodegraph;
|
struct graph *nodegraph;
|
||||||
@ -86,25 +90,22 @@ DEFUN (grammar_test_complete,
|
|||||||
// print completions or relevant error message
|
// print completions or relevant error message
|
||||||
if (!MATCHER_ERROR(result))
|
if (!MATCHER_ERROR(result))
|
||||||
{
|
{
|
||||||
struct listnode *ln;
|
vector comps = completions_to_vec (completions);
|
||||||
struct cmd_token_t *tkn;
|
struct cmd_token_t *tkn;
|
||||||
|
|
||||||
// calculate length of longest tkn->text in completions
|
// calculate length of longest tkn->text in completions
|
||||||
int width = 0;
|
unsigned int width = 0, i = 0;
|
||||||
for (ALL_LIST_ELEMENTS_RO (completions,ln,tkn)) {
|
for (i = 0; i < vector_active (comps); i++) {
|
||||||
if (tkn && tkn->text) {
|
tkn = vector_slot (comps, i);
|
||||||
int len = strlen (tkn->text);
|
unsigned int len = strlen (tkn->text);
|
||||||
width = len > width ? len : width;
|
width = len > width ? len : width;
|
||||||
}
|
|
||||||
else {
|
|
||||||
fprintf (stdout, "tkn: %p\n", tkn);
|
|
||||||
fprintf (stdout, "tkn->text: %p\n", tkn->text);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// print completions
|
// print completions
|
||||||
for (ALL_LIST_ELEMENTS_RO (completions,ln,tkn))
|
for (i = 0; i < vector_active (comps); i++) {
|
||||||
|
tkn = vector_slot (comps, i);
|
||||||
fprintf (stdout, " %-*s %s%s", width, tkn->text, tkn->desc, "\n");
|
fprintf (stdout, " %-*s %s%s", width, tkn->text, tkn->desc, "\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
fprintf (stdout, "%% No match%s", "\n");
|
fprintf (stdout, "%% No match%s", "\n");
|
||||||
@ -295,6 +296,46 @@ init_cmdgraph (struct graph **graph)
|
|||||||
fprintf (stdout, "initialized graph\n");
|
fprintf (stdout, "initialized graph\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
compare_completions (const void *fst, const void *snd)
|
||||||
|
{
|
||||||
|
struct cmd_token_t *first = *(struct cmd_token_t **) fst,
|
||||||
|
*secnd = *(struct cmd_token_t **) snd;
|
||||||
|
return strcmp (first->text, secnd->text);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector
|
||||||
|
completions_to_vec (struct list *completions)
|
||||||
|
{
|
||||||
|
vector comps = vector_init (VECTOR_MIN_SIZE);
|
||||||
|
|
||||||
|
struct listnode *ln;
|
||||||
|
struct cmd_token_t *token;
|
||||||
|
unsigned int i, exists;
|
||||||
|
for (ALL_LIST_ELEMENTS_RO(completions,ln,token))
|
||||||
|
{
|
||||||
|
// linear search for token in completions vector
|
||||||
|
exists = 0;
|
||||||
|
for (i = 0; i < vector_active (comps) && !exists; i++)
|
||||||
|
{
|
||||||
|
struct cmd_token_t *curr = vector_slot (comps, i);
|
||||||
|
exists = !strcmp (curr->text, token->text) &&
|
||||||
|
!strcmp (curr->desc, token->desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!exists)
|
||||||
|
vector_set (comps, copy_cmd_token (token));
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort completions
|
||||||
|
qsort (comps->index,
|
||||||
|
vector_active (comps),
|
||||||
|
sizeof (void *),
|
||||||
|
&compare_completions);
|
||||||
|
|
||||||
|
return comps;
|
||||||
|
}
|
||||||
|
|
||||||
struct cmd_token_t *
|
struct cmd_token_t *
|
||||||
new_cmd_token (enum cmd_token_type_t type, char *text, char *desc)
|
new_cmd_token (enum cmd_token_type_t type, char *text, char *desc)
|
||||||
{
|
{
|
||||||
@ -326,9 +367,12 @@ struct cmd_token_t *
|
|||||||
copy_cmd_token (struct cmd_token_t *token)
|
copy_cmd_token (struct cmd_token_t *token)
|
||||||
{
|
{
|
||||||
struct cmd_token_t *copy = new_cmd_token (token->type, NULL, NULL);
|
struct cmd_token_t *copy = new_cmd_token (token->type, NULL, NULL);
|
||||||
copy->text = token->text ? XSTRDUP (MTYPE_CMD_TOKENS, token->text) : NULL;
|
copy->value = token->value;
|
||||||
copy->desc = token->desc ? XSTRDUP (MTYPE_CMD_TOKENS, token->desc) : NULL;
|
copy->max = token->max;
|
||||||
copy->arg = token->arg ? XSTRDUP (MTYPE_CMD_TOKENS, token->arg) : NULL;
|
copy->min = token->min;
|
||||||
|
copy->text = token->text ? XSTRDUP (MTYPE_CMD_TOKENS, token->text) : NULL;
|
||||||
|
copy->desc = token->desc ? XSTRDUP (MTYPE_CMD_TOKENS, token->desc) : NULL;
|
||||||
|
copy->arg = token->arg ? XSTRDUP (MTYPE_CMD_TOKENS, token->arg) : NULL;
|
||||||
|
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user