含有章节索引的中文 文章模板

-- limodou [2004-08-28 04:10:50]

1. Meteor源程序

程序不长,因此列在这里

1.1. 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)

1.2. 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('&', '&amp;')
 181         text = text.replace('<', '&lt;')
 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':'<&amp;>'}, {'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