Changeset 484

Show
Ignore:
Timestamp:
12/09/07 09:17:01 (1 year ago)
Author:
athomas
Message:

cly: More doc updates. Added a Boolean node-type. Updated setup.py for release.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • cly/trunk/cly/builder.py

    r482 r484  
    2121__all__ = ['Node', 'Alias', 'Group', 'Action', 'Variable', 'Grammar', 'Help', 
    2222           'LazyHelp', 'Word', 'String', 'URI', 'LDAPDN', 'Integer', 'Float', 'IP', 
    23            'Hostname', 'Host', 'EMail', 'File'
     23           'Hostname', 'Host', 'EMail', 'File', 'Boolean'
    2424__docformat__ = 'restructuredtext en' 
    2525 
     
    873873 
    874874 
     875class 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 
    875895class Float(Variable): 
    876896    """Matches a floating point number. 
  • cly/trunk/doc/developers-guide.rst

    r482 r484  
    203203argument. Refer to `Passing User-defined Objects to Callbacks`_ for more 
    204204information about user contexts. 
     205 
     206Implementing Custom Completion 
     207~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     208 
     209To implement your own custom completion, override ``Node.candidates(context, 
     210text)``. This can be achieved by passing ``candidates=<callable>`` to the 
     211``Node`` constructor or by normal subclassing. Unless ``match_candidates=True`` 
     212though, the node will still match any input that matches its ``pattern``. 
     213Setting this flag to ``False`` will constrain the node to only match valid 
     214candidates. 
     215 
     216The `canidates()` method itself must return a list of strings *with trailing 
     217whitespace* that match the ``text`` argument. ``context`` is a parser context 
     218object, described elsewhere. 
     219 
     220Here'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   
    205258 
    206259Adding Help 
     
    378431All ``Node`` constructor arguments that are not strings but are known to the 
    379432``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: 
     433converted to integers, callback arguments may contain lambdas, etc. 
     434 
     435In 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 
     447This evaluation can also be forced by using the ``eval`` XML namespace: 
    382448 
    383449.. code-block:: xml 
     
    394460------- 
    395461 
    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 
     462A grammar is simply a data structure. To actually utilise it one needs to bind 
     463it to a ``Parser`` object and parse some input with it. The parser takes care 
     464of creating a ``Context`` for each parse run, parsing the input, and executing 
     465any callbacks. 
     466 
     467Parse Context 
     468~~~~~~~~~~~~~ 
     469A parse context is created automatically when input is parsed. It contains all 
     470the information needed to parse input tokens, including the current cursor 
    402471position in the input stream, the current node in the grammar, variables 
    403472collected and a history of nodes traversed. 
     
    408477 
    409478  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 
     482If the input is invalid the context will have consumed as much input as 
     483possible. The attributes ``parsed`` and ``remaining`` contain how much text has 
     484been consumed and remains, respectively. The context has a number of additional 
     485attributes and methods that are useful to both ``Node`` implementations and 
     486``Parser`` users. These are documented in detail in the API documentation. 
    414487 
    415488Passing User-defined Objects to Callbacks 
  • cly/trunk/doc/tutorial.rst

    r439 r484  
    2020 
    2121The 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 code  
    23 required to implement a command line interface, this is fairly small. 
     22line interface working. As one of CLY's main goals is to minimize the amount of 
     23code required to implement a command line interface, this is fairly small. 
    2424 
    2525.. code-block:: python 
     
    4040    interact(grammar) 
    4141 
    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`` 
     42This calls ``interact()`` with an empty grammar, which won't do much at this 
     43stage, but will allow interaction. 
     44 
     45CLY uses readline for its interactive terminal, so all normal readline options 
     46apply including emacs and vi modes. Command and variable completion can be 
     47triggered by pressing ``<Tab>`` (this can be overridden), pressing ``?`` at any 
     48time will display context-sensitive help, and finally, you can press 
     49``<Ctrl-D>`` to terminate the console interface. 
     50 
     51Step Three - And the first *command*-ment shall be ``quit`` 
    4652----------------------------------------------------------- 
    4753 
     
    8288 
    8389It'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 where  
     90want to pass user inputted variables along to each ``Action``. This is where  
    8591the ``Variable`` class hierarchy comes in. The class matches user input 
    8692and stores the (potentially transformed into another type) value in the ``vars`` 
  • cly/trunk/setup.py

    r455 r484  
    99      author='Alec Thomas', 
    1010      author_email='alec@swapoff.org', 
    11       version='0.9alpha2', 
    12       description='"cmd" on steroids', 
     11      version='0.9', 
     12      description='A module for adding powerful text-based consoles to your application.', 
    1313      long_description=\ 
    1414"""CLY is a Python module for simplifying the creation of interactive shells.