|
1 | 1 |
|
| 2 | +try: |
| 3 | + next |
| 4 | +except NameError: |
| 5 | + from .backwards import next |
2 | 6 | import re
|
3 | 7 |
|
4 | 8 | from . import nodes
|
@@ -51,33 +55,41 @@ def parse(self, source):
|
51 | 55 |
|
52 | 56 | line = raw_line.lstrip()
|
53 | 57 |
|
54 |
| - # We track the inter-line depth seperate from the intra-line depth |
55 |
| - # so that indentation due to whitespace always results in more |
56 |
| - # depth in the graph than many nested nodes from a single line. |
57 |
| - # We treat a whitespace-only line as if the indentation level has |
58 |
| - # not changed |
59 |
| - inter_depth = len(raw_line) - len(line) |
60 |
| - intra_depth = 0 |
61 |
| - |
62 |
| - # Cleanup the stack. We should only need to do this here as the |
63 |
| - # depth only goes up until it is calculated from the next line. |
64 |
| - self._prep_stack_for_depth((inter_depth, intra_depth)) |
65 |
| - |
| 58 | + if line: |
| 59 | + |
| 60 | + # We track the inter-line depth seperate from the intra-line depth |
| 61 | + # so that indentation due to whitespace always results in more |
| 62 | + # depth in the graph than many nested nodes from a single line. |
| 63 | + inter_depth = len(raw_line) - len(line) |
| 64 | + intra_depth = 0 |
| 65 | + |
| 66 | + # Cleanup the stack. We should only need to do this here as the |
| 67 | + # depth only goes up until it is calculated from the next line. |
| 68 | + self._prep_stack_for_depth((inter_depth, intra_depth)) |
| 69 | + |
| 70 | + else: |
| 71 | + |
| 72 | + # Pretend that a blank line is at the same depth as the |
| 73 | + # previous. |
| 74 | + inter_depth, intra_depth = self._stack[-1][0] |
| 75 | + |
66 | 76 | # Greedy nodes recieve all content until we fall out of their scope.
|
67 | 77 | if isinstance(self._topmost_node, nodes.GreedyBase):
|
| 78 | + topmost = self._topmost_node |
| 79 | + # Blank lines go at the same level as the previous if it is |
| 80 | + # not the parent greedy node. |
| 81 | + if not line and topmost is not topmost.outermost_node: |
| 82 | + self._stack.pop() |
68 | 83 | self._add_node(
|
69 |
| - self._topmost_node.__class__.with_parent(self._topmost_node, line), |
| 84 | + topmost.with_parent(topmost, line), |
70 | 85 | (inter_depth, intra_depth)
|
71 | 86 | )
|
72 | 87 | continue
|
73 | 88 |
|
| 89 | + # Discard all empty lines that are not in a greedy context. |
74 | 90 | if not line:
|
75 |
| - # I am unsure if I should just be discarding all empty lines |
76 |
| - # like this. There are some scenarios in which an empty line |
77 |
| - # would still be used, such as in a multiline string inside a |
78 |
| - # source block. |
79 | 91 | continue
|
80 |
| - |
| 92 | + |
81 | 93 | # Main loop. We process a series of tokens, which consist of either
|
82 | 94 | # nodes to add to the stack, or strings to be re-parsed and
|
83 | 95 | # attached as inline.
|
@@ -143,7 +155,7 @@ def _parse_line(self, line):
|
143 | 155 |
|
144 | 156 | # Tags.
|
145 | 157 | m = re.match(r'''
|
146 |
| - (?:%(%?\w*))? # tag name. the extra % is for mako |
| 158 | + (?:%(%?(?:\w+:)?\w*))? # tag name. the extra % is for mako |
147 | 159 | (?:
|
148 | 160 | \[(.+?)(?:,(.+?))?\] # object reference and prefix
|
149 | 161 | )?
|
|
0 commit comments