# HG changeset patch # User Paul Boddie # Date 1286134686 -7200 # Node ID 1e0cdf78d59c731532c1821fe7bd860fc897a89f # Parent a19b22ba78ce97b486796c62549ed32d10ab5077 Introduced formatting styles that can be combined and applied to formatting actions. Changed the format syntax so that formatting actions may resemble function invocations, grouping arguments together with each action. Added a line-break action. diff -r a19b22ba78ce -r 1e0cdf78d59c ImprovedMoinSearch.py --- a/ImprovedMoinSearch.py Sun Oct 03 16:52:40 2010 +0200 +++ b/ImprovedMoinSearch.py Sun Oct 03 21:38:06 2010 +0200 @@ -15,16 +15,20 @@ paragraph_regexp = re.compile(r"(?P(?:^[^#=\s].*$\n)+)", re.UNICODE | re.MULTILINE) def range_groups(min_name, max_name): - return r"(?P<%s>-?\d+)?(?:\s*-\s*(?P<%s>-?\d+))?" % (min_name, max_name) + return r"(?:\((?P<%s>-?\d+)?(?:\s*-\s*(?P<%s>-?\d+))?\))" % (min_name, max_name) format_options_regexp = re.compile( - r"(?P\[)?" + r"(" + r"(?P(link|l):)" + r"|(?P(strong|str|bold|b):)" + r"|(?P(emphasis|em|italic|i):)" + r")*" r"(" r"(?P(heading|title|h)\s*" + range_groups("min_heading", "max_heading") + ")" - r"|(?P(paragraph|para|p)\s*(?P\d+)?)" + r"|(?P(paragraph|para|p)\s*" + r"(?:\((?P\d+)?\))?" + ")" r"|(?P(name|page)\s*" + range_groups("first", "last") + ")" - r")" - r"(?(link)\]|)", + r"|(?P(break|br))" + r")", re.UNICODE) def convert_index(i, length): @@ -53,6 +57,8 @@ results = searchPages(request, query, **kw) return results.hits +# Action functions. + def getFirstPageHeading(request, page, start=0, min_level=None, max_level=None): """ @@ -134,6 +140,54 @@ return "/".join(parts), (start, start) +# Formatting styles. + +def asLink(styles, formatter, text, page): + output = [] + output.append(formatter.pagelink(on=1, pagename=page.page_name)) + if not styles: + output.append(asText(None, formatter, text, page)) + else: + output.append(next_style(styles, formatter, text, page)) + output.append(formatter.pagelink(on=0)) + return u''.join(output) + +def _asStyledText(styles, formatter, text, page, fn): + output = [] + output.append(fn(on=1)) + if not styles: + output.append(asText(None, formatter, text, page)) + else: + output.append(next_style(styles, formatter, text, page)) + output.append(fn(on=0)) + return u''.join(output) + +def asStrong(styles, formatter, text, page): + return _asStyledText(styles, formatter, text, page, formatter.strong) + +def asEmphasis(styles, formatter, text, page): + return _asStyledText(styles, formatter, text, page, formatter.emphasis) + +def asText(styles, formatter, text, page): + if not styles: + return formatter.text(text) + else: + return next_style(styles, formatter, text, page) + +def asBreak(styles, formatter, text, page): + return formatter.linebreak(0) + +def next_style(styles, formatter, text, page): + return styles[0](styles[1:], formatter, text, page) + +style_functions = { + "link" : asLink, + "strong" : asStrong, + "em" : asEmphasis, + } + +# Formatting functions. + def formatResultPages(request, formatter, pages, paging, format, page_from=0): """ @@ -150,15 +204,27 @@ if format: for match in format_options_regexp.finditer(format): - as_link = match.group("link") + + # Apply styles by gathering style functions. + + styles = [] + for style in ("strong", "em", "link"): + if match.group(style): + styles.append(style_functions[style]) + styles.append(asText) + + # Add actions, arguments and styles. + if match.group("heading"): - actions.append((getFirstPageHeading, map(int_or_none, (match.group("min_heading"), match.group("max_heading"))), as_link)) + actions.append((getFirstPageHeading, map(int_or_none, (match.group("min_heading"), match.group("max_heading"))), styles)) elif match.group("paragraph"): - actions.append((getParagraph, map(int_or_none, (match.group("paragraph_number"),)), as_link)) + actions.append((getParagraph, map(int_or_none, (match.group("paragraph_number"),)), styles)) elif match.group("name"): - actions.append((getPageName, map(int_or_none, (match.group("first"), match.group("last"))), as_link)) + actions.append((getPageName, map(int_or_none, (match.group("first"), match.group("last"))), styles)) + elif match.group("break"): + actions.append((None, None, [asBreak])) else: - actions.append((getPageName, (), True)) + actions.append((getPageName, (), [asLink])) # Use paging only when there are enough results. @@ -180,27 +246,36 @@ start = 0 first = 1 - for action, args, as_link in actions: - result = action(request, page, start, *args) + for action, args, styles in actions: + + # Process requested actions. + + if action is not None: + result = action(request, page, start, *args) + if result is not None: + text, span = result - if result is not None: + # Or handle null actions. + + else: + text, span = None, None + + # Where actions are performed, there must be a result. + + if action is None or result is not None: + if not first: output.append(" ") - if as_link: - output.append(formatter.pagelink(on=1, pagename=page.page_name)) - text, span = result - output.append(formatter.text(text)) + output.append(next_style(styles, formatter, text, page)) # Position the search for the next action. - _start, _end = span - start = _end + 1 + if span is not None: + _start, _end = span + start = _end + 1 - if as_link: - output.append(formatter.pagelink(on=0)) - - first = 0 + first = 0 output.append(formatter.listitem(on=0))