Show
Ignore:
Timestamp:
09/22/08 15:40:45 (18 months ago)
Author:
JensDiemer
Message:

add macro function to creole markup

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/pylucid_project/PyLucid/system/markups/creole.py

    r1769 r1771  
    7777    #-------------------------------------------------------------------------- 
    7878 
     79    macro_block = r'''(?P<macro_block> 
     80            \s* << (?P<macro_block_start>\w+) \s* (?P<macro_block_args>.*?) >> 
     81            (?P<macro_block_text>(.|\n)+?) 
     82            <</(?P=macro_block_start)>> \s* 
     83        )''' 
     84         
    7985    macro = r'''(?P<macro> 
    8086            << 
    81             (?P<macro_name> \w+) 
    82             (\( (?P<macro_args> .*?) \))? \s* 
    83             ([|] \s* (?P<macro_text> .+?) \s* )? 
     87            (?P<macro_name> \w+) (?P<macro_args>.*?) 
    8488            >> 
    8589        )''' 
     
    9599    # For the block elements: 
    96100    separator = r'(?P<separator> ^ \s* ---- \s* $ )' # horizontal line 
    97     line = r'(?P<line> ^ \s* $ )' # empty line that separates paragraphs 
     101    line = r'''(?P<line> ^\s*$ )''' # empty line that separates paragraphs 
    98102    head = r'''(?P<head> 
    99103            ^ 
    100104            (?P<head_head>=+) \s* 
    101105            (?P<head_text> .*? ) 
    102             =* \s*$ 
    103         )\n*''' 
     106            =*$ 
     107        )''' 
    104108    text = r'(?P<text> .+ ) (?P<break> (?<!\\)$\n(?!\s*$) )?' 
    105109    list = r'''(?P<list> 
     
    124128    pre_escape = r' ^(?P<indent>\s*) ~ (?P<rest> \}\}\} \s*) $' 
    125129 
    126     # Pass-through all django template blocktags 
    127     passthrough_block = r'''^ \s*(?P<passthrough_block> 
    128             {%.*?%} 
    129             (.|\n)+? 
    130             {%.*?%} 
    131         ) \s*$ 
    132         ''' 
    133     passthrough_line = r'''(?P<passthrough_line> 
     130    # Pass-through all django template blocktags        
     131    pass_block = r'''(?P<pass_block> 
     132            {% \s* (?P<pass_block_start>.+?) \s* (?P<pass_block_args>.*?) \s* %} 
     133            (\n|.)*? 
     134            {% \s* end(?P=pass_block_start) \s* %} 
     135        )''' 
     136         
     137    pass_line = r'''\n(?P<pass_line> 
     138            (\n|\s)* 
    134139            ({%.*?%})| 
    135140            ({{.*?}}) 
    136         )''' 
     141            (\n|\s)* 
     142        )''' 
     143    pass_inline = r'''(?P<pass_inline> 
     144            ({%.*?%})| 
     145            ({{.*?}}) 
     146        )''' 
     147         
    137148    #Pass-through html code lines 
    138149    html = r'''(?P<html> 
    139             ^ \s*<.*?> \s*$ 
     150            ^[ \t]*<[a-zA-Z].*?<(/[a-zA-Z ]+?)>[ \t]*$ 
    140151        )''' 
    141152 
     
    153164            ) \s* 
    154165        ''' % '|'.join([link, macro, image, code]) 
    155          
     166 
    156167    #-------------------------------------------------------------------------- 
    157     blockelements = ( 
    158         "head", "list", "pre", "code", "table", "separator", "macro", 
    159         "passthrough_block", "html" 
    160     ) 
     168#    blockelements = ( 
     169#        "head", "list", "pre", "code", "table", "separator", "macro", 
     170#        "pass_block", "pass_line", "html" 
     171#    ) 
    161172 
    162173class Parser: 
     
    177188    block_re = re.compile( 
    178189        '|'.join([ 
    179             Rules.passthrough_block, 
     190            Rules.pass_block, 
     191            Rules.pass_line, 
     192            Rules.macro_block, 
    180193            Rules.html, 
    181194            Rules.line, Rules.head, Rules.separator, Rules.pre, Rules.list, 
     
    189202            Rules.link, Rules.url, Rules.macro, 
    190203            Rules.code, Rules.image, 
    191             Rules.passthrough_line, 
     204            Rules.pass_inline, 
    192205            Rules.strong, Rules.emph, Rules.linebreak, 
    193206            Rules.escape, Rules.char 
     
    201214        self.cur = self.root        # The most recent document node 
    202215        self.text = None            # The node to add inline characters to 
     216        self.last_text_break = None # Last break node, inserted by _text_repl() 
    203217 
    204218    #-------------------------------------------------------------------------- 
     219 
     220    def cleanup_break(self, old_cur): 
     221        """ 
     222        remove unused end line breaks. 
     223        Should be called before a new block element. 
     224        e.g.: 
     225          <p>line one<br /> 
     226          line two<br />     <--- remove this br-tag 
     227          </p> 
     228        """ 
     229        if self.cur.children: 
     230            last_child = self.cur.children[-1] 
     231            if last_child.kind == "break": 
     232                del(self.cur.children[-1]) 
    205233 
    206234    def _upto(self, node, kinds): 
     
    210238        Start at the node node. 
    211239        """ 
     240        self.cleanup_break(node) # remove unused end line breaks. 
    212241        while node.parent is not None and not node.kind in kinds: 
    213242            node = node.parent 
     243         
    214244        return node 
    215245 
     
    221251    # same method needs several names, because of group names in regexps. 
    222252 
    223     def _passthrough_block_repl(self, groups): 
    224         """ Pass-through all django template blocktags """ 
     253    def _pass_block_repl(self, groups): 
     254        """ Pass-through all django template blocktags """           
    225255        self._upto_block() 
    226         DocNode("passthrough_block", self.root, groups["passthrough_block"]) 
     256        self.cur = self.root 
     257        DocNode("pass_block", self.cur, groups["pass_block"]) 
     258        self.text = None 
     259    _pass_block_start_repl = _pass_block_repl 
     260    _pass_block_end_repl = _pass_block_repl 
     261 
     262    def _pass_line_repl(self, groups): 
     263        """ Pass-through all django tags witch is alone in a code line """ 
     264        self._upto_block() 
     265        self.cur = self.root 
     266        DocNode("pass_line", self.cur, groups["pass_line"]) 
    227267        self.text = None 
    228268         
    229     def _passthrough_line_repl(self, groups): 
    230         """ Pass-through all django tags """ 
    231         DocNode("passthrough_line", self.cur, groups["passthrough_line"]) 
    232         self.text = None 
    233          
     269    def _pass_inline_repl(self, groups): 
     270        """ Pass-through all inline django tags""" 
     271        DocNode("pass_inline", self.cur, groups["pass_inline"]) 
     272        self.text = None 
     273 
    234274    def _html_repl(self, groups): 
    235275        """ Pass-through html code """ 
     
    239279 
    240280    def _text_repl(self, groups): 
    241 #        print "_text_repl()", self.cur.kind, groups.get('break') != None            
     281#        print "_text_repl()", self.cur.kind, groups.get('break') != None 
    242282        if self.cur.kind in ('table', 'table_row', 'bullet_list', 
    243283                                                                'number_list'): 
    244284            self._upto_block() 
    245              
     285 
    246286        if self.cur.kind in ('document', 'section', 'blockquote'): 
    247287            self.cur = DocNode('paragraph', self.cur) 
    248              
    249         self.parse_inline(groups.get('text', '')) 
    250          
     288 
     289        self.parse_inline(groups.get('text', u"")) 
     290 
    251291        if groups.get('break') and self.cur.kind in ('paragraph', 
    252292            'emphasis', 'strong', 'code'): 
    253             DocNode('break', self.cur, '') 
    254              
     293            self.last_text_break = DocNode('break', self.cur, u"") 
     294 
    255295        self.text = None 
    256296    _break_repl = _text_repl 
     
    260300        if not groups.get('escaped_url'): 
    261301            # this url is NOT escaped 
    262             target = groups.get('url_target', '') 
     302            target = groups.get('url_target', u"") 
    263303            node = DocNode('link', self.cur) 
    264304            node.content = target 
     
    268308            # this url is escaped, we render it as text 
    269309            if self.text is None: 
    270                 self.text = DocNode('text', self.cur, u'') 
     310                self.text = DocNode('text', self.cur, u"") 
    271311            self.text.content += groups.get('url_target') 
    272312    _url_target_repl = _url_repl 
     
    276316    def _link_repl(self, groups): 
    277317        """Handle all kinds of links.""" 
    278         target = groups.get('link_target', '') 
    279         text = (groups.get('link_text', '') or '').strip() 
     318        target = groups.get('link_target', u"") 
     319        text = (groups.get('link_text', u"") or u"").strip() 
    280320        parent = self.cur 
    281321        self.cur = DocNode('link', self.cur) 
     
    288328    _link_text_repl = _link_repl 
    289329 
     330    def _add_macro(self, macro_name, macro_args, macro_text=u""): 
     331#        self._upto_block() 
     332        node = DocNode("macro", self.cur, macro_text.strip()) 
     333        node.macro_name = macro_name 
     334        node.macro_args = macro_args.strip() 
     335        self.text = None 
     336 
     337    def _macro_block_repl(self, groups): 
     338        """Handles macros using the placeholder syntax.""" 
     339        #self.debug_groups(groups) 
     340        self._upto_block() 
     341        self.cur = self.root 
     342        self._add_macro( 
     343            macro_name = groups['macro_block_start'], 
     344            macro_text = groups.get('macro_block_text', u""), 
     345            macro_args = groups.get('macro_block_args', u""), 
     346        ) 
     347        self.text = None 
     348    _macro_block_start_repl = _macro_block_repl 
     349    _macro_block_args_repl = _macro_block_repl 
     350    _macro_block_text_repl = _macro_block_repl 
     351 
    290352    def _macro_repl(self, groups): 
    291353        """Handles macros using the placeholder syntax.""" 
    292         name = groups.get('macro_name', '') 
    293         text = (groups.get('macro_text', '') or '').strip() 
    294         node = DocNode('macro', self.cur, name) 
    295         node.args = groups.get('macro_args', '') or '' 
    296         DocNode('text', node, text or name) 
    297         self.text = None 
     354        macro_name = groups.get('macro_name', u"") 
     355        macro_args = groups.get('macro_args', u"") 
     356        self._add_macro(macro_name, macro_args) 
     357        self.text = None 
     358 
     359#        text = (groups.get('macro_text', u"") or u"").strip() 
     360#        node = DocNode('macro', self.cur, name) 
     361#        node.args = groups.get('macro_args', u"") or '' 
     362#        DocNode('text', node, text or name) 
     363#        self.text = None 
    298364    _macro_name_repl = _macro_repl 
    299365    _macro_args_repl = _macro_repl 
    300     _macro_text_repl = _macro_repl 
     366#    _macro_text_repl = _macro_repl 
    301367 
    302368    def _image_repl(self, groups): 
    303369        """Handles images and attachemnts included in the page.""" 
    304         target = groups.get('image_target', '').strip() 
    305         text = (groups.get('image_text', '') or '').strip() 
     370        target = groups.get('image_target', u"").strip() 
     371        text = (groups.get('image_text', u"") or u"").strip() 
    306372        node = DocNode("image", self.cur, target) 
    307373        DocNode('text', node, text or node.content) 
     
    315381 
    316382    def _item_repl(self, groups): 
    317         bullet = groups.get('item_head', u'') 
    318         text = groups.get('item_text', u'') 
     383        bullet = groups.get('item_head', u"") 
     384        text = groups.get('item_text', u"") 
    319385        if bullet[-1] == '#': 
    320386            kind = 'number_list' 
     
    371437                self.text = None 
    372438            else: 
    373                 text = m.group('head').strip('= ')  
     439                text = m.group('head').strip('= ') 
    374440                self.cur = DocNode('table_head', tr) 
    375                 self.text = DocNode('text', self.cur, u'') 
     441                self.text = DocNode('text', self.cur, u"") 
    376442            self.parse_inline(text) 
    377              
     443 
    378444        self.cur = tb 
    379445        self.text = None 
     
    382448        self._upto_block() 
    383449        kind = groups.get('pre_kind', None) 
    384         text = groups.get('pre_text', u'') 
     450        text = groups.get('pre_text', u"") 
    385451        def remove_tilde(m): 
    386452            return m.group('indent') + m.group('rest') 
     
    396462        """ Transfer newline from the original markup into the html code """ 
    397463        self._upto_block() 
    398         DocNode('line', self.cur, "") 
     464        DocNode('line', self.cur, u"") 
    399465 
    400466    def _code_repl(self, groups): 
    401         DocNode('code', self.cur, groups.get('code_text', u'').strip()) 
     467        DocNode('code', self.cur, groups.get('code_text', u"").strip()) 
    402468        self.text = None 
    403469    _code_text_repl = _code_repl 
     
    424490    def _escape_repl(self, groups): 
    425491        if self.text is None: 
    426             self.text = DocNode('text', self.cur, u'') 
    427         self.text.content += groups.get('escaped_char', u'') 
     492            self.text = DocNode('text', self.cur, u"") 
     493        self.text.content += groups.get('escaped_char', u"") 
    428494 
    429495    def _char_repl(self, groups): 
    430496        if self.text is None: 
    431             self.text = DocNode('text', self.cur, u'') 
    432         self.text.content += groups.get('char', u'') 
    433  
    434     #-------------------------------------------------------------------------- 
    435      
    436     def check_break(self): 
    437         """ 
    438         remove unused end line breaks. Should be called on every block element. 
    439         e.g.: 
    440           <p>line one<br /> 
    441           line two<br />     <--- remove this br-tag 
    442           </p> 
    443         """ 
    444         if self.cur.children == []: 
    445             return 
    446         if self.cur.children[-1].kind == "break": 
    447             del(self.cur.children[-1]) 
    448      
     497            self.text = DocNode('text', self.cur, u"") 
     498        self.text.content += groups.get('char', u"") 
     499 
    449500    #-------------------------------------------------------------------------- 
    450501 
     
    455506            if text is not None: 
    456507                #if name != "char": print "%15s: %r" % (name, text) 
    457                 if name in Rules.blockelements: 
    458                     self.check_break() 
     508                #print "%15s: %r" % (name, text) 
    459509                replace = getattr(self, '_%s_repl' % name) 
    460510                replace(groups) 
     
    476526 
    477527    #-------------------------------------------------------------------------- 
    478     def debug(self): 
     528    def debug(self, start_node=None): 
    479529        """ 
    480530        Display the current document tree 
    481531        """ 
    482532        print "_"*80 
    483         print "  document tree:" 
     533                 
     534        if start_node == None: 
     535            start_node = self.root 
     536            print "  document tree:" 
     537        else: 
     538            print "  tree from %s:" % start_node 
     539             
    484540        print "="*80 
    485541        def emit(node, ident=0): 
    486542            for child in node.children: 
    487                 print u"%s%s" % (u" "*ident, child) 
     543                print u"%s%s: %r" % (u" "*ident, child.kind, child.content) 
    488544                emit(child, ident+4) 
    489         emit(self.root) 
     545        emit(start_node) 
    490546        print "*"*80 
    491      
     547 
    492548    def debug_groups(self, groups): 
    493549        print "_"*80 
     
    511567        self.parent = parent 
    512568        self.kind = kind 
     569 
     570        if content: 
     571            content = unicode(content) 
    513572        self.content = content 
     573 
    514574        if self.parent is not None: 
    515575            self.parent.children.append(self) 
     
    517577    def __str__(self): 
    518578#        return "DocNode kind '%s', content: %r" % (self.kind, self.content) 
    519         return "%s: %r" % (self.kind, self.content) 
     579        return "<DocNode %s: %r>" % (self.kind, self.content) 
     580    def __repr__(self): 
     581        return u"<DocNode %s: %r>" % (self.kind, self.content) 
     582 
     583    def debug(self): 
     584        print "_"*80 
     585        print "\tDocNode - debug:" 
     586        print "str(): %s" % self 
     587        print "attributes:" 
     588        for i in dir(self): 
     589            if i.startswith("_"): 
     590                continue 
     591            print "%20s: %r" % (i, getattr(self, i, "---")) 
    520592 
    521593 
     
    549621picture [[www.domain.tld | {{ foo.JPG | Foo }} ]] as a link 
    550622 
    551 END""" 
    552  
     623END 
     624 
     625==== Headline 1 
     626 
     627{% a tag 1 %} 
     628 
     629==== Headline 2 
     630 
     631{% a tag 2 %} 
     632 
     633the end 
     634""" 
     635 
     636    txt = r""" 
     637==== Headline 1 
     638 
     639The current page name: >{{ PAGE.name }}< great? 
     640 
     641{% a tag 1 %} 
     642 
     643==== Headline 2 
     644 
     645{% a tag 2 %} 
     646 
     647some text 
     648 
     649{% something arg1="foo" arg2="bar" arg2=3 %} 
     650foobar 
     651{% endsomething %} 
     652 
     653the end 
     654""" 
     655 
     656    txt = r"""A {% lucidTag page_update_list count=10 %} PyLucid plugin 
     657 
     658{% sourcecode py %} 
     659import sys 
     660 
     661sys.stdout("Hello World!") 
     662{% endsourcecode %} 
     663A [[www.domain.tld|link]].""" 
     664 
     665    txt = r""" 
     666==== Headline 1 
     667 
     668On {% a tag 1 %} line 
     669line two 
     670 
     671==== Headline 2 
     672 
     673{% a tag 2 %} 
     674 
     675A block: 
     676{% block %} 
     677<Foo:> {{ Bar }} 
     678{% endblock %} 
     679end block 
     680 
     681{% block1 arg="jo" %} 
     682eofjwqp 
     683{% endblock1 %} 
     684 
     685A block without the right end block: 
     686{% block1 %} 
     687111 
     688{% endblock2 %} 
     689BBB 
     690 
     691A block without endblock: 
     692{% block3 %} 
     693222 
     694{% block3 %} 
     695CCC 
     696 
     697the end""" 
     698#    txt = r''' 
     699#<<jojo>> 
     700#owrej 
     701#<<code>> 
     702#some code 
     703#<</code>> 
     704#a macro: 
     705#<<code ext=.css>> 
     706#/* Stylesheet */ 
     707#form * { 
     708#  vertical-align:middle; 
     709#} 
     710#<</code>> 
     711#the end 
     712#<<code>> 
     713#<<code>> 
     714#jup 
     715#<</code>> 
     716#''' 
     717 
     718 
     719    print "-"*80 
    553720    p = Parser(txt) 
    554721    document = p.parse() 
    555722    p.debug() 
    556  
     723     
    557724    def test_rules(rules, txt): 
    558725        def display_match(match): 
     
    563730        re.sub(rules, display_match, txt) 
    564731 
    565     print "_"*80 
    566     print "plain block rules match:" 
    567     test_rules(Parser("").block_re, txt) 
    568  
    569     print "_"*80 
    570     print "plain inline rules match:" 
    571     test_rules(Parser("").inline_re, txt) 
     732#    print "_"*80 
     733#    print "plain block rules match:" 
     734#    test_rules(Parser("").block_re, txt) 
     735# 
     736#    print "_"*80 
     737#    print "plain inline rules match:" 
     738#    test_rules(Parser("").inline_re, txt) 
    572739 
    573740    print "---END---"