Maytag Metalark avatar Maytag Metalark committed 6661f24

Reorganizing a little.

Comments (0)

Files changed (25)

 include COPYING
 include *.txt
+include ez_setup.py
 recursive-include docs *.*
 recursive-include misc *.*

misc/README.core.templ

+{#
+    Copyright 2013 Brian Mearns
+
+    This file is part of templ.
+
+    templ is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    templ is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with templ.  If not, see <http://www.gnu.org/licenses/>.
+}{
+}{v
+    {$ EXAMPLE-TEMPLATE {lambda
+        {' :SYNTAX :INTRO :OUTRO :TEMPLATE }
+        {implode <<<
+            {p {' {$ :INTRO}}}
+            {pre
+                {' :syntax templ}
+                {$ :TEMPLATE}
+            }
+
+            {p {' {$ :OUTRO}}}
+            {pre
+                {' :syntax {$ :SYNTAX}}
+                {buffer {eval {$ :TEMPLATE}}}
+            }
+        >>> }
+    }}
+}{doc "templ - Template Processing Language"
+
+%Body content
+{'
+
+    {section "Introduction" {'
+
+        {p 
+<<<{b templ} is the {b Tem}plate {b P}rocessing {b L}anguage. >>>
+        }
+        
+        {p
+<<<{code templ} is a (Turing complete) programming language, used for content generation
+from text-based template files and a simple but powerful processing language
+({code templ} itself) which is embedded directly in the template file. >>>
+        }
+        
+        {p <<<{code templ} can be used for: {ul {'
+    "Code generation."
+    "Form letters."
+    "Server-side scripting for web servers."
+    "Customized markup with variant output formats."
+    "Any other kind of dynamic text-based content generation."
+            }}>>>     
+        }
+
+
+        {section "Contact Information" {'
+
+            {p <<<This project is currently hosted on {link bitbucket "https://bitbucket.org"}, 
+at {link "https://bitbucket.org/bmearns/templ/"}. The primary author is Brian Mearns:
+you can contact Brian through bitbucket at {link "https://bitbucket.org/bmearns"}. >>>
+            }
+
+        }}
+
+        {section "Copyright and License" {'
+
+            {p <<<{code templ} is {em "free software"}: you can redistribute it and/or modify
+it under the terms of the {b GNU Affero General Public License} as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version. >>> }
+
+            {p <<<{code templ} is distributed in the hope that it will be useful,
+but {b without any warranty}; without even the implied warranty of
+{em merchantability} or {em fitness for a particular purpose}.  See the
+GNU Affero General Public License for more details. >>> }
+
+            {p <<<A copy of the GNU Affero General Public License is available in the templ
+distribution under the file LICENSE.txt. If you did not receive a copy of
+this file, see {link "http://www.gnu.org/licenses/"}. >>> }
+        }}
+
+
+
+    }} %end section intro
+
+    {section "Examples" {'
+
+        {p
+    <<<The following show some simple example templates and they're output, to give
+an idea of what can be done with templ.>>>
+        }
+
+
+        {section "Templ Basics"
+            <<< {EXAMPLE-TEMPLATE
+                "text"
+                {implode <<<The following template shows some of the basic elements of {code templ} templates:>>>}
+                "The output looks like this:"
+"Hello, World!
+My Name is {set :NAME \"templ\"}. I am the TEMplate Processing Language.
+Sometimes, {$ :NAME} likes to speak in the third person.
+
+{$ :NAME} can do math:
+    1 + 1 = {+ 1 1}
+    1 + 2 = {+ 1 2}
+    2 + 3 = {+ 2 3}
+    3 + 5 = {+ 3 5}
+    etc...
+
+{$ :NAME} can operate on strings and lists:
+    {implode \"a\" {' b n n s}}
+    {str {cat {' a b c } {' d e f } }}
+
+{$ :NAME} can do conditional processing:
+    {if
+        {== {+ 2 2} 5}
+        \"Oh No!\"
+
+        {== {+ 2 2} 4}
+        \"Phew!\"
+
+        \"How did I get here?\"
+    }
+
+{$ :NAME} can loop (and do trig):
+{for :THETA {range 0 40 10} {
+    echo \"    sin(\" {$ :THETA} \") = \" {sin {rad {$ :THETA}}} {eol}}
+}
+
+{$ :NAME} can even do list comprehensions and user defined functions:
+{v {set
+    :MY-FUNC
+    {lambda
+        {' :THETA }
+        {:
+            {let :RADS}
+            {$ :RADS {rad {$ :THETA}}}
+
+            {echo \"Processing theta=\" {$ :THETA} \"...\" {eol}}
+
+            %return value
+            {+ {cos {$ :RADS}} {sin {$ :RADS}} }
+        }
+    }
+}}{wrap \"{\" \"}\" {implode {glue \",\" {eol} \"    \"} {gen
+    :T
+    {range 40 80 10}
+    {join \":\" {$ :T} {:MY-FUNC {$ :T}}}
+}}}
+"
+        }
+        
+>>> } % end section "Basics"
+
+        {section "Code Generation - A Sine Lookup Table"
+            <<< {EXAMPLE-TEMPLATE
+                c
+                {implode
+<<<The following template shows an example of how to use {code templ}
+to generate C-code, in this case a sine lookup table.>>>
+                }
+                "The output looks like this:"
+"{v
+    {set :SIZE 10}
+}const double sine_lut[{get :SIZE}] =
+\\{
+{for i {range {get :SIZE}} {::
+    {let :THETA}
+    {$ :THETA {mult
+        {$ i}
+        {div 360 {$ :SIZE}}
+    }}
+    {spit {'
+        \"    \"
+        {round 
+            {sin {rad {$ :THETA}}}
+            4
+        }
+        ,
+        {\\t}
+        \"// i = \"
+        {get i}
+        \", theta = \"
+        {$ :THETA}
+        \" deg\"
+        {eol}
+    }}
+}}\\};
+" }
+
+>>> } % end section "Code Generation..."
+
+
+        {section "Embedded Data"
+            <<< {EXAMPLE-TEMPLATE
+                c
+                {implode
+<<<The next example shows how {code templ} allows you to easily embed data
+directly in the template file that uses it, allowing you to keep just
+one file under version control, for instance. >>>
+                }
+                "It produces this:"
+                "
+{v
+    %Embedded data
+    {$ :DATA {'
+        %   Name            Year    Month (-1)      Date
+        {'  \"Alan T.\"     1912    05              23 }
+        {'  \"John V.\"     1903    11              28 }
+        {'  \"Claude S.\"   1916    03              30 }
+        {'  \"George B.\"   1815    10              2  }
+        {'  \"George B.\"   1815    10              2  }
+        {'  \"Ada L.\"      1815    11              15 }
+        {'  \"Charles B.\"  1791    11              26 }
+        {'  \"Donald K.\"   1938    0               10 }
+        {'  \"Dennis R.\"   1941    8               9  }
+    }}
+}{for :ROW {$ :DATA} {:
+    {$ :STAMP {stamp {slice 1 {$ :ROW}}}}
+    {$ :NOW {stamp}}
+    {$ :AGE {floor {div {- {$ :NOW} {$ :STAMP}} {* 60 60 24 365.25}}}}
+    {echo {@ 0 {$ :ROW}} \", age \" {$ :AGE} \" years.\" {eol} }
+}}"
+    }
+    
+>>> } % end section "Embedded Data"
+
+
+        {section "Programmatic Invocation"
+            <<<{p 
+<<<The real power of {code templ} comes from the programmatic interface,
+which allows you to predefine symbols, and even executables (functions, macros
+and operators) in python, which are then accessible from the template.
+Because, although {code templ} {em is} Turing complete, and you {em could} do all
+of your processing directly in the template (or a separate included template), doing
+advanced data processing in python can help keep your template files simpler. >>>
+            }>>>}
+
+    }} %end section Examples
+
+}}{#
+ vim: set ft=templ:
+}

misc/README.rest.templ

+{#
+    Copyright 2013 Brian Mearns
+
+    This file is part of templ.
+
+    templ is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    templ is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with templ.  If not, see <http://www.gnu.org/licenses/>.
+}{
+}{include rest.itmpl }{
+}{include README.core.templ }{
+}{#
+ vim: set ft=templ:
+}

misc/README.txt.templ

+{#
+    Copyright 2013 Brian Mearns
+
+    This file is part of templ.
+
+    templ is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    templ is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with templ.  If not, see <http://www.gnu.org/licenses/>.
+}{
+}{include txtdoc.itmpl }{
+}{include README.core.templ }{
+}{#
+ vim: set ft=templ:
+}
+{v 
+    {$ NAME templ}
+}Welcome to the {$ NAME} demo template!
+
+{$ NAME} is the TEMplate Processing Language, used for content generation
+from text-based template files and a simple but powerful processing language
+({$ NAME} itself). {$ NAME} can be used for:
+{v {for EXAMPLE {'
+        "Code generation."
+        "Form letters."
+        "Server-side scripting for web servers."
+        "Customized markup with variant output formats."
+        "Any other kind of dynamic text-based content generation."
+    }
+    {:
+        {echo "    * "}
+        {echo {$ EXAMPLE}}
+        {echo "
+"}
+    }
+}}
+The {$ NAME} language is just a simple text-based language, but it is Turing
+Complete and comes equipped with a number of useful functions. You could,
+theoretically, use it as a general scripting language, though it really is
+best suited for it's natural purpose, processing templates.
+
+Still, it's very powerful for this. For instance, you could easily generate a
+sine lookup table for C:
+
+/**********************************************/
+{v {set SIZE 10}
+}const double sine_lut[{get SIZE}] =
+\{
+{for i {range {get SIZE}} {:
+    {echo {glue
+        "    "
+        {round 
+            {sin {div
+                {mult {get i} 2 {pi}}
+                {get SIZE}
+            }}
+            4
+        }
+        , {tab} "// i = " {get i}
+        {lnbrk}
+    }}
+}}
+\};
+/**********************************************/
+
+One of the nice things about {$ NAME} is that you can embed data directly into
+your template file so that you only need to keep one file under version
+control:
+
+###############################################
+{v {set YEAR 2012}
+}{v
+{set DATA {'
+    %   Name            Month       Year        Score
+    {'  "Alan T."       June        1912        61  }
+    {'  "John B."       December    1924        53  }
+    {'  "John von N."   December    1903        47  }
+    {'  "Claude S."      April       1916        59  }
+}}
+}{
+   for ROW {get DATA}
+   {spit
+<<<User "{at 0 {get ROW}}" (age {
+    sub {get YEAR} {at 2 {get ROW}}
+    }) has a score of: {at 3 {get ROW}}
+>>>
+    }
+}###############################################
+
+Alternatively, you can invoke {$ NAME} from python and pass in your own data
+to prepopulate variables. This lets you generate code based on data stored in
+other files, other formats, or even remote locations like databases or network
+services.
+
+By the way, if you're using the {$ NAME} demo program, you can see what this
+template file actually looks like (unprocessed) by preceding the filename with
+a + character. Or you could always just open it in a text editor.
+
+{ dont 
+% "dont" is kind of like a multi-line comment. So if you're not editing with
+% Vim, you can ignore the rest of the file.
+"
+ vim: set ft=templ tw=78:
+" }

misc/functions.templ

+{  rem "
+
+This template generates an HTML page containing a list and description of 
+every built in executable object (functions, macros, and operators) for
+templ.
+
+"
+}{syntax html}<html>
+    <head>
+        <title>templ builtin functions, operators, and macros</title>
+        <style type='text/css'>
+        /* <![CDATA[ */
+            
+            h2 \{
+                margin: 10px 0 8px 0;
+            \}
+            h3 \{
+                margin: 8px 0 4px 0;
+            \}
+            h4 \{
+                margin: 4px 0 16px 0;
+            \}
+
+            li \{
+                border-bottom: 1px solid;
+            \}
+
+        /* ]]> */
+        </style>
+    </head>
+    <body>
+        <h1>templ builtin functions, operators, and macros</h1>
+
+            <ul style='padding: 0; list-item-type: none;'>
+{end-syntax html}
+{v{:
+    % Get the list of vars now, before we add any of our own.
+    {set VARS {sort {vars}}}
+    {set HTMLESC {lambda {:
+        {strrep > &gt;
+            {strrep < &lt; {@ 0 {$ :argv}}}
+        }
+    }}}
+    % Iterate over all variable symbols, which includes all available functions
+    {for FUNCNAME {$ VARS}
+    {:
+        % Set FUNC to be the actual value
+        {set FUNC {$ {$ FUNCNAME}}}
+
+        %See if it's an executable
+        {if {is-exe {$ FUNC}}
+        {:
+            % Only use the symbols that are the actual name of the function, not all the aliases.
+            {if {=== {$ FUNCNAME} {exe-name {$ FUNC}} }
+            {:
+                %Show the canonical name.
+                {spit <<<
+            <li class='exe'>
+                <a title="{HTMLESC {$ FUNCNAME} }">
+                <h2 class='name'>{HTMLESC {$ FUNCNAME }}</h2>
+                >>>
+                }
+
+                % Show the aliases.
+                {set ALIASES {aliases {$ FUNC}}}
+                {if {len {$ ALIASES}} {:
+                    {spit <<<
+                <h3 class='aliases'>aka: {implode ", " {gen
+                        ALIAS {$ ALIASES} {implode "" {' "\"<span class='alias'>" {$ ALIAS} "</span>\""}}
+                    }}</h3>
+                    >>> }
+                }}
+
+                %What type of executable.
+                {spit <<<
+                <h4 class='type'>{if
+                        
+                        {is-func {$ FUNC}}
+                        function
+
+                        {is-oper {$ FUNC}}
+                        operator
+                
+                        {is-macro {$ FUNC}}
+                        macro
+
+                    }</h4>
+                >>>
+                }
+
+                %The doc string
+                {spit <<<
+                <pre class='doc'>{HTMLESC {doc {$ FUNC }}}</pre>
+            </li>
+                >>>
+                }
+
+            }} %end if it's the name
+        }} %end if is-exe
+    }} %end for
+}}
+        </ul>
+    </body>
+</html>
+{ dont
+ vim: set syntax=templ:
+}
+{#
+    Copyright 2013 Brian Mearns
+
+    This file is part of templ.
+
+    templ is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    templ is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with templ.  If not, see <http://www.gnu.org/licenses/>.
+}{
+}{v {:
+
+    {set htmlesc {lambda {:
+        {strrep > &gt;
+            {strrep < &lt; 
+                {strrep & &amp; {@ 0 {$ :argv}}}
+            }
+        }
+    }}}
+
+
+{$ html {macro
+    "Wraps content in HTML."
+
+    {' :pageTitle :headList :contentList }
+    
+    %We're building up an expression that will be evaluated.
+    % That expression will be a List, so we're building a list.
+    %First thing in the list is the tag. In this case, we start
+    % by defining a new scope to put our local functions in.
+    {poe {::
+
+        %Now define our Local Executables as elements of the list.
+        {set em {macro
+            "Generates emphasized text."
+            {' }
+            {poe {glue <em> {implode " " {ete {esc-list {$ :argv }}}} </em>}}
+        }}
+
+        {set code {macro
+            "Generates text formatted to look like an inline code snippet."
+            {nil}
+            {poe {glue <tt> {implode " " {ete {esc-list {$ :argv }}}} </tt>}}
+        }}
+
+        {set b {macro
+            "Generates bold text."
+            {' :text}
+            {poe {glue <b> {implode " " {ete {esc-list {$ :argv }}}} </b>}}
+        }}
+
+        {set p {macro
+            {' :textList }
+            {poe {glue <p> {implode "" {ete {$ :textList }}} </p>}}
+        }}
+
+        {set ul {macro
+            {' :list }
+            {poe {glue "
+        <ul>
+            " 
+            {implode "
+            " {gen :item {ete {$ :list }} {glue <li> {$ :item} </li> }}}
+            "
+        </ul>
+"
+            }}
+        }}
+
+        {set pre {lambda
+            {::
+                {let :options :content :class}
+                {$ :options {nil}}
+                {$ :content ""}
+                {$ :class ""}
+
+                {if
+                    {== 1 {len {$ :argv}}} {:
+                        {$ :content {@ 0 {$ :argv}}}
+                    }
+
+                    {== 2 {len {$ :argv}}} {:
+                        {$ :options {@ 0 {$ :argv}}}
+                        {$ :content {@ 1 {$ :argv}}}
+
+                        %Check and parse options.
+                        {if                         
+                            {not {is-list {$ :options}}}
+                            {error "Invalid options, expected a list."}
+                        }
+                        {if
+                            {hasf :syntax {$ :options}}
+                            {$ :class {glue " class='pre-" {getf :syntax {$ :options}} "'"}}
+                        }
+                    }
+
+                    %else
+                    {error {glue "Incorrect number of arguments to pre: expected one or two, not " {len {$ :argv}}}}
+                }
+
+                {if
+                    {not {is-str {$ :content}}}
+                    {error {glue "Invalid content, expected a String, not a " {type {$ :content}}}}
+                }
+
+
+                {glue "<pre" {$ :class} ">" {$ :content} "</pre>" }
+            }
+        }}
+
+        {set link {macro
+            {if 
+                {== 1 {len {$ :argv}}} {poe {::
+                    {$ :href {ete {@ 0 {$ :argv}}}}
+                    {glue "<a href='" {htmlesc {$ :href}} "'>" {$ :href} "</a>"}
+                }}
+
+                {== 2 {len {$ :argv}}} {poe {::
+                    {$ :text {ete {@ 0 {$ :argv}}}}
+                    {$ :href {ete {@ 1 {$ :argv}}}}
+                    {glue "<a href='" {htmlesc {$ :href}} "'>" {$ :text} "</a>"}
+                }}
+
+                {error
+                    "Incorrect number of arguments for link. Expected exactly 1 or 2."
+                }
+            }
+        }}
+
+        {$ :html-depth 1}
+        {$ :html-section-number {' 0 }}
+        {$ :html-sections {' }}
+
+        {set section {macro
+            {' :title :bodylist}
+            {:
+                %Increment the section number
+                {$ :html-section-number
+                    {append 
+                        {+ 1 {@ -1 {$ :html-section-number }}}
+                        {slice 0 -1 {$ :html-section-number }}
+                    }
+                }
+
+                {$ :html-sections {append {' {$ :html-section-number} {$ :title}} {$ :html-sections} }}
+
+                {$ :new-html-section-number
+                    {append 0 {$ :html-section-number }}
+                }
+
+                %The macro-subst.
+                {poe {::
+                    % Copy the html values into this new scope, and adjust appropriately.
+                    {let :html-depth :html-section-number }
+                    {$ :html-depth {ete {+ 1 {$ :html-depth}}}}
+                    {$ :html-section-number {ete {insert ' {$ :new-html-section-number }}}}
+
+                    {glue
+                        "<a id='section-" {ete {implode _ {$ :html-section-number}}} "'></a>" {\n}
+                        <h {ete {+ 1 {$ :html-depth }}} >
+                            "<span class='section-number'>" {ete {implode . {$ :html-section-number }}}:"</span> "
+                            {ete {$ :title}}
+                        </h {ete {+ 1 {$ :html-depth }}} >
+                        {implode "" {ete {$ :bodylist}} }
+                    }
+                }}
+            }
+        }}
+
+        %Evaluate this now, so we get all the sections and stuff. Generate macro
+        % subst to assign it (evaluated) to :htmlBodyContent.
+        {$ :htmlBodyContent {implode {ete {$ :contentList}}}}
+
+        {glue 
+            {implode 
+<<<<html>
+    <head>
+        <title> >>>
+            }
+            
+            {ete {$ :pageTitle}}
+
+            {implode
+    <<< </title>
+        {implode {ete {$ :headList}}}
+    </head>
+    <body>
+        <a id='__TOP__' />
+
+        <h1>{ete {$ :pageTitle}}</h1>
+        
+        <a id='__TOC__' />
+        <h2 id='__contents__'>Contents</h2>
+>>>     
+            }
+
+            {ul
+                {gen 
+                    :section
+                    {$ :html-sections}
+                    {:
+                        {unpack {' :section-number :section-title } {$ :section }}
+                        {$ :section-label {implode _ {$ :section-number } }}
+                        {$ :section-number {implode . {$ :section-number } }}
+
+                        {glue
+                            "<a href='#section-"
+                            {$ :section-label }
+                            "'>"
+                            {$ :section-number }
+                            " "
+                            {$ :section-title }
+                            "</a>"
+                        }
+                    }
+                }
+            }
+
+            {$ :htmlBodyContent }
+            {implode <<<
+    </body>
+</html>
+>>>
+            }
+        }
+
+        %end html macro body.
+    }}
+
+}}}}
+{#
+    Copyright 2013 Brian Mearns
+
+    This file is part of templ.
+
+    templ is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    templ is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with templ.  If not, see <http://www.gnu.org/licenses/>.
+}{
+}{v {:
+
+{$ doc {macro
+    "Wraps content in reStructured text"
+
+    {' :pageTitle :contentList }
+    
+    %We're building up an expression that will be evaluated.
+    % That expression will be a List, so we're building a list.
+    %First thing in the list is the tag. In this case, we start
+    % by defining a new scope to put our local functions in.
+    {poe {::
+
+        %Now define our Local Executables as elements of the list.
+        {set em {macro
+            "Generates emphasized text."
+            {' :text }
+            {poe {wrap "\\ " {wrap * {implode " " {ete {esc-list {$ :argv }}}} }}}
+        }}
+
+        {set code {macro
+            "Generates text formatted to look like an inline code snippet."
+            {' :text }
+            {poe {wrap "\\ " {wrap `` {implode " " {ete {esc-list {$ :argv }}}} }}}
+        }}
+
+        {set b {macro
+            "Generates bold text."
+            {' :text }
+            {poe {wrap "\\ " {wrap ** {implode " " {ete {esc-list {$ :argv }}}} }}}
+        }}
+
+        {set p {macro
+            {' :textList }
+            {poe {wrap {glue {eol} {eol}} {implode "" {ete {$ :textList }}} }}
+        }}
+
+        {set ul {macro
+            {' :list }
+            {poe
+                {glue {eol} {eol}
+                    {implode {eol}
+                        {gen
+                            :item {ete {$ :list }}
+                            {glue "- " {strrep {eol} " " {$ :item}}}
+                        }
+                    }
+                }
+            }
+        }}
+
+        {set pre {lambda
+            {::
+                {let :options :content :class}
+                {$ :options {nil}}
+                {$ :content ""}
+
+                {if
+                    {== 1 {len {$ :argv}}} {:
+                        {$ :content {@ 0 {$ :argv}}}
+                    }
+
+                    {== 2 {len {$ :argv}}} {:
+                        {$ :options {@ 0 {$ :argv}}}
+                        {$ :content {@ 1 {$ :argv}}}
+
+                        %Check and parse options.
+                        {if                         
+                            {not {is-list {$ :options}}}
+                            {error "Invalid options, expected a list."}
+                        }
+                    }
+
+                    %else
+                    {error {glue "Incorrect number of arguments to pre: expected one or two, not " {len {$ :argv}}}}
+                }
+
+                {if
+                    {not {is-str {$ :content}}}
+                    {error {glue "Invalid content, expected a String, not a " {type {$ :content}}}}
+                }
+
+
+                {glue {eol} {eol} "::" {eol} {eol} "    " {strrep {eol} {glue {eol} "    "} {$ :content}}}
+            }
+        }}
+
+        {set link {macro
+            {if 
+                {== 1 {len {$ :argv}}} {poe {::
+                    {$ :href {ete {@ 0 {$ :argv}}}}
+                    {glue "`" {$ :href} " <" {$ :href} ">`_" }
+                }}
+
+                {== 2 {len {$ :argv}}} {poe {::
+                    {$ :text {ete {@ 0 {$ :argv}}}}
+                    {$ :href {ete {@ 1 {$ :argv}}}}
+                    {glue "`" {$ :text} " <" {$ :href} ">`_" }
+                }}
+
+                {error
+                    "Incorrect number of arguments for link. Expected exactly 1 or 2."
+                }
+            }
+        }}
+
+        {$ :rest-sect-lines {' = - ~ ` : ' "\"" ~ ^ _ * + # < > }}
+        {$ :rest-depth 0}
+        {$ :rest-section-number {' 0 }}
+        {$ :rest-sections {' }}
+
+        {set section {macro
+            {' :title :bodylist}
+            {:
+                %Increment the section number
+                {$ :rest-section-number
+                    {append 
+                        {+ 1 {@ -1 {$ :rest-section-number }}}
+                        {slice 0 -1 {$ :rest-section-number }}
+                    }
+                }
+
+                {$ :rest-sections {append {' {$ :rest-section-number} {$ :title}} {$ :rest-sections} }}
+
+                {$ :new-rest-section-number
+                    {append 0 {$ :rest-section-number }}
+                }
+
+                %The macro-subst.
+                {poe {::
+                    % Now copy the rest values into this new scope, and adjust appropriately.
+                    {let :rest-depth :rest-section-number }
+                    {$ :rest-depth {ete {+ 1 {$ :rest-depth}}}}
+                    {$ :rest-section-number {ete {insert ' {$ :new-rest-section-number }}}}
+
+                    {let :title-line}
+                    {$ :title-line {glue {ete {implode "." {$ :rest-section-number}}} ": " {ete {$ :title}}}}
+
+                    %FIXME: Check the depth.
+                    {let :line-char :line }
+                    {$ :line-char {@ {$ :rest-depth} {$ :rest-sect-lines}}}
+                    {$ :line {implode {gen i {range {strlen {$ :title-line}}} {$ :line-char}}}}
+
+
+                    {glue
+                        {eol} {eol}
+                        ".. _Section-" {ete {implode "." {$ :rest-section-number}}} ":"
+                        {eol} {eol}
+                        {$ :title-line}
+                        {eol}
+                        {$ :line}
+                        {implode "" {ete {$ :bodylist}} }
+                    }
+                }}
+            }
+        }}
+
+        %Evaluate this now, so we get all the sections and stuff. Generate macro
+        % subst to assign it (evaluated) to :htmlBodyContent.
+        {$ :bodyContent {implode {ete {$ :contentList}}}}
+
+        {$ :tline {implode {gen i {range {strlen {ete {$ :pageTitle}}}} "="}}}
+
+        % FIXME: Add TOC
+        % FIXME: Add copyright notice? Add a new "comment" macro, and then add the copyright as a comment, in the bodyContent when
+        % invoking the reST macro.
+        {glue 
+            {eol} {$ :tline} {eol} {ete {$ :pageTitle}} {eol} {$ :tline} {eol} {eol}
+"
+.. contents:: Contents
+    :depth: 2
+"
+            {$ :bodyContent }
+
+            {section "Complete Contents" {'
+"
+.. contents::
+    :depth: 10
+"
+            }}
+
+        }
+
+        %end reST macro body.
+    }}
+
+}}}}

misc/tutorial.core.templ

+{#
+    Copyright 2013 Brian Mearns
+
+    This file is part of templ.
+
+    templ is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    templ is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with templ.  If not, see <http://www.gnu.org/licenses/>.
+}{
+}{v {:
+    {$ TEMPLATE-CODE {lambda
+        {' :TEMPLATE }
+        {pre {' :syntax templ} {$ :TEMPLATE }}
+    }}
+
+    {$ EXAMPLE-TEMPLATE {lambda
+        {' :SYNTAX :INTRO :OUTRO :TEMPLATE }
+        {implode <<<
+            {p {' {$ :INTRO}}}
+            {TEMPLATE-CODE {$ :TEMPLATE}}
+
+            {p {' {$ :OUTRO}}}
+            {pre
+                {' :syntax {$ :SYNTAX}}
+                {buffer {eval {$ :TEMPLATE}}}
+            }
+        >>> }
+    }}
+
+    {$ templ {macro {' code "templ" }}}
+
+}}{doc "templ - Basic Tutorial and Overview"
+
+%Body content
+{'
+
+    {section "Introduction" {'
+
+        {section "Overview" {'
+            {p 
+<<<{b templ} (pronounced just like "temple") is the {b Tem}plate {b P}rocessing {b L}anguage: it's used for processing template files
+in order to produce an output file. Template files are simply user supplied files that define how the output
+should be generated. Templates are usually just plain text, but binary content is also supported.>>>
+            }
+
+            {p 
+<<<In its simplest (and least useful) form, a template file simply contains the data that is desired for
+the output. However, what makes a a template file interesting, and what makes {templ} itself useful,
+is the use of embedded {templ} statements, which are evaluated by the {templ} processor in order
+to produce the output.>>>
+            }
+
+        }} % section "Overview"
+
+        {section "Template Files" {'
+
+            {p
+<<<At the top level, a {templ} template file consists of two types of elements: {em text} and {em statements}.
+Text is simply raw (more-or-less) content that will be written to the output stream. Statements are
+{templ} code that the processor will evaluate in order to determine the output, as well as its own
+behavior. What distinguishes a statement from text is that statements are wrapped in curly braces: "\{" and "\}".
+Anything that's not wrapped in curly braces is treated as text and is copied very-nearly verbatim to the
+output (more on all of these qualifications later).>>>
+            }
+
+        }} % end section "Template Files"
+
+        {section "Hello, Templ!" {'
+
+            {EXAMPLE-TEMPLATE "text"
+                {implode 
+<<<This wouldn't be much a programming tutorial without the classic "hello world" program. So let's see
+how it looks in {templ}. Open a plain text file, and enter the contents below. Save the file as "hello.templ":>>>
+                }
+
+                {implode
+<<<Now you need to invoke the {templ} processor in order to process this template file and produce the output. To do so
+simply execute this command from the directory where your "hello.templ" file is saved: {code "templ hello.templ"}. The
+output will be written to the console. It should look like this:>>>
+                }
+
+                "hello, templ!"
+            }
+
+            {p
+<<<I apologize if you were thoroughly bored by that example, but it serves to illustrate that there is no special format
+for template files: other than explicit {templ} statements, it's all just content for the output stream. So if all you do
+is write some text in a file without any curly braces, all templ will do is copy it to the output.>>>
+            }
+
+            {EXAMPLE-TEMPLATE "text"
+
+                {implode
+<<<But that is really boring, so let's do something just slightly more interesting. This time, we'll actually introduce a
+{templ} statement. Edit your "hello.templ" file to look like this:>>>
+                }
+
+                {implode
+<<<The statement we added is the stuff between the curly braces: {code "{echo templ}"}. The output is shown below: it looks the same. 
+That's because the {code echo} function simply tells {templ} to write the given string to the output stream.>>>
+                }
+
+                "hello, {echo templ}!"
+            }
+
+            {section "Get Used to Curly Braces" {'
+                {p
+<<<Ok, still pretty boring, but at least now we're actually writing {templ} code. There's a couple important things to notice in
+this example. For one thing, the format for invoking a function may not be what you're used to in most other languages. {templ}
+uses a syntax known as "S-expressions", similar to Lisp, in which the function to be invoked is the first element in a list whic
+also contains the arguments to be passed to the function. The syntax is semantically the same as the more familiar "M-expressions"
+in which the function is outside of the list of arguments, but the different way of writing it is important for allowing template
+files to be less structured than what you would normally see in source code.>>>
+                }
+            }}
+
+            {section "Basic Data Types - Strings and Lists." {'
+                {p
+<<<The other thing to notice from this example is that the string we passed to the {code echo} function isn't quoted in any way.
+{templ} has relatively few data types: for the most part you'll be using primarily {em Strings} and {em Lists}. That means you don't
+need anything special like quotes to differentiate a String: just write it out as part of an expression.>>>
+                }
+
+                {p
+<<<You've already seen a List: the expression {code "{echo templ}"} is a List. You write a List by simply wrapping a sequence of
+elements in curly braces. The elements can be Strings or nested Lists, and are separated by whitespace.>>>
+                }
+                
+                {section "Quoted Strings" {'
+                    {p
+<<<This poses a problem if you want to include whitespace in one of those Strings, so {templ} allows you to wrap your strings in
+double-quote characters, just like you're probably used to in other programming languages. Quoted Strings are only terminated by
+a closing double-quote character, so they can include whitespace (even vertical whitespace, like linebreaks). You also need to use
+a quoted String if you want to include a curly brace in a String, otherwise {templ} will think it's the beginning (or end) or a
+List.>>>
+                    }
+
+                    {p
+<<<If you want to include a double-quote character in a quoted String, you need to escape it with a leading backslash character: {wrap "\"" \}
+Without the backslash, the double-quote will just tell {templ} to terminate the quoting and will not be included in the String.
+Similarly, if you want to include a backslash in a quoted-string, you need to escape it with another leading backslash.>>>
+                    }
+
+                    {p
+<<<The Backslash and double-quote characters are the {em only} characters that have a special meaning when escaped in a quoted String.
+If any other character in a quoted String is prefixed with a backslash, the backslash is simply ignored, and the following character
+is treated normally. Put another way, a backslash character in a quoted String simply tells {templ} to include the subsequent
+character in the String, and ignore any special syntactic meaning it would otherwise have (which only double-quote and backslash
+characters have, anyway).>>>
+                    }
+
+                    {p
+<<<To be perfectly clear, {templ} quoted Strings {em do not have} the special escape sequences you might be used to from other programming
+languages, such as "\\n" for linebreaks, "\\t" for horizontal tab, etc. Since these characters have no special meaning in {templ} quoted Strings,
+you can just include them directly in your quoted String. Alternatively, there are built-in macros such as {code "{eol}"} and
+{code "{\\t}"} for all of the common escape sequences (specifically, those defined by the ISO C99 standard), as well as the built-in {code chr} function
+which returns a one-character String with character-value equal to a specified numeric value.>>>
+                    }
+
+                    {EXAMPLE-TEMPLATE "text"
+                        {implode
+<<<A final note about quoted Strings: a quoted String is not necessarily an isolated value, it can also be a portion of another String.
+In other words, you can tie together quoted and non-quoted Strings to your heart's content, as long as there's no spaces or curly braces
+in between them. For example:>>>
+                        }
+
+                        {implode
+<<<Lexically, there are four different elements here: the two quoted Strings {code "\"he\""} and {code "\" tem\""}, and
+the two {em unquoted} Strings {code "\"llo,\""} and {code "\"ple!\""}.
+Stringing together all of these different lexical elements results in just a single String value: the output is shown here:>>>
+                        }
+
+                        "{echo \"he\"llo,\" tem\"ple!}"
+
+                    }
+
+                }} % end section "Quoted Strings" 
+
+                % TODO: XXX: Lists. The nil function, the list function.
+
+            }} % end section - "Basic Data Types"
+
+        }} % end section "Hello, ..."
+
+        {section "The temple Processing Routine" {'
+
+            {p
+<<<As mentioned, a template file consists of text and expressions. In general, {templ} expressions can be
+Lists or Strings, but at the top level, only Lists are treated as expressions, everything else is treated as text.>>>
+            }
+
+            {p
+<<<When a top level List element is encountered by the {templ} processor, the entire List is parsed and then {em evaluated}. 
+Generally, Lists in a template file represent an {em executable} to be invoked (like the {code echo} function
+we saw above). The first element of the List specifies the executable to invoke, and the remaining elements are the arguments
+to pass. Like a lot of other programming languages, the arguments are generally each evaluated one at a time before invoking
+the executable and passing in the values that result from the evaluation. {em Unlike} a lot of programming languages, the
+elements of the List are evaluated in order from {em left to right}.
+This is important because the first element of the List, the one that specifies the executable to invoke, must also be 
+evaluated, and then {em resolved}. We'll learn more about what this means and why it matters later, but for now, just keep
+in mind that arguments are evaluated left to right.>>>
+            }
+
+            {p
+<<<When evaluating the elements of the List, Strings are {em self-evaluating}, meaning that when they are evaluated, the
+resulting value is simply the String value itself. Nested Lists (elements of a List which are themselves Lists), are
+evaluated just like top level Lists are: as describing an executable to invoke and the arguments to pass to it.>>>
+            }
+
+            {EXAMPLE-TEMPLATE "text"
+
+                {implode
+<<<The following template uses a nested List, and introduces another built-in function, {code glue}, which simply
+joins multiple String values together in the order given.>>>
+                }
+
+                {implode
+<<<The result is (suprise, surprise) the same thing as before.>>>
+                }
+
+"{echo {glue \"hello, \" \"templ!\"}}"
+
+            }
+
+            {p
+<<<To evaluate the top level List, the {code echo} String element
+is evaluated first. Strings are self evaluating, so this just results in the String value {code "\"echo\""}, which resolves
+to the {code echo} function we've seen before (don't worry about resolution right now).>>>
+            }
+
+            {p
+<<<The second element of the top level List is a nested list, so it needs to be evaluated next. This evaluates by invoking
+the {code glue} function to glue together the two given Strings. This entire list (the nested one) therefore evaluates to
+the String object {code "\"hello, templ!\""}.>>>
+            }
+
+            {p
+<<<So after evaluating the elements of the top list, we end up with an expression that invokes the {code echo} function with
+the argument {code "\"hello, templ!\""}, just like we had before.>>>
+            }
+
+            {EXAMPLE-TEMPLATE "text"
+
+                {implode
+<<<Of course, we can continue nesting Lists as deeply as we want to come up with some truly obnoxious code like this:>>>
+                }
+
+                {implode
+<<<It's probably worth mentioning at this point that all of that whitespace I added this time around is irrelvant: {templ}
+requires a whitespace character to separate adjacent String elements in a List, but you are free to add as much additional
+whitespace as you'd like, it makes no difference to {templ}. This is helpful for structuring your code in a way that is
+somewhat easier to follow. You can see in the output below that all that whitespace hasn't changed anything:>>>
+                }
+
+"{echo
+    {glue
+        {glue h e \"l\"l\"o\"}
+        ,
+        \" \"
+        {glue 
+            {glue 
+                te mp 
+                {glue l e}
+            }
+            !
+        }
+    }
+}"
+            }
+
+            {section "Code Formatting" {'
+                {p {'
+                    {implode <<<A few general suggestions on formating your code:>>>}
+                    {ul {'
+                        {implode                    
+    <<<Keep the first element of a list (the one that specifies the executable to be invoked)
+    on the same line as the opening curly brace, generally with no space separating it from the brace. This makes it much
+    more obvious what is being invoked.>>>
+                        }
+
+                        {implode
+    <<<Indent all subsequent elements of the list relative to the opening brace. This helps establish sematic scope for the reader.>>>
+                        }
+
+                        {implode
+    <<<Don't ever use tabs, use spaces. Tabstops may be set differently by different users and in different editors, so things that are
+    nicely aligned with tabs in one circumstance may look horrendous in another. The standard indentation level is 4 spaces. Three is
+    also acceptable but kind of weird. Two in somewhat common, and econimical, but is not as visually helpful as a larger indent. More
+    than 4 is excessive and will quickly lead to lines that don't have available width. If you want to use tabs because you can't handle
+    the extra couple of backspaces, either stop being lazy or get a better editor.>>>
+                        }
+
+                        {implode
+    <<<Put the closing brace on a new line, aligned in the same column as the opening brace. This make it obvious where
+    the List ends, and therefore what is included in it.>>>
+                        }
+
+                    }}
+                }}
+            }} % end section "Code Formatting"
+
+
+        {section "Output Values" {'
+
+            {p
+<<<Remember that {templ} is, first and foremost, a template processing language; its main goal in life is to
+process input and produce output. Therefore, when the {templ} processor finishes evaluating a top level
+expression, it assumes that the result of that expression is intended as output.>>>
+            }
+
+            {p
+<<<That's all fine and good when the resulting value is a String, {templ} will just write the String value to
+the output stream. But {templ} can't write a List or an executable to the output stream, so if a top level
+expression ever evaluates to something other than a String, {templ} will err.>>>
+            }
+
+            {p
+<<<The fact that top level String values are written directly to the output stream means a lot of our examples
+above which used the {code echo} function, didn't actually need to use it. If we were already invoking a
+function that results in a String, such as the {code glue} function, we could simply make that our top level
+expression and {templ} will output the resulting String to the output stream, just like the {code echo}
+function does.>>>
+            }
+
+            {EXAMPLE-TEMPLATE "text"
+
+                {implode
+<<<In the following template, we simply did away with the {code echo} function from our previous template, and
+left the call to the {code glue} function as the top level expression.>>>
+                }
+
+                {implode
+<<<You can see that the output is the same, because {templ} writes the result of calling the {code glue}
+function directly to the output stream.>>>
+                }
+
+"{glue
+    {glue h e \"l\"l\"o\"}
+    ,
+    \" \"
+    {glue 
+        {glue 
+            te mp 
+            {glue l e}
+        }
+        !
+    }
+}"
+            }
+
+            {p
+<<<You may be wondering why you would ever need to use the {code echo} function, if {templ} will just echo
+your top level Strings automatically. There are times where you will want to write to the output stream from
+somewhere other than the top level, for instance inside a loop. In times like this, the {code echo} function
+comes in very useful.>>>
+            }
+
+            {section "The str Function" {'
+                % TODO: Add examples, including Lists. Basic list functions are introduced in the Basic types
+                % section above.
+                {p
+<<<For convenience, {templ} does provide a builtin {code str} function, which is used to convert any value
+into a String. Simply pass in any value, and a String representation of that value will result.>>>
+                }
+
+            }} % end section "...str..."
+
+
+            {section "Null Values and the void Function" {'
+                {p
+<<<Actually, there's one other type besides Strings that {templ} can write directly to the output stream: the
+Null type. This is a special type which only has one value (called the Null value) which generally represents
+the absense of a value. If a top level expression evaluates to the Null value, the output for that expression
+is simply an empty string (or more accurately, there is no output).>>>
+                }
+
+                {p
+<<<Note, however, that this is only a special case for the top level processor. Otherwise, a Null value is {em
+not} the same thing as an empty string, they just happen to result in the same output at the top level.
+Specifically, passing a Null value to the {code str} function does {em not} result in any empty string, it
+results in the String value {code "\"NULL\""}.>>>
+                }
+
+                {p
+<<<To produce a Null value, you can use the {code void} function. the {code void} function can take up to 1
+argument, which {em is} evaluated  but the result of the {code void} expression is always a Null value. You
+can also invoke it without any arguments, in which case it simply results in a Null value.>>>
+                }
+
+                {p
+<<<The {code void} function is a useful way to supress the result of a top level expression. Actually it's no
+longer a top level expression because you're wrapping it up in a {code void} expression, but that's the whole
+point: the original expression is evaluated as desired, but the {code void} ensures that whatever
+type that expression results in, the top level output will be a nice safe Null value that won't err and won't
+effect your output.>>>
+                }
+
+                {p
+<<<A lot of {templ} functions have {em aliases}, which are just different symbols you can use to invoke them.
+The void function has a very nice alias, which is simply the single character {code v}. You are likely to see
+the function referenced with this alias a lot more often than with the gratuitous {code void} symbol.>>>
+                }
+
+                {EXAMPLE-TEMPLATE "text"
+
+                    {implode
+<<<The following very simple macro shows the {code void} function at work (using the common {code v}
+alias).>>>
+                    }
+
+                    {implode
+<<<And the output:>>>
+                    }
+
+"Null output: {v}
+A Null value, as a String: {str {v}}
+The void function, to supress output: Foo{v \"---\"}Bar"
+
+                }
+
+            }} % end section "...null...void..."
+
+
+        }} %end section "Output Values"
+
+        }} % end section "...Processing Routine"
+
+        {section "Comments" {'
+
+            {p
+<<<Sometimes, even the best formatting can't make the intentions of your code clear, and it helps to be able to explain yourself
+in prose. Most programming languages provide a syntax for comments, and {templ} is no exception. When the {templ} parser encounters
+a percent-sign character, "%", anywhere inside an expression except for in a quoted string, the subsequent characters up to and
+including the end of the current line is treated as a comment. The comment is ignored by the processor, as if the entire thing
+(including the initial "%" character) was just whitespace. One thing to note is that comments do function as {em separators}
+between String values, just like whitespace characters.>>>
+            }
+
+            {EXAMPLE-TEMPLATE "text"
+                {implode
+<<<You can put whatever you want in a comment: the processor won't attempt to evaluate it, and the parser won't try to parse it, 
+except to find the end of the line. That means you don't have to worry about it being well formed, and you can use comments
+to comment out mis-formed code during debugging.>>>
+                }
+
+                {}
+
+"If you're having trouble with malformed code, for instance if you've lost track of
+whether or not a string is properly escaped or not, {echo 
+    %\"like \\\"this\\\" one for instance, \\\"
+}you can comment it out for debugging."
+            }
+
+            {section "Block Comments - The \"Dont\" Operator" {'
+
+                {p
+<<<End-of-line comments are helpful for short comments and because the contents don't need to be well formed, but they're tedious
+if you want to write long comments across multiple lines. {templ} provides an operator called {code dont} which can be used for multi-line, or 
+{em block} comments. The argument elements in a {code dont} expression are {em not evaluated}, and the result of the entire expression
+is a special {code Null} value which we'll learn more about later. In other words, a {code dont} expression doesn't do anything, which
+makes it useful for long comments.>>>
+                }
+
+                {p
+<<<However, unlike end-of-line comments, the parser doesn't know about the {code dont} operator, so the entire expression must be wellformed.
+The contents of the expression don't need to be evaluatable, but they do need to be parseable. The upside is that {code dont} expressions can
+be nested without any issues, unlike block-comments in certain other programming languages.>>>
+                }
+
+                {p
+<<<For instance, the following template is {em malformed}: {templ} will err if you try to process this template, even though the malformed code
+is in a {code dont} expression.>>>
+                }
+
+                {TEMPLATE-CODE
+"{dont
+    Please don't evaluate {this code
+}"
+                }
+
+                {p
+<<<This next template, on the other hand, works fine, because we used an end-of-line comment to take care of that extra open curly brace.>>>
+                }
+
+                {TEMPLATE-CODE
+"{dont
+    % Please don't parse {this code
+}"
+                }
+
+                {p
+<<<Finally, here is an in-depth example of a {em working} block comment:>>>
+                }
+
+                {TEMPLATE-CODE
+"{dont
+    Block comments are good for long comments,
+    Because they can span multiple lines.
+    {
+        They need to be well-formed, but not necessarily valid code.
+    }
+    {dont
+        You can nest them as well, which is helpful for commenting out large
+        blocks of code, even if the block already includes comments.
+    }
+    % For malformed code, like if you have an extra } or {, for instance,
+    % you can also include end-of-line comments in block comments.
+}"
+                }
+
+                {p
+<<<As mentioned, {code dont} expressions evaluate to a Null type value. Despite being null, the result is still
+a value, and {em will} act as an element in an element in a List, so you have to be careful about where you place
+them. For instance, assuming the {code one-arg} executable only accepts one argument, the following template will
+err because the {code dont} expression looks like another argument:>>>
+                }
+
+                {TEMPLATE-CODE
+"{one-arg Foobar {dont ...Block Comment... }}"
+                }
+
+                {p
+<<<At the top level, Null typed values simply act as empty strings, so you can put {code dont} expressions
+at the top level of your template without any harm. We'll see other places it's safe to use them later when we learn about
+the {code block} operator.>>>
+                }
+
+            }} % end section "Block Comments"
+
+        }} %end section "Comments"
+
+        {section "About all Those Qualifications on Text Elements" {'
+
+            {p
+<<<So we mentioned that text elements at the top level of a template file are just a nice easy way to specify content to put
+in the output stream when there's no special processing that requires {templ} expressions. But we also kept qualifying them
+as "more-or-less [raw]" and "very-nearly verbatim".>>>
+            }
+
+            {p
+<<<Hopefully you're getting an idea now of why we needed to add all of these qualifications, small as they may be. There's
+one particular character that can't be used directly in text elements: the open curly brace. If you try to just stick an
+open curly brace in a text element, the {templ} parser will see it as the start of a List expression. So if you want to put
+an open curly brace in the text, you need to escape it with a leading backslash, just like you escape double-quote characters
+in quoted-strings.>>>
+            }
+
+            {p
+<<<But backslash escaping does not work in general in text elements: that would be too much of a burden when you're writing
+a text element if you have to escape every occurence of a backslash. Instead, a backslash in a text element only serves as
+an escape when it immediately precedes an open curly brace or, for symmetry, a closing curly brace. Note that it is not
+{em necessary} to escape closing curly braces, but it is recommended just for visual consistency with open curly braces.>>>
+            }
+
+            {EXAMPLE-TEMPLATE "text"
+                {implode
+<<<Otherwise, a backslash in a text element is simply a backslash: no need to escape it and it doesn't have any effect on
+non-curly brace subsequent characters. Take a look at this example which only contains a text element:>>>
+                }
+
+                {implode
+<<<The output is shown below. It looks a lot like the input template: the only difference is that the backslashes before the
+curly braces at the end of the template are not included in the output, because they were only used to escape the curly braces.>>>
+                }
+
+"Unix paths use (forward) slashes: \"/usr/bin/templ\". Windows uses backslashes: \"C:\\Windows\\\".
+templ uses a lot (a LOT) of curly braces, which look like \\{ and \\}."
+            }
+        }} % end section "All those Qualifications..."
+
+    }} %end section "Introduction"
+
+
+    {section "Variables" {'
+
+        {p
+<<<It wouldn't be much of a programming language without a way to store and recall data. {templ} uses a structure
+called {em the stack} to store what are effectively variables. Essentially, the stack acts like a dictionary
+which maps data to String values called {em symbols}. These symbols are the {templ} equivalent of
+variables.>>>
+        }
+
+        {p
+<<<Because the symbols which are used to map stored values in the stack are just ordinary String values, using
+them in a {templ} expression has no special effect: it still just evaluates to the String itself, not to the
+stored value. To get the stored value of a symbol from the stack, you can use the {code getset} function,
+passing in the symbol you want to lookup.
+>>>
+        }
+
+        {EXAMPLE-TEMPLATE "text"
+            {implode
+<<<As its name implies, the {code getset} function can also be used for setting the value of a symbol in the
+stack. To do so, simply pass in two arguments to the {code getset} function: the symbol, and then the value to
+store at that symbol. Both uses of {code getset} are shown in the following example template:>>>
+            }
+
+            {implode
+<<<On the first line of the template, {code getset} is used in its "setting" form, with two arguments. The
+symbol is first, "FOOBAR", and then the value, which is a self referential String. On the second line, it's
+used in its "getting" form with just one argument, the symbol to lookup. One thing to notice is that this
+template output the value twice. This is because the {code getset} function always results in the value of the
+specified symbol, even when setting it.>>>
+            }
+
+"{getset FOOBAR \"The value of \\\"FOOBAR\\\".\"}
+{getset FOOBAR}"
+
+        }
+
+    }}
+        
+}}{#
+
+
+ vim: set ft=templ tw=110:
+}

misc/tutorial.css

+pre
+{
+    background: none repeat scroll 0 0 #F7F7F7;
+    border: 1px solid #DDDDDD;
+    font-size: 12px;
+    padding: 9px 12px;
+    font-family: Monaco,"Courier New",monospace;
+}
+
+.contents p.topic-title
+{
+    font-size: 16pt;
+    font-weight: bold;
+}
+.contents ul
+{
+    padding-left: 15px;
+    list-style-type: disc;
+}
+

misc/tutorial.rest.templ

+{#
+    Copyright 2013 Brian Mearns
+
+    This file is part of templ.
+
+    templ is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    templ is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with templ.  If not, see <http://www.gnu.org/licenses/>.
+}{
+}{include rest.itmpl }{
+}{include tutorial.core.templ }{
+}{#
+ vim: set ft=templ tw=110:
+}

misc/txtdoc.itmpl

+{#
+    Copyright 2013 Brian Mearns
+
+    This file is part of templ.
+
+    templ is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    templ is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with templ.  If not, see <http://www.gnu.org/licenses/>.
+}{
+}{v {:
+
+{$ doc {macro
+    "Generates a plain text document."
+
+    {' :pageTitle :contentList }
+    
+    %We're building up an expression that will be evaluated.
+    % That expression will be a List, so we're building a list.
+    %First thing in the list is the tag. In this case, we start
+    % by defining a new scope to put our local functions in.
+    {poe {::
+
+        %Now define our Local Executables as elements of the list.
+        {set em {macro
+            "Generates emphasized text."
+            {' :text }
+            {poe {implode " " {ete {esc-list {$ :argv }}}} }
+        }}
+
+        {set code {macro
+            "Generates text formatted to look like an inline code snippet."
+            {' :text }
+            {poe {implode " " {ete {esc-list {$ :argv }}}} }
+        }}
+
+        {set b {macro
+            "Generates bold text."
+            {' :text }
+            {poe {implode " " {ete {esc-list {$ :argv }}}} }
+        }}
+
+        {set p {macro
+            {' :textList }
+            {poe {wrap {glue {eol}} {implode "" {ete {$ :textList }}} }}
+        }}
+
+        {set ul {macro
+            {' :list }
+            {poe
+                {glue {eol}
+                    {implode {eol}
+                        {gen
+                            :item {ete {$ :list }}
+                            {glue "- " {strrep {eol} " " {$ :item}}}
+                        }
+                    }
+                }
+            }
+        }}
+
+        {set pre {lambda
+            {::
+                {let :options :content :class}
+                {$ :options {nil}}
+                {$ :content ""}
+
+                {if
+                    {== 1 {len {$ :argv}}} {:
+                        {$ :content {@ 0 {$ :argv}}}
+                    }
+
+                    {== 2 {len {$ :argv}}} {:
+                        {$ :options {@ 0 {$ :argv}}}
+                        {$ :content {@ 1 {$ :argv}}}
+
+                        %Check and parse options.
+                        {if                         
+                            {not {is-list {$ :options}}}
+                            {error "Invalid options, expected a list."}
+                        }
+                    }
+
+                    %else
+                    {error {glue "Incorrect number of arguments to pre: expected one or two, not " {len {$ :argv}}}}
+                }
+
+                {if
+                    {not {is-str {$ :content}}}
+                    {error {glue "Invalid content, expected a String, not a " {type {$ :content}}}}
+                }
+
+
+                {glue {strrep {eol} {glue {eol} "    "} {$ :content}}}
+            }
+        }}
+
+        {set link {macro
+            {if 
+                {== 1 {len {$ :argv}}} {poe {::
+                    {$ :href {ete {@ 0 {$ :argv}}}}
+                    {glue "<" {$ :href} ">" }
+                }}
+
+                {== 2 {len {$ :argv}}} {poe {::
+                    {$ :text {ete {@ 0 {$ :argv}}}}
+                    {$ :href {ete {@ 1 {$ :argv}}}}
+                    {glue {$ :text} "(<" {$ :href} ">)" }
+                }}
+
+                {error
+                    "Incorrect number of arguments for link. Expected exactly 1 or 2."
+                }
+            }
+        }}
+
+        {$ :rest-depth 0}
+        {$ :rest-section-number {' 0 }}
+        {$ :rest-sections {' }}
+
+        {set section {macro
+            {' :title :bodylist}
+            {:
+                %Increment the section number
+                {$ :rest-section-number
+                    {append 
+                        {+ 1 {@ -1 {$ :rest-section-number }}}
+                        {slice 0 -1 {$ :rest-section-number }}
+                    }
+                }
+
+                {$ :rest-sections {append {' {$ :rest-section-number} {$ :title}} {$ :rest-sections} }}
+
+                {$ :new-rest-section-number
+                    {append 0 {$ :rest-section-number }}
+                }
+
+                %The macro-subst.
+                {poe {::
+                    % Now copy the rest values into this new scope, and adjust appropriately.
+                    {let :rest-depth :rest-section-number }
+                    {$ :rest-depth {ete {+ 1 {$ :rest-depth}}}}
+                    {$ :rest-section-number {ete {insert ' {$ :new-rest-section-number }}}}
+
+                    {let :title-line}
+                    {$ :title-line {glue {ete {implode "." {$ :rest-section-number}}} ": " {ete {$ :title}}}}
+
+                    %FIXME: Check the depth.
+                    {let :line-char :line }
+                    {$ :line {implode {gen i {range {strlen {$ :title-line}}} "-"}}}
+
+
+                    {glue
+                        {eol} {eol}
+                        {$ :title-line}
+                        {eol}
+                        {$ :line}
+                        {implode "" {ete {$ :bodylist}} }
+                    }
+                }}
+            }
+        }}
+
+        %Evaluate this now, so we get all the sections and stuff. Generate macro
+        % subst to assign it (evaluated) to :htmlBodyContent.
+        {$ :bodyContent {implode {ete {$ :contentList}}}}
+
+        {$ :tline {implode {gen i {range {strlen {ete {$ :pageTitle}}}} "="}}}
+
+        % FIXME: Add TOC
+        % FIXME: Add copyright notice? Add a new "comment" macro, and then add the copyright as a comment, in the bodyContent when
+        % invoking the reST macro.
+        {glue 
+            {eol} {ete {$ :pageTitle}} {eol} {$ :tline} {eol} {eol}
+
+            {$ :bodyContent }
+
+            {eol}
+        }
+
+        %end reST macro body.
+    }}
+
+}}}}
 
 globs = texec.getGlobalScope()
 
-os.chdir("templ")
+os.chdir("misc")
 readmePath = "README.txt.templ"
 istream = open(readmePath, "r")
 ostream = cStringIO.StringIO()
 otstream.close()
 os.chdir("..")
 
+lid = open("LICENSE.txt", "r")
+license = lid.read()
+lid.close()
 
 setup(
     name='templ',
     author_email='bmearns@ieee.org',
     packages=['templ',],
     url='https://bitbucket.org/bmearns/templ/',
-    license='LICENSE.txt',
+    license=license,
     description='Template Processing Language.',
     long_description=readme,
     entry_points = {
         "console_scripts" : [
             'templ = templ.templ:main',
         ],
-    }
+    },
+    data_files = [
+        ('misc', ['LICENSE.txt', 'README.txt', 'BUGS.txt', 'CHANGES.txt']),
+    ],
 )
 

templ/README.core.templ

-{#
-    Copyright 2013 Brian Mearns
-
-    This file is part of templ.
-
-    templ is free software: you can redistribute it and/or modify
-    it under the terms of the GNU Affero General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    templ is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU Affero General Public License for more details.
-
-    You should have received a copy of the GNU Affero General Public License
-    along with templ.  If not, see <http://www.gnu.org/licenses/>.
-}{
-}{v
-    {$ EXAMPLE-TEMPLATE {lambda
-        {' :SYNTAX :INTRO :OUTRO :TEMPLATE }
-        {implode <<<
-            {p {' {$ :INTRO}}}
-            {pre
-                {' :syntax templ}
-                {$ :TEMPLATE}
-            }
-
-            {p {' {$ :OUTRO}}}
-            {pre
-                {' :syntax {$ :SYNTAX}}
-                {buffer {eval {$ :TEMPLATE}}}
-            }
-        >>> }
-    }}
-}{doc "templ - Template Processing Language"
-
-%Body content
-{'
-
-    {section "Introduction" {'
-
-        {p 
-<<<{b templ} is the {b Tem}plate {b P}rocessing {b L}anguage. >>>
-        }
-        
-        {p
-<<<{code templ} is a (Turing complete) programming language, used for content generation
-from text-based template files and a simple but powerful processing language
-({code templ} itself) which is embedded directly in the template file. >>>
-        }
-        
-        {p <<<{code templ} can be used for: {ul {'
-    "Code generation."
-    "Form letters."
-    "Server-side scripting for web servers."
-    "Customized markup with variant output formats."
-    "Any other kind of dynamic text-based content generation."
-            }}>>>     
-        }
-
-
-        {section "Contact Information" {'
-
-            {p <<<This project is currently hosted on {link bitbucket "https://bitbucket.org"}, 
-at {link "https://bitbucket.org/bmearns/templ/"}. The primary author is Brian Mearns:
-you can contact Brian through bitbucket at {link "https://bitbucket.org/bmearns"}. >>>
-            }
-
-        }}
-
-        {section "Copyright and License" {'
-
-            {p <<<{code templ} is {em "free software"}: you can redistribute it and/or modify
-it under the terms of the {b GNU Affero General Public License} as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version. >>> }
-
-            {p <<<{code templ} is distributed in the hope that it will be useful,
-but {b without any warranty}; without even the implied warranty of
-{em merchantability} or {em fitness for a particular purpose}.  See the
-GNU Affero General Public License for more details. >>> }
-
-            {p <<<A copy of the GNU Affero General Public License is available in the templ
-distribution under the file LICENSE.txt. If you did not receive a copy of
-this file, see {link "http://www.gnu.org/licenses/"}. >>> }
-        }}
-
-
-
-    }} %end section intro
-
-    {section "Examples" {'
-
-        {p
-    <<<The following show some simple example templates and they're output, to give
-an idea of what can be done with templ.>>>
-        }
-
-
-        {section "Templ Basics"
-            <<< {EXAMPLE-TEMPLATE
-                "text"
-                {implode <<<The following template shows some of the basic elements of {code templ} templates:>>>}
-                "The output looks like this:"
-"Hello, World!
-My Name is {set :NAME \"templ\"}. I am the TEMplate Processing Language.
-Sometimes, {$ :NAME} likes to speak in the third person.
-
-{$ :NAME} can do math:
-    1 + 1 = {+ 1 1}
-    1 + 2 = {+ 1 2}
-    2 + 3 = {+ 2 3}
-    3 + 5 = {+ 3 5}
-    etc...
-
-{$ :NAME} can operate on strings and lists:
-    {implode \"a\" {' b n n s}}
-    {str {cat {' a b c } {' d e f } }}
-
-{$ :NAME} can do conditional processing:
-    {if
-        {== {+ 2 2} 5}
-        \"Oh No!\"
-
-        {== {+ 2 2} 4}
-        \"Phew!\"
-
-        \"How did I get here?\"
-    }
-
-{$ :NAME} can loop (and do trig):
-{for :THETA {range 0 40 10} {
-    echo \"    sin(\" {$ :THETA} \") = \" {sin {rad {$ :THETA}}} {eol}}
-}
-
-{$ :NAME} can even do list comprehensions and user defined functions:
-{v {set
-    :MY-FUNC
-    {lambda
-        {' :THETA }
-        {:
-            {let :RADS}
-            {$ :RADS {rad {$ :THETA}}}
-
-            {echo \"Processing theta=\" {$ :THETA} \"...\" {eol}}
-
-            %return value
-            {+ {cos {$ :RADS}} {sin {$ :RADS}} }
-        }
-    }
-}}{wrap \"{\" \"}\" {implode {glue \",\" {eol} \"    \"} {gen
-    :T
-    {range 40 80 10}
-    {join \":\" {$ :T} {:MY-FUNC {$ :T}}}
-}}}
-"
-        }
-        
->>> } % end section "Basics"
-
-        {section "Code Generation - A Sine Lookup Table"
-            <<< {EXAMPLE-TEMPLATE
-                c
-                {implode
-<<<The following template shows an example of how to use {code templ}
-to generate C-code, in this case a sine lookup table.>>>
-                }
-                "The output looks like this:"
-"{v
-    {set :SIZE 10}
-}const double sine_lut[{get :SIZE}] =
-\\{
-{for i {range {get :SIZE}} {::
-    {let :THETA}
-    {$ :THETA {mult
-        {$ i}
-        {div 360 {$ :SIZE}}
-    }}
-    {spit {'
-        \"    \"
-        {round 
-            {sin {rad {$ :THETA}}}
-            4
-        }
-        ,
-        {\\t}
-        \"// i = \"
-        {get i}
-        \", theta = \"
-        {$ :THETA}
-        \" deg\"
-        {eol}
-    }}
-}}\\};
-" }
-
->>> } % end section "Code Generation..."
-
-
-        {section "Embedded Data"
-            <<< {EXAMPLE-TEMPLATE
-                c
-                {implode
-<<<The next example shows how {code templ} allows you to easily embed data
-directly in the template file that uses it, allowing you to keep just
-one file under version control, for instance. >>>
-                }
-                "It produces this:"
-                "
-{v
-    %Embedded data
-    {$ :DATA {'
-        %   Name            Year    Month (-1)      Date
-        {'  \"Alan T.\"     1912    05              23 }
-        {'  \"John V.\"     1903    11              28 }
-        {'  \"Claude S.\"   1916    03              30 }
-        {'  \"George B.\"   1815    10              2  }
-        {'  \"George B.\"   1815    10              2  }
-        {'  \"Ada L.\"      1815    11              15 }
-        {'  \"Charles B.\"  1791    11              26 }
-        {'  \"Donald K.\"   1938    0               10 }
-        {'  \"Dennis R.\"   1941    8               9  }
-    }}
-}{for :ROW {$ :DATA} {:
-    {$ :STAMP {stamp {slice 1 {$ :ROW}}}}
-    {$ :NOW {stamp}}
-    {$ :AGE {floor {div {- {$ :NOW} {$ :STAMP}} {* 60 60 24 365.25}}}}
-    {echo {@ 0 {$ :ROW}} \", age \" {$ :AGE} \" years.\" {eol} }
-}}"
-    }
-    
->>> } % end section "Embedded Data"
-
-
-        {section "Programmatic Invocation"
-            <<<{p 
-<<<The real power of {code templ} comes from the programmatic interface,
-which allows you to predefine symbols, and even executables (functions, macros
-and operators) in python, which are then accessible from the template.
-Because, although {code templ} {em is} Turing complete, and you {em could} do all
-of your processing directly in the template (or a separate included template), doing
-advanced data processing in python can help keep your template files simpler. >>>
-            }>>>}
-
-    }} %end section Examples
-
-}}{#
- vim: set ft=templ:
-}

templ/README.rest.templ

-{#
-    Copyright 2013 Brian Mearns
-
-    This file is part of templ.
-
-    templ is free software: you can redistribute it and/or modify
-    it under the terms of the GNU Affero General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    templ is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU Affero General Public License for more details.
-
-    You should have received a copy of the GNU Affero General Public License
-    along with templ.  If not, see <http://www.gnu.org/licenses/>.
-}{
-}{include rest.itmpl }{
-}{include README.core.templ }{
-}{#
- vim: set ft=templ:
-}

templ/README.txt.templ

-{#
-    Copyright 2013 Brian Mearns
-
-    This file is part of templ.
-
-    templ is free software: you can redistribute it and/or modify
-    it under the terms of the GNU Affero General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    templ is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU Affero General Public License for more details.
-
-    You should have received a copy of the GNU Affero General Public License
-    along with templ.  If not, see <http://www.gnu.org/licenses/>.
-}{
-}{include txtdoc.itmpl }{
-}{include README.core.templ }{
-}{#
- vim: set ft=templ:
-}

templ/demo.templ

-{v 
-    {$ NAME templ}
-}Welcome to the {$ NAME} demo template!
-
-{$ NAME} is the TEMplate Processing Language, used for content generation
-from text-based template files and a simple but powerful processing language
-({$ NAME} itself). {$ NAME} can be used for:
-{v {for EXAMPLE {'
-        "Code generation."
-        "Form letters."
-        "Server-side scripting for web servers."
-        "Customized markup with variant output formats."
-        "Any other kind of dynamic text-based content generation."
-    }
-    {:
-        {echo "    * "}
-        {echo {$ EXAMPLE}}
-        {echo "
-"}
-    }
-}}
-The {$ NAME} language is just a simple text-based language, but it is Turing
-Complete and comes equipped with a number of useful functions. You could,
-theoretically, use it as a general scripting language, though it really is
-best suited for it's natural purpose, processing templates.
-
-Still, it's very powerful for this. For instance, you could easily generate a
-sine lookup table for C:
-
-/**********************************************/
-{v {set SIZE 10}
-}const double sine_lut[{get SIZE}] =
-\{
-{for i {range {get SIZE}} {:
-    {echo {glue
-        "    "
-        {round 
-            {sin {div
-                {mult {get i} 2 {pi}}
-                {get SIZE}
-            }}
-            4
-        }
-        , {tab} "// i = " {get i}
-        {lnbrk}
-    }}
-}}
-\};
-/**********************************************/
-
-One of the nice things about {$ NAME} is that you can embed data directly into
-your template file so that you only need to keep one file under version
-control:
-
-###############################################
-{v {set YEAR 2012}
-}{v
-{set DATA {'
-    %   Name            Month       Year        Score
-    {'  "Alan T."       June        1912        61  }
-    {'  "John B."       December    1924        53  }
-    {'  "John von N."   December    1903        47  }
-    {'  "Claude S."      April       1916        59  }
-}}
-}{
-   for ROW {get DATA}
-   {spit
-<<<User "{at 0 {get ROW}}" (age {
-    sub {get YEAR} {at 2 {get ROW}}