含有章节索引的中文 文章模板
-- limodou [DateTime(2004-08-28T04:10:50Z)] TableOfContents
Meteor源程序
程序不长,因此列在这里
Template程序代码
1 #coding=utf-8
2
3 import re
4 import sets
5 import copy
6 import types
7
8 class T:
9 def __init__(self, string):
10 self.text = string
11
12 def getText(self):
13 return self.text
14
15 #预处理器基类
16 class PreprocessBase:
17 #ptype 为处理器的名字,如'py'
18 def __init__(self, ptype, beginchars='<#', endchars='#>'):
19 self.ptype = ptype
20 self.beginchars = beginchars #define template var's left delimeter chars
21 self.endchars = endchars #define template var's right delimeter chars
22
23 #进行模板分析,应返回T对象的一个字典和相应的相关集
24 def process(self, filename):
25 return {}, {}
26
27 def getPattern(self):
28 return r'%s(\w+)%s' % (self.beginchars, self.endchars)
29
30 class PyPreprocess(PreprocessBase):
31 def process(self, filename):
32 mod = __import__(filename)
33 components = filename.split('.')
34 for comp in components[1:]:
35 mod = getattr(mod, comp)
36
37 vars = {}
38 nodes = {}
39 for vn in dir(mod):
40 v = getattr(mod, vn)
41 if hasattr(v, '__class__') and v.__class__.__name__ == 'T':
42 vars[vn] = v
43 nodes[vn] = self._get_rely_on_node(v.getText())
44
45 return vars, nodes
46
47 #取模板元素的相关集
48 def _get_rely_on_node(self, s): #search for %(name)s format, make a dict
49 re_node = re.compile(self.getPattern())
50
51 return list(sets.Set(re_node.findall(s)))
52
53 class NoPreprocess(Exception): pass
54 class CircleFound(Exception): pass
55
56 #定义模板处理类
57 class Template:
58
59 preprocess ={}
60
61 def __init__(self):
62 self.vars = {}
63 self.nodes = {}
64
65 #装入模板
66 def load(self, tplfile, tpltype='py'):
67 self.pre = self.preprocess.get(tpltype, None)
68 if not self.pre:
69 raise NoPreprocess(), 'No proper preprocess'
70
71 vars, nodes = self.pre.process(tplfile)
72 self.vars.update(vars)
73 self.nodes.update(nodes)
74
75 #生成模板值
76 #values应为字典的字典。即每一个模板元素如果引用有外部的变量,那么在values中应有此模板元素的一个键。
77 #同时它的值应为所有外部变量的一个字典
78 def value(self, target, values):
79 self.global_values = values[target]
80 self.target = target
81 return self._value(target, values[target])
82
83 def _value(self, target, values=None):
84
85 text = self.OnReplace(target, values)
86 if text is not None:
87 return text
88
89 nodes = self.nodes[target]
90
91 if not isinstance(values, types.ListType):
92 values = [values]
93
94 s = []
95 for v in values:
96 vals = {}
97 for node in nodes:
98 if not v.has_key(node):
99 if node in self.vars.keys():
100 vals[node] = self._value(node, self.global_values.get(node, {}))
101 else:
102 if node in self.vars.keys(): #如果node是一个模板变量,则继续替换
103 vals[node] = self._value(node, v[node])
104 else: #说明为一个外部变量
105 vals[node] = v[node]
106 s.append(self._replace(target, self.vars[target].getText(), vals))
107
108 return ''.join(s)
109
110 #可以自已写处理函数
111 #name为模板元素的名字
112 #text为要替换的引用变量的名字
113 def OnReplace(self, name, values):
114 return None
115
116 #把一段文件本的可替换信息使用values中的变量进行替换
117 #text是段字符串
118 #values是一个对应替换信息的字典
119 def _replace(self, name, text, values):
120 def dosup(matchobj, name=name, text=text, values=values):
121 if values:
122 result = values.get(matchobj.groups()[0], matchobj.group())
123 else:
124 result = matchobj.group()
125 return result
126
127 if not text:
128 return text
129 return re.sub(self.pre.getPattern(), dosup, text)
130
131
132 #注册预处理器函数,是一个处理器实例
133 def register(preprocess):
134 Template.preprocess[preprocess.ptype] = preprocess
135
136 register(PyPreprocess('py'))
137
138 if __name__ == '__main__':
139 vars = {
140 'program':{
141 'hello':[
142 {'var' :'var1'},
143 {'var' :'var2'},
144 {'var' :'var3'},
145 ],
146 },
147 }
148 template = Template()
149 template.load('tmp2')
150 print template.value('program', vars)
