]>
Commit | Line | Data |
---|---|---|
9b9cdb46 QY |
1 | FRR Command Line Interface |
2 | ========================== | |
3 | ||
4 | Definition Grammar | |
5 | ------------------ | |
6 | ||
7 | This is a reference for the syntax used when defining new CLI commands. An | |
8 | example definition is: | |
9 | ||
4e3e06d6 | 10 | ``` |
9b9cdb46 QY |
11 | DEFUN (command_name, |
12 | command_name_cmd, | |
13 | --> "example <command|line [interface]> DEFINITION...", | |
14 | <..doc strings..>) | |
4e3e06d6 | 15 | ``` |
9b9cdb46 QY |
16 | |
17 | The arrowed part is the definition string. | |
18 | ||
19 | Explicit syntax rules in Flex and Bison may be found in lib/command_lex.l and | |
20 | lib/command_parse.y, respectively. If you can read BNF and regex those will be | |
21 | more useful than this document. | |
22 | ||
23 | If the parser is throwing syntax or other errors and you can't figure out why, | |
24 | it's unlikely to be a bug in the parser. If the error message is not useful, | |
25 | please file a bug for a better error message. If all else fails, read the token | |
26 | definitions in the lexer source and the Bison BNF in the parser source. | |
27 | ||
28 | Characters allowed in each token type: | |
29 | ||
30 | Tokens | |
31 | ------ | |
4e3e06d6 | 32 | * `WORD` -- A token that begins with +, -, or a lowercase letter. It is |
9779e3f1 QY |
33 | an unchanging part of the command and will only match itself. |
34 | Example: "show ip bgp", every token is a WORD. | |
4e3e06d6 DL |
35 | * `IPV4` -- 'A.B.C.D', matches an IPv4 address. |
36 | * `IPV6` -- 'X:X::X:X', matches an IPv6 address. | |
37 | * `IPV4_PREFIX` -- 'A.B.C.D/M', matches an IPv4 prefix in CIDR notation. | |
38 | * `IPV6_PREFIX` -- 'X:X::X:X/M', matches an IPv6 prefix in CIDR notation. | |
9779e3f1 QY |
39 | * `MAC` -- 'M:A:C', matches a 48-bit mac address |
40 | * `MAC_PREFIX` -- 'M:A:C/M', matches a 48-bit mac address with a mask | |
4e3e06d6 DL |
41 | * `VARIABLE` -- Begins with a capital letter. Matches any input. |
42 | * `RANGE` -- Numeric range delimited by parentheses, e.g. (-100 - 100) or | |
9779e3f1 | 43 | (10-20). Will only match numbers in the range. |
9b9cdb46 QY |
44 | |
45 | Rules | |
46 | ----- | |
4e3e06d6 | 47 | * `<angle|brackets>` -- Contain sequences of tokens separated by pipes and |
9b9cdb46 | 48 | provide mutual exclusion. Sequences may contain |
4e3e06d6 DL |
49 | `<mutual|exclusion>` but not as the first token. |
50 | Disallowed: `"example <<a|b> c|d>"` | |
51 | Allowed: `"example <a c|b c|d>"` | |
52 | * `[square brackets]` -- Contains sequences of tokens that are optional (can be | |
53 | omitted). `[<a|b>]` can be shortened to `[a|b]`. | |
54 | * `{curly|braces}` -- similar to angle brackets, but instead of mutual | |
9b9cdb46 QY |
55 | exclusion, curly braces indicate that one or more of the |
56 | pipe-separated sequences may be provided in any order. | |
4e3e06d6 | 57 | * `VARIADICS...` -- Any token which accepts input (so anything except WORD) |
9b9cdb46 QY |
58 | and that occurs as the last token of a line may be |
59 | followed by an ellipsis, which indicates that input | |
60 | matching the token may be repeated an unlimited number | |
61 | of times. | |
4e3e06d6 DL |
62 | * `$name` -- Specify a variable name for the preceding token. See |
63 | "Variable Names" below. | |
9b9cdb46 QY |
64 | |
65 | Some general notes: | |
66 | ||
67 | * Options are allowed at the beginning of the command. The developer is | |
68 | entreated to use these extremely sparingly. They are most useful for | |
69 | implementing the 'no' form of configuration commands. Please think carefully | |
70 | before using them for anything else. There is usually a better solution, even | |
71 | if it is just separating out the command definition into separate ones. | |
72 | ||
73 | * The developer should judiciously apply separation of concerns when defining | |
74 | CLI. CLI definitions for two unrelated or vaguely related commands or | |
75 | configuration items should be defined in separate commands. Clarity is | |
76 | preferred over LOC (within reason). | |
77 | ||
4e3e06d6 DL |
78 | Variable Names |
79 | -------------- | |
80 | The parser tries to fill the "varname" field on each token. This can happen | |
81 | either manually or automatically. Manual specifications work by appending | |
82 | `"$name"` after the input specifier: | |
83 | ||
84 | ``` | |
85 | foo bar$cmd WORD$name A.B.C.D$ip | |
86 | ``` | |
87 | ||
88 | Note that you can also assign variable names to fixed input tokens, this can | |
89 | be useful if multiple commands share code. You can also use "$name" after a | |
90 | multiple-choice option: | |
91 | ||
92 | ``` | |
93 | foo bar <A.B.C.D|X:X::X:X>$addr [optionA|optionB]$mode | |
94 | ``` | |
95 | ||
96 | The variable name is in this case assigned to the last token in each of the | |
97 | branches. | |
98 | ||
99 | Automatic assignment of variable names works by applying the following rules: | |
100 | ||
101 | - manual names always have priority | |
102 | - a "[no]" at the beginning receives "no" as varname on the "no" token | |
32a71fd8 | 103 | - VARIABLE tokens whose text is not "WORD" or "NAME" receive a cleaned lowercase |
4e3e06d6 DL |
104 | version of the token text as varname, e.g. "ROUTE-MAP" becomes "route_map". |
105 | - other variable tokens (i.e. everything except "fixed") receive the text of | |
106 | the preceding fixed token as varname, if one can be found. E.g.: | |
107 | "ip route A.B.C.D/M INTERFACE" assigns "route" to the "A.B.C.D/M" token. | |
108 | ||
109 | These rules should make it possible to avoid manual varname assignment in 90% | |
110 | of the cases. | |
111 | ||
ae56903c DL |
112 | DEFPY |
113 | ----- | |
114 | ||
115 | `DEFPY(...)` is an enhanced version of `DEFUN()` which is preprocessed by | |
116 | ` python/clidef.py`. The python script parses the command definition string, | |
117 | extracts variable names and types, and generates a C wrapper function that | |
118 | parses the variables and passes them on. This means that in the CLI function | |
119 | body, you will receive additional parameters with appropriate types. | |
120 | ||
121 | This is best explained by an example: | |
122 | ||
123 | ``` | |
124 | DEFPY(func, func_cmd, "[no] foo bar A.B.C.D (0-99)$num", "...help...") | |
125 | ||
126 | => | |
127 | ||
128 | func(self, vty, argc, argv, /* standard CLI arguments */ | |
129 | ||
130 | const char *no, /* unparsed "no" */ | |
131 | struct in_addr bar, /* parsed IP address */ | |
132 | const char *bar_str, /* unparsed IP address */ | |
133 | long num, /* parsed num */ | |
134 | const char *num_str) /* unparsed num */ | |
135 | ``` | |
136 | ||
137 | Note that as documented in the previous section, "bar" is automatically | |
138 | applied as variable name for "A.B.C.D". The python code then detects this | |
139 | is an IP address argument and generates code to parse it into a | |
140 | `struct in_addr`, passing it in `bar`. The raw value is passed in `bar_str`. | |
141 | The range/number argument works in the same way with the explicitly given | |
142 | variable name. | |
143 | ||
144 | ### Type rules | |
145 | ||
146 | | Token(s) | Type | Value if omitted by user | | |
147 | |--------------------------|-------------|--------------------------| | |
148 | | `A.B.C.D` | `struct in_addr` | 0.0.0.0 | | |
149 | | `X:X::X:X` | `struct in6_addr` | :: | | |
150 | | `A.B.C.D + X:X::X:X` | `const union sockunion *` | NULL | | |
151 | | `A.B.C.D/M` | `const struct prefix_ipv4 *` | NULL | | |
152 | | `X:X::X:X/M` | `const struct prefix_ipv6 *` | NULL | | |
153 | | `A.B.C.D/M + X:X::X:X/M` | `const struct prefix *` | NULL | | |
154 | | `(0-9)` | `long` | 0 | | |
155 | | `VARIABLE` | `const char *` | NULL | | |
156 | | `word` | `const char *` | NULL | | |
157 | | _all other_ | `const char *` | NULL | | |
158 | ||
159 | Note the following details: | |
160 | ||
161 | * not all parameters are pointers, some are passed as values. | |
162 | * when the type is not `const char *`, there will be an extra `_str` argument | |
163 | with type `const char *`. | |
164 | * you can give a variable name not only to `VARIABLE` tokens but also to | |
165 | `word` tokens (e.g. constant words). This is useful if some parts of a | |
166 | command are optional. The type will be `const char *`. | |
167 | * `[no]` will be passed as `const char *no`. | |
168 | * pointers will be NULL when the argument is optional and the user did not | |
169 | use it. | |
170 | * if a parameter is not a pointer, but is optional and the user didn't use it, | |
171 | the default value will be passed. Check the `_str` argument if you need to | |
172 | determine whether the parameter was omitted. | |
173 | * if the definition contains multiple parameters with the same variable name, | |
174 | they will be collapsed into a single function parameter. The python code | |
175 | will detect if the types are compatible (i.e. IPv4 + IPv6 variantes) and | |
176 | choose a corresponding C type. | |
177 | * the standard DEFUN parameters (self, vty, argc, argv) are still present and | |
178 | can be used. A DEFUN can simply be **edited into a DEFPY without further | |
179 | changes and it will still work**; this allows easy forward migration. | |
180 | * a file may contain both DEFUN and DEFPY statements. | |
181 | ||
182 | ### Getting a parameter dump | |
183 | ||
184 | The clidef.py script can be called to get a list of DEFUNs/DEFPYs with | |
185 | the parameter name/type list: | |
186 | ||
187 | ``` | |
188 | lib/clippy python/clidef.py --all-defun --show lib/plist.c > /dev/null | |
189 | ``` | |
190 | ||
191 | The generated code is printed to stdout, the info dump to stderr. The | |
192 | `--all-defun` argument will make it process DEFUN blocks as well as DEFPYs, | |
193 | which is useful prior to converting some DEFUNs. **The dump does not list | |
194 | the `_str` arguments** to keep the output shorter. | |
195 | ||
196 | Note that the clidef.py script cannot be run with python directly, it needs | |
197 | to be run with _clippy_ since the latter makes the CLI parser available. | |
198 | ||
199 | ### Include & Makefile requirements | |
200 | ||
201 | A source file that uses DEFPY needs to include the `_clippy.c` file **before | |
202 | all DEFPY statements**: | |
203 | ||
204 | ``` | |
205 | /* GPL header */ | |
206 | #include ... | |
207 | ||
208 | ... | |
209 | ||
210 | #include "filename_clippy.c" | |
211 | ||
212 | DEFPY(...) | |
213 | DEFPY(...) | |
214 | ||
215 | install_element(...) | |
216 | ``` | |
217 | ||
218 | This dependency needs to be marked in Makefile.am: (there is no ordering | |
219 | requirement) | |
220 | ||
221 | ``` | |
222 | include ../common.am | |
223 | ||
224 | # ... | |
225 | ||
226 | # if linked into a LTLIBRARY (.la/.so): | |
227 | filename.lo: filename_clippy.c | |
228 | ||
229 | # if linked into an executable or static library (.a): | |
230 | filename.o: filename_clippy.c | |
231 | ``` | |
232 | ||
9b9cdb46 QY |
233 | Doc Strings |
234 | ----------- | |
235 | Each token in a command definition should be documented with a brief doc | |
236 | string that informs a user of the meaning and/or purpose of the subsequent | |
237 | command tree. These strings are provided as the last parameter to DEFUN macros, | |
238 | concatenated together and separated by an escaped newline ('\n'). These are | |
239 | best explained by example. | |
240 | ||
4e3e06d6 | 241 | ``` |
9b9cdb46 QY |
242 | DEFUN (config_terminal, |
243 | config_terminal_cmd, | |
244 | "configure terminal", | |
245 | "Configuration from vty interface\n" | |
246 | "Configuration terminal\n") | |
4e3e06d6 | 247 | ``` |
9b9cdb46 QY |
248 | |
249 | The last parameter is split into two lines for readability. Two newline | |
250 | delimited doc strings are present, one for each token in the command. The | |
251 | second string documents the functionality of the 'terminal' command in the | |
252 | 'configure' tree. | |
253 | ||
254 | Note that the first string, for 'configure' does not contain documentation for | |
255 | 'terminal'. This is because the CLI is best envisioned as a tree, with tokens | |
256 | defining branches. An imaginary 'start' token is the root of every command in a | |
257 | CLI node. Each subsequent written token descends into a subtree, so the | |
258 | documentation for that token ideally summarizes all the functionality contained | |
259 | in the subtree. | |
260 | ||
261 | A consequence of this structure is that the developer must be careful to use | |
262 | the same doc strings when defining multiple commands that are part of the same | |
263 | tree. Commands which share prefixes must share the same doc strings for those | |
264 | prefixes. On startup the parser will generate warnings if it notices | |
265 | inconsistent doc strings. Behavior is undefined; the same token may show up | |
266 | twice in completions, with different doc strings, or it may show up once with a | |
267 | random doc string. Parser warnings should be heeded and fixed to avoid | |
268 | confusing users. | |
269 | ||
270 | The number of doc strings provided must be equal to the amount of tokens | |
271 | present in the command definition, read left to right, ignoring any special | |
272 | constructs. | |
273 | ||
274 | In the examples below, each arrowed token needs a doc string. | |
275 | ||
4e3e06d6 | 276 | ``` |
9b9cdb46 QY |
277 | "show ip bgp" |
278 | ^ ^ ^ | |
279 | ||
280 | "command <foo|bar> [example]" | |
281 | ^ ^ ^ ^ | |
4e3e06d6 | 282 | ``` |
9b9cdb46 QY |
283 | |
284 | Data Structures | |
285 | --------------- | |
286 | On startup, the CLI parser sequentially parses each command string definition | |
287 | and constructs a directed graph with each token forming a node. This graph is | |
288 | the basis of the entire CLI system. It is used to match user input in order to | |
289 | generate command completions and match commands to functions. | |
290 | ||
291 | There is one graph per CLI node (not the same as a graph node in the CLI | |
292 | graph). The CLI node struct keeps a reference to its graph (see lib/command.h). | |
293 | ||
294 | While most of the graph maintains the form of a tree, special constructs | |
295 | outlined in the Rules section introduce some quirks. <>, [] and {} form | |
296 | self-contained 'subgraphs'. Each subgraph is a tree except that all of the | |
297 | 'leaves' actually share a child node. This helps with minimizing graph size and | |
298 | debugging. | |
299 | ||
300 | As an example, the subgraph generated by <foo|bar> looks like this: | |
301 | ||
302 | . | |
303 | . | |
304 | | | |
305 | +----+---+ | |
306 | +--- -+ FORK +----+ | |
307 | | +--------+ | | |
308 | +--v---+ +--v---+ | |
309 | | foo | | bar | | |
310 | +--+---+ +--+---+ | |
311 | | +------+ | | |
312 | +------> JOIN <-----+ | |
313 | +---+--+ | |
314 | | | |
315 | . | |
316 | . | |
317 | ||
318 | FORK and JOIN nodes are plumbing nodes that don't correspond to user input. | |
319 | They're necessary in order to deduplicate these constructs where applicable. | |
320 | ||
321 | Options follow the same form, except that there is an edge from the FORK node | |
322 | to the JOIN node. | |
323 | ||
324 | Keywords follow the same form, except that there is an edge from JOIN to FORK. | |
325 | Because of this the CLI graph cannot be called acyclic. There is special logic | |
326 | in the input matching code that keeps a stack of paths already taken through | |
327 | the node in order to disallow following the same path more than once. | |
328 | ||
329 | Variadics are a bit special; they have an edge back to themselves, which allows | |
330 | repeating the same input indefinitely. | |
331 | ||
332 | The leaves of the graph are nodes that have no out edges. These nodes are | |
333 | special; their data section does not contain a token, as most nodes do, or | |
334 | NULL, as in FORK/JOIN nodes, but instead has a pointer to a cmd_element. All | |
335 | paths through the graph that terminate on a leaf are guaranteed to be defined | |
336 | by that command. When a user enters a complete command, the command matcher | |
337 | tokenizes the input and executes a DFS on the CLI graph. If it is | |
338 | simultaneously able to exhaust all input (one input token per graph node), and | |
339 | then find exactly one leaf connected to the last node it reaches, then the | |
340 | input has matched the corresponding command and the command is executed. If it | |
341 | finds more than one node, then the command is ambiguous (more on this in | |
342 | deduplication). If it cannot exhaust all input, the command is unknown. If it | |
343 | exhausts all input but does not find an edge node, the command is incomplete. | |
344 | ||
345 | The parser uses an incremental strategy to build the CLI graph for a node. Each | |
346 | command is parsed into its own graph, and then this graph is merged into the | |
347 | overall graph. During this merge step, the parser makes a best-effort attempt | |
348 | to remove duplicate nodes. If it finds a node in the overall graph that is | |
349 | equal to a node in the corresponding position in the command graph, it will | |
350 | intelligently merge the properties from the node in the command graph into the | |
351 | already-existing node. Subgraphs are also checked for isomorphism and merged | |
352 | where possible. The definition of whether two nodes are 'equal' is based on the | |
353 | equality of some set of token properties; read the parser source for the most | |
354 | up-to-date definition of equality. | |
355 | ||
356 | When the parser is unable to deduplicate some complicated constructs, this | |
357 | can result in two identical paths through separate parts of the graph. If | |
358 | this occurs and the user enters input that matches these paths, they will | |
359 | receive an 'ambiguous command' error and will be unable to execute the command. | |
360 | Most of the time the parser can detect and warn about duplicate commands, but | |
361 | it will not always be able to do this. Hence care should be taken before | |
362 | defining a new command to ensure it is not defined elsewhere. | |
363 | ||
364 | ||
365 | Command handlers | |
366 | ---------------- | |
367 | The block that follows a CLI definition is executed when a user enters input | |
368 | that matches the definition. Its function signature looks like this: | |
369 | ||
370 | int (*func) (const struct cmd_element *, struct vty *, int, struct cmd_token *[]); | |
371 | ||
372 | The first argument is the command definition struct. The last argument is an | |
373 | ordered array of tokens that correspond to the path taken through the graph, | |
374 | and the argument just prior to that is the length of the array. | |
375 | ||
376 | The arrangement of the token array has changed from the prior incarnation of | |
377 | the CLI system. In the old system, missing arguments were padded with NULLs so | |
378 | that the same parts of a command would show up at the same indices regardless | |
379 | of what was entered. The new system does not perform such padding and therefore | |
380 | it is generally _incorrect_ to assume consistent indices in this array. As a | |
381 | simple example: | |
382 | ||
383 | Command definition: | |
4e3e06d6 | 384 | ``` |
9b9cdb46 | 385 | command [foo] <bar|baz> |
4e3e06d6 | 386 | ``` |
9b9cdb46 QY |
387 | |
388 | User enters: | |
4e3e06d6 | 389 | ``` |
9b9cdb46 | 390 | command foo bar |
4e3e06d6 | 391 | ``` |
9b9cdb46 QY |
392 | |
393 | Array: | |
4e3e06d6 | 394 | ``` |
9b9cdb46 QY |
395 | [0] -> command |
396 | [1] -> foo | |
397 | [2] -> bar | |
4e3e06d6 | 398 | ``` |
9b9cdb46 QY |
399 | |
400 | User enters: | |
4e3e06d6 | 401 | ``` |
9b9cdb46 | 402 | command baz |
4e3e06d6 | 403 | ``` |
9b9cdb46 QY |
404 | |
405 | Array: | |
4e3e06d6 | 406 | ``` |
9b9cdb46 QY |
407 | [0] -> command |
408 | [1] -> baz | |
4e3e06d6 | 409 | ``` |
9b9cdb46 QY |
410 | |
411 | ||
412 | ||
413 | Command abbreviation & matching priority | |
414 | ---------------------------------------- | |
415 | As in the prior implementation, it is possible for users to elide parts of | |
416 | tokens when the CLI matcher does not need them to make an unambiguous match. | |
417 | This is best explained by example. | |
418 | ||
419 | Command definitions: | |
4e3e06d6 | 420 | ``` |
9b9cdb46 QY |
421 | command dog cow |
422 | command dog crow | |
4e3e06d6 | 423 | ``` |
9b9cdb46 QY |
424 | |
425 | User input: | |
4e3e06d6 | 426 | ``` |
9b9cdb46 QY |
427 | c d c -> ambiguous command |
428 | c d co -> match "command dog cow" | |
4e3e06d6 | 429 | ``` |
9b9cdb46 QY |
430 | |
431 | In the new implementation, this functionality has improved. Where previously | |
432 | the parser would stop at the first ambiguous token, it will now look ahead and | |
433 | attempt to disambiguate based on tokens later on in the input string. | |
434 | ||
435 | Command definitions: | |
4e3e06d6 | 436 | ``` |
9b9cdb46 QY |
437 | show ip bgp A.B.C.D |
438 | show ipv6 bgp X:X::X:X | |
4e3e06d6 | 439 | ``` |
9b9cdb46 QY |
440 | |
441 | User enters: | |
4e3e06d6 | 442 | ``` |
9b9cdb46 QY |
443 | s i b 4.3.2.1 -> match "show ip bgp A.B.C.D" |
444 | s i b ::e0 -> match "show ipv6 bgp X:X::X:X" | |
4e3e06d6 | 445 | ``` |
9b9cdb46 QY |
446 | |
447 | Previously both of these commands would be ambiguous since 'i' does not | |
448 | explicitly select either 'ip' or 'ipv6'. However, since the user later provides | |
449 | a token that matches only one of the commands (an IPv4 or IPv6 address) the | |
450 | parser is able to look ahead and select the appropriate command. This has some | |
451 | implications for parsing the argv*[] that is passed to the command handler. | |
452 | ||
453 | Now consider a command definition such as: | |
4e3e06d6 | 454 | ``` |
9b9cdb46 | 455 | command <foo|VAR> |
4e3e06d6 | 456 | ``` |
9b9cdb46 QY |
457 | |
458 | 'foo' only matches the string 'foo', but 'VAR' matches any input, including | |
459 | 'foo'. Who wins? In situations like this the matcher will always choose the | |
460 | 'better' match, so 'foo' will win. | |
461 | ||
462 | Consider also: | |
4e3e06d6 | 463 | ``` |
9b9cdb46 | 464 | show <ip|ipv6> foo |
4e3e06d6 | 465 | ``` |
9b9cdb46 QY |
466 | |
467 | User input: | |
4e3e06d6 | 468 | ``` |
9b9cdb46 | 469 | show ip foo |
4e3e06d6 | 470 | ``` |
9b9cdb46 QY |
471 | |
472 | 'ip' partially matches 'ipv6' but exactly matches 'ip', so 'ip' will win. | |
473 | ||
474 | ||
475 | struct cmd_token | |
476 | ---------------- | |
477 | ||
4e3e06d6 | 478 | ``` |
9b9cdb46 QY |
479 | /* Command token struct. */ |
480 | struct cmd_token | |
481 | { | |
482 | enum cmd_token_type type; // token type | |
483 | u_char attr; // token attributes | |
484 | bool allowrepeat; // matcher allowed to match token repetitively? | |
485 | ||
486 | char *text; // token text | |
487 | char *desc; // token description | |
488 | long long min, max; // for ranges | |
489 | char *arg; // user input that matches this token | |
4e3e06d6 | 490 | char *varname; // variable name |
9b9cdb46 | 491 | }; |
4e3e06d6 | 492 | ``` |
9b9cdb46 QY |
493 | |
494 | This struct is used in the CLI graph to match input against. It is also used to | |
495 | pass user input to command handler functions, as it is frequently useful for | |
496 | handlers to have access to that information. When a command is matched, the | |
497 | sequence of cmd_tokens that form the matching path are duplicated and placed in | |
498 | order into argv*[]. Before this happens the ->arg field is set to point at the | |
499 | snippet of user input that matched it. | |
500 | ||
501 | For most nontrivial commands the handler function will need to determine which | |
502 | of the possible matching inputs was entered. Previously this was done by | |
503 | looking at the first few characters of input. This is now considered an | |
504 | anti-pattern and should be avoided. Instead, the ->type or ->text fields for | |
505 | this logic. The ->type field can be used when the possible inputs differ in | |
506 | type. When the possible types are the same, use the ->text field. This field | |
507 | has the full text of the corresponding token in the definition string and using | |
508 | it makes for much more readable code. An example is helpful. | |
509 | ||
510 | Command definition: | |
4e3e06d6 | 511 | ``` |
9b9cdb46 | 512 | command <(1-10)|foo|BAR> |
4e3e06d6 | 513 | ``` |
9b9cdb46 QY |
514 | |
515 | In this example, the user may enter any one of: | |
516 | * an integer between 1 and 10 | |
517 | * "foo" | |
518 | * anything at all | |
519 | ||
520 | If the user enters "command f", then: | |
521 | ||
4e3e06d6 | 522 | ``` |
9b9cdb46 QY |
523 | argv[1]->type == WORD_TKN |
524 | argv[1]->arg == "f" | |
525 | argv[1]->text == "foo" | |
4e3e06d6 | 526 | ``` |
9b9cdb46 QY |
527 | |
528 | Range tokens have some special treatment; a token with ->type == RANGE_TKN will | |
529 | have the ->min and ->max fields set to the bounding values of the range. | |
530 | ||
531 | ||
532 | Permutations | |
533 | ------------ | |
534 | Finally, it is sometimes useful to check all the possible combinations of input | |
535 | that would match an arbitrary definition string. There is a tool in tools/ | |
536 | called 'permutations' that reads CLI definition strings on stdin and prints out | |
537 | all matching input permutations. It also dumps a text representation of the | |
538 | graph, which is more useful for debugging than anything else. It looks like | |
539 | this: | |
540 | ||
4e3e06d6 | 541 | ``` |
9b9cdb46 QY |
542 | $ ./permutations "show [ip] bgp [<view|vrf> WORD]" |
543 | ||
544 | show ip bgp view WORD | |
545 | show ip bgp vrf WORD | |
546 | show ip bgp | |
547 | show bgp view WORD | |
548 | show bgp vrf WORD | |
549 | show bgp | |
4e3e06d6 | 550 | ``` |
9b9cdb46 QY |
551 | |
552 | This functionality is also built into VTY/VTYSH; the 'list permutations' | |
553 | command will list all possible matching input permutations in the current CLI | |
554 | node. |