Anonymous avatar Anonymous committed 9b93e96

Working on cleaning up some of the demo templates, and the setup.py file.

Comments (0)

Files changed (14)

 build
 dist
 
+templ.egg-info
-from distutils.core import setup
+from setuptools import setup
+import sys
+
+sys.path.append("templ")
+import templ.version as version
 
 setup(
     name='templ',
-    version='0.0.0-dev',
+    version=version.setuptools_str(),
     author='Brian Mearns',
+    author_email='bmearns@ieee.org',
     packages=['templ',],
     url='https://bitbucket.org/bmearns/templ/',
     license='LICENSE.txt',
     description='Template Processing Language.',
     long_description=open('README.txt').read(),
+    entry_points = {
+        "console_scripts" : [
+            'templ = templ.TemplCore:main',
+        ],
+    }
 )
 

templ/README.core.templ

+{#
+    Copyright 2012 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 2012 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.templ

-{#
-    Copyright 2012 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}{
-}{v
-    {$ EXAMPLE-TEMPLATE {lambda
-        {' :SYNTAX :INTRO :OUTRO :TEMPLATE }
-        {implode <<<
-            {p {' {$ :INTRO}}}
-            {pre
-                {' :syntax templ}
-                {$ :TEMPLATE}
-            }
-
-            {p {' {$ :OUTRO}}}
-            {pre
-                {' :syntax {$ :SYNTAX}}
-                {buffer {eval {$ :TEMPLATE}}}
-            }
-        >>> }
-    }}
-}{reST "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}}} {\\n}}
-}
-
-{$ :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} \"...\" {\\n}}
-
-            %return value
-            {+ {cos {$ :RADS}} {sin {$ :RADS}} }
-        }
-    }
-}}{wrap \"{\" \"}\" {implode {glue \",\" {\\n} \"    \"} {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\"
-        {lnbrk}
-    }}
-}}\\};
-" }
-
->>> } % 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.\" {\\n} }
-}}"
-    }
-    
->>> } % 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.txt.templ

+{#
+    Copyright 2012 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 {:
 
-{$ reST {macro
+{$ doc {macro
     "Wraps content in reStructured text"
 
     {' :pageTitle :contentList }
 
         {set p {macro
             {' :textList }
-            {poe {wrap {glue {\n} {\n}} {implode "" {ete {$ :textList }}} }}
+            {poe {wrap {glue {eol} {eol}} {implode "" {ete {$ :textList }}} }}
         }}
 
         {set ul {macro
             {' :list }
             {poe
-                {glue {\n} {\n}
-                    {implode {\n}
+                {glue {eol} {eol}
+                    {implode {eol}
                         {gen
                             :item {ete {$ :list }}
-                            {glue "- " {strrep {\n} " " {$ :item}}}
+                            {glue "- " {strrep {eol} " " {$ :item}}}
                         }
                     }
                 }
                 }
 
 
-                {glue {\n} {\n} "::" {\n} {\n} "    " {strrep {\n} {glue {\n} "    "} {$ :content}}}
+                {glue {eol} {eol} "::" {eol} {eol} "    " {strrep {eol} {glue {eol} "    "} {$ :content}}}
             }
         }}
 
 
 
                     {glue
-                        {\n} {\n}
+                        {eol} {eol}
                         ".. _Section-" {ete {implode "." {$ :rest-section-number}}} ":"
-                        {\n} {\n}
+                        {eol} {eol}
                         {$ :title-line}
-                        {\n}
+                        {eol}
                         {$ :line}
                         {implode "" {ete {$ :bodylist}} }
                     }
         % 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 
-            {\n} {$ :tline} {\n} {ete {$ :pageTitle}} {\n} {$ :tline} {\n} {\n}
+            {eol} {$ :tline} {eol} {ete {$ :pageTitle}} {eol} {$ :tline} {eol} {eol}
 "
 .. contents:: Contents
     :depth: 2
 import os
 import filepos as tFilepos
 
+#Needed for main
+import tbuiltin
+import sys
+import errno
+import version
+
+
 TOKEN_EOI = 0
 TOKEN_SPACE = 1
 TOKEN_OCUR = 2
 
 
 
-if __name__ == "__main__":
+def printVersion(ostream):
+    ostream.write("templ v{version} - {datestr}\n\n".format(version=version.string(), datestr=version.datestr()))
 
-    import tbuiltin
-    import sys
-    import errno
-    import version
-
-    def printVersion(ostream):
-        ostream.write("templ v{version} - {datestr}\n\n".format(version=version.string(), datestr=version.datestr()))
-
-    def printUsage(ostream):
-        ostream.write(
+def printUsage(ostream, argv=sys.argv):
+    ostream.write(
 """Usage: {PROG} [options] [TEMPLATE_FILE [OUTFILE]]
    or: {PROG} [options] - [OUTFILE]
 
-""".format(PROG=sys.argv[0]))
+""".format(PROG=argv[0]))
 
 
-    def printHelp(ostream):
-        printVersion(ostream)
-        printUsage(ostream)
-        ostream.write(
+def printHelp(ostream, argv=sys.argv):
+    printVersion(ostream)
+    printUsage(ostream, argv)
+    ostream.write(
 """Processes TEMPLATE_FILE through the templ processor, writing the output to
 OUTFILE. In the second usage, the use of "-" as the TEMPLATE_FILE indicates
 that the template should be read from STDIN. This is also the default if
 
 
 Copyright {COPYRIGHT} Brian Mearns. Program licensed under GNU AGPLv3.
+
 For more information about this product see:
             <https://bitbucket.org/bmearns/templ/>.
 """.format(COPYRIGHT=version.COPYRIGHT)
-        )
-        sys.exit(errno.EINVAL)
+    )
 
 
+def main():
 
     templates = []
     infile = None
         arg = sys.argv[i]
         i += 1
         if arg in ("-h", "-?", "/?", "--help"):
-            printHelp(sys.stdout)
-            sys.exit(0)
+            printHelp(sys.stdout, sys.argv)
+            return (0)
 
         elif arg in ("-V", "--version"):
             printVersion(sys.stdout)
-            sys.exit(0)
+            return (0)
 
         elif arg in ("--usage", ):
-            printUsage(sys.stdout)
-            sys.exit(0)
+            printUsage(sys.stdout, sys.argv)
+            return (0)
 
         elif arg in ("--debug", ):
             debug = True
             if i == argc:
                 sys.stderr.write("%s: Error: Missing required parameter for option %d.\n" % (sys.argv[0], arg))
                 sys.stderr.write("%s: Try `%s --help`\n" % (sys.argv[0], sys.argv[0]))
-                sys.exit(errno.EINVAL)
+                return (errno.EINVAL)
             else:
                 name = sys.argv[i]
                 i += 1
             else:
                 sys.stderr.write("%s: Error: Unexpected argument \"%s\".\n" % (sys.argv[0], arg))
                 sys.stderr.write("%s: Try `%s --help`\n" % (sys.argv[0], sys.argv[0]))
-                sys.exit(errno.EINVAL)
+                return (errno.EINVAL)
                 
 
     istream = None
             except Exception: pass
 
             sys.stderr.write(str(e) + "\n")
-            sys.exit(-1)
+            return (-1)
 
         try: istream.close()
         except Exception: pass
             except Exception: pass
 
         sys.stderr.write("An IO Error occurred: %s\n" % str(e))
-        sys.exit(errno.EIO)
+        return (errno.EIO)
 
+if __name__ == "__main__":
+    ec = main()
+    sys.exit(ec)
 
-{str {' foo bar}}
+{
+}
+
+{
+}

templ/tutorial.core.templ

+{#
+    Copyright 2012 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:
+}

templ/tutorial.rest.templ

+{#
+    Copyright 2012 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:
+}

templ/tutorial.templ

-{#
-    Copyright 2012 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}{
-}{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" }}}
-
-}}{reST "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 "{\\n}"} 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:
-}
-

templ/txtdoc.itmpl

+{#
+    Copyright 2012 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