| | 1082 | class TextTemplate(Template): |
| | 1083 | """ |
| | 1084 | >>> tmpl = TextTemplate('''Dear $name, |
| | 1085 | ... |
| | 1086 | ... We have the following items for you: |
| | 1087 | ... #for item in items |
| | 1088 | ... * $item |
| | 1089 | ... #endfor |
| | 1090 | ... |
| | 1091 | ... All the best, |
| | 1092 | ... Foobar |
| | 1093 | ... #endif''') |
| | 1094 | >>> print tmpl.generate(name='Joe', items=[1, 2, 3]).render('text') |
| | 1095 | Dear Joe, |
| | 1096 | <BLANKLINE> |
| | 1097 | We have the following items for you: |
| | 1098 | * 1 |
| | 1099 | * 2 |
| | 1100 | * 3 |
| | 1101 | <BLANKLINE> |
| | 1102 | All the best, |
| | 1103 | Foobar |
| | 1104 | <BLANKLINE> |
| | 1105 | """ |
| | 1106 | |
| | 1107 | directives = [('def', DefDirective), |
| | 1108 | ('when', WhenDirective), |
| | 1109 | ('otherwise', OtherwiseDirective), |
| | 1110 | ('for', ForDirective), |
| | 1111 | ('if', IfDirective), |
| | 1112 | ('choose', ChooseDirective), |
| | 1113 | ('with', WithDirective)] |
| | 1114 | _dir_by_name = dict(directives) |
| | 1115 | _dir_order = [directive[1] for directive in directives] |
| | 1116 | |
| | 1117 | _directive_re = re.compile('^#(\w+.*)\n?', re.MULTILINE) |
| | 1118 | |
| | 1119 | def parse(self): |
| | 1120 | stream = [] # list of events of the "compiled" template |
| | 1121 | dirmap = {} # temporary mapping of directives to elements |
| | 1122 | depth = 0 |
| | 1123 | |
| | 1124 | source = self.source.read() |
| | 1125 | offset = 0 |
| | 1126 | lineno = 1 |
| | 1127 | for idx, mo in enumerate(self._directive_re.finditer(source)): |
| | 1128 | start, end = mo.span() |
| | 1129 | if start > offset: |
| | 1130 | text = source[offset:start] |
| | 1131 | for kind, data, pos in self._interpolate(text, self.filename, lineno, 0): |
| | 1132 | stream.append((kind, data, pos)) |
| | 1133 | lineno += len(text.splitlines()) |
| | 1134 | |
| | 1135 | text = source[start + 1:end] |
| | 1136 | lineno += len(text.splitlines()) |
| | 1137 | directive = text.split(None, 1) |
| | 1138 | if len(directive) > 1: |
| | 1139 | command, value = directive |
| | 1140 | else: |
| | 1141 | command, value = directive[0], None |
| | 1142 | |
| | 1143 | if not command.startswith('end'): |
| | 1144 | cls = self._dir_by_name.get(command) |
| | 1145 | if cls is None: |
| | 1146 | raise BadDirectiveError(command) |
| | 1147 | directive = cls(value, self.filename, lineno, 0) |
| | 1148 | dirmap[depth] = (directive, len(stream)) |
| | 1149 | depth += 1 |
| | 1150 | else: |
| | 1151 | depth -= 1 |
| | 1152 | command = command[3:] |
| | 1153 | if depth in dirmap: |
| | 1154 | directive, start_offset = dirmap.pop(depth) |
| | 1155 | substream = stream[start_offset:] |
| | 1156 | stream[start_offset:] = [(SUB, ([directive], substream), |
| | 1157 | (self.filename, lineno, 0))] |
| | 1158 | |
| | 1159 | offset = end |
| | 1160 | |
| | 1161 | return stream |
| | 1162 | |
| | 1163 | def _match(self, stream, ctxt=None): |
| | 1164 | return stream |
| | 1165 | |
| | 1166 | |