Sophie

Sophie

distrib > Fedora > 13 > i386 > media > os > by-pkgid > 19c0846d50c5b0d671ee1dea8e95ddee > files > 41

python-cly-0.9-2.fc12.i686.rpm

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.5: http://docutils.sourceforge.net/" />
<title>CLY Tutorial</title>
<style type="text/css">

.highlight .c { color: #008800; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #FF0000 } /* Error */
.highlight .k { color: #AA22FF; font-weight: bold } /* Keyword */
.highlight .o { color: #666666 } /* Operator */
.highlight .cm { color: #008800; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #008800 } /* Comment.Preproc */
.highlight .c1 { color: #008800; font-style: italic } /* Comment.Single */
.highlight .cs { color: #008800; font-weight: bold } /* Comment.Special */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
.highlight .go { color: #808080 } /* Generic.Output */
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0040D0 } /* Generic.Traceback */
.highlight .kc { color: #AA22FF; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #AA22FF; font-weight: bold } /* Keyword.Declaration */
.highlight .kp { color: #AA22FF } /* Keyword.Pseudo */
.highlight .kr { color: #AA22FF; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #AA22FF; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #666666 } /* Literal.Number */
.highlight .s { color: #BB4444 } /* Literal.String */
.highlight .na { color: #BB4444 } /* Name.Attribute */
.highlight .nb { color: #AA22FF } /* Name.Builtin */
.highlight .nc { color: #0000FF } /* Name.Class */
.highlight .no { color: #880000 } /* Name.Constant */
.highlight .nd { color: #AA22FF } /* Name.Decorator */
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #00A000 } /* Name.Function */
.highlight .nl { color: #A0A000 } /* Name.Label */
.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #B8860B } /* Name.Variable */
.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.highlight .mf { color: #666666 } /* Literal.Number.Float */
.highlight .mh { color: #666666 } /* Literal.Number.Hex */
.highlight .mi { color: #666666 } /* Literal.Number.Integer */
.highlight .mo { color: #666666 } /* Literal.Number.Oct */
.highlight .sb { color: #BB4444 } /* Literal.String.Backtick */
.highlight .sc { color: #BB4444 } /* Literal.String.Char */
.highlight .sd { color: #BB4444; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #BB4444 } /* Literal.String.Double */
.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #BB4444 } /* Literal.String.Heredoc */
.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.highlight .sx { color: #008000 } /* Literal.String.Other */
.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
.highlight .s1 { color: #BB4444 } /* Literal.String.Single */
.highlight .ss { color: #B8860B } /* Literal.String.Symbol */
.highlight .bp { color: #AA22FF } /* Name.Builtin.Pseudo */
.highlight .vc { color: #B8860B } /* Name.Variable.Class */
.highlight .vg { color: #B8860B } /* Name.Variable.Global */
.highlight .vi { color: #B8860B } /* Name.Variable.Instance */
.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */

/*
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:Date: $Date$
:Revision: $Revision$
:Copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.

See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/

/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
  border: 0 }

table.borderless td, table.borderless th {
  /* Override padding for "table.docutils td" with "! important".
     The right padding separates the table cells. */
  padding: 0 0.5em 0 0 ! important }

.first {
  /* Override more specific margin styles with "! important". */
  margin-top: 0 ! important }

.last, .with-subtitle {
  margin-bottom: 0 ! important }

.hidden {
  display: none }

a.toc-backref {
  text-decoration: none ;
  color: black }

blockquote.epigraph {
  margin: 2em 5em ; }

dl.docutils dd {
  margin-bottom: 0.5em }

/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
  font-weight: bold }
*/

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

/* Uncomment (and remove this text!) to get reduced vertical space in
   compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
  margin-bottom: 0.5em }

div.compound .compound-last, div.compound .compound-middle {
  margin-top: 0.5em }
*/

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em ;
  margin-right: 2em }

div.footer, div.header {
  clear: both;
  font-size: smaller }

div.line-block {
  display: block ;
  margin-top: 1em ;
  margin-bottom: 1em }

div.line-block div.line-block {
  margin-top: 0 ;
  margin-bottom: 0 ;
  margin-left: 1.5em }

div.sidebar {
  margin-left: 1em ;
  border: medium outset ;
  padding: 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
  margin-top: 0.4em }

h1.title {
  text-align: center }

h2.subtitle {
  text-align: center }

hr.docutils {
  width: 75% }

img.align-left {
  clear: left }

img.align-right {
  clear: right }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em ;
  background-color: #eeeeee }

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

span.section-subtitle {
  /* font-size relative to parent (h1..h6 element) */
  font-size: 80% }

table.citation {
  border-left: solid 1px gray;
  margin-left: 1px }

table.docinfo {
  margin: 2em 4em }

table.docutils {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.footnote {
  border-left: solid 1px black;
  margin-left: 1px }

table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

table.docutils th.field-name, table.docinfo th.docinfo-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap ;
  padding-left: 0 }

h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
  font-size: 100% }

tt.docutils {
  background-color: #eeeeee }

ul.auto-toc {
  list-style-type: none }

</style>
</head>
<body>
<div class="document" id="cly-tutorial">
<h1 class="title">CLY Tutorial</h1>

<div class="contents topic" id="contents">
<p class="topic-title first">Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#before-you-start" id="id1">Before you start</a></li>
<li><a class="reference internal" href="#step-one-fundamentals" id="id2">Step One - Fundamentals</a></li>
<li><a class="reference internal" href="#step-two-interaction" id="id3">Step Two - Interaction</a></li>
<li><a class="reference internal" href="#step-three-and-the-first-command-ment-shall-be-quit" id="id4">Step Three - And the first <em>command</em>-ment shall be <tt class="docutils literal"><span class="pre">quit</span></tt></a></li>
<li><a class="reference internal" href="#step-four-variables" id="id5">Step Four - Variables</a></li>
<li><a class="reference internal" href="#step-five-recursion" id="id6">Step Five - Recursion</a></li>
<li><a class="reference internal" href="#step-six-completion" id="id7">Step Six - Completion</a></li>
<li><a class="reference internal" href="#conclusion" id="id8">Conclusion</a></li>
</ul>
</div>
<div class="section" id="before-you-start">
<h1><a class="toc-backref" href="#id1">Before you start</a></h1>
<p>As with most things, it is usually better in the long run if you think about
your design before implementation. With that formality out of the way, the
beauty of CLY, and Python in general, is that it is easy and fun to experiment
with.</p>
<p>For the purposes of this tutorial I will implement a basic &quot;shell&quot;, with the
commands <tt class="docutils literal"><span class="pre">cat</span></tt> and <tt class="docutils literal"><span class="pre">quit</span></tt>. <tt class="docutils literal"><span class="pre">cat</span></tt> will have full tab completion of files
and directories.</p>
</div>
<div class="section" id="step-one-fundamentals">
<h1><a class="toc-backref" href="#id2">Step One - Fundamentals</a></h1>
<p>The first step is just to import the bare essentials required to get a command
line interface working. As one of CLY's main goals is to minimize the amount of
code required to implement a command line interface, this is fairly small.</p>
<div class="highlight"><pre><span class="kn">from</span> <span class="nn">cly</span> <span class="kn">import</span> <span class="o">*</span>
</pre></div>
</div>
<div class="section" id="step-two-interaction">
<h1><a class="toc-backref" href="#id3">Step Two - Interaction</a></h1>
<p>Making your program interactive is as simple as calling the <tt class="docutils literal"><span class="pre">interact()</span></tt>
function with a grammar:</p>
<div class="highlight"><pre><span class="kn">from</span> <span class="nn">cly</span> <span class="kn">import</span> <span class="o">*</span>

<span class="n">grammar</span> <span class="o">=</span> <span class="n">Grammar</span><span class="p">()</span>
<span class="n">interact</span><span class="p">(</span><span class="n">grammar</span><span class="p">)</span>
</pre></div>
<p>This calls <tt class="docutils literal"><span class="pre">interact()</span></tt> with an empty grammar, which won't do much at this
stage, but will allow interaction.</p>
<p>CLY uses readline for its interactive terminal, so all normal readline options
apply including emacs and vi modes. Command and variable completion can be
triggered by pressing <tt class="docutils literal"><span class="pre">&lt;Tab&gt;</span></tt> (this can be overridden), pressing <tt class="docutils literal"><span class="pre">?</span></tt> at any
time will display context-sensitive help, and finally, you can press
<tt class="docutils literal"><span class="pre">&lt;Ctrl-D&gt;</span></tt> to terminate the console interface.</p>
</div>
<div class="section" id="step-three-and-the-first-command-ment-shall-be-quit">
<h1><a class="toc-backref" href="#id4">Step Three - And the first <em>command</em>-ment shall be <tt class="docutils literal"><span class="pre">quit</span></tt></a></h1>
<p>The first command we will implement is <tt class="docutils literal"><span class="pre">quit</span></tt>, as it is the most basic.</p>
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">from</span> <span class="nn">cly</span> <span class="kn">import</span> <span class="o">*</span>

<span class="k">def</span> <span class="nf">do_quit</span><span class="p">():</span>
    <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mf">0</span><span class="p">)</span>


<span class="n">grammar</span> <span class="o">=</span> <span class="n">Grammar</span><span class="p">(</span>
    <span class="n">quit</span><span class="o">=</span><span class="n">Node</span><span class="p">(</span><span class="s">&#39;Quit&#39;</span><span class="p">)(</span>
        <span class="n">Action</span><span class="p">(</span><span class="s">&#39;Quit&#39;</span><span class="p">,</span> <span class="n">do_quit</span><span class="p">),</span>
    <span class="p">),</span>
<span class="p">)</span>

<span class="n">interact</span><span class="p">(</span><span class="n">grammar</span><span class="p">)</span>
</pre></div>
<p><strong>Note:</strong> The apparent redundancy of having two <em>Quit</em> nodes is explained
by the behaviour of the <tt class="docutils literal"><span class="pre">Action</span></tt> node. This node matches the end of the
current command. For example, the following would execute <tt class="docutils literal"><span class="pre">quit()</span></tt> when an
empty line is passed as the command:</p>
<div class="highlight"><pre><span class="n">grammar</span> <span class="o">=</span> <span class="n">Grammar</span><span class="p">(</span>
    <span class="n">Action</span><span class="p">(</span><span class="s">&#39;Quit&#39;</span><span class="p">,</span> <span class="n">do_quit</span><span class="p">),</span>
<span class="p">)</span>
</pre></div>
<p>Which is generally not what one wants.</p>
</div>
<div class="section" id="step-four-variables">
<h1><a class="toc-backref" href="#id5">Step Four - Variables</a></h1>
<p>It's all well and good to call a function with no arguments, but you'll often
want to pass user inputted variables along to each <tt class="docutils literal"><span class="pre">Action</span></tt>. This is where
the <tt class="docutils literal"><span class="pre">Variable</span></tt> class hierarchy comes in. The class matches user input
and stores the (potentially transformed into another type) value in the <tt class="docutils literal"><span class="pre">vars</span></tt>
dictionary of the current parse <tt class="docutils literal"><span class="pre">Context</span></tt>. When an <tt class="docutils literal"><span class="pre">Action</span></tt> node is selected it
passes these variables on to its callback as arguments.</p>
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">from</span> <span class="nn">cly</span> <span class="kn">import</span> <span class="o">*</span>

<span class="k">def</span> <span class="nf">do_quit</span><span class="p">():</span>
    <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mf">0</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">do_cat</span><span class="p">(</span><span class="nb">file</span><span class="p">):</span>
    <span class="k">print</span> <span class="nb">open</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">expanduser</span><span class="p">(</span><span class="nb">file</span><span class="p">))</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>

<span class="n">grammar</span> <span class="o">=</span> <span class="n">Grammar</span><span class="p">(</span>
    <span class="n">quit</span><span class="o">=</span><span class="n">Node</span><span class="p">(</span><span class="s">&#39;Quit&#39;</span><span class="p">)(</span>
        <span class="n">Action</span><span class="p">(</span><span class="s">&#39;Quit&#39;</span><span class="p">,</span> <span class="n">do_quit</span><span class="p">),</span>
    <span class="p">),</span>
    <span class="n">cat</span><span class="o">=</span><span class="n">Node</span><span class="p">(</span><span class="s">&#39;Concatenate files&#39;</span><span class="p">)(</span>
        <span class="nb">file</span><span class="o">=</span><span class="n">Variable</span><span class="p">(</span><span class="s">&#39;File to concatenate&#39;</span><span class="p">,</span> <span class="n">pattern</span><span class="o">=</span><span class="s">r&#39;\S+&#39;</span><span class="p">)(</span>
            <span class="n">Action</span><span class="p">(</span><span class="s">&#39;Concatenate files&#39;</span><span class="p">,</span> <span class="n">do_cat</span><span class="p">),</span>
        <span class="p">),</span>
    <span class="p">),</span>
<span class="p">)</span>

<span class="n">interact</span><span class="p">(</span><span class="n">grammar</span><span class="p">)</span>
</pre></div>
</div>
<div class="section" id="step-five-recursion">
<h1><a class="toc-backref" href="#id6">Step Five - Recursion</a></h1>
<p>This is cool, but what if we want to be able to &quot;cat&quot; multiple files?</p>
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">from</span> <span class="nn">cly</span> <span class="kn">import</span> <span class="o">*</span>

<span class="k">def</span> <span class="nf">do_quit</span><span class="p">():</span>
    <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mf">0</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">do_cat</span><span class="p">(</span><span class="n">files</span><span class="p">):</span>
    <span class="k">for</span> <span class="nb">file</span> <span class="ow">in</span> <span class="n">files</span><span class="p">:</span>
        <span class="k">print</span> <span class="nb">open</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">expanduser</span><span class="p">(</span><span class="nb">file</span><span class="p">))</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>

<span class="n">grammar</span> <span class="o">=</span> <span class="n">Grammar</span><span class="p">(</span>
    <span class="n">quit</span><span class="o">=</span><span class="n">Node</span><span class="p">(</span><span class="s">&#39;Quit&#39;</span><span class="p">)(</span>
        <span class="n">Action</span><span class="p">(</span><span class="s">&#39;Quit&#39;</span><span class="p">,</span> <span class="n">do_quit</span><span class="p">),</span>
    <span class="p">),</span>
    <span class="n">cat</span><span class="o">=</span><span class="n">Node</span><span class="p">(</span><span class="s">&#39;Concatenate files&#39;</span><span class="p">)(</span>
        <span class="n">files</span><span class="o">=</span><span class="n">Variable</span><span class="p">(</span><span class="s">&#39;File to concatenate&#39;</span><span class="p">,</span> <span class="n">pattern</span><span class="o">=</span><span class="s">r&#39;\S+&#39;</span><span class="p">,</span> <span class="n">traversals</span><span class="o">=</span><span class="mf">0</span><span class="p">)(</span>
            <span class="n">Action</span><span class="p">(</span><span class="s">&#39;Concatenate files&#39;</span><span class="p">,</span> <span class="n">do_cat</span><span class="p">),</span>
            <span class="n">Alias</span><span class="p">(</span><span class="s">&#39;..&#39;</span><span class="p">),</span>
        <span class="p">),</span>
    <span class="p">),</span>
<span class="p">)</span>

<span class="n">interact</span><span class="p">(</span><span class="n">grammar</span><span class="p">)</span>
</pre></div>
<p>Each <tt class="docutils literal"><span class="pre">Node</span></tt> has a <tt class="docutils literal"><span class="pre">traversals</span></tt> member which specifies the number of times that
node can be traversed in a parse context. This is <tt class="docutils literal"><span class="pre">1</span></tt> by default, but if we set
this to <tt class="docutils literal"><span class="pre">0</span></tt> the node may be traversed any number of times.</p>
<p>The second new feature is the <tt class="docutils literal"><span class="pre">Alias</span></tt> class which, as the name suggests,
makes this node an alias for another node in the grammar tree. The node to
alias is specified as either a relative or absolute path. In this case, the
parent node, whose absolute path is <tt class="docutils literal"><span class="pre">/cat/files</span></tt>.</p>
</div>
<div class="section" id="step-six-completion">
<h1><a class="toc-backref" href="#id7">Step Six - Completion</a></h1>
<p>Variables can have extra intelligence built into them to customise their
behaviour. To make life a bit easier for the end developer a selection of
variables are available in <tt class="docutils literal"><span class="pre">cly.builder</span></tt>. This includes a <tt class="docutils literal"><span class="pre">File</span></tt> class
which we will use to provide file completion:</p>
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">from</span> <span class="nn">cly</span> <span class="kn">import</span> <span class="o">*</span>

<span class="k">def</span> <span class="nf">do_quit</span><span class="p">():</span>
    <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mf">0</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">do_cat</span><span class="p">(</span><span class="n">files</span><span class="p">):</span>
    <span class="k">for</span> <span class="nb">file</span> <span class="ow">in</span> <span class="n">files</span><span class="p">:</span>
        <span class="k">print</span> <span class="nb">open</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">expanduser</span><span class="p">(</span><span class="nb">file</span><span class="p">))</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>

<span class="n">grammar</span> <span class="o">=</span> <span class="n">Grammar</span><span class="p">(</span>
    <span class="n">quit</span><span class="o">=</span><span class="n">Node</span><span class="p">(</span><span class="s">&#39;Quit&#39;</span><span class="p">)(</span>
        <span class="n">Action</span><span class="p">(</span><span class="s">&#39;Quit&#39;</span><span class="p">,</span> <span class="n">do_quit</span><span class="p">),</span>
    <span class="p">),</span>
    <span class="n">cat</span><span class="o">=</span><span class="n">Node</span><span class="p">(</span><span class="s">&#39;Concatenate files&#39;</span><span class="p">)(</span>
        <span class="n">files</span><span class="o">=</span><span class="n">File</span><span class="p">(</span><span class="s">&#39;File to concatenate&#39;</span><span class="p">,</span> <span class="n">traversals</span><span class="o">=</span><span class="mf">0</span><span class="p">)(</span>
            <span class="n">Action</span><span class="p">(</span><span class="s">&#39;Concatenate files&#39;</span><span class="p">,</span> <span class="n">do_cat</span><span class="p">),</span>
            <span class="n">Alias</span><span class="p">(</span><span class="s">&#39;..&#39;</span><span class="p">),</span>
        <span class="p">),</span>
    <span class="p">),</span>
<span class="p">)</span>

<span class="n">interact</span><span class="p">(</span><span class="n">grammar</span><span class="p">)</span>
</pre></div>
<p>Variables can be used to not only validate input, but parse it into a useful
state. By overriding the <tt class="docutils literal"><span class="pre">parse()</span></tt> method of a <tt class="docutils literal"><span class="pre">Variable</span></tt> any type can be
inserted into the context. An example of this is the IP variable, which
returns the IP as a tuple of integers.</p>
</div>
<div class="section" id="conclusion">
<h1><a class="toc-backref" href="#id8">Conclusion</a></h1>
<p>Hopefully this will have given you a taste of what CLY is capable of. There are quite a
number of <a class="reference external" href="http://swapoff.org/cly/docs">other features</a> which allow you to extensively customise the
behaviour of your command line applications.</p>
</div>
</div>
</body>
</html>