Edgewall Software

Ticket #47: texttmpl.2.diff

File texttmpl.2.diff, 4.3 KB (added by cmlenz, 8 years ago)

Updated to include position info

  • markup/template.py

     
    6262    """ 
    6363 
    6464    def __init__(self, name, filename='<string>', lineno=-1): 
    65         message = 'bad directive "%s"' % name.localname 
     65        message = 'bad directive "%s"' % name 
    6666        TemplateSyntaxError.__init__(self, message, filename, lineno) 
    6767 
    6868 
     
    811811                if tag in self.NAMESPACE: 
    812812                    cls = self._dir_by_name.get(tag.localname) 
    813813                    if cls is None: 
    814                         raise BadDirectiveError(tag, pos[0], pos[1]) 
     814                        raise BadDirectiveError(tag.localname, pos[0], pos[1]) 
    815815                    value = attrib.get(getattr(cls, 'ATTRIBUTE', None), '') 
    816816                    directives.append(cls(value, *pos)) 
    817817                    strip = True 
     
    821821                    if name in self.NAMESPACE: 
    822822                        cls = self._dir_by_name.get(name.localname) 
    823823                        if cls is None: 
    824                             raise BadDirectiveError(name, pos[0], pos[1]) 
     824                            raise BadDirectiveError(name.localname, pos[0], 
     825                                                    pos[1]) 
    825826                        directives.append(cls(value, *pos)) 
    826827                    else: 
    827828                        if value: 
     
    10781079SUB = Template.SUB 
    10791080 
    10801081 
     1082class 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 
    10811167class TemplateLoader(object): 
    10821168    """Responsible for loading templates from files on the specified search 
    10831169    path.