这是我学python学习的第一个项目,就是python教程后面的第一个文本标记,在这里写下来 跟大家一起分享一下

1,首先 需要一个文件util.py(代码如下

  1. '''''  
  2. Created on 2012-7-30  
  3.  
  4. @author: mars  
  5. ''' 
  6. def lines(file):  
  7.     for line in file:yield line  
  8.     yield '/n' 
  9. def blocks(file):  
  10.     block=[]  
  11.     for line in lines(file):  
  12.         if  line.strip():  
  13.             block.append(line)  
  14.         elif block:  
  15.             yield ''.join(block).strip()   
  16.             block=[] 

)

主要目的是将文本分块,注意此处yiled生成器的用法,还有block函数,在lines函数下 参数是file,for line in file :yiled  line

yield '/n'

就是在文本最后面加上一个空行,方便后面的block的...strip()....函数的调用。

而block 函数就是将文本分块,首先block=[] 是一个空的列表,for循环检查文件中分行的部分,如果分行了 就将他弄为一个块,而且 ,然后如果是块的话 也就是执行elif语句部分,将块内用空格(' '.join)连接起来 最后又block置空!

2,接下来要出场的就是处理程序,也就是handler.py 代码如下

 

  1. '''''  
  2. Created on 2012-7-12  
  3.  
  4. @author: mars  
  5. ''' 
  6. class Handler:  
  7.     def callback(self,prefix,name,*args):  
  8.         method=getattr(self,prefix+name,None)  
  9.         if callable(method):  
  10.             return method(*args)  
  11.     def start(self,name):  
  12.         self.callback('start_', name)   
  13.     def end(self,name):     
  14.         self.callback("end_", name)    
  15.       
  16. class HTMLRenderer(Handler):  
  17.     def start_document(self):  
  18.         print('<html><head><title>..</title></head><body>')  
  19.     def end_document(self):  
  20.         print('</body></html>')  
  21.     def start_paragraph(self):  
  22.         print('<p>')  
  23.     def end_paragraph(self):  
  24.         print('</p>')  
  25.     def start_heading(self):  
  26.         print('<h2>')  
  27.     def end_heading(self):  
  28.         print('</h2>')   
  29.     def start_listitem(self):  
  30.         print('<li>')  
  31.     def end_listitem(self):  
  32.         print('</li>')      
  33.     def start_list(self):  
  34.         print('<ul>')  
  35.     def end_list(self):  
  36.         print('</ul>')  
  37.     def start_title(self):  
  38.         print('<h1>')  
  39.     def end_title(self):  
  40.         print('</h1>')  
  41.     def feed(self,data):  
  42.         print data             
  43.  
  44.     def sub(self,name):  
  45.             def substitution(match):  
  46.                 result=self.callback("sub_", name,match)  
  47.                 if result is None:match.group(0)  
  48.                 return result  
  49.             return substitution  
  50.        
  51.     def sub_emphasis(self,match):  
  52.         return '<em>%s</em>' %match.group(1)   
  53.     def sub_url(self,match):  
  54.         return '<a href="%s">%s</a>' %(match.group(1) ,match.group(1))  
  55.     def sub_main(self,match):  
  56.         return '<a href=" mail to %s">%s</a>' %(match.group(1) ,match.group(1))    
  57.  
  58.                                         
  59.            

这里主要值得说一下的是,def callback(self,prefix,name,*args):
        method=getattr(self,prefix+name,None)
        if callable(method):
            return method(*args)

这里的method右边的getattr Found at: __builtin__
getattr(object, name[, default]) -> value得知返回的是value

而下面的callable(method) callable Found at: __builtin__
callable(object) -> bool是一个bool型 最后返回的是method(*args) 比如callback的参数是prefix 'start_',name 是 document 的话 最后返回的就是start_document,

而下面的htmlHandler继承handler类,下面的函数你一看 就更加明白了

3,然后就是rules了,代码如下:

  1. '''''  
  2. Created on 2012-7-12  
  3.  
  4. @author: mars  
  5. ''' 
  6. class Rule:  
  7.     def action(self,block,handler):  
  8.         handler.start(self.type)  
  9.         handler.feed(block)  
  10.         handler.end(self.type)  
  11.         return True 
  12. class HeadingRule(Rule):  
  13.     type='heading' 
  14.     def condition(self,block):  
  15.         return not '\n' in block and len(block)<=70 and not block[-1]==':' 
  16. class TitleRule(HeadingRule):  
  17.     type='title' 
  18.     first=True 
  19.     def condition(self,block):  
  20.         if not self.first: return False 
  21.         self.first=False 
  22.         return HeadingRule.condition(self, block)  
  23. class ListItemRule(Rule):  
  24.     type='listitem' 
  25.     def condition(self,block):  
  26.         return block[0]=='-' 
  27.     def action(self,block,handler):  
  28.         handler.start(self.type)  
  29.         handler.feed(block[1:].strip())  
  30.         handler.end(self.type)  
  31.         return True              
  32. class ListRule(ListItemRule):  
  33.     type='list' 
  34.     inside=False 
  35.     def condition(self,block):  
  36.         return True     
  37.     def action(self,block,handler):  
  38.         if  not self.inside and ListItemRule.condition(self, block):  
  39.             handler.start(self.type)  
  40.             self.inside=True 
  41.         elif self.inside and not ListItemRule.condition(self, block):  
  42.             handler.end(self.type)  
  43.             self.inside=False 
  44.         return False   
  45. class ParagraphRule(Rule):  
  46.     type='paragraph'     
  47.     def condition(self,block):  
  48.         return True        

其实这个也很简单,仔细看,首先是Rule类 是个基类,他又start feed(就是给出block的数据) 还有end ,然后后面的函数继承下来,并给type赋值为 需要的标签类型

4,最后的就是markup.py了,也就是主执行程序,主要是过滤器

  1. '''''  
  2. Created on 2012-7-12  
  3.  
  4. @author: mars  
  5. ''' 
  6. import sys,re  
  7. from handlers import *  
  8. from rules import *  
  9. from util import *  
  10. class Parser:  
  11.     def __init__(self,handler):  
  12.         self.handler=handler  
  13.         self.rules=[]  
  14.         self.filters=[]  
  15.     def addRule(self,rule):  
  16.         self.rules.append(rule)  
  17.     def addFilter(self,pattern,name):  
  18.         def filter(block,handler):  
  19.             return re.sub(pattern,handler.sub(name),block)  
  20.         self.filters.append(filter)  
  21.     def parse(self,file):  
  22.         self.handler.start('document')  
  23.         for block in blocks(file):  
  24.             for filter in self.filters:  
  25.                 block=filter(block,self.handler)  
  26.             for rule in self.rules:  
  27.                 if rule.condition(block):  
  28.                     last=rule.action(block,self.handler)  
  29.                     if last:  
  30.                         break    
  31.         self.handler.end('document')  
  32. class BasicTextParser(Parser):  
  33.     def __init__(self,handler):  
  34.         Parser.__init__(self,handler)  
  35.         self.addRule(ListRule())  
  36.         self.addRule(ListItemRule())  
  37.         self.addRule(TitleRule())  
  38.         self.addRule(HeadingRule())  
  39.         self.addRule(ParagraphRule())  
  40.           
  41.         self.addFilter(r'\*(.+?)\*''emphasis')  
  42.         self.addFilter(r'(http://[\.a-zA-Z/]+)''url')  
  43.         self.addFilter(r'([\.a-zA-Z]+@[\.a-zA-Z]+[a-zA-Z]+)''mail')  
  44. handler=HTMLRenderer()  
  45. parser=BasicTextParser(handler)  
  46. parser.parse(sys.stdin)  
  47.                   
  48.                 
  49.          

主要想说的就是这个

def parse(self,file):
        self.handler.start('document')
        for block in blocks(file):
            for filter in self.filters:
                block=filter(block,self.handler)#重新将块绑定到结果
            for rule in self.rules:
                if rule.condition(block):
                    last=rule.action(block,self.handler)
                    if last:
                        break 

这段是调用处理程序start('doucument')开始,调用end('document')结尾,在这个中间迭代文本文件中所有的块,对每个块 使用过滤器(也就是filters)和规则(rules),而且使用过滤器只是用block和处理程序来调用filter函数(filter Found at: __module_not_in_the_pythonpath_)并且重新将块绑定到结果