From 3dabe23c995fca20b5460a12ade3549f7f1810fe Mon Sep 17 00:00:00 2001
From: Mike Bayer <mike_mp@zzzcomputing.com>
Date: Wed, 2 May 2007 01:01:45 +0000
Subject: [PATCH] - control lines, i.e. % lines, support backslashes to
 continue long   lines (#32) - fixed single "#" comments in docs

---
 CHANGES                       |  4 +++-
 doc/build/content/caching.txt |  2 +-
 doc/build/content/defs.txt    |  6 +++---
 doc/build/content/unicode.txt |  4 ++--
 lib/mako/ast.py               |  2 +-
 lib/mako/lexer.py             |  2 +-
 test/lexer.py                 | 11 +++++++++++
 test/template.py              | 10 ++++++++++
 8 files changed, 32 insertions(+), 9 deletions(-)

diff --git a/CHANGES b/CHANGES
index 0e62f4c..26539d3 100644
--- a/CHANGES
+++ b/CHANGES
@@ -16,7 +16,9 @@
 - the Template returned by html_error_template now defaults to
   output_encoding=sys.getdefaultencoding(),
   encoding_errors='htmlentityreplace' [ticket:37]
-    
+- control lines, i.e. % lines, support backslashes to continue long
+  lines (#32)
+  
 0.1.5
 - AST expression generation - added in just about everything 
   expression-wise from the AST module  [ticket:26]
diff --git a/doc/build/content/caching.txt b/doc/build/content/caching.txt
index 8aae6d2..e6dee41 100644
--- a/doc/build/content/caching.txt
+++ b/doc/build/content/caching.txt
@@ -34,5 +34,5 @@ The options available are:
     
         ${next.body()}
         
-        # rest of template
+        ## rest of template
     
diff --git a/doc/build/content/defs.txt b/doc/build/content/defs.txt
index 43e84ac..fb81ec2 100644
--- a/doc/build/content/defs.txt
+++ b/doc/build/content/defs.txt
@@ -95,7 +95,7 @@ Assigning to a name inside of a def declares that name as local to the scope of
         x = 10
     %>
     <%def name="somedef()">
-        # error !
+        ## error !
         somedef, x is ${x}  
         <%
             x = 27  
@@ -199,7 +199,7 @@ Produces (whitespace formatted):
 You don't have to stick to calling just the `body()` function.  The caller can define any number of callables, allowing the `<%call>` tag to produce whole layouts:
 
     <%def name="layout()">
-        # a layout def
+        ## a layout def
         <div class="mainlayout">
             <div class="header">
                 ${caller.header()}
@@ -213,7 +213,7 @@ You don't have to stick to calling just the `body()` function.  The caller can d
         </div>
     </%def>
 
-    # calls the layout def
+    ## calls the layout def
     <%call expr="layout">
         <%def name="header()">
             I am the header
diff --git a/doc/build/content/unicode.txt b/doc/build/content/unicode.txt
index 9f92a9c..6daba9d 100644
--- a/doc/build/content/unicode.txt
+++ b/doc/build/content/unicode.txt
@@ -48,11 +48,11 @@ looks something like this:
     
 That is, **the output of all expressions is run through the `unicode` builtin**.  This is the default setting, and can be modified to expect various encodings.  The `unicode` step serves both the purpose of rendering non-string expressions into strings (such as integers or objects which contain `__str()__` methods), and to ensure that the final output stream is constructed as a unicode object.  The main implication of this is that **any raw bytestrings that contain an encoding other than ascii must first be decoded to a Python unicode object**.   It means you can't say this:
 
-    ${"voix m’a réveillé."}  # error !
+    ${"voix m’a réveillé."}  ## error !
 
 You must instead say this:
 
-    ${u"voix m’a réveillé."}  # OK !
+    ${u"voix m’a réveillé."}  ## OK !
 
 Similarly, if you are reading data from a file, or returning data from some object that is returning a Python bytestring containing a non-ascii encoding, you have to explcitly decode to unicode first, such as:
 
diff --git a/lib/mako/ast.py b/lib/mako/ast.py
index 0d00f30..db2c316 100644
--- a/lib/mako/ast.py
+++ b/lib/mako/ast.py
@@ -139,7 +139,7 @@ class PythonFragment(PythonCode):
     etc.
     """
     def __init__(self, code, **exception_kwargs):
-        m = re.match(r'^(\w+)(?:\s+(.*?))?:$', code.strip())
+        m = re.match(r'^(\w+)(?:\s+(.*?))?:$', code.strip(), re.S)
         if not m:
             raise exceptions.CompileException("Fragment '%s' is not a partial control statement" % code, **exception_kwargs)
         (keyword, expr) = m.group(1,2)
diff --git a/lib/mako/lexer.py b/lib/mako/lexer.py
index dafa10d..34e7c1a 100644
--- a/lib/mako/lexer.py
+++ b/lib/mako/lexer.py
@@ -283,7 +283,7 @@ class Lexer(object):
             return False
 
     def match_control_line(self):
-        match = self.match(r"(?<=^)[\t ]*(%|##)[\t ]*([^\r\n]*)(?:\r?\n|\Z)", re.M)
+        match = self.match(r"(?<=^)[\t ]*(%|##)[\t ]*((?:(?:\\r?\n)|[^\r\n])*)(?:\r?\n|\Z)", re.M)
         if match:
             operator = match.group(1)
             text = match.group(2)
diff --git a/test/lexer.py b/test/lexer.py
index fd8ea75..e088a50 100644
--- a/test/lexer.py
+++ b/test/lexer.py
@@ -290,6 +290,17 @@ text text la la
         nodes = Lexer(template).parse()
         assert repr(nodes) == r"""TemplateNode({}, [Text(u'\n\n\n', (1, 1)), ControlLine(u'for', u"for file in requestattr['toc'].filenames:", False, (4, 1)), Text(u'    x\n', (5, 1)), ControlLine(u'for', u'endfor', True, (6, 1))])"""
 
+    def test_long_control_lines(self):
+        template = \
+        """
+    % for file in \\
+        requestattr['toc'].filenames:
+        x
+    % endfor
+        """
+        nodes = Lexer(template).parse()
+        assert repr(nodes) == r"""TemplateNode({}, [Text(u'\n', (1, 1)), ControlLine(u'for', u"for file in \\\n        requestattr['toc'].filenames:", False, (2, 1)), Text(u'        x\n', (4, 1)), ControlLine(u'for', u'endfor', True, (5, 1)), Text(u'        ', (6, 1))])"""
+
     def test_unmatched_control(self):
         template = """
 
diff --git a/test/template.py b/test/template.py
index c3d2b12..0d931c6 100644
--- a/test/template.py
+++ b/test/template.py
@@ -243,6 +243,16 @@ class ControlTest(unittest.TestCase):
             "yes x has test"
         ]
 
+    def test_multiline_control(self):
+        t = Template("""
+    % for x in \\
+        [y for y in [1,2,3]]:
+        ${x}
+    % endfor
+""")
+        #print t.code
+        assert flatten_result(t.render()) == "1 2 3"
+        
 class GlobalsTest(unittest.TestCase):
     def test_globals(self):
         t= Template("""
-- 
GitLab