Changeset 484
- Timestamp:
- 12/09/07 09:17:01 (1 year ago)
- Files:
-
- cly/trunk/cly/builder.py (modified) (2 diffs)
- cly/trunk/doc/developers-guide.rst (modified) (4 diffs)
- cly/trunk/doc/tutorial.rst (modified) (3 diffs)
- cly/trunk/setup.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
cly/trunk/cly/builder.py
r482 r484 21 21 __all__ = ['Node', 'Alias', 'Group', 'Action', 'Variable', 'Grammar', 'Help', 22 22 'LazyHelp', 'Word', 'String', 'URI', 'LDAPDN', 'Integer', 'Float', 'IP', 23 'Hostname', 'Host', 'EMail', 'File' ]23 'Hostname', 'Host', 'EMail', 'File', 'Boolean'] 24 24 __docformat__ = 'restructuredtext en' 25 25 … … 873 873 874 874 875 class Boolean(Variable): 876 """Matches a boolean. 877 878 >>> from cly.parser import Parser 879 >>> parser = Parser(Grammar(foo=Boolean('Foo'))) 880 >>> parser.parse('true').vars['foo'] 881 True 882 >>> parser.parse('no').remaining 883 False 884 """ 885 TRUE = 'true yes aye enable enabled on 1'.split() 886 FALSE = 'false no disable disabled off 0'.split() 887 888 pattern = r'(?i)(%s)' % '|'.join(TRUE + FALSE) 889 890 def parse(self, context, match): 891 boolean = match.group() 892 return boolean in self.TRUE 893 894 875 895 class Float(Variable): 876 896 """Matches a floating point number. cly/trunk/doc/developers-guide.rst
r482 r484 203 203 argument. Refer to `Passing User-defined Objects to Callbacks`_ for more 204 204 information about user contexts. 205 206 Implementing Custom Completion 207 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 208 209 To implement your own custom completion, override ``Node.candidates(context, 210 text)``. This can be achieved by passing ``candidates=<callable>`` to the 211 ``Node`` constructor or by normal subclassing. Unless ``match_candidates=True`` 212 though, the node will still match any input that matches its ``pattern``. 213 Setting this flag to ``False`` will constrain the node to only match valid 214 candidates. 215 216 The `canidates()` method itself must return a list of strings *with trailing 217 whitespace* that match the ``text`` argument. ``context`` is a parser context 218 object, described elsewhere. 219 220 Here's an example of how one could implement a kill command: 221 222 .. code-block:: python 223 224 import os 225 import signal 226 from cly import * 227 228 # Build dictionary of signal_name:signal 229 signals = dict([(s[3:], getattr(signal, s)) 230 for s in dir(signal) 231 if s.startswith('SIG') 232 and not s.startswith('SIG_')]) 233 234 def complete_signals(context, text): 235 return [s + ' ' for s in signals.keys() if s.startswith(text)] 236 237 def kill(pid, signal=None): 238 try: 239 os.kill(pid, signals.get(signal, signals['TERM'])) 240 except OSError, e: 241 print 'error:', e 242 243 grammar = Grammar( 244 kill=Node( 245 pid=Integer('PID to kill')( 246 action=Action('Send signal', kill), 247 signal=Variable('Signal to send to process', 248 candidates=complete_signals, 249 match_candidates=True)( 250 Alias('/kill/pid/action'), 251 ), 252 ), 253 ), 254 ) 255 256 interact(grammar) 257 205 258 206 259 Adding Help … … 378 431 All ``Node`` constructor arguments that are not strings but are known to the 379 432 ``Parser`` will be evaluated as Python code, meaning integer arguments will be 380 converted to integers, callback arguments may contain lambdas, etc. This 381 evaluation can be forced by using the ``eval`` XML namespace: 433 converted to integers, callback arguments may contain lambdas, etc. 434 435 In this example ``traversals`` will be converted to an integer and passed to the 436 ``Node`` constructor: 437 438 .. code-block:: xml 439 440 <?xml version="1.0"?> 441 <grammar> 442 <node traversals="0"> 443 ... 444 </node> 445 </grammar> 446 447 This evaluation can also be forced by using the ``eval`` XML namespace: 382 448 383 449 .. code-block:: xml … … 394 460 ------- 395 461 396 A grammar is simply a data structure, to actually utilise it one needs to bind 397 it to a ``Parser`` object. The parser takes care of creating a context for each 398 parse run, parsing the input, and usually executing any callbacks. 399 400 The context is created automatically on parser construction and contains all the 401 information needed to parse input commands. This includes the current cursor 462 A grammar is simply a data structure. To actually utilise it one needs to bind 463 it to a ``Parser`` object and parse some input with it. The parser takes care 464 of creating a ``Context`` for each parse run, parsing the input, and executing 465 any callbacks. 466 467 Parse Context 468 ~~~~~~~~~~~~~ 469 A parse context is created automatically when input is parsed. It contains all 470 the information needed to parse input tokens, including the current cursor 402 471 position in the input stream, the current node in the grammar, variables 403 472 collected and a history of nodes traversed. … … 408 477 409 478 parser = Parser(grammar) 410 parser.execute('some input text') 411 412 This will parse the input text and execute any callbacks. If a parse 413 error occurs a ``cly.exceptions.ParseError`` will be raised. 479 context = parser.parse('some input text') 480 print context.vars 481 482 If the input is invalid the context will have consumed as much input as 483 possible. The attributes ``parsed`` and ``remaining`` contain how much text has 484 been consumed and remains, respectively. The context has a number of additional 485 attributes and methods that are useful to both ``Node`` implementations and 486 ``Parser`` users. These are documented in detail in the API documentation. 414 487 415 488 Passing User-defined Objects to Callbacks cly/trunk/doc/tutorial.rst
r439 r484 20 20 21 21 The first step is just to import the bare essentials required to get a command 22 line interface working. As CLY's main goal is to minimize the amount of code23 required to implement a command line interface, this is fairly small.22 line interface working. As one of CLY's main goals is to minimize the amount of 23 code required to implement a command line interface, this is fairly small. 24 24 25 25 .. code-block:: python … … 40 40 interact(grammar) 41 41 42 This calls ``interact()`` with an empty grammar, which won't do much but 43 will actually allow interaction. 44 45 Step Three - And the first *command* ment shall be ``quit`` 42 This calls ``interact()`` with an empty grammar, which won't do much at this 43 stage, but will allow interaction. 44 45 CLY uses readline for its interactive terminal, so all normal readline options 46 apply including emacs and vi modes. Command and variable completion can be 47 triggered by pressing ``<Tab>`` (this can be overridden), pressing ``?`` at any 48 time will display context-sensitive help, and finally, you can press 49 ``<Ctrl-D>`` to terminate the console interface. 50 51 Step Three - And the first *command*-ment shall be ``quit`` 46 52 ----------------------------------------------------------- 47 53 … … 82 88 83 89 It's all well and good to call a function with no arguments, but you'll often 84 want to pass user inputted variables along to the ``Action``s. This is where90 want to pass user inputted variables along to each ``Action``. This is where 85 91 the ``Variable`` class hierarchy comes in. The class matches user input 86 92 and stores the (potentially transformed into another type) value in the ``vars`` cly/trunk/setup.py
r455 r484 9 9 author='Alec Thomas', 10 10 author_email='alec@swapoff.org', 11 version='0.9 alpha2',12 description=' "cmd" on steroids',11 version='0.9', 12 description='A module for adding powerful text-based consoles to your application.', 13 13 long_description=\ 14 14 """CLY is a Python module for simplifying the creation of interactive shells.
