summaryrefslogtreecommitdiff
path: root/docs/users_guide_2_src/05_language.txt
diff options
context:
space:
mode:
authorR. Tyler Ballance <tyler@monkeypox.org>2009-11-16 21:09:13 -0800
committerR. Tyler Ballance <tyler@monkeypox.org>2009-11-16 21:09:13 -0800
commitd9ce7916e309e2393d824e249f512d2629e5e181 (patch)
tree6b7ad5cd6292f6e017e048fbeb4551facbabd174 /docs/users_guide_2_src/05_language.txt
parente43765a679b84c52df875e9629d303e304af50a1 (diff)
downloadpython-cheetah-docs.tar.gz
Revert "Delete the "old" docs directory to make way for fancy smancy sphinx"docs
This reverts commit 5dc95cfcd015628665d3672e56d0551943b5db6b.
Diffstat (limited to 'docs/users_guide_2_src/05_language.txt')
-rwxr-xr-xdocs/users_guide_2_src/05_language.txt651
1 files changed, 651 insertions, 0 deletions
diff --git a/docs/users_guide_2_src/05_language.txt b/docs/users_guide_2_src/05_language.txt
new file mode 100755
index 0000000..673abca
--- /dev/null
+++ b/docs/users_guide_2_src/05_language.txt
@@ -0,0 +1,651 @@
+\section{Language Overview}
+\label{language}
+
+Cheetah's basic syntax was inspired by the Java-based template engines Velocity
+and WebMacro. It has two types of tags: {\bf \$placeholders} and {\bf
+\#directives}. Both types are case-sensitive.
+
+Placeholder tags begin with a dollar sign (\code{\$varName}) and are similar to
+data fields in a form letter or to the \code{\%(key)s} fields on the left side
+of Python's \code{\%} operator. When the template is filled, the placeholders
+are replaced with the values they refer to.
+
+Directive tags begin with a hash character (\#) and are used for comments,
+loops, conditional blocks, includes, and all other advanced features.
+({\em Note:} you can customize the start and end delimeters for placeholder
+and directive tags, but in this Guide we'll assume you're using the default.)
+
+Placeholders and directives can be escaped by putting a backslash before them.
+\verb+\$var+ and \verb+\#if+ will be output as literal text.
+
+A placeholder or directive can span multiple physical lines, following the same
+rules as Python source code: put a backslash (\verb+\+) at the end of all
+lines except the last line. However, if there's an unclosed parenthesis,
+bracket or brace pending, you don't need the backslash.
+
+\begin{verbatim}
+#if $this_is_a_very_long_line and $has_lots_of_conditions \
+ and $more_conditions:
+<H1>bla</H1>
+#end if
+
+#if $country in ('Argentina', 'Uruguay', 'Peru', 'Colombia',
+ 'Costa Rica', 'Venezuela', 'Mexico')
+<H1>Hola, senorita!</H1>
+#else
+<H1>Hey, baby!</H1>
+#end if
+\end{verbatim}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Language Constructs -- Summary}
+\label{language.constructs}
+
+\begin{enumerate}
+\item Comments and documentation strings
+ \begin{enumerate}
+ \item \code{\#\# single line}
+ \item \code{\#* multi line *\#}
+ \end{enumerate}
+
+\item Generation, caching and filtering of output
+ \begin{enumerate}
+ \item plain text
+ \item look up a value: \code{\$placeholder}
+ \item evaluate an expression: \code{\#echo} \ldots
+ \item same but discard the output: \code{\#silent} \ldots
+ \item one-line if: \code{\#if EXPR then EXPR else EXPR}
+ \item gobble the EOL: \code{\#slurp}
+ \item parsed file includes: \code{\#include} \ldots
+ \item raw file includes: \code{\#include raw} \ldots
+ \item verbatim output of Cheetah code: \code{\#raw} \ldots \code{\#end raw}
+ \item cached placeholders: \code{\$*var}, \code{\$*<interval>*var}
+ \item cached regions: \code{\#cache} \ldots \code{\#end cache}
+ \item set the output filter: \code{\#filter} \ldots
+ \item control output indentation: \code{\#indent} \ldots ({\em not
+implemented yet})
+ \end{enumerate}
+
+\item Importing Python modules and objects: \code{\#import} \ldots,
+ \code{\#from} \ldots
+
+\item Inheritance
+ \begin{enumerate}
+ \item set the base class to inherit from: \code{\#extends}
+ \item set the name of the main method to implement: \code{\#implements}
+\ldots
+ \end{enumerate}
+
+\item Compile-time declaration
+ \begin{enumerate}
+ \item define class attributes: \code{\#attr} \ldots
+ \item define class methods: \code{\#def} \ldots \code{\#end def}
+ \item \code{\#block} \ldots \code{\#end block} provides a simplified
+ interface to \code{\#def} \ldots \code{\#end def}
+ \end{enumerate}
+
+\item Run-time assignment
+ \begin{enumerate}
+ \item local vars: \code{\#set} \ldots
+ \item global vars: \code{\#set global} \ldots
+ \item deleting local vars: \code{\#del} \ldots
+ \end{enumerate}
+
+\item Flow control
+ \begin{enumerate}
+ \item \code{\#if} \ldots \code{\#else} \ldots \code{\#else if} (aka
+ \code{\#elif}) \ldots \code{\#end if}
+ \item \code{\#unless} \ldots \code{\#end unless}
+ \item \code{\#for} \ldots \code{\#end for}
+ \item \code{\#repeat} \ldots \code{\#end repeat}
+ \item \code{\#while} \ldots \code{\#end while}
+ \item \code{\#break}
+ \item \code{\#continue}
+ \item \code{\#pass}
+ \item \code{\#stop}
+ \end{enumerate}
+
+\item error/exception handling
+ \begin{enumerate}
+ \item \code{\#assert}
+ \item \code{\#raise}
+ \item \code{\#try} \ldots \code{\#except} \ldots \code{\#else} \ldots
+ \code{\#end try}
+ \item \code{\#try} \ldots \code{\#finally} \ldots \code{\#end try}
+ \item \code{\#errorCatcher} \ldots set a handler for exceptions raised by
+\$placeholder calls.
+ \end{enumerate}
+
+\item Instructions to the parser/compiler
+ \begin{enumerate}
+ \item \code{\#breakpoint}
+ \item \code{\#compiler-settings} \ldots \code{\#end compiler-settings}
+ \end{enumerate}
+
+\item Escape to pure Python code
+ \begin{enumerate}
+ \item evalute expression and print the output: \code{<\%=} \ldots
+ \code{\%>}
+ \item execute code and discard output: \code{<\%} \ldots \code{\%>}
+ \end{enumerate}
+
+\item Fine control over Cheetah-generated Python modules
+ \begin{enumerate}
+ \item set the source code encoding of compiled template modules: \code{\#encoding}
+ \item set the sh-bang line of compiled template modules: \code{\#shBang}
+ \end{enumerate}
+
+\end{enumerate}
+
+The use of all these constructs will be covered in the next several chapters.
+
+%% @@MO: TODO: reconcile the order of this summary with the order in the
+%% detail sections.
+
+% @@MO: PSP chapter with examples. What does write() do? Print?
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Placeholder Syntax Rules}
+\label{language.placeholders.syntax}
+
+\begin{itemize}
+
+\item Placeholders follow the same syntax rules as Python variables except
+ that they are preceded by \code{\$} (the short form) or enclosed in
+ \code{\$\{\}} (the long form).
+ Examples:
+\begin{verbatim}
+$var
+${var}
+$var2.abc['def']('gh', $subplaceholder, 2)
+${var2.abc['def']('gh', $subplaceholder, 2)}
+\end{verbatim}
+ We recommend \code{\$} in simple cases, and \code{\$\{\}} when followed
+ directly by a letter or when Cheetah or a human template maintainer might
+ get confused about where the placeholder ends. You may alternately use
+ \verb+$()+ or \verb+$[]+, although this may confuse the (human) template
+ maintainer:
+\begin{verbatim}
+$(var)
+$[var]
+$(var2.abc['def']('gh', $subplaceholder, 2))
+$[var2.abc['def']('gh', $subplaceholder, 2)]
+\end{verbatim}
+ {\em Note:} Advanced users can change the delimiters to anything they
+ want via the \code{\#compiler} directive.
+
+ {\em Note 2:} The long form can be used only with top-level placeholders,
+ not in expressions. See section \ref{language.placeholders.positions}
+ for an elaboration on this.
+
+\item To reiterate Python's rules, placeholders consist of one or more
+ identifiers separated by periods. Each identifier must start with a letter
+ or an underscore, and the subsequent characters must be letters, digits or
+ underscores. Any identifier may be followed by arguments enclosed in
+ \verb+()+ and/or keys/subscripts in \verb+[]+.
+
+\item Identifiers are case sensitive. \code{\$var} does not equal \code{\$Var}
+ or \code{\$vAr} or \code{\$VAR}.
+
+\item Arguments inside \verb+()+ or \verb+[]+ are just like in Python.
+ Strings may be quoted using any Python quoting style. Each argument is an
+ expression and may use any of Python's expression operators. Variables
+ used in argument expressions are placeholders and should be prefixed with
+ \code{\$}. This also applies to the *arg and **kw forms. However, you do
+ {\em not} need the \code{\$} with the special Python constants \code{None},
+ \code{True} and \code{False}.
+ Examples:
+\begin{verbatim}
+$hex($myVar)
+$func($arg=1234)
+$func2($*args, $**kw)
+$func3(3.14159, $arg2, None, True)
+$myList[$mySubscript]
+\end{verbatim}
+
+\item Trailing periods are ignored. Cheetah will recognize that the placeholder
+ name in \code{\$varName.} is \code{varName}, and the period will be left
+ alone in the template output.
+
+\item The syntax \code{\$\{placeholderName, arg1="val1"\}} passes arguments to
+ the output filter (see \code{\#filter}, section \ref{output.filter}.
+ The braces and comma are required in this case. It's conventional to
+ omit the \code{\$} before the keyword arguments (i.e. \code{arg1}) in this
+ case.
+
+\item Cheetah ignores all dollar signs (\code{\$}) that are not followed by a
+ letter or an underscore.
+
+\end{itemize}
+
+The following are valid \$placeholders:
+\begin{verbatim}
+$a $_ $var $_var $var1 $_1var $var2_ $dict.key $list[3]
+$object.method $object.method() $object.method
+$nest($nest($var))
+\end{verbatim}
+
+These are not \$placeholders but are treated as literal text:
+\begin{verbatim}
+$@var $^var $15.50 $$
+\end{verbatim}
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Where can you use placeholders?}
+\label{language.placeholders.positions}
+
+There are three places you can use placeholders: top-level position,
+expression position and LVALUE position. Each has slightly different
+syntax rules.
+
+Top-level position means interspersed in text. This is the only place
+you can use the placeholder long form: \code{\$\{var\}}.
+
+{\em Expression position} means inside a Cheetah expression, which is the same
+as a Python expression. The placeholder names a searchList or other variable
+to be read. Expression position occurs inside () and $[]$ arguments within
+placeholder tags (i.e., a placeholder inside a placeholder), and in several
+directive tags.
+
+{\em LVALUE position} means naming a variable that will be written to. LVALUE
+is a computer science term meaning ``the left side of an assignment
+statement''. The first argument of directives \code{\#set}, \code{\#for},
+\code{\#def}, \code{\#block} and \code{\#attr} is an LVALUE.
+
+This stupid example shows the three positions. Top-level position is shown
+in \code{courier}, expression position is {\em italic}, and LVALUE position is
+{\bf bold}.
+
+\begin{quote}
+\#for {\bf \$count} in {\em \$range}({\em \$ninetyNine}, 0, -1)\\
+\#set {\bf \$after} = {\em \$count} - 1\\
+\code{\$count} bottles of beer on the wall. \code{\$count} bottles of beer!\\
+~~~~Take one down, pass it around. \code{\$after} bottles of beer on the wall.\\
+\#end for\\
+\code{\$hex}({\em \$myVar}, {\bf \$default}={\em None})
+\end{quote}
+
+The output of course is:
+\begin{verbatim}
+99 bottles of beer on the wall. 99 bottles of beer!
+ Take one down, pass it around. 98 bottles of beer on the wall.
+98 bottles of beer on the wall. 98 bottles of beer!
+ Take one down, pass it around. 97 bottles of beer on the wall.
+...
+\end{verbatim}
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Are all those dollar signs really necessary?}
+\label{language.placeholders.dollar-signs}
+
+\code{\$} is a ``smart variable prefix''. When Cheetah sees \code{\$}, it
+determines both the variable's position and whether it's a searchList value or
+a non-searchList value, and generates the appropriate Python code.
+
+In top-level position, the \code{\$} is {\em required}. Otherwise there's
+nothing to distinguish the variable from ordinary text, and the variable name
+is output verbatim.
+
+In expression position, the \code{\$} is {\em required} if the value comes from
+the searchList or a ``\#set global'' variable, {\em recommended} for
+local/global/builtin variables, and {\em not necessary} for the special
+constants \code{None}, \code{True} and \code{False}. This works because
+Cheetah generates a function call for a searchList placeholder, but a bare
+variable name for a local/global/builtin variable.
+
+In LVALUE position, the \code{\$} is {\em recommended}. Cheetah knows where
+an LVALUE is expected, so it can handle your variable name whether it has
+\code{\$} or not.
+
+EXCEPTION: Do {\em not} use the \code{\$} prefix for intermediate variables in
+a Python list comprehensions. This is a limitation of Cheetah's parser; it
+can't tell which variables in a list comprehension are the intermediate
+variables, so you have to help it. For example:
+\begin{verbatim}
+#set $theRange = [x ** 2 for x in $range(10)]
+\end{verbatim}
+\code{\$theRange} is a regular \code{\#set} variable. \code{\$range} is a
+Python built-in function. But \code{x} is a scratch variable internal to
+the list comprehension: if you type \code{\$x}, Cheetah will miscompile
+it.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{NameMapper Syntax}
+\label{language.namemapper}
+
+One of our core aims for Cheetah was to make it easy for non-programmers to
+use. Therefore, Cheetah uses a simplified syntax for mapping placeholders
+in Cheetah to values in Python. It's known as the {\bf NameMapper syntax}
+and allows for non-programmers to use Cheetah without knowing (a) the
+difference between an instance and a dictionary, (b) what functions and methods
+are, and (c) what 'self' is. A side benefit is that you can change the
+underlying data structure (e.g., instance to dictionary or vice-versa) without
+having to modify the templates.
+
+NameMapper syntax is used for all variables in Cheetah placeholders and
+directives. If desired, it can be turned off via the \code{Template} class'
+\code{'useNameMapper'} compiler setting. But it's doubtful you'd ever want to
+turn it off.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsubsection{Example}
+\label{language.namemapper.example}
+
+Consider this scenario:
+
+You are building a customer information system. The designers with you want to
+use information from your system on the client's website --AND-- they want to
+understand the display code and so they can maintian it themselves.
+
+You write a UI class with a 'customers' method that returns a dictionary of all
+the customer objects. Each customer object has an 'address' method that returns
+the a dictionary with information about the customer's address. The designers
+want to be able to access that information.
+
+Using PSP, the display code for the website would look something like the
+following, assuming your servlet subclasses the class you created for managing
+customer information:
+
+\begin{verbatim}
+ <%= self.customer()[ID].address()['city'] %> (42 chars)
+\end{verbatim}
+
+With Cheetah's NameMapper syntax, you can use any of the following:
+
+\begin{verbatim}
+ $self.customers()[$ID].address()['city'] (39 chars)
+ --OR--
+ $customers()[$ID].address()['city']
+ --OR--
+ $customers()[$ID].address().city
+ --OR--
+ $customers()[$ID].address.city
+ --OR--
+ $customers[$ID].address.city (27 chars)
+\end{verbatim}
+
+Which of these would you prefer to explain to the designers, who have no
+programming experience? The last form is 15 characters shorter than the PSP
+version and -- conceptually -- far more accessible. With PHP or ASP, the
+code would be even messier than with PSP.
+
+This is a rather extreme example and, of course, you could also just implement
+\code{\$getCustomer(\$ID).city} and obey the Law of Demeter (search Google for more
+on that). But good object orientated design isn't the point of this example.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsubsection{Dictionary Access}
+\label{language.namemapper.dict}
+
+NameMapper syntax allows access to dictionary items with the same dotted
+notation used to access object attributes in Python. This aspect of NameMapper
+syntax is known as 'Unified Dotted Notation'.
+For example, with Cheetah it is possible to write:
+\begin{verbatim}
+ $customers()['kerr'].address() --OR-- $customers().kerr.address()
+\end{verbatim}
+where the second form is in NameMapper syntax.
+
+This works only with dictionary keys that also happen to be valid Python
+identifiers.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsubsection{Autocalling}
+\label{language.namemapper.autocalling}
+
+Cheetah automatically detects functions and methods in Cheetah \$variables and
+calls them if the parentheses have been left off. Our previous example can be
+further simplified to:
+\begin{verbatim}
+ $customers.kerr.address
+\end{verbatim}
+
+As another example, if 'a' is an object, 'b' is a method
+\begin{verbatim}
+ $a.b
+\end{verbatim}
+
+is equivalent to
+
+\begin{verbatim}
+ $a.b()
+\end{verbatim}
+
+If b returns a dictionary, then following variations are possible
+\begin{verbatim}
+ $a.b.c --OR-- $a.b().c --OR-- $a.b()['c']
+\end{verbatim}
+where 'c' is a key in the dictionary that a.b() returns.
+
+Further notes:
+\begin{itemize}
+\item When Cheetah autocalls a function/method, it calls it without any
+arguments. Thus, the function/method must have been declared without arguments
+(except \code{self} for methods) or to provide default values for all arguments.
+If the function requires arguments, you must use the \code{()}.
+
+\item Cheetah autocalls only functions and methods. Classes and other callable
+objects are not autocalled. The reason is that the primary purpose of a
+function/method is to call it, whereas the primary purpose of an instance is to
+look up its attributes or call its methods, not to call the instance itself.
+And calling a class may allocate large sums of memory uselessly or have other
+side effects, depending on the class. For instance, consider
+\code{\$myInstance.fname}. Do we want to look up \code{fname} in the namespace
+of \code{myInstance} or in the namespace of whatever \code{myinstance} returns?
+It could go either way, so Cheetah follows the principle of least surprise. If
+you {\em do} want to call the instance, put the \code{()} on, or rename the
+\code{.\_\_call\_\_()} method to \code{.\_\_str\_\_}.
+
+\item Autocalling can be disabled via Cheetah's 'useAutocalling' compiler
+setting. You can also disable it for one placeholder by using the syntax
+\code{\$getVar('varName', 'default value', False)}. (\code{.getVar()} works
+only with searchList values.)
+\end{itemize}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Namespace cascading and the searchList}
+\label{language.searchList}
+
+When Cheetah maps a variable name in a template to a Python value, it searches
+several namespaces in order:
+
+\begin{enumerate}
+\item {\bf Local variables:} created by \code{\#set},
+ \code{\#for}, or predefined by Cheetah.
+\item The {\bf searchList}, consisting of:
+ \begin{enumerate}
+ \item \code{\#set\ global} variables.
+ \item The {\bf searchList} containers you passed to the \code{Template}
+ constructor, if any.
+ \item The {\bf Template instance} (``self''). This contains any attributes
+ you assigned, \code{\#def} methods and \code{\#block methods},
+ attributes/methods inherited via \code{\#extends}, and other
+ attributes/methods built into \code{Template} or inherited by it
+ (there's a list of all these methods in section
+ \ref{tips.allMethods}).
+ \end{enumerate}
+\item {\bf Python globals:} created by \code{\#import},
+ \code{\#from\ ...\ import}, or otherwise predefined by Cheetah.
+\item {\bf Python builtins:} \code{None}, \code{max}, etc.
+\end{enumerate}
+
+The first matching name found is used.
+
+Remember, these namespaces apply only to the {\em first} identifier after the
+\code{\$}. In a placeholder like \code{\$a.b}, only `a' is looked up in the
+searchList and other namespaces. `b' is looked up only inside `a'.
+
+A searchList container can be any Python object with attributes or keys:
+dictionaries, instances, classes or modules. If an instance contains both
+attributes and keys, its attributes are searched first, then its keys.
+
+Because the \code{Template} instance is part of the searchList, you can
+access its attributes/methods without `self': \code{\$myAttr}. However, use
+the `self' if you want to make sure you're getting the \code{Template}
+attribute and not a same-name variable defined in a higher namespace:
+\code{\$self.myAttr}. This works because ``self'' itself is a local variable.
+
+The final resulting value, after all lookups and function calls (but before the
+filter is applied) is called the {\em placeholder value}, no matter which
+namespace it was found in.
+
+{\em {\bf Note carefully:}} if you put an object `myObject' in the searchList,
+you {\em cannot} look up \code{\$myObject}! You can look up only the
+attributes/keys {\em inside} `myObject'.
+
+Earlier versions of Cheetah did not allow you to override Python builtin
+names, but this was fixed in Cheetah 0.9.15.
+
+If your template will be used as a Webware servlet, do not override methods
+'name' and 'log' in the \code{Template} instance or it will interfere with
+Webware's logging. However, it {\em is} OK to use those variables in a higher
+namespace, since Webware doesn't know about Cheetah namespaces.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Missing Values}
+\label{language.namemapper.missing}
+
+If NameMapper can not find a Python value for a Cheetah variable name, it will
+raise the NameMapper.NotFound exception. You can use the \code{\#errorCatcher}
+directive (section \ref{errorHandling.errorCatcher}) or {\bf errorCatcher}
+Template constructor argument (section \ref{howWorks.constructing}) to specify
+an alternate behaviour. BUT BE AWARE THAT errorCatcher IS ONLY INTENDED FOR
+DEBUGGING!
+
+To provide a default value for a placeholder, write it like this:
+\code{\$getVar('varName', 'default value')}. If you don't specify a default
+and the variable is missing, \code{NameMapper.NotFound} will be raised.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Directive Syntax Rules}
+\label{language.directives.syntax}
+
+
+Directive tags begin with a hash character (\#) and are used for comments,
+loops, conditional blocks, includes, and all other advanced features. Cheetah
+uses a Python-like syntax inside directive tags and understands any valid
+Python expression. {\bf However, unlike Python, Cheetah does not use colons
+(:) and indentation to mark off multi-line directives.} That doesn't work in
+an environment where whitespace is significant as part of the text. Instead,
+multi-line directives like \code{\#for} have corresponding closing tags
+(\code{\#end for}). Most directives are direct mirrors of Python statements.
+
+Many directives have arguments after the opening tag, which must be in the
+specified syntax for the tag. All end tags have the following syntax:
+\begin{verbatim}
+#end TAG_NAME [EXPR]
+\end{verbatim}
+The expression is ignored, so it's essentially a comment.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsubsection{Directive closures and whitespace handling}
+\label{language.directives.closures}
+Directive tags can be closed explicitly with \code{\#}, or implicitly with the
+end of the line if you're feeling lazy.
+
+\begin{verbatim}
+#block testBlock #
+Text in the body of the
+block directive
+#end block testBlock #
+\end{verbatim}
+is identical to:
+\begin{verbatim}
+#block testBlock
+Text in the body of the
+block directive
+#end block testBlock
+\end{verbatim}
+
+When a directive tag is closed explicitly, it can be followed with other text on
+the same line:
+
+\begin{verbatim}
+bah, bah, #if $sheep.color == 'black'# black#end if # sheep.
+\end{verbatim}
+
+When a directive tag is closed implicitly with the end of the line, all trailing
+whitespace is gobbled, including the newline character:
+\begin{verbatim}
+"""
+foo #set $x = 2
+bar
+"""
+outputs
+"""
+foo bar
+"""
+
+while
+"""
+foo #set $x = 2 #
+bar
+"""
+outputs
+"""
+foo
+bar
+"""
+\end{verbatim}
+
+When a directive tag is closed implicitly AND there is no other text on the
+line, the ENTIRE line is gobbled up including any preceeding whitespace:
+\begin{verbatim}
+"""
+foo
+ #set $x = 2
+bar
+"""
+outputs
+"""
+foo
+bar
+"""
+
+while
+"""
+foo
+ - #set $x = 2
+bar
+"""
+outputs
+"""
+foo
+ - bar
+"""
+\end{verbatim}
+
+The \code{\#slurp} directive (section \ref{output.slurp}) also gobbles up
+whitespace.
+
+Spaces outside directives are output {\em exactly} as written. In the
+black sheep example, there's a space before ``black'' and another before
+``sheep''. So although it's legal to put multiple directives on one line,
+it can be hard to read.
+
+\begin{verbatim}
+#if $a# #echo $a + 1# #end if
+ - There's a space between each directive,
+ or two extra spaces total.
+#if $a##echo $a + 1##end if
+ - No spaces, but you have to look closely
+ to verify none of the ``##'' are comment markers.
+#if $a##echo $a + 1##end if ### A comment.
+ - In ``###'', the first ``#'' ends the directive,
+ the other two begin the comment. (This also shows
+ how you can add extra whitespace in the directive
+ tag without affecting the output.)
+#if $a##echo $a + 1##end if # ## A comment.
+ - More readable, but now there's a space before the
+ comment.
+\end{verbatim}
+
+% Local Variables:
+% TeX-master: "users_guide"
+% End:
+
+% # vim: sw=4 ts=4 expandtab