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 category_regexp = None 16 17 Dependencies = ['pages'] 18 19 def isMoin15(): 20 return version.release.startswith("1.5.") 21 22 def getCategoryPattern(request): 23 global category_regexp 24 25 try: 26 return request.cfg.cache.page_category_regexact 27 except AttributeError: 28 29 # Use regular expression from MoinMoin 1.7.1 otherwise. 30 31 if category_regexp is None: 32 category_regexp = re.compile(u'^%s$' % ur'(?P<all>Category(?P<key>(?!Template)\S+))', re.UNICODE) 33 return category_regexp 34 35 def getCategories(request): 36 37 """ 38 From the AdvancedSearch macro, return a list of category page names using 39 the given 'request'. 40 """ 41 42 # This will return all pages with "Category" in the title. 43 44 cat_filter = getCategoryPattern(request).search 45 pagenames = request.rootpage.getPageList(filter=cat_filter) 46 pagenames.sort() 47 return pagenames 48 49 def getCategoryMapping(category_pagenames, request): 50 51 """ 52 For the given 'category_pagenames' return a list of tuples of the form 53 (category name, category page name) using the given 'request'. 54 """ 55 56 cat_pattern = getCategoryPattern(request) 57 mapping = [] 58 for pagename in category_pagenames: 59 name = cat_pattern.match(pagename).group("key") 60 if name != "Category": 61 mapping.append((name, pagename)) 62 mapping.sort() 63 return mapping 64 65 def getPages(pagename, request): 66 67 "Return the links minus category links for 'pagename' using the 'request'." 68 69 query = search.QueryParser().parse_query('"%s"' % pagename) 70 if isMoin15(): 71 results = search.searchPages(request, query) 72 results.sortByPagename() 73 else: 74 results = search.searchPages(request, query, "page_name") 75 76 cat_pattern = getCategoryPattern(request) 77 pages = [] 78 for page in results.hits: 79 if not cat_pattern.match(page.page_name): 80 pages.append(page) 81 return pages 82 83 def execute(macro, args): 84 request = macro.request 85 fmt = macro.formatter 86 page = fmt.page 87 88 # Interpret the arguments. 89 90 try: 91 selected_category_names = wikiutil.parse_quoted_separated(args, name_value=False) 92 except AttributeError: 93 selected_category_names = args.split(",") 94 95 selected_category_names = [arg for arg in selected_category_names if arg] 96 97 # Get the categories. 98 99 categories = getCategoryMapping(getCategories(request), request) 100 101 # Generate a menu with the categories, together with expanded submenus for 102 # the categories employed by the current page, the category represented by 103 # the current page, or for those categories specified in the macro 104 # arguments. 105 106 output = [] 107 output.append(fmt.bullet_list(on=1, attr={"class" : "category-menu"})) 108 109 for category in categories: 110 category_name, category_pagename = category 111 112 pages_in_category = getPages(category_pagename, request) 113 pagenames_in_category = [p.page_name for p in pages_in_category] 114 page_is_category = page.page_name == category_pagename 115 116 # Generate the submenu where appropriate. 117 118 if selected_category_names and category_name in selected_category_names or \ 119 not selected_category_names and ( 120 page_is_category or page.page_name in pagenames_in_category): 121 122 if page_is_category: 123 output.append(fmt.listitem(on=1, attr={"class" : "selected current"})) 124 output.append(fmt.text(category_name)) 125 else: 126 output.append(fmt.listitem(on=1, attr={"class" : "selected"})) 127 output.append(fmt.pagelink(on=1, pagename=category_pagename)) 128 output.append(fmt.text(category_name)) 129 output.append(fmt.pagelink(on=0, pagename=category_pagename)) 130 131 output.append(fmt.bullet_list(on=1, attr={"class" : "category-submenu"})) 132 133 # Visit each page in the category. 134 135 last_parts = [] 136 137 for page_in_category in pages_in_category: 138 pagename = page_in_category.page_name 139 140 if page.page_name == pagename: 141 output.append(fmt.listitem(on=1, attr={"class" : "selected"})) 142 else: 143 output.append(fmt.listitem(on=1)) 144 output.append(fmt.pagelink(on=1, pagename=pagename)) 145 146 # Abbreviate long hierarchical names. 147 148 parts = pagename.split("/") 149 common = 0 150 for last, current in map(None, last_parts, parts): 151 if last == current: 152 common += 1 153 else: 154 break 155 156 prefix = u"\u2014" * common 157 suffix = "/".join(parts[common:]) 158 159 output.append(fmt.text("%s %s" % (prefix, suffix))) 160 output.append(fmt.pagelink(on=0, pagename=pagename)) 161 output.append(fmt.listitem(on=0)) 162 163 last_parts = parts 164 165 output.append(fmt.bullet_list(on=0)) 166 output.append(fmt.listitem(on=0)) 167 168 # Otherwise generate a simple link. 169 170 else: 171 output.append(fmt.listitem(on=1)) 172 output.append(fmt.pagelink(on=1, pagename=category_pagename)) 173 output.append(fmt.text(category_name)) 174 output.append(fmt.pagelink(on=0, pagename=category_pagename)) 175 output.append(fmt.listitem(on=0)) 176 177 output.append(fmt.bullet_list(on=0)) 178 179 return ''.join(output) 180 181 # vim: tabstop=4 expandtab shiftwidth=4