changeset 1187:1bdac55acc14

paging support for fullsearch action, fullsearch macro broken
author Franz Pletz <fpletz AT franz-pletz DOT org>
date Tue, 18 Jul 2006 17:15:02 +0200
parents 3172214eac96
children f4f7b0c2a9f2
files MoinMoin/action/fullsearch.py MoinMoin/multiconfig.py MoinMoin/search/results.py docs/CHANGES.fpletz
diffstat 4 files changed, 73 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/action/fullsearch.py	Tue Jul 18 15:36:02 2006 +0200
+++ b/MoinMoin/action/fullsearch.py	Tue Jul 18 17:15:02 2006 +0200
@@ -42,6 +42,7 @@
     needle = request.form.get(fieldname, [''])[0]
     case = int(request.form.get('case', [0])[0])
     regex = int(request.form.get('regex', [0])[0]) # no interface currently
+    hitsFrom = int(request.form.get('from', [0])[0])
 
     max_context = 1 # only show first `max_context` contexts XXX still unused
 
@@ -94,15 +95,16 @@
     request.write(request.formatter.startContent("content"))
 
     # First search stats
-    request.write(results.stats(request, request.formatter))
+    request.write(results.stats(request, request.formatter, hitsFrom))
 
     # Then search results
     info = not titlesearch
     if context:
         output = results.pageListWithContext(request, request.formatter, info=info,
-                                             context=context)
+                context=context, hitsFrom=hitsFrom)
     else:
-        output = results.pageList(request, request.formatter, info=info)
+        output = results.pageList(request, request.formatter, info=info,
+                hitsFrom=hitsFrom)
     request.write(output)
 
     request.write(request.formatter.endContent())
--- a/MoinMoin/multiconfig.py	Tue Jul 18 15:36:02 2006 +0200
+++ b/MoinMoin/multiconfig.py	Tue Jul 18 17:15:02 2006 +0200
@@ -295,6 +295,7 @@
     xapian_search = False # disabled until xapian is finished
     xapian_index_dir = None
     xapian_stemming = True
+    search_results_per_page = 10
 
     mail_login = None # or "user pwd" if you need to use SMTP AUTH
     mail_sendmail = None # "/usr/sbin/sendmail -t -i" to not use SMTP, but sendmail
--- a/MoinMoin/search/results.py	Tue Jul 18 15:36:02 2006 +0200
+++ b/MoinMoin/search/results.py	Tue Jul 18 17:15:02 2006 +0200
@@ -10,7 +10,7 @@
     @license: GNU GPL, see COPYING for details
 """
 
-import StringIO, time
+import StringIO, time, re
 from MoinMoin import config, wikiutil
 from MoinMoin.Page import Page
 
@@ -266,31 +266,37 @@
         self.hits = [item[1] for item in tmp]
         self.sort = 'page_name'
         
-    def stats(self, request, formatter):
+    def stats(self, request, formatter, hitsFrom):
         """ Return search statistics, formatted with formatter
 
         @param request: current request
         @param formatter: formatter to use
+        @param hitsFrom: current position in the hits
         @rtype: unicode
         @return formatted statistics
         """
         _ = request.getText
         output = [
             formatter.paragraph(1),
-            formatter.text(_("%(hits)d results out of about %(pages)d pages.") %
-                   {'hits': len(self.hits), 'pages': self.pages}),
+            formatter.text(_("Hits %(hitsFrom)d to %(hitsTo)d "
+                "from %(hits)d results out of about %(pages)d pages.") %
+                   {'hits': len(self.hits), 'pages': self.pages,
+                       'hitsFrom': hitsFrom + 1,
+                       'hitsTo': hitsFrom + request.cfg.search_results_per_page}),
             u' (%s)' % formatter.text(_("%.2f seconds") % self.elapsed),
             formatter.paragraph(0),
             ]
         return ''.join(output)
 
-    def pageList(self, request, formatter, info=0, numbered=1):
+    def pageList(self, request, formatter, info=0, numbered=1,
+            hitsFrom=0):
         """ Format a list of found pages
 
         @param request: current request
         @param formatter: formatter to use
         @param info: show match info in title
         @param numbered: use numbered list for display
+        @param hitsFrom: current position in the hits
         @rtype: unicode
         @return formatted page list
         """
@@ -298,15 +304,17 @@
         f = formatter
         write = self.buffer.write
         if numbered:
-            list = f.number_list
+            list = lambda on: f.number_list(on, start=hitsFrom+1)
         else:
             list = f.bullet_list
 
         # Add pages formatted as list
         if self.hits:
             write(list(1))
-
-            for page in self.hits:
+            
+            # XXX: Do some xapian magic here
+            hitsTo = hitsFrom + request.cfg.search_results_per_page
+            for page in self.hits[hitsFrom:hitsTo]:
                 if page.attachment:
                     querydict = {
                         'action': 'AttachFile',
@@ -330,11 +338,14 @@
                     ]
                 write(''.join(item))
             write(list(0))
+            write(self.formatPrevNextPageLinks(hitsFrom=hitsFrom,
+                hitsPerPage=request.cfg.search_results_per_page,
+                hitsNum=len(self.hits)))
 
         return self.getvalue()
 
     def pageListWithContext(self, request, formatter, info=1, context=180,
-                            maxlines=1):
+                            maxlines=1, hitsFrom=0):
         """ Format a list of found pages with context
 
         The default parameter values will create Google-like search
@@ -345,8 +356,9 @@
         @param request: current request
         @param formatter: formatter to use
         @param info: show match info near the page link
-        @param context: how many characters to show around each match. 
-        @param maxlines: how many contexts lines to show. 
+        @param context: how many characters to show around each match.
+        @param maxlines: how many contexts lines to show.
+        @param hitsFrom: current position in the hits
         @rtype: unicode
         @return formatted page list with context
         """
@@ -358,7 +370,9 @@
         if self.hits:
             write(f.definition_list(1))
 
-            for page in self.hits:
+            # XXX: Do some xapian magic here
+            hitsTo = hitsFrom+request.cfg.search_results_per_page
+            for page in self.hits[hitsFrom:hitsTo]:
                 matchInfo = ''
                 if info:
                     matchInfo = self.formatInfo(f, page)
@@ -389,6 +403,9 @@
                     ]
                 write(''.join(item))
             write(f.definition_list(0))
+            write(self.formatPrevNextPageLinks(hitsFrom=hitsFrom,
+                hitsPerPage=request.cfg.search_results_per_page,
+                hitsNum=len(self.hits)))
         
         return self.getvalue()
 
@@ -596,6 +613,39 @@
             return ''.join(output)
         return ''
 
+    def formatPrevNextPageLinks(self, hitsFrom, hitsPerPage, hitsNum):
+        """ Format previous and next page links in page
+
+        @param hitsFrom: current position in the hits
+        @param hitsPerPage: number of hits per page
+        @param hitsNum: number of hits
+        @rtype: unicode
+        @return: links to previous and next pages (if exist)
+        """
+        _ = self.request.getText
+        f = self.formatter
+        from_re = r'\&from=[\d]+'
+        uri = re.sub(from_re, '', self.request.request_uri)
+        from_uri = lambda n: '%s&from=%i' % (uri, n)
+        l = []
+        if hitsFrom > 0:        # previous page available
+            n = hitsFrom - hitsPerPage
+            if n < 0: n = 0
+            l.append(''.join([
+                f.url(1, href=from_uri(n)),
+                _('Previous Page'),
+                f.url(0)
+            ]))
+        if hitsFrom < hitsNum:  # next page available
+            n = hitsFrom + hitsPerPage
+            if n >= hitsNum: n = hitsNum - 1
+            l.append(''.join([
+                f.url(1, href=from_uri(n)),
+                _('Next Page'),
+                f.url(0)
+            ]))
+        return f.text(' | ').join(l)
+
     def querystring(self, querydict=None):
         """ Return query string, used in the page link """
         if querydict is None:
--- a/docs/CHANGES.fpletz	Tue Jul 18 15:36:02 2006 +0200
+++ b/docs/CHANGES.fpletz	Tue Jul 18 17:15:02 2006 +0200
@@ -25,8 +25,10 @@
     * New config options:
         xapian_search        0      enables xapian-powered search
         xapian_index_dir     None   directory for xapian indices
-        xapian_stemming      True   Toggles usage of stemmer, fallback
+        xapian_stemming      True   toggles usage of stemmer, fallback
                                     to False if no stemmer installed
+        search_results_per_page 10  determines how many hits should be
+                                    shown on a fullsearch action
   
   Bugfixes (only stuff that is buggy in moin/1.6 main branch):
     * ...
@@ -157,4 +159,6 @@
 
 2006-07-18
     * Fixed some bugs, whitespaces at EOL, better i18n for SystemInfo
+    * Implemented paging support for searches, needs some style
+      adjustments, breaks FullSearch macro for now