1 # -*- coding: iso-8859-1 -*- 2 """ 3 MoinMoin - CategoryMenu Macro 4 5 @copyright: 2008 by Paul Boddie <paul@boddie.org.uk> 6 @copyright: 2000-2004 Juergen Hermann <jh@web.de>, 7 2005-2008 MoinMoin:ThomasWaldmann. 8 @license: GNU GPL (v2 or later), see COPYING.txt for details. 9 """ 10 11 from MoinMoin.Page import Page 12 from MoinMoin import wikiutil, search, version 13 import re 14 15 __version__ = "0.1" 16 17 Dependencies = ['pages'] 18 19 # Regular expressions where MoinMoin does not provide the required support. 20 21 category_regexp = None 22 23 # Utility functions. 24 25 def isMoin15(): 26 return version.release.startswith("1.5.") 27 28 def getCategoryPattern(request): 29 global category_regexp 30 31 try: 32 return request.cfg.cache.page_category_regexact 33 except AttributeError: 34 35 # Use regular expression from MoinMoin 1.7.1 otherwise. 36 37 if category_regexp is None: 38 category_regexp = re.compile(u'^%s$' % ur'(?P<all>Category(?P<key>(?!Template)\S+))', re.UNICODE) 39 return category_regexp 40 41 # The main activity functions. 42 43 def getCategories(request): 44 45 """ 46 From the AdvancedSearch macro, return a list of category page names using 47 the given 'request'. 48 """ 49 50 # This will return all pages with "Category" in the title. 51 52 cat_filter = getCategoryPattern(request).search 53 return request.rootpage.getPageList(filter=cat_filter) 54 55 def getCategoryMapping(category_pagenames, request): 56 57 """ 58 For the given 'category_pagenames' return a list of tuples of the form 59 (category name, category page name) using the given 'request'. 60 """ 61 62 cat_pattern = getCategoryPattern(request) 63 mapping = [] 64 for pagename in category_pagenames: 65 name = cat_pattern.match(pagename).group("key") 66 if name != "Category": 67 mapping.append((name, pagename)) 68 mapping.sort() 69 return mapping 70 71 def getPages(pagename, request): 72 73 "Return the links minus category links for 'pagename' using the 'request'." 74 75 query = search.QueryParser().parse_query('category:%s' % pagename) 76 if isMoin15(): 77 results = search.searchPages(request, query) 78 results.sortByPagename() 79 else: 80 results = search.searchPages(request, query, "page_name") 81 82 cat_pattern = getCategoryPattern(request) 83 pages = [] 84 for page in results.hits: 85 if not cat_pattern.match(page.page_name): 86 pages.append(page) 87 return pages 88 89 def execute(macro, args): 90 91 """ 92 Execute the 'macro' with the given 'args': an optional list of selected 93 category names (categories whose pages are to be shown). 94 """ 95 96 request = macro.request 97 fmt = macro.formatter 98 page = fmt.page 99 100 # Interpret the arguments. 101 102 try: 103 selected_category_names = wikiutil.parse_quoted_separated(args, name_value=False) 104 except AttributeError: 105 selected_category_names = args.split(",") 106 107 selected_category_names = [arg for arg in selected_category_names if arg] 108 109 # Get the categories. 110 111 categories = getCategoryMapping(getCategories(request), request) 112 113 # Generate a menu with the categories, together with expanded submenus for 114 # the categories employed by the current page, the category represented by 115 # the current page, or for those categories specified in the macro 116 # arguments. 117 118 output = [] 119 output.append(fmt.bullet_list(on=1, attr={"class" : "category-menu"})) 120 121 for category in categories: 122 category_name, category_pagename = category 123 124 pages_in_category = getPages(category_pagename, request) 125 pagenames_in_category = [p.page_name for p in pages_in_category] 126 page_is_category = page.page_name == category_pagename 127 128 # Generate the submenu where appropriate. 129 130 if selected_category_names and category_name in selected_category_names or \ 131 not selected_category_names and ( 132 page_is_category or page.page_name in pagenames_in_category): 133 134 if page_is_category: 135 output.append(fmt.listitem(on=1, attr={"class" : "selected current"})) 136 output.append(fmt.text(category_name)) 137 else: 138 output.append(fmt.listitem(on=1, attr={"class" : "selected"})) 139 output.append(fmt.pagelink(on=1, pagename=category_pagename)) 140 output.append(fmt.text(category_name)) 141 output.append(fmt.pagelink(on=0, pagename=category_pagename)) 142 143 output.append(fmt.bullet_list(on=1, attr={"class" : "category-submenu"})) 144 145 # Visit each page in the category. 146 147 last_parts = [] 148 149 for page_in_category in pages_in_category: 150 pagename = page_in_category.page_name 151 152 if page.page_name == pagename: 153 output.append(fmt.listitem(on=1, attr={"class" : "selected"})) 154 else: 155 output.append(fmt.listitem(on=1)) 156 output.append(fmt.pagelink(on=1, pagename=pagename)) 157 158 # Abbreviate long hierarchical names. 159 160 parts = pagename.split("/") 161 common = 0 162 for last, current in map(None, last_parts, parts): 163 if last == current: 164 common += 1 165 else: 166 break 167 168 # Use an em-dash to indicate subpages. 169 170 prefix = u"\u2014" * common 171 suffix = "/".join(parts[common:]) 172 173 output.append(fmt.text("%s %s" % (prefix, suffix))) 174 output.append(fmt.pagelink(on=0, pagename=pagename)) 175 output.append(fmt.listitem(on=0)) 176 177 last_parts = parts 178 179 output.append(fmt.bullet_list(on=0)) 180 output.append(fmt.listitem(on=0)) 181 182 # Otherwise generate a simple link. 183 184 else: 185 output.append(fmt.listitem(on=1)) 186 output.append(fmt.pagelink(on=1, pagename=category_pagename)) 187 output.append(fmt.text(category_name)) 188 output.append(fmt.pagelink(on=0, pagename=category_pagename)) 189 output.append(fmt.listitem(on=0)) 190 191 output.append(fmt.bullet_list(on=0)) 192 193 return ''.join(output) 194 195 # vim: tabstop=4 expandtab shiftwidth=4