Edgewall Software

Ticket #47: texttmpl.diff

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

Template subclass that does basic text-based templating

  • markup/template.py

     
    753753            self.filepath = None 
    754754 
    755755        self.filters = [] 
    756         self.parse() 
     756        self.stream = self.parse() 
    757757 
    758758    def __repr__(self): 
    759759        return '<%s "%s">' % (self.__class__.__name__, self.filename) 
     
    851851            else: 
    852852                stream.append((kind, data, pos)) 
    853853 
    854         self.stream = stream 
     854        return stream 
    855855 
    856856    _FULL_EXPR_RE = re.compile(r'(?<!\$)\$\{(.+?)\}', re.DOTALL) 
    857857    _SHORT_EXPR_RE = re.compile(r'(?<!\$)\$([a-zA-Z][a-zA-Z0-9_\.]*)') 
     
    10491049                yield kind, data, pos 
    10501050 
    10511051 
     1052class TextTemplate(Template): 
     1053    """ 
     1054    >>> tmpl = TextTemplate('''Dear $name, 
     1055    ...  
     1056    ... We have the following items for you: 
     1057    ... #for item in items 
     1058    ...  * $item 
     1059    ... #endfor 
     1060    ...  
     1061    ... All the best, 
     1062    ... Foobar 
     1063    ... #endif''') 
     1064    >>> print tmpl.generate(name='Joe', items=[1, 2, 3]).render('text') 
     1065    Dear Joe, 
     1066    <BLANKLINE> 
     1067    We have the following items for you: 
     1068     * 1 
     1069     * 2 
     1070     * 3 
     1071    <BLANKLINE> 
     1072    All the best, 
     1073    Foobar 
     1074    <BLANKLINE> 
     1075    """ 
     1076 
     1077    _DIRECTIVE_RE = re.compile('^#(\w+.*)\n?', re.MULTILINE) 
     1078 
     1079    def parse(self): 
     1080        stream = [] # list of events of the "compiled" template 
     1081        dirmap = {} # temporary mapping of directives to elements 
     1082        depth = 0 
     1083 
     1084        source = self.source.read() 
     1085        for idx, part in enumerate(self._DIRECTIVE_RE.split(source)): 
     1086 
     1087            if idx % 2: 
     1088                directive = part.split(None, 1) 
     1089                if len(directive) > 1: 
     1090                    command, value = directive 
     1091                else: 
     1092                    command, value = directive[0], None 
     1093 
     1094                if not command.startswith('end'): 
     1095                    cls = self._dir_by_name.get(command) 
     1096                    if cls is None: 
     1097                        raise BadDirectiveError(command) 
     1098                    directive = cls(value, None, -1, -1) 
     1099                    dirmap[depth] = (directive, len(stream)) 
     1100                    depth += 1 
     1101                else: 
     1102                    depth -= 1 
     1103                    command = command[3:] 
     1104                    if depth in dirmap: 
     1105                        directive, start_offset = dirmap.pop(depth) 
     1106                        substream = stream[start_offset:] 
     1107                        stream[start_offset:] = [(SUB, ([directive], substream), 
     1108                                                  (None, -1, -1))] 
     1109 
     1110            else: 
     1111                for kind, data, pos in self._interpolate(part): 
     1112                    stream.append((kind, data, (None, -1, -1))) 
     1113 
     1114        return stream 
     1115 
     1116 
    10521117EXPR = Template.EXPR 
    10531118SUB = Template.SUB 
    10541119