# HG changeset patch # User Paul Boddie # Date 1277423301 -7200 # Node ID 64514a01af2b20d0bc2f6c1bdaa59d25de8c0689 Improved search macro support for MoinMoin. diff -r 000000000000 -r 64514a01af2b ImprovedMoinSearch.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ImprovedMoinSearch.py Fri Jun 25 01:48:21 2010 +0200 @@ -0,0 +1,90 @@ +# -*- coding: iso-8859-1 -*- +""" + MoinMoin - ImprovedMoinSearch library + + @copyright: 2010 Paul Boddie + @license: GNU GPL (v2 or later), see COPYING.txt for details. +""" + +from MoinMoin.search import searchPages +from MoinMoin.Page import Page +import re + +heading_regexp = re.compile(r"^(?P=+)(?P.*?)(?P=level)$", re.UNICODE | re.MULTILINE) +heading_options_regexp = re.compile(r"heading\s*(?P\d+)?(?:\s*-\s*(?P\d+))?", re.UNICODE) + +def getSearchResultPages(request, query, **kw): + + """ + Return matching pages using the given 'request' and search 'query'. Optional + keyword arguments are passed to the underlying search infrastructure. + """ + + results = searchPages(request, query, **kw) + return results.hits + +def getFirstPageHeading(request, page, min_level=1, max_level=1): + + """ + Using the given 'request', return the first heading in the given 'page' + having a heading level of at least 'min_level' (which is 1 if not specified) + and at most 'max_level' (which is 1 if not specified). + """ + + full_page = Page(request, page.page_name) + body = full_page.get_raw_body() + + for match in heading_regexp.finditer(body): + level = len(match.group("level")) + + if (min_level is None or level >= min_level) and \ + (max_level is None or level <= max_level): + + return match.group("heading") + + return None + +def formatResultPages(request, formatter, pages, paging, format): + + """ + Using the given 'request' and 'formatter', return a formatted string showing + the result 'pages', providing paging controls when 'paging' is set to a true + value, and providing page details according to the given 'format'. + """ + + m = heading_options_regexp.search(format) + if m: + format = "heading" + min_level = int_or_none(m.group("min")) + max_level = int_or_none(m.group("max")) + else: + format = "name" + + output = [] + + output.append(formatter.number_list(on=1)) + + for page in pages: + output.append(formatter.listitem(on=1)) + + if format == "heading": + text = getFirstPageHeading(request, page, min_level, max_level) or page.page_name + else: + text = page.page_name + + output.append(formatter.pagelink(on=1, pagename=page.page_name)) + output.append(formatter.text(text)) + output.append(formatter.pagelink(on=0)) + output.append(formatter.listitem(on=0)) + + output.append(formatter.number_list(on=0)) + + return "".join(output) + +def int_or_none(x): + if x is None: + return x + else: + return int(x) + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r 000000000000 -r 64514a01af2b instmacros --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/instmacros Fri Jun 25 01:48:21 2010 +0200 @@ -0,0 +1,13 @@ +#!/bin/bash + +if [[ ! $1 ]] ; then + echo "Please specify a directory such as ../mysite/wiki or /tmp/mysite/wiki." + echo "This should be the root of your Wiki installation and contain the data" + echo "directory." + echo + echo "You may wish to uncomment and modify the chown command in this script." + exit +fi + +cp macros/*.py $1/data/plugin/macro/ +#chown www-data: $1/data/plugin/macro/*.py diff -r 000000000000 -r 64514a01af2b macros/PageListPlus.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/macros/PageListPlus.py Fri Jun 25 01:48:21 2010 +0200 @@ -0,0 +1,84 @@ +# -*- coding: iso-8859-1 -*- +""" + MoinMoin - PageListPlus + + print a list of pages whose title matches the search term + + @copyright: 2010 Paul Boddie + @license: GNU GPL, see COPYING for details. +""" + +Dependencies = ["pages"] +from MoinMoin import wikiutil +import ImprovedMoinSearch +import re + +format_pattern = re.compile("""format:(?P['"])(?P.*?)(?P=quote)""") +paging_pattern = re.compile("""paging:(?Pon|off|yes|no|true|false)""") + +def extract_option(query, pattern, group): + + """ + Remove from 'query', using the given regular expression 'pattern' object, + a particular form of argument text, accessing such text through the group + with the given 'group' name, and returning a tuple of the form + (edited_query, value_of_group). + """ + + m = format_pattern.search(query) + if m: + value = m.group(group) + query = query[:m.start()] + query[m.end():] + else: + value = None + return query, value + +# Macro functions. + +def execute(macro, args): + + """ + Execute the 'macro' with the given 'args': + """ + + request = macro.request + formatter = macro.formatter + _ = macro._ + + # If called with empty or no argument, default to regex search for .+, the full page list. + + needle = wikiutil.get_unicode(request, args, 'needle', u'regex:.+') + + # Extract format and paging options. + + needle, format = extract_option(needle, format_pattern, "format") + needle, paging = extract_option(needle, paging_pattern, "paging") + + # With whitespace argument, return same error message as FullSearch. + + if not needle.strip(): + err = _('Please use a more selective search term instead of {{{"%s"}}}', wiki=True) % needle + return '%s' % err + + # Return a title search for needle, sorted by name. + + try: + pages = ImprovedMoinSearch.getSearchResultPages(request, needle, titlesearch=1, sort='page_name') + + # Format the results. + + ret = ImprovedMoinSearch.formatResultPages(request, formatter, pages, paging, format) + + except ValueError: + + # Same error as in MoinMoin/action/fullsearch.py, keep it that way! + + ret = ''.join([formatter.text('<>')]) + + return ret + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r 000000000000 -r 64514a01af2b setup.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/setup.py Fri Jun 25 01:48:21 2010 +0200 @@ -0,0 +1,13 @@ +#! /usr/bin/env python + +from distutils.core import setup + +setup( + name = "ImprovedMoinSearch", + description = "Augment MoinMoin search support with enhanced search-related macros", + author = "Paul Boddie", + author_email = "paul@boddie.org.uk", + url = "http://moinmo.in/MacroMarket/ImprovedMoinSearch", + version = "0.1", + py_modules = ["ImprovedMoinSearch"] + )