Attachment 'multisearch.diff'

Download

   1 diff -Nur trunk-orig/moin/MoinMoin/Page.py test/moin/MoinMoin/Page.py
   2 --- trunk-orig/moin/MoinMoin/Page.py	Sun Mar 16 22:17:53 2003
   3 +++ test/moin/MoinMoin/Page.py	Sun Apr 13 21:55:02 2003
   4 @@ -234,6 +234,7 @@
   5          print_mode = request.form.has_key('action') and request.form['action'].value == 'print'
   6          content_only = keywords.get('content_only', 0)
   7          self.hilite_re = keywords.get('hilite_re', None)
   8 +        self.hilite_words_re = keywords.get('hilite_words_re', None)
   9          if msg is None: msg = ""
  10  
  11          # count hit?
  12 diff -Nur trunk-orig/moin/MoinMoin/macro/MultiSearch.py test/moin/MoinMoin/macro/MultiSearch.py
  13 --- trunk-orig/moin/MoinMoin/macro/MultiSearch.py	Thu Jan  1 01:00:00 1970
  14 +++ test/moin/MoinMoin/macro/MultiSearch.py	Mon Apr 14 03:01:03 2003
  15 @@ -0,0 +1,61 @@
  16 +"""
  17 +    MoinMoin - MultiSearch Macro
  18 +
  19 +    Copyright (c) 2003 Ronny Buchmann <ronny-vlug@vlugnet.org>
  20 +    Modified by ThomasWaldmann
  21 +    All rights reserved, see COPYING for details.
  22 +
  23 +    based on FullSearch.py
  24 +        Copyright (c) 2000, 2001, 2002 by Jürgen Hermann <jh@web.de>
  25 +
  26 +    [[MultiSearch]]
  27 +        displays a search dialog, as it always did
  28 +
  29 +    [[MultiSearch('HelpContents')]]
  30 +        embeds a search result into a page, as if you entered
  31 +        "HelpContents" into the search dialog
  32 +
  33 +    $Id: $
  34 +"""
  35 +
  36 +# Imports
  37 +import re, urllib
  38 +from MoinMoin import config, user, wikiutil
  39 +
  40 +_args_re_pattern = r'((?P<hquote>[\'"])(?P<htext>.+?)(?P=hquote))|'
  41 +
  42 +
  43 +def execute(macro, text, args_re=re.compile(_args_re_pattern)):
  44 +    _ = macro.request.getText
  45 +
  46 +    # if no args given, invoke "classic" behavior
  47 +    if text is None:
  48 +        return macro._m_search("multisearch")
  49 +
  50 +    # parse and check arguments
  51 +    args = args_re.match(text)
  52 +    if not args:
  53 +        return '<p><strong class="error">Invalid MultiSearch arguments "%s"!</strong></p>' % (text,)
  54 +
  55 +    needle = args.group('htext')
  56 +    if not needle:
  57 +        return '<p><strong class="error">No argument given for MultiSearch!</strong></p>' % (text,)
  58 +
  59 +    # do the search
  60 +    pagecount, hits = wikiutil.multisearchPages(needle, context=0)
  61 +
  62 +    # generate the result
  63 +    result = macro.formatter.number_list(1)
  64 +    for (count, pagename, dummy) in hits:
  65 +        result = result + macro.formatter.listitem(1)
  66 +        result = result + wikiutil.link_tag('%s?action=highlight&value=%s&words=1' %
  67 +            (wikiutil.quoteWikiname(pagename), urllib.quote_plus(needle)),
  68 +            pagename)
  69 +        result = result + ' . . . . ' + `count` + [
  70 +            _(' match'),
  71 +            _(' matches')][count != 1]
  72 +        result = result + macro.formatter.listitem(0)
  73 +    result = result + macro.formatter.number_list(0)
  74 +
  75 +    return result
  76 +
  77 diff -Nur trunk-orig/moin/MoinMoin/parser/wiki.py test/moin/MoinMoin/parser/wiki.py
  78 --- trunk-orig/moin/MoinMoin/parser/wiki.py	Sat Mar 22 12:16:20 2003
  79 +++ test/moin/MoinMoin/parser/wiki.py	Sun Apr 13 22:26:50 2003
  80 @@ -763,7 +763,42 @@
  81  
  82      def highlight_text(self, text, **kw):
  83          if kw.get('flow', 1): self._check_p()
  84 -        if not self.hilite_re: return self.formatter.text(text)
  85 +        if not self.hilite_re:
  86 +            if not self.hilite_words_re:
  87 +                return self.formatter.text(text)
  88 +            else: # hilite_words_re
  89 +                result = []
  90 +                matches = []
  91 +                # find matches of all words and sort them
  92 +                for word_re in self.hilite_words_re:
  93 +                    lastpos = 0
  94 +                    match = word_re.search(text)
  95 +                    while 1:
  96 +                        match = word_re.search(text, lastpos)
  97 +                        if not match: break
  98 +                        lastpos = match.end()+1
  99 +                        matches.append((match.start(), match.end()))
 100 +                matches.sort()
 101 +                # actually output it
 102 +                lastpos = 0
 103 +                hilite_open = 0
 104 +                for (start, end) in matches:
 105 +                    if start <= lastpos: # overlapping match
 106 +                        result.append(self.formatter.text(text[lastpos:end]))
 107 +                        lastpos = end
 108 +                    else: # new match
 109 +                        if hilite_open:
 110 +                            result.append(self.formatter.highlight(0))
 111 +                            hilite_open = 0
 112 +                        result.append(self.formatter.text(text[lastpos:start-1]))
 113 +                        result.append(self.formatter.highlight(1))
 114 +                        result.append(self.formatter.text(text[start:end]))
 115 +                        lastpos = end
 116 +                        hilite_open = 1
 117 +                if lastpos < len(text):
 118 +                    result.append(self.formatter.highlight(0))
 119 +                    result.append(self.formatter.text(text[lastpos:]))
 120 +                return string.join(result, '')
 121  
 122          result = []
 123          lastpos = 0
 124 @@ -823,6 +858,7 @@
 125          """
 126          self.formatter = formatter
 127          self.hilite_re = self.formatter.page.hilite_re
 128 +        self.hilite_words_re = self.formatter.page.hilite_words_re
 129  
 130          # prepare regex patterns
 131          rules = string.replace(self.formatting_rules, '\n', '|')
 132 @@ -926,7 +962,7 @@
 133                      self.in_table = 0
 134  
 135              # convert line from wiki markup to HTML and print it
 136 -            if self.hilite_re:
 137 +            if self.hilite_re or self.hilite_words_re:
 138                  self.request.write(self.highlight_scan(scan_re, line + " "))
 139              else:
 140                  line, count = re.subn(scan_re, self.replace, line + " ")
 141 diff -Nur trunk-orig/moin/MoinMoin/wikiaction.py test/moin/MoinMoin/wikiaction.py
 142 --- trunk-orig/moin/MoinMoin/wikiaction.py	Thu Mar 13 09:13:11 2003
 143 +++ test/moin/MoinMoin/wikiaction.py	Mon Apr 14 03:16:43 2003
 144 @@ -86,6 +86,54 @@
 145      print_search_stats(request, len(hits), pagecount, start)
 146      wikiutil.send_footer(request, pagename, editable=0, showactions=0, form=request.form)
 147  
 148 +def do_multisearch(pagename, request, fieldname='value'):
 149 +    _ = request.getText
 150 +    start = time.clock()
 151 +
 152 +    # send http headers
 153 +    webapi.http_headers(request)
 154 +
 155 +    # get parameters
 156 +    if request.form.has_key(fieldname):
 157 +        needle = request.form[fieldname].value
 158 +    else:
 159 +        needle = ''
 160 +    try:
 161 +        context = int(request.form['context'].value)
 162 +    except (KeyError, ValueError):
 163 +        context = 0
 164 +    max_context = 10 # only show first `max_context` contexts
 165 +
 166 +    # check for sensible search term
 167 +    #if len(needle) < 3:
 168 +    #    Page(pagename).send_page(request,
 169 +    #        msg=_("<b>Please use a more selective search term instead of '%(needle)s'!</b>") % locals())
 170 +    #    return
 171 +
 172 +    # send title
 173 +    wikiutil.send_title(request, _('Full text search for "%s"') % (needle,))
 174 +
 175 +    # search the pages
 176 +    pagecount, hits = wikiutil.multisearchPages(needle, context=context)
 177 +
 178 +    # print the result
 179 +    print "<UL>"
 180 +    for (count, page_name, fragments) in hits:
 181 +        print '<LI>' + Page(page_name).link_to(querystr=
 182 +            'action=highlight&value=%s&words=1' % urllib.quote_plus(needle))
 183 +        print ' . . . . ' + `count`
 184 +        print (_(' match'), _(' matches'))[count != 1]
 185 +        if context:
 186 +            for hit in fragments[:max_context]:
 187 +                print '<br>', '&nbsp;'*8, '<font color="#808080">...%s<b>%s</b>%s...</font>' \
 188 +                    % tuple(map(cgi.escape, hit))
 189 +            if len(fragments) > max_context:
 190 +                print '<br>', '&nbsp;'*8, '<font color="#808080">...</font>'
 191 +    print "</UL>"
 192 +
 193 +    print_search_stats(request, len(hits), pagecount, start)
 194 +    wikiutil.send_footer(request, pagename, editable=0, showactions=0, form=request.form)
 195 +
 196  
 197  def do_titlesearch(pagename, request, fieldname='value'):
 198      _ = request.getText
 199 @@ -146,14 +194,24 @@
 200          needle = request.form["value"].value
 201      else:
 202          needle = ''
 203 +    if request.form.has_key('words'):
 204 +        words = request.form["words"].value
 205 +    else:
 206 +        words = 0
 207  
 208 -    try:
 209 -        needle_re = re.compile(needle, re.IGNORECASE)
 210 -    except re.error:
 211 -        needle = re.escape(needle)
 212 -        needle_re = re.compile(needle, re.IGNORECASE)
 213 -
 214 -    Page(pagename).send_page(request, hilite_re=needle_re)
 215 +    if words:
 216 +        needle_words = string.split(needle)
 217 +        words_re = []
 218 +        for needle_word in needle_words:
 219 +            words_re.append(re.compile(re.escape(needle_word), re.IGNORECASE))
 220 +        Page(pagename).send_page(request, hilite_words_re=words_re)
 221 +    else:
 222 +        try:
 223 +            needle_re = re.compile(needle, re.IGNORECASE)
 224 +        except re.error:
 225 +            needle = re.escape(needle)
 226 +            needle_re = re.compile(needle, re.IGNORECASE)
 227 +        Page(pagename).send_page(request, hilite_re=needle_re)
 228  
 229  
 230  #############################################################################
 231 diff -Nur trunk-orig/moin/MoinMoin/wikimacro.py test/moin/MoinMoin/wikimacro.py
 232 --- trunk-orig/moin/MoinMoin/wikimacro.py	Thu Mar 13 09:13:11 2003
 233 +++ test/moin/MoinMoin/wikimacro.py	Mon Apr 14 02:58:21 2003
 234 @@ -119,6 +119,11 @@
 235                  + '<br><input type="checkbox" name="case" value="1">'
 236                  + self._('Case-sensitive searching')
 237              )
 238 +        if type == "multisearch":
 239 +            boxes = (
 240 +                  '<br><input type="checkbox" name="context" value="40" checked>'
 241 +                + self._('Display context of search results')
 242 +            )
 243          return self.formatter.rawHTML((
 244              '<form method="GET">'
 245              '<input type="hidden" name="action" value="%s">'
 246 diff -Nur trunk-orig/moin/MoinMoin/wikiutil.py test/moin/MoinMoin/wikiutil.py
 247 --- trunk-orig/moin/MoinMoin/wikiutil.py	Wed Apr  9 21:02:41 2003
 248 +++ test/moin/MoinMoin/wikiutil.py	Mon Apr 14 04:04:25 2003
 249 @@ -393,6 +393,97 @@
 250  
 251      return (len(all_pages), hits)
 252  
 253 +def multisearchPages(needle, **kw):
 254 +    """ Search the text of all pages for "needle", and return a tuple of
 255 +        (number of pages, hits).
 256 +
 257 +        "needle" is a google style search pattern, we do an AND search in
 258 +        any case (doing OR searches is pointless as this can be done via
 259 +        multiple search calls).
 260 +
 261 +        words are searched case-insensitive. If you want to search for a
 262 +        case-sensitive match, use +searchword.
 263 +        Use -excludeword to exclude pages containing excludeword.
 264 +
 265 +        `hits` is a list of tuples containing the number of hits on a page
 266 +        and the pagename. When context>0, a list of triples with the text of
 267 +        the hit and the text on each side of it is added; otherwise, the
 268 +        third element is None.
 269 +
 270 +        context != 0: Provide `context` chars of text on each side of a hit
 271 +    """
 272 +    from MoinMoin.Page import Page
 273 +
 274 +    context = int(kw.get('context', 0))
 275 +
 276 +    needle_words = needle.split()
 277 +    needle_res = []
 278 +    for word in needle_words:
 279 +        re_mode = re.IGNORECASE
 280 +        exclude = 0
 281 +        if word.startswith("-"):   # -exclude
 282 +            exclude = 1
 283 +            word = word[1:]
 284 +        elif word.startswith("+"): # +CaseSensitive
 285 +            re_mode = 0
 286 +            word = word[1:]
 287 +        if word.startswith("/") and word.endswith("/"): # /regex/
 288 +            word = word[1:-1]
 289 +        else:
 290 +            word = re.escape(word)
 291 +        c_re = re.compile(word, re_mode)
 292 +        needle_res.append((exclude, c_re))
 293 +
 294 +    hits = []
 295 +    all_pages = getPageList(config.text_dir)
 296 +    for page_name in all_pages:
 297 +        # we also search the title by faking it into the "body":
 298 +        body = "****** %s ******\n" % page_name + Page(page_name).get_raw_body()
 299 +        count = 0
 300 +        hit = 0
 301 +        matches = []
 302 +        # search every pre-compiled re
 303 +        for (exclude, needle_re) in needle_res:
 304 +            if exclude:
 305 +                hit = (needle_re.search(body) == None)
 306 +            else:
 307 +	        if context:
 308 +		    pos = 0
 309 +		    while 1:
 310 +		        match = needle_re.search(body, pos)
 311 +		        if not match: break
 312 +		        pos = match.end()+1
 313 +		        matches.append((match.start(), match.end()))
 314 +		    hit = pos # if pos > 0: we have a hit
 315 +	        else:
 316 +	            hit = len(needle_re.findall(body))
 317 +		    count = count + hit
 318 +	    if not hit: break
 319 +        if not hit: continue
 320 +        # now output all hits in correct order
 321 +        if context:
 322 +            matches.sort()
 323 +            fragments = []
 324 +            # at the moment fragments can be listed several times
 325 +            # if more than one needle_word appears within
 326 +            for (start, end) in matches:
 327 +                fragments.append((
 328 +                    body[start-context:start],
 329 +                    body[start:end],
 330 +                    body[end:end+context],
 331 +                ))
 332 +            if fragments:
 333 +                hits.append((len(fragments), page_name, fragments))
 334 +        else:
 335 +            if count:
 336 +                hits.append((count, page_name, None))
 337 +
 338 +    # The default comparison for tuples compares elements in order,
 339 +    # so this sorts by number of hits
 340 +    hits.sort()
 341 +    hits.reverse()
 342 +
 343 +    return (len(all_pages), hits)
 344  
 345  #############################################################################
 346  ### Misc

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2005-07-12 02:26:49, 6.3 KB) [[attachment:NewTableOfContents-1.3.4.py]]
  • [get | view] (2005-05-01 18:12:47, 2.6 KB) [[attachment:README]]
  • [get | view] (2003-12-07 18:15:55, 1.3 KB) [[attachment:TableOfContents-startdepth.diff]]
  • [get | view] (2005-06-25 14:38:34, 4.3 KB) [[attachment:moin-1.3.4-rss_rc.py-per_page_feeds.patch]]
  • [get | view] (2005-06-09 20:25:52, 10.1 KB) [[attachment:moin-cache-friendly.diff]]
  • [get | view] (2005-04-27 17:22:13, 2.3 KB) [[attachment:moin-negotiate-auth.diff]]
  • [get | view] (2005-04-04 05:12:33, 18.0 KB) [[attachment:moinmoin-1.3.4-editor-insert-patch.diff]]
  • [get | view] (2005-04-04 05:50:16, 43.3 KB) [[attachment:moinmoin-1.3.4-editor-insert-screenshot.png]]
  • [get | view] (2005-08-17 20:24:31, 18.1 KB) [[attachment:moinmoin-1.3.5-editor-insert-patch.diff]]
  • [get | view] (2003-12-07 18:15:55, 13.0 KB) [[attachment:multisearch.diff]]
  • [get | view] (2005-06-14 14:45:06, 0.8 KB) [[attachment:vary-cookie.diff]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.