| 21 | | children as positional or keyword arguments. Each positional argument is |
|---|
| 22 | | treated as an `anonymous node` and thus should usually be reserved for terminal |
|---|
| 23 | | nodes or nodes whose help will be explicitly overridden. The keyword of each |
|---|
| 24 | | keyword argument is interpreted as the shell command at that position in the |
|---|
| 25 | | grammar in addition to, unless overridden, the name of that child node. |
|---|
| | 21 | children as positional or keyword arguments. The actual key of each keyword |
|---|
| | 22 | argument is interpreted as the command at that position in the grammar. |
|---|
| | 23 | Additionally, unless overridden, it is treated as the name of that child node. |
|---|
| | 24 | Each positional argument is treated as an `anonymous node` and thus should |
|---|
| | 25 | usually be reserved for terminal nodes or nodes whose name, pattern and help |
|---|
| | 26 | will be explicitly overridden. |
|---|
| 50 | | The first argument to every CLY grammar node **must** be a help string. This is |
|---|
| 51 | | used to construct contextual help when a user presses `?`. |
|---|
| 52 | | |
|---|
| 53 | | Context |
|---|
| 54 | | ~~~~~~~ |
|---|
| 55 | | Each command is parsed in a new context. The context stores state like |
|---|
| 56 | | variables collected, number of traversals of nodes, etc. Mostly, it can be |
|---|
| 57 | | ignored but is mentioned here for reference. |
|---|
| | 57 | The first argument to every CLY grammar node **must** be either a help string |
|---|
| | 58 | or a callable that returns an iterable of ``(key, help)`` tuples. This is used |
|---|
| | 59 | to construct contextual help when a user presses `?`. |
|---|
| | 60 | |
|---|
| | 61 | In the vast majority of cases a simple string, or possibly a pair, will be sufficient. |
|---|
| | 62 | For when it is not, the convenience class ``cly.parser.Help`` is available to |
|---|
| | 63 | construct help, either from a single pair: |
|---|
| | 64 | |
|---|
| | 65 | .. code-block:: python |
|---|
| | 66 | |
|---|
| | 67 | one=Node(Help.pair('one', 'Command 1')) |
|---|
| | 68 | |
|---|
| | 69 | or from a list of tuples: |
|---|
| | 70 | |
|---|
| | 71 | .. code-block:: python |
|---|
| | 72 | |
|---|
| | 73 | help = [('one', 'Command 1'), |
|---|
| | 74 | ('1', 'Command 1')] |
|---|
| | 75 | |
|---|
| | 76 | one=Node(Help(help), pattern=r'one|1') |
|---|
| 82 | | Variable nodes insert their matching input into the ``vars`` of the |
|---|
| 83 | | ``Context``, after being parsed by the ``parse()`` method. If the attribute |
|---|
| 84 | | ``traversals != 1``, values are collected into a list rather than a scalar. |
|---|
| 85 | | CLY includes a number of potentially useful ``Variable`` subclasses such as |
|---|
| 86 | | ``URI``, ``Integer``, ``Float``, etc. |
|---|
| | 102 | Variable nodes insert their matching input into the ``vars`` dictionary of |
|---|
| | 103 | the ``Context``, after being parsed by the ``parse()`` method. If the |
|---|
| | 104 | ``Variable`` attribute ``traversals`` is not 1, values are collected into a |
|---|
| | 105 | list rather than a scalar. CLY includes a number of potentially useful |
|---|
| | 106 | ``Variable`` subclasses such as ``URI``, ``Integer``, ``Float``, etc. |
|---|
| 129 | | .. code-block:: python |
|---|
| 130 | | |
|---|
| 131 | | def add_host(hostname, ip, comment=''): |
|---|
| 132 | | ... |
|---|
| 133 | | |
|---|
| 134 | | # add <hostname> <ip> [<comment>] |
|---|
| 135 | | add=Node('Add a host')( |
|---|
| 136 | | hostname=Variable('Host name')( |
|---|
| 137 | | ip=IP('IP address')( |
|---|
| 138 | | action=Action('Add host', add_host), |
|---|
| 139 | | # Optional comment |
|---|
| 140 | | comment=Variable('Comment', pattern=r'.+')( |
|---|
| 141 | | Alias('../../action'), |
|---|
| | 151 | .. code-block:: python |
|---|
| | 152 | |
|---|
| | 153 | def add_host(hostname, ip, comment=''): |
|---|
| | 154 | ... |
|---|
| | 155 | |
|---|
| | 156 | # add <hostname> <ip> [<comment>] |
|---|
| | 157 | add=Node('Add a host')( |
|---|
| | 158 | hostname=Variable('Host name')( |
|---|
| | 159 | ip=IP('IP address')( |
|---|
| | 160 | action=Action('Add host', add_host), |
|---|
| | 161 | # Optional comment |
|---|
| | 162 | comment=Variable('Comment', pattern=r'.+')( |
|---|
| | 163 | Alias('../../action'), |
|---|
| | 164 | ) |
|---|
| 150 | | .. code-block:: python |
|---|
| 151 | | |
|---|
| 152 | | def add_host(hostname, ip, comment=''): |
|---|
| 153 | | ... |
|---|
| 154 | | |
|---|
| 155 | | grammar = Grammar( |
|---|
| 156 | | add=Node('Add a host')( |
|---|
| 157 | | hostname=Variable('Host name')( |
|---|
| 158 | | Action('Add host', add_host, valid=lambda context: 'ip' in context.vars), |
|---|
| 159 | | ip=Node('IP address', traversals=0)( |
|---|
| 160 | | ip=IP('IP address', traversals=0)( |
|---|
| 161 | | Alias('../../../*') |
|---|
| | 178 | .. code-block:: python |
|---|
| | 179 | |
|---|
| | 180 | def add_host(hostname, ip, comment=''): |
|---|
| | 181 | ... |
|---|
| | 182 | |
|---|
| | 183 | grammar = Grammar( |
|---|
| | 184 | add=Node('Add a host')( |
|---|
| | 185 | hostname=Variable('Host name')( |
|---|
| | 186 | Action('Add host', add_host, valid=lambda context: 'ip' in context.vars), |
|---|
| | 187 | ip=Node('IP address', traversals=0)( |
|---|
| | 188 | ip=IP('IP address', traversals=0)( |
|---|
| | 189 | Alias('../../../*') |
|---|
| | 190 | ), |
|---|
| | 191 | ), |
|---|
| | 192 | comment=Node('Comment')( |
|---|
| | 193 | comment=String('Comment')( |
|---|
| | 194 | Alias('../../../*') |
|---|
| | 195 | ), |
|---|
| 164 | | comment=Node('Comment')( |
|---|
| 165 | | comment=String('Comment')( |
|---|
| 166 | | Alias('../../../*') |
|---|
| 167 | | ), |
|---|
| 168 | | ), |
|---|
| 169 | | ), |
|---|
| 170 | | ), |
|---|
| 171 | | ) |
|---|
| 172 | | |
|---|
| 173 | | Which corresponds to something like this command syntax:: |
|---|
| 174 | | |
|---|
| 175 | | add <hostname> ip <ip> [ip <ip> [ip <ip> ...]] [comment <comment>] |
|---|
| | 198 | ), |
|---|
| | 199 | ) |
|---|
| | 200 | |
|---|
| | 201 | Which corresponds to something like this command syntax: |
|---|
| | 202 | |
|---|
| | 203 | .. code-block:: xml |
|---|
| | 204 | |
|---|
| | 205 | add <hostname> ip <ip> [ip <ip> [ip <ip> ...]] [comment <comment>] |
|---|
| | 206 | |
|---|
| | 207 | Context |
|---|
| | 208 | ~~~~~~~ |
|---|
| | 209 | Each command is parsed within a context. The context stores state information |
|---|
| | 210 | such as variables collected, number of traversals of nodes, cursor location, |
|---|
| | 211 | etc. Mostly it can be ignored, but is mentioned here for reference. |
|---|