]> Devi Nivas Git - chevron.git/commitdiff
Add better error messages
authornoah morrison <noah@morrison.ph>
Wed, 8 Apr 2015 02:49:10 +0000 (22:49 -0400)
committernoah morrison <noah@morrison.ph>
Wed, 8 Apr 2015 02:49:10 +0000 (22:49 -0400)
Fixes issue #15 on github

The tokenizer now keeps track of the current line,
and raises a more descriptive error message when it fails.

If running from the CLI then exit with status 1.

chevron/main.py
chevron/tokenizer.py

index 402319dbf17e4c3eef09e2d30514d295cffbd8f8..8615ff01d0a3fa2d4be1c3cabfd559d9053a907d 100755 (executable)
@@ -26,7 +26,11 @@ def main(template, data={}, **kwargs):
         }
 
         args.update(kwargs)
-        return render(**args)
+        try:
+            return render(**args)
+        except SyntaxError as e:
+            print('Chevron: syntax error')
+            print('    ' + '\n    '.join(e.args[0].split('\n')))
 
 
 def cli_main():
@@ -77,7 +81,10 @@ def cli_main():
 
     args = vars(parser.parse_args())
 
-    print(main(**args))
+    result = main(**args)
+    if result is None:
+        exit(1)
+    print(result)
 
 if __name__ == '__main__':
     cli_main()
index 95a49863510a70689d6c34634bccd3887fedd42f..9fdefd38da87cea0cb5ff339df5c5d3f9fb7a9c3 100644 (file)
@@ -1,5 +1,9 @@
 #!/usr/bin/python
 
+# Globals
+_CURRENT_LINE = 1
+_LAST_TAG_LINE = None
+
 
 #
 # Helper functions
@@ -8,9 +12,12 @@
 def grab_literal(template, l_del):
     """Parse a literal from the template"""
 
+    global _CURRENT_LINE
+
     try:
         # Look for the next tag and move the template to it
         literal, template = template.split(l_del, 1)
+        _CURRENT_LINE += literal.count('\n')
         return (literal, template)
 
     # There are no more tags in the template?
@@ -55,6 +62,8 @@ def r_sa_check(template, tag_type, is_standalone):
 
 def parse_tag(template, l_del, r_del):
     """Parse a tag from a template"""
+    global _CURRENT_LINE
+    global _LAST_TAG_LINE
 
     tag_types = {
         '!': 'comment',
@@ -88,7 +97,8 @@ def parse_tag(template, l_del, r_del):
 
         # Otherwise we should complain
         else:
-            raise SyntaxError('Unmatched set delimiter tag')
+            raise SyntaxError('unclosed set delimiter tag\n'
+                              'at line {0}'.format(_CURRENT_LINE))
 
     # If we might be a no html escape tag
     elif tag_type == 'no escape?':
@@ -183,6 +193,7 @@ def tokenize(template, def_ldel='{{', def_rdel='}}'):
         elif tag_type in ['section', 'inverted section']:
             # Then open a new section
             open_sections.append(tag_key)
+            _LAST_TAG_LINE = _CURRENT_LINE
 
         # If we are an end tag
         elif tag_type == 'end':
@@ -191,8 +202,11 @@ def tokenize(template, def_ldel='{{', def_rdel='}}'):
             last_section = open_sections.pop()
             if tag_key != last_section:
                 # Otherwise we need to complain
-                raise SyntaxError('End tag does not match '
-                                  'the currently opened section')
+                raise SyntaxError('Trying to close tag "{0}"\n'
+                                  'last open tag is "{1}"\n'
+                                  'line {2}'
+                                  .format(tag_key, last_section,
+                                          _CURRENT_LINE + 1))
 
         # Do the second check to see if we're a standalone
         is_standalone = r_sa_check(template, tag_type, is_standalone)
@@ -219,4 +233,7 @@ def tokenize(template, def_ldel='{{', def_rdel='}}'):
     # If there are any open sections when we're done
     if open_sections:
         # Then we need to complain
-        raise SyntaxError("End of file while a section was open")
+        raise SyntaxError('Unexpected EOF\n'
+                          'the tag "{0}" was never closed\n'
+                          'was opened at line {1}'
+                          .format(open_sections[-1], _LAST_TAG_LINE))