1.1 --- a/ImprovedMoinSearch.py Sun Oct 03 16:52:40 2010 +0200
1.2 +++ b/ImprovedMoinSearch.py Sun Oct 03 21:38:06 2010 +0200
1.3 @@ -15,16 +15,20 @@
1.4 paragraph_regexp = re.compile(r"(?P<paragraph>(?:^[^#=\s].*$\n)+)", re.UNICODE | re.MULTILINE)
1.5
1.6 def range_groups(min_name, max_name):
1.7 - return r"(?P<%s>-?\d+)?(?:\s*-\s*(?P<%s>-?\d+))?" % (min_name, max_name)
1.8 + return r"(?:\((?P<%s>-?\d+)?(?:\s*-\s*(?P<%s>-?\d+))?\))" % (min_name, max_name)
1.9
1.10 format_options_regexp = re.compile(
1.11 - r"(?P<link>\[)?"
1.12 + r"("
1.13 + r"(?P<link>(link|l):)"
1.14 + r"|(?P<strong>(strong|str|bold|b):)"
1.15 + r"|(?P<em>(emphasis|em|italic|i):)"
1.16 + r")*"
1.17 r"("
1.18 r"(?P<heading>(heading|title|h)\s*" + range_groups("min_heading", "max_heading") + ")"
1.19 - r"|(?P<paragraph>(paragraph|para|p)\s*(?P<paragraph_number>\d+)?)"
1.20 + r"|(?P<paragraph>(paragraph|para|p)\s*" + r"(?:\((?P<paragraph_number>\d+)?\))?" + ")"
1.21 r"|(?P<name>(name|page)\s*" + range_groups("first", "last") + ")"
1.22 - r")"
1.23 - r"(?(link)\]|)",
1.24 + r"|(?P<break>(break|br))"
1.25 + r")",
1.26 re.UNICODE)
1.27
1.28 def convert_index(i, length):
1.29 @@ -53,6 +57,8 @@
1.30 results = searchPages(request, query, **kw)
1.31 return results.hits
1.32
1.33 +# Action functions.
1.34 +
1.35 def getFirstPageHeading(request, page, start=0, min_level=None, max_level=None):
1.36
1.37 """
1.38 @@ -134,6 +140,54 @@
1.39
1.40 return "/".join(parts), (start, start)
1.41
1.42 +# Formatting styles.
1.43 +
1.44 +def asLink(styles, formatter, text, page):
1.45 + output = []
1.46 + output.append(formatter.pagelink(on=1, pagename=page.page_name))
1.47 + if not styles:
1.48 + output.append(asText(None, formatter, text, page))
1.49 + else:
1.50 + output.append(next_style(styles, formatter, text, page))
1.51 + output.append(formatter.pagelink(on=0))
1.52 + return u''.join(output)
1.53 +
1.54 +def _asStyledText(styles, formatter, text, page, fn):
1.55 + output = []
1.56 + output.append(fn(on=1))
1.57 + if not styles:
1.58 + output.append(asText(None, formatter, text, page))
1.59 + else:
1.60 + output.append(next_style(styles, formatter, text, page))
1.61 + output.append(fn(on=0))
1.62 + return u''.join(output)
1.63 +
1.64 +def asStrong(styles, formatter, text, page):
1.65 + return _asStyledText(styles, formatter, text, page, formatter.strong)
1.66 +
1.67 +def asEmphasis(styles, formatter, text, page):
1.68 + return _asStyledText(styles, formatter, text, page, formatter.emphasis)
1.69 +
1.70 +def asText(styles, formatter, text, page):
1.71 + if not styles:
1.72 + return formatter.text(text)
1.73 + else:
1.74 + return next_style(styles, formatter, text, page)
1.75 +
1.76 +def asBreak(styles, formatter, text, page):
1.77 + return formatter.linebreak(0)
1.78 +
1.79 +def next_style(styles, formatter, text, page):
1.80 + return styles[0](styles[1:], formatter, text, page)
1.81 +
1.82 +style_functions = {
1.83 + "link" : asLink,
1.84 + "strong" : asStrong,
1.85 + "em" : asEmphasis,
1.86 + }
1.87 +
1.88 +# Formatting functions.
1.89 +
1.90 def formatResultPages(request, formatter, pages, paging, format, page_from=0):
1.91
1.92 """
1.93 @@ -150,15 +204,27 @@
1.94
1.95 if format:
1.96 for match in format_options_regexp.finditer(format):
1.97 - as_link = match.group("link")
1.98 +
1.99 + # Apply styles by gathering style functions.
1.100 +
1.101 + styles = []
1.102 + for style in ("strong", "em", "link"):
1.103 + if match.group(style):
1.104 + styles.append(style_functions[style])
1.105 + styles.append(asText)
1.106 +
1.107 + # Add actions, arguments and styles.
1.108 +
1.109 if match.group("heading"):
1.110 - actions.append((getFirstPageHeading, map(int_or_none, (match.group("min_heading"), match.group("max_heading"))), as_link))
1.111 + actions.append((getFirstPageHeading, map(int_or_none, (match.group("min_heading"), match.group("max_heading"))), styles))
1.112 elif match.group("paragraph"):
1.113 - actions.append((getParagraph, map(int_or_none, (match.group("paragraph_number"),)), as_link))
1.114 + actions.append((getParagraph, map(int_or_none, (match.group("paragraph_number"),)), styles))
1.115 elif match.group("name"):
1.116 - actions.append((getPageName, map(int_or_none, (match.group("first"), match.group("last"))), as_link))
1.117 + actions.append((getPageName, map(int_or_none, (match.group("first"), match.group("last"))), styles))
1.118 + elif match.group("break"):
1.119 + actions.append((None, None, [asBreak]))
1.120 else:
1.121 - actions.append((getPageName, (), True))
1.122 + actions.append((getPageName, (), [asLink]))
1.123
1.124 # Use paging only when there are enough results.
1.125
1.126 @@ -180,27 +246,36 @@
1.127
1.128 start = 0
1.129 first = 1
1.130 - for action, args, as_link in actions:
1.131 - result = action(request, page, start, *args)
1.132 + for action, args, styles in actions:
1.133 +
1.134 + # Process requested actions.
1.135 +
1.136 + if action is not None:
1.137 + result = action(request, page, start, *args)
1.138 + if result is not None:
1.139 + text, span = result
1.140
1.141 - if result is not None:
1.142 + # Or handle null actions.
1.143 +
1.144 + else:
1.145 + text, span = None, None
1.146 +
1.147 + # Where actions are performed, there must be a result.
1.148 +
1.149 + if action is None or result is not None:
1.150 +
1.151 if not first:
1.152 output.append(" ")
1.153 - if as_link:
1.154 - output.append(formatter.pagelink(on=1, pagename=page.page_name))
1.155
1.156 - text, span = result
1.157 - output.append(formatter.text(text))
1.158 + output.append(next_style(styles, formatter, text, page))
1.159
1.160 # Position the search for the next action.
1.161
1.162 - _start, _end = span
1.163 - start = _end + 1
1.164 + if span is not None:
1.165 + _start, _end = span
1.166 + start = _end + 1
1.167
1.168 - if as_link:
1.169 - output.append(formatter.pagelink(on=0))
1.170 -
1.171 - first = 0
1.172 + first = 0
1.173
1.174 output.append(formatter.listitem(on=0))
1.175