Changeset 3106


Ignore:
Timestamp:
Aug 23, 2006 8:02:56 PM (11 years ago)
Author:
moschny
Message:
  • Refactoring: Capture the state of one macro invocation in an instance of the new Invocation class. This way, fewer variables need to be passed around. Additionally, the indented output can be handled by methods, which is much cleaner.
  • Make 'WikiStart' the default for curpage, as suggested on the TracNav homepage.
  • Clean-ups.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trac/plugins/tracnav/tracnav/tracnav.py

    r3097 r3106  
    5656"""
    5757__id__        = '$Id$'
    58 __version__   = '3.92pre5'
     58__version__   = '3.92pre6'
    5959__revision__  = '$LastChangedRevision$'
    6060
     
    110110
    111111
    112 class TracNav(Component):
    113 
    114     implements(IWikiMacroProvider, ITemplateProvider)
    115 
    116     def get_toc(self, req, name):
     112class Invocation(object):
     113
     114    def __init__(self, env, req, args, out):
     115
     116        #save for later use
     117        self.env = env
     118        self.req = req
     119        self.out = out
     120        self.col = 0
     121       
     122        #needed several times
     123        self.preview = req.args.get('preview', '')
     124        self.curpage = req.args.get('page', 'WikiStart')
     125        self.modify = req.perm.has_permission('WIKI_MODIFY')
     126
     127        # parse arguments
     128        self.names = []
     129        self.collapse = True
     130        if args:
     131            for arg in args.split('|'):
     132                if arg == 'nocollapse':
     133                    self.collapse = False
     134                else:
     135                    self.names.append(arg)
     136
     137    def get_toc(self, name):
    117138        """
    118139        Fetch the wiki page containing the toc, if available.
    119140        """
    120         preview = req.args.get('preview', '')
    121         curpage = req.args.get('page')
    122 
    123         if preview and name == curpage:
    124             return req.args.get('text', '')
     141        if self.preview and name == self.curpage:
     142            return self.req.args.get('text', '')
    125143        elif WikiSystem(self.env).has_page(name):
    126144            return WikiPage(self.env, name).text
     
    128146            return ''
    129147
    130 
    131     def get_toc_entry(self, toc_text, req):
     148    def get_toc_entry(self, toc_text):
    132149        """
    133150        Parse and format the entries in toc_text.
    134151        """
    135         formatter = TocFormatter(self.env, req)
     152        formatter = TocFormatter(self.env, self.req)
    136153        for match in LISTRULE.finditer(toc_text):
    137154            indent = len(match.group('indent'))
    138155            label, link = formatter.format_toc(match.group('rest'))
    139156            yield indent, link, label
    140 
    141157
    142158    def get_toc_entry_and_indent(self, gen):
     
    154170            yield indent
    155171            yield link, label       
    156 
    157172
    158173    def _parse_toc(self, gen, next_indent, level = 0):
     
    179194                return toclist, next_indent
    180195
    181 
    182     def parse_toc(self, toc_text, req = None):
     196    def parse_toc(self, toc_text):
    183197        """
    184198        Recursively construct the toc tree using _parse_toc().
    185199        """
    186         gen = self.get_toc_entry(toc_text, req)
    187         gen = self.get_toc_entry_and_indent(gen)
     200        gen = self.get_toc_entry_and_indent(self.get_toc_entry(toc_text))
    188201        toc, _ = self._parse_toc(gen, gen.next())
    189202        return toc
    190203
    191 
    192     def execute(self, req, args):
     204    def write(self, what):
     205        self.out.write(' ' * self.col)
     206        self.out.write(what)
     207        return self
     208
     209    def indent_more(self):
     210        self.col += 1
     211        return self
     212
     213    def indent_less(self):
     214        self.col -= 1
     215        return self
     216
     217    def run(self):
    193218        """
    194219        Main routine of the wiki macro.
    195220        """
    196 
    197         #init
    198         out = StringIO()
    199         names = []
    200         collapse = True
    201         curpage = req.args.get('page','')
    202 
    203         # parse arguments
    204         if args:
    205             for arg in args.split('|'):
    206                 if arg == 'nocollapse':
    207                     collapse = False
    208                 else:
    209                     names.append(arg)
    210        
    211221        # header
    212         col = 0
    213         out.write('%s<div class="wiki-toc trac-nav">\n' % self.i(col))
    214         col += 1
    215         out.write('%s<h2><a href="%s">TracNav</a> menu</h2>\n' % \
    216                   (self.i(col), TRACNAVHOME))
     222        self.write('<div class="wiki-toc trac-nav">\n').indent_more()
     223        self.write('<h2><a href="%s">TracNav</a> menu</h2>\n' % TRACNAVHOME)
    217224
    218225        # add TOCs
    219         for name in (names or ["TOC"]):
    220             toc_text = self.get_toc(req, name)
    221             toc = self.parse_toc(toc_text, req)
     226        for name in (self.names or ["TOC"]):
     227            toc = self.parse_toc(self.get_toc(name))
    222228            if not toc:
    223229                toc = self.parse_toc(' * TOC "%s" is empty!' % name)
    224             if collapse:
    225                 (found, filtered) = self.filter_toc(curpage, toc)
    226                 if found:
    227                     self.display_all(out, req, name, filtered, col)
    228                 else:
    229                     self.display_all(out, req, name, toc, col)
     230            found, filtered = self.filter_toc(toc)
     231            if (not self.collapse) or (not found):
     232                self.display_all(name, toc)
    230233            else:
    231                 self.display_all(out, req, name, toc, col)
    232 
    233         # footer
    234         col -= 1
    235         out.write('%s</div>\n' % self.i(col))
     234                self.display_all(name, filtered)
     235
     236        # footer
     237        self.indent_less().write('</div>\n')
    236238
    237239        # add our stylesheet
    238         add_stylesheet(req, 'tracnav/css/tracnav.css')
    239 
    240         # emit
    241         return out.getvalue()
    242 
    243 
    244     def filter_toc(self, curpage, toc, level = 0):
    245         found = 0
     240        add_stylesheet(self.req, 'tracnav/css/tracnav.css')
     241
     242    def filter_toc(self, toc, level = 0):
     243        found = False
    246244        result = []
    247245        for name, title, sub in toc:
    248246            if sub == None:
    249                 if name == curpage:
    250                     found = 1
     247                if name == self.curpage:
     248                    found = True
    251249                result.append((name, title, None))
    252250            else:
    253                 (subfound, subtoc) = self.filter_toc(curpage, sub, level + 1)
     251                subfound, subtoc = self.filter_toc(sub, level + 1)
    254252                if subfound:
    255                     found = 1
     253                    found = True
    256254                if subfound or (name == None):
    257255                    if level == 0 and name != None:
     
    263261                else:
    264262                    result.append((name, title, []))
    265         return (found, result)
    266 
    267 
    268     def i(self, col):
    269         return ' ' * col
    270 
    271 
    272     def display_all(self, out, req, name, toc, col):
    273         preview = req.hdf.getValue('args.preview', '')
    274         curpage = req.hdf.getValue('wiki.page_name', '')
    275 
    276         if (not preview) and req.hdf.getValue('trac.acl.WIKI_MODIFY', ''):
    277             out.write('%s<div class="edit"><a href="%s?action=edit">edit</a></div>\n' % \
    278                     (self.i(col), self.env.href.wiki(name)))
    279         out.write('%s<ul>\n' % self.i(col))
    280         col += 1
    281         self.display(out, curpage, toc, 0, col)
    282         col -= 1
    283         out.write('%s</ul>\n' % self.i(col))
    284 
    285 
    286     def display(self, out, curpage, toc, depth, col):
     263        return found, result
     264
     265    def display_all(self, name, toc):
     266        if (not self.preview) and (self.modify):
     267            self.write('<div class="edit"><a href="%s?action=edit">edit</a></div>\n' % \
     268                self.env.href.wiki(name))
     269        self.write('<ul>\n').indent_more()
     270        self.display(toc, 0)
     271        self.indent_less().write('</ul>\n')
     272
     273    def display(self, toc, depth):
    287274        for name, title, sub in toc:
    288275            li_style = ' style="padding-left: %dem;"' % (depth + 1)
    289276            if sub == None:
    290                 if name == curpage:
     277                if name == self.curpage:
    291278                    cls = ' class="active"'
    292279                else:
    293280                    cls = ''
    294                 out.write('%s<li%s%s>%s</li>\n' % \
    295                         (self.i(col), li_style, cls, title))
     281                self.write('<li%s%s>%s</li>\n' % (li_style, cls, title))
    296282            else:
    297                 out.write('%s<li%s>\n' % (self.i(col), li_style))
    298                 col += 1
     283                self.write('<li%s>\n' % li_style).indent_more()
    299284                if name == None or sub:
    300                     out.write('%s<h4>%s</h4>\n' % (self.i(col), title))
    301                 else:
    302                     out.write('%s<h4>%s...</h4>\n' % (self.i(col), title))
    303                 col -= 1
    304                 out.write('%s</li>\n' % self.i(col))
     285                    self.write('<h4>%s</h4>\n' % title)
     286                else:
     287                    self.write('<h4>%s...</h4>\n' % title)
     288                self.indent_less().write('</li>\n')
    305289                if len(sub) > 0:
    306                     self.display(out, curpage, sub, depth + 1, col)
    307 
     290                    self.display(sub, depth + 1)
     291
     292
     293class TracNav(Component):
     294
     295    implements(IWikiMacroProvider, ITemplateProvider)
    308296
    309297    def get_macros(self):
    310298        yield 'TracNav'
    311         yield 'JPNav'
    312 
     299        yield 'JPNav' # legacy
    313300
    314301    def render_macro(self, req, name, args):
    315         return self.execute(req, args)
    316    
     302        out = StringIO()
     303        Invocation(self.env, req, args, out).run()
     304        return out.getvalue()
    317305
    318306    def get_macro_description(self, name):
     
    320308        return getdoc(getmodule(self))
    321309
    322 
    323310    def get_htdocs_dirs(self):
    324311        from pkg_resources import resource_filename
    325312        return [('tracnav', resource_filename(__name__, 'htdocs'))]
    326313
    327 
    328314    def get_templates_dirs(self):
    329315        # we don't provide templates
    330316        return []
    331    
Note: See TracChangeset for help on using the changeset viewer.