Sophie

Sophie

distrib > Mandriva > 2009.1 > x86_64 > by-pkgid > dd5ff701fdd2df6775e5cf25b2dd9e7c > files > 6

moin-1.1-3mdv2007.1.src.rpm

"""
    MoinMoin - SearchInPagesAndSort Macro
    A line-oriented search macro over multiple pages, with sorting

    Pascal Bauermeister <pascal.bauermeister@smartdata.ch>

    [[SearchInPages(PageRegex,TextRegex,SortKey)]]
        Search for TextRegex in pages marching PagesRegex, and sort on
        1) SortKey  2) TextRegex  3) found line

    Original version:
    * 2003/04/24 10:32:04
    
    Updates:
    * Wed Oct 29 14:48:02 CET 2003
      works with MoinMoin Release 1.1 [Revision 1.173] and Python 2.3.2

"""

# Imports
import cgi, os, re, string, sys, time, urllib, cStringIO
from MoinMoin import config, user, util, wikiutil
from MoinMoin.Page import Page, webapi
from MoinMoin.parser.wiki import Parser

_arg_page = r'(?P<hquote1>[\'"])(?P<hpage>.+?)(?P=hquote1)'
_arg_text = r'(?P<hquote2>[\'"])(?P<htext>.+?)(?P=hquote2)'
_arg_key  = r'(?P<hquote3>[\'"])(?P<hkey>.+?)(?P=hquote3)'
_args_re = re.compile(r'^(%s(,%s(,%s)?)?)?$' % (_arg_page, _arg_text, _arg_key))


def execute(macro, text, args_re=_args_re):
    result = ""

    # parse and check arguments
    args = args_re.match(text)
    if text is None or not args:
        return ( '<p><strong class="error">Invalid SearchInPages arguments "%s"!' +
                 '</strong></p>' ) % text

    text = args.group('htext')
    pages = args.group('hpage')
    key = args.group('hkey')

    # get a list of pages matching the PageRegex
    try:
        pages_re = re.compile(pages, re.IGNORECASE)
    except re.error:
        pages_re = re.compile(re.escape(pages), re.IGNORECASE)
    all_pages = wikiutil.getPageList(config.text_dir)
    hits = filter(pages_re.search, all_pages)
    hits.sort()

    if len(hits) == 0:
        return '<p><strong class="error">No page matching "%s"!</strong></p>' % (pages)


    # compile all regex
    try:
        text_re = re.compile(text, re.IGNORECASE)
    except:
        text_re = re.compile(re.escape(text), re.IGNORECASE)

    if key != None:
      try:
          key_re = re.compile(key, re.IGNORECASE)
      except:
          key_re = re.compile(re.escape(key), re.IGNORECASE)


    # we will collect matching lines in each matching page
    all_matches = []

    for page_name in hits:
        body = Page(page_name).get_raw_body()
        pos = 0
        last_start = -1
        last_end = -1
        while 1:
            keep_line = 1
            
            # search text
            match = text_re.search(body, pos)
            if not match: break
            pos = match.end()+1

            # cut before start of line
            start_pos = match.start()
            rev = 0
            while body[start_pos] != '\n' and start_pos:
                start_pos = start_pos - 1
                rev = 1
            if rev:
                start_pos = start_pos + 1

            # cut at end of line
            end_pos = body.find("\n", match.end())

            # extract line
            line = body[start_pos:end_pos].strip()

            # store this record if it differs from previous one
            if start_pos == last_start or end_pos == last_end: keep_line = 0

            # store this record if it it is not a comment
            if line.startswith("##"): keep_line = 0

            # store this record if it differs from previous one
            if keep_line:

                # remove possible list item leaders
                for heading in ["*", "1.", "a.", "A.", "i.", "I.", "1.#n"]:
                    if line.startswith(heading):
                        line = line.replace(heading, "", 1)
                line = line.strip()

                # find the sort key
                nbmatches = 0
                keypos = 0
                found = 0
                while 1:
                    if key == None:
                        keyval = ""
                    else:
                        keymatch = key_re.search(line, keypos)
                        if keymatch:
                            keyval = line[keymatch.start():keymatch.end()]
                            keypos = keymatch.end()
                            nbmatches = nbmatches + 1
                            found = 1
                        else:
                            if nbmatches>0: break
                            keyval = "[unassigned]"

                    # store info
                    item = []
                    item.append(keyval)                          # key text
                    item.append(body[match.start():match.end()]) # search text
                    item.append(line)                            # line text
                    item.append(page_name)                       # page name
                    all_matches.append(item)
                    if found == 0: break

                last_start = start_pos
                last_end = end_pos

        # sort and format records
        bullet_list_open = macro.formatter.bullet_list(1)
        bullet_list_close = macro.formatter.bullet_list(0)
        listitem_open = macro.formatter.listitem(1)
        listitem_close = macro.formatter.listitem(0)

        all_matches.sort()
        result = ""
        result = result+"\n" + bullet_list_open
        keyval = ""
        head_count = 0

        # treat records for output
        for item in all_matches:
            pagename = item[3]
            text = item[2]
            if key != None and item[0] != keyval:
                # this is a new heading
                keyval = item[0]
                if head_count:
                    result = result+"\n    " + bullet_list_close
                    result = result+"\n  " + listitem_close
                head_count = head_count +1
                result = result+"\n  " + listitem_open
                result = result+ keyval
                result = result+"\n    " + bullet_list_open

            # parse the text in wiki source format
            stdout = sys.stdout
            sys.stdout = cStringIO.StringIO()
            Parser(text, macro.request).format(macro.formatter)	
            text_fmt = sys.stdout.getvalue()
            sys.stdout = stdout

            # correct the format
            if text_fmt.startswith("\n<p>"):
                 text_fmt = text_fmt[4:]
                        
            # insert text
            result = result+"\n      " + listitem_open
            result = result + text_fmt
            result = result + "&nbsp;&nbsp;&nbsp;<font size=-1>"
            result = result + wikiutil.link_tag(pagename)
            result = result + "</font>"
            result = result+"\n      " + listitem_close

        # all items done, close (hopefully) gracefully
        if head_count:
            result = result+"\n      " + listitem_close
            result = result+"\n    " + bullet_list_close
        if key != None:
            result = result+"\n  " + listitem_close
        result = result+"\n" + bullet_list_close

    # done
    return result