含有章节索引的中文 文章模板
-- limodou [2004-08-28 04:10:50]
Contents
Meteor源程序
程序不长,因此列在这里
Template程序代码
1 #coding=utf-8
2
3 # Programmer: limodou
4 # E-mail: [email protected]
5 #
6 # Copyleft 2004 limodou
7 #
8 # Distributed under the terms of the GPL (GNU Public License)
9 #
10 # NewEdit is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 2 of the License, or
13 # (at your option) any later version.
14 #
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
19 #
20 # You should have received a copy of the GNU General Public License
21 # along with this program; if not, write to the Free Software
22 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #
24 # $Id$
25
26
27 import re
28 import sets
29 import types
30 import csv
31 import os
32 import shutil
33 import os.path
34
35 class TemplateException(Exception): pass
36 class ObjectType(TemplateException): pass
37 class NoPreprocess(TemplateException): pass
38
39 class T:
40 def __init__(self, string):
41 self.text = string
42
43 def getText(self):
44 return self.text
45
46 #预处理器基类
47 class PreprocessBase:
48 #ptype 为处理器的名字,如'py'
49 def __init__(self, ptype, beginchars='<#', endchars='#>'):
50 self.ptype = ptype
51 self.beginchars = beginchars #define template var's left delimeter chars
52 self.endchars = endchars #define template var's right delimeter chars
53
54 #进行模板分析,应返回T对象的一个字典和相应的相关集
55 def process(self, obj):
56 return {}, {}
57
58 def getPattern(self):
59 return r'%s(\w+)%s' % (self.beginchars, self.endchars)
60
61 class PyPreprocess(PreprocessBase):
62 def process(self, modulename):
63 mod = __import__(modulename)
64 components = modulename.split('.')
65 for comp in components[1:]:
66 mod = getattr(mod, comp)
67
68 vars = {}
69 nodes = {}
70 for vn in dir(mod):
71 v = getattr(mod, vn)
72 if hasattr(v, '__class__') and v.__class__.__name__ == 'T':
73 vars[vn] = v
74 nodes[vn] = self._get_rely_on_node(v.getText())
75
76 return vars, nodes
77
78 #取模板元素的相关集
79 def _get_rely_on_node(self, s): #search for %(name)s format, make a dict
80 re_node = re.compile(self.getPattern())
81
82 return list(sets.Set(re_node.findall(s)))
83
84 #定义模板处理类
85 class Template:
86
87 preprocess ={}
88
89 def __init__(self):
90 self.vars = {}
91 self.nodes = {}
92
93 #装入模板
94 def load(self, tplfile, tpltype='py'):
95 self.pre = self.preprocess.get(tpltype, None)
96 if not self.pre:
97 raise NoPreprocess, 'No proper preprocess'
98
99 vars, nodes = self.pre.process(tplfile)
100 self.vars.update(vars)
101 self.nodes.update(nodes)
102
103 #生成模板值
104 #values应为字典的字典。即每一个模板元素如果引用有外部的变量,那么在values中应有此模板元素的一个键。
105 #同时它的值应为所有外部变量的一个字典
106 def value(self, target, values={}):
107 self.global_values = values.get(target, {})
108 self.target = target
109 return self._value(target, self.global_values)
110
111 def _value(self, target, values=None):
112
113 text = self.OnReplace(target, values)
114 if text is not None:
115 return text
116
117 nodes = self.nodes[target]
118
119 if not isinstance(values, types.ListType):
120 values = [values]
121
122 s = []
123 for v in values:
124 vals = {}
125 for node in nodes:
126 if not v.has_key(node):
127 if node in self.vars.keys():
128 vals[node] = self._value(node, self.global_values.get(node, {}))
129 else:
130 if node in self.vars.keys(): #如果node是一个模板变量,则继续替换
131 vals[node] = self._value(node, v[node])
132 else: #说明为一个外部变量
133 vals[node] = v[node]
134 s.append(self._replace(target, self.vars[target].getText(), vals))
135
136 return ''.join(s)
137
138 #可以自已写处理函数
139 #name为模板元素的名字
140 #text为要替换的引用变量的名字
141 def OnReplace(self, name, values):
142 return None
143
144 #把一段文件本的可替换信息使用values中的变量进行替换
145 #text是段字符串
146 #values是一个对应替换信息的字典
147 def _replace(self, name, text, values):
148 def dosup(matchobj, name=name, text=text, values=values):
149 if values:
150 result = values.get(matchobj.groups()[0], matchobj.group())
151 else:
152 result = matchobj.group()
153 return result
154
155 if not text:
156 return text
157 return re.sub(self.pre.getPattern(), dosup, text)
158
159 def writeDot(self, f=None):
160 s = []
161 for key, values in self.nodes.items():
162 for v in values:
163 s.append('%s -> %s;\n' % (key, v))
164 text = 'digraph G{\n' + ''.join(s) + '}\n'
165 if isinstance(f, types.FileType):
166 f.write(text)
167
168 return text
169
170
171 #注册预处理器函数,是一个处理器实例
172 def register(preprocess):
173 Template.preprocess[preprocess.ptype] = preprocess
174
175 register(PyPreprocess('py'))
176
177 class TemplateScript:
178 def __init__(self):
179 self.template = Template()
180
181 #script为一个cvs格式的迭代器对象。需要有next方法。可以直接传入打开的文件对象
182 def __call__(self, script, vars=None):
183 if not vars:
184 vars = {}
185 lines = csv.reader(script, delimiter=' ')
186 for v in lines:
187 if v:
188 self._do(vars, *v)
189
190 def _do(self, vars, *args):
191 para = args
192 cmd = para[0].lower()
193 if cmd and cmd[0] == '#':
194 return
195 if cmd == 'mkdir':
196 if not os.path.exists(para[1]):
197 os.makedirs(para[1])
198 elif cmd == 'copy':
199 if os.path.isdir(para[2]):
200 dstfile = os.path.join(para[2], para[1])
201 else:
202 dstfile = para[2]
203 shutil.copyfile(para[1], dstfile)
204 elif cmd == 'run':
205 self.template.load(para[1], para[2])
206 file(para[4], 'wb').write(self.template.value(para[3], vars))
207
208 if __name__ == '__main__':
209 vars = {
210 'program':{
211 'hello':[
212 {'var' :'var1'},
213 {'var' :'var2'},
214 {'var' :'var3'},
215 ],
216 },
217 }
218 # template = Template()
219 # template.load('tmp2')
220 # print template.value('program', vars)
221
222 import StringIO
223
224 buf = StringIO.StringIO("""mkdir src/doc
225 mkdir build
226 copy dict.xml src/doc
227 run tmp2 py "program" build/s.py
228 """)
229
230 ts = TemplateScript()
231 ts(buf, vars)
Tree模块程序
1 #coding=utf-8
2 # Programmer: limodou
3 # E-mail: [email protected]
4 #
5 # Copyleft 2004 limodou
6 #
7 # Distributed under the terms of the GPL (GNU Public License)
8 #
9 # NewEdit is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 2 of the License, or
12 # (at your option) any later version.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with this program; if not, write to the Free Software
21 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #
23 # $Id$
24
25 """
26 本模块是用于保存树状结构的数据。保存和存储时均以树的引用方式来引用,如tree["/root/node"]
27 内部使用字典来保存,有多种接口可以将内容保存为其它的形式或从其它的形式读出数据
28 """
29
30 import types
31 #import xml.sax
32 import xml.dom.minidom
33
34 class UnsupportType(Exception): pass
35
36 class Tree:
37 def __init__(self, dicts=None):
38 if not dicts:
39 self.dicts = {}
40 else:
41 self.dicts = dicts
42 self.tab = ' ' * 4
43
44 def __getitem__(self, key):
45 path = self._path(key)
46
47 dict = self.getNode(self.dicts, path)
48 return dict.get(path[-1], None)
49
50 def __setitem__(self, key, value):
51 path = self._path(key)
52
53 dict = self.getNode(self.dicts, path)
54 dict[path[-1]] = value
55
56 def append(self, key, value):
57 path = self._path(key)
58 key = path[-1]
59
60 dict = self.getNode(self.dicts, path)
61 print 'dict', dict
62
63 if dict.has_key(key):
64 if isinstance(dict[key], types.ListType):
65 dict[key].append(value)
66 elif isinstance(dict[key], types.TupleType):
67 dict[key] = dict[key] + (value,)
68 else:
69 dict[key] = [dict[key], value]
70 else:
71 dict[key] = value
72
73 def getNode(self, dicts, path):
74 if len(path) > 1:
75 node = path[0]
76 if not dicts.has_key(node):
77 dicts[node] = {}
78 return self.getNode(dicts[node], path[1:])
79 return dicts
80
81 def _path(self, key):
82 if key.startswith('/'):
83 key = key[1:]
84 return key.split('/')
85
86 def write_to_xml(self):
87 s = []
88 s.append('<?xml version="1.0" encoding="utf-8"?>\n')
89 s.append('<tree>\n')
90 self._write_dict(s, self.dicts, level = 1)
91 s.append('</tree>\n')
92 return ''.join(s)
93
94 def _write_dict(self, s, dicts, level):
95 for key, value in dicts.items():
96 if isinstance(value, types.DictType):
97 s.append(self.tab * level + '<%s>\n' % key)
98 self._write_dict(s, value, level + 1)
99 s.append(self.tab * level + '</%s>\n' % key)
100 elif isinstance(value, types.BooleanType):
101 s.append(self.tab * level + '<%s type="boolean">%s</%s>\n' % (key, str(value), key))
102 elif isinstance(value, types.StringType):
103 s.append(self.tab * level + '<%s type="string">%s</%s>\n' % (key, self._quoteText(value), key))
104 elif isinstance(value, types.UnicodeType):
105 s.append(self.tab * level + '<%s type="unicode">%s</%s>\n' % (key, self._quoteText(value.encode('utf-8')), key))
106 elif isinstance(value, types.IntType):
107 s.append(self.tab * level + '<%s type="int">%d</%s>\n' % (key, value, key))
108 elif isinstance(value, types.LongType):
109 s.append(self.tab * level + '<%s type="long">%ld</%s>\n' % (key, value, key))
110 elif isinstance(value, types.FloatType):
111 s.append(self.tab * level + '<%s type="float">%f</%s>\n' % (key, value, key))
112 elif isinstance(value, types.ListType) or isinstance(value, types.TupleType):
113 for v in value:
114 dic = {key:v}
115 self._write_dict(s, dic, level)
116 else:
117 raise UnsupportType, 'Unsupport type'
118
119 def read_from_xml(self, text):
120 self.dicts = {}
121 dom = xml.dom.minidom.parseString(text)
122 root = dom.documentElement
123 self._read_from_xml(self.dicts, root)
124
125 def _read_from_xml(self, dicts, root):
126 for node in root.childNodes:
127 name = node.nodeName.encode('utf-8')
128 if node.nodeType == node.ELEMENT_NODE:
129 if node.hasAttribute('type'):
130 t = node.getAttribute('type')
131 content = self._getTagText(node)
132
133 if t == 'int':
134 value = int(content)
135 elif t == 'long':
136 value = long(content)
137 elif t == 'string':
138 value = content.encode('utf-8')
139 elif t == 'unicode':
140 value = content
141 elif t == 'boolean':
142 if content == 'True':
143 value = True
144 else:
145 value = False
146 elif t == 'float':
147 value = float(content)
148 else:
149 raise UnsupportType, 'Unsupport type'
150
151 if dicts.has_key(name):
152 v = dicts[name]
153 if isinstance(v, types.ListType):
154 v.append(value)
155 else:
156 dicts[name] = [dicts[name], value]
157 else:
158 dicts[name] = value
159 else:
160 dic = {}
161 if dicts.has_key(name):
162 v = dicts[name]
163 if isinstance(v, types.ListType):
164 v.append(dic)
165 else:
166 dicts[name] = [dicts[name], dic]
167 else:
168 dicts[name] = dic
169
170 self._read_from_xml(dic, node)
171
172 def _getTagText(self, tag):
173 rc = ''
174 for node in tag.childNodes:
175 if node.nodeType in ( node.TEXT_NODE, node.CDATA_SECTION_NODE):
176 rc = rc + node.data
177 return rc
178
179 def _quoteText(self, text):
180 text = text.replace('&', '&')
181 text = text.replace('<', '<')
182 return text
183
184 def getDict(self):
185 return self.dicts
186
187 if __name__ == '__main__':
188 tree = Tree()
189
190 name = '中国'
191 tree['/root/command/test1'] =[{ 'var':'<&>'}, {'var':'limodou'}]
192 tree['/root/command/ttt'] =[unicode(name, 'utf-8'), 100, {'a':False}]
193 tree['/root/command/ttt'] =[(1,2), ('aaa', 'bbb', 'cccc')] #this form is not support
194 text = tree.write_to_xml()
195 file("dict.xml", 'w').write(text)
196 text = file('dict.xml').read()
197 tree.read_from_xml(text)
198 print tree.dicts