00001
00002 """
00003 MoinMoin - FullSearch Macro
00004
00005 <<FullSearch>>
00006 displays a search dialog, as it always did.
00007
00008 <<FullSearch()>>
00009 does the same as clicking on the page title, only that
00010 the result is embedded into the page. note the '()' after
00011 the macro name, which is an empty argument list.
00012
00013 <<FullSearch(Help)>>
00014 embeds a search result into a page, as if you entered
00015 'Help' into the search box.
00016
00017 The macro creates a page list without context or match info, just
00018 like PageList macro. It does not make sense to have context in non
00019 interactive search, and this kind of search is used usually for
00020 Category pages, where we don't care about the context.
00021
00022 TODO: If we need to have context for some cases, either we add a context argument,
00023 or make another macro that uses context, which may be easier to use.
00024
00025 @copyright: 2000-2004 Juergen Hermann <jh@web.de>,
00026 2006 MoinMoin:FranzPletz
00027 @license: GNU GPL, see COPYING for details.
00028 """
00029
00030 import re
00031 from MoinMoin import wikiutil, search
00032 from StackNavi import macro_StackNavi
00033 from MoinMoin.parser import text_moin_wiki as wiki
00034 import string, StringIO
00035
00036 Dependencies = ["pages"]
00037
00038
00039
00040 def pageListWithContext(self, macro, request, formatter, info=1, context=180,
00041 maxlines=1, paging=True, hitsFrom=0, hitsInfo=0):
00042 """ Format a list of found pages with context
00043
00044 The default parameter values will create Google-like search
00045 results, as this is the most known search interface. Good
00046 interface is familiar interface, so unless we have much better
00047 solution (we don't), being like Google is the way.
00048
00049 @param request: current request
00050 @param formatter: formatter to use
00051 @param info: show match info near the page link
00052 @param context: how many characters to show around each match.
00053 @param maxlines: how many contexts lines to show.
00054 @param paging: toggle paging
00055 @param hitsFrom: current position in the hits
00056 @param hitsInfo: toggle hits info line
00057 @rtype: unicode
00058 @return formatted page list with context
00059 """
00060 self._reset(request, formatter)
00061 f = formatter
00062 write = self.buffer.write
00063 _ = request.getText
00064
00065 if paging and len(self.hits) <= request.cfg.search_results_per_page:
00066 paging = False
00067
00068 if len(self.hits) == 0:
00069 write(f.definition_list(1) + f.definition_term(1) + "No results found." + f.definition_term(0) + f.definition_list(0))
00070
00071 else:
00072
00073 if paging:
00074 hitsTo = hitsFrom + request.cfg.search_results_per_page
00075 displayHits = self.hits[hitsFrom:hitsTo]
00076 else:
00077 displayHits = self.hits
00078
00079 display_results = []
00080
00081 for page in displayHits:
00082 f.div(0, css_class='content')
00083 write(macro_StackNavi(macro, page.page_name))
00084
00085 return getvalue(self)
00086
00087 def getvalue(self):
00088 """ Return output in div with CSS class """
00089 value = [
00090 self.formatter.div(1, css_class='content'),
00091 self.buffer.getvalue(),
00092 self.formatter.div(0),
00093 ]
00094 return '\n'.join(value)
00095
00096
00097
00098 class Node:
00099 def __init__(self, pagename, body, dependencies):
00100 self.pagename = pagename
00101 self.body = body
00102 self.dependencies = dependencies
00103
00104 def __repr__(self):
00105 return "<Node %s %s>" % (self.pagename, self.dependencies)
00106
00107 def topoSort(dependencies):
00108 dead = {}
00109 list = []
00110
00111 for node in dependencies.values(): dead[node] = False
00112
00113 nonterminals = []
00114 terminals = []
00115 for node in dependencies.values():
00116 if node.dependencies:
00117 nonterminals.append(node)
00118 else:
00119 terminals.append(node)
00120
00121 for node in nonterminals:
00122 visit(dependencies, terminals, node, list, dead);
00123
00124 list.reverse()
00125
00126 list = list + terminals
00127 return list
00128
00129 def visit(dependencies, terminals, dependency, list, dead):
00130 if dependency is None: return
00131 if dead.get(dependency, False): return
00132
00133 dead[dependency] = True
00134
00135 if dependency.dependencies:
00136 for node in dependency.dependencies:
00137 visit(dependencies, terminals, dependencies.get(node, None), list, dead)
00138 try:
00139 terminals.remove(dependency)
00140 except ValueError: pass
00141
00142 list.append(dependency)
00143
00144 def sortResults(display_results):
00145 dependencies = {}
00146
00147 for pagename, nextpages, body in display_results:
00148 node = Node(pagename, body, nextpages)
00149 dependencies[pagename] = node
00150
00151 results = topoSort(dependencies)
00152
00153 return results
00154
00155
00156 def execute(macro, needle):
00157 request = macro.request
00158 _ = request.getText
00159
00160
00161
00162 if needle.isspace():
00163 err = _('Please use a more selective search term instead of '
00164 '{{{"%s"}}}', wiki=True) % needle
00165 return '<span class="error">%s</span>' % err
00166
00167 needle = needle.strip()
00168
00169
00170 if(needle=='all'):
00171 results = search.searchPages(request, 'CategoryStack -StackList -StackTemplate', sort='page_name')
00172 else:
00173 lookfor= needle + ' CategoryStack -StackList -StackTemplate'
00174 results = search.searchPages(request, lookfor, sort='page_name')
00175 return pageListWithContext(results, macro, request, macro.formatter, paging=False)
00176
00177
00178 ret = []
00179 for result in results:
00180 pass
00181
00182 return string.join(ret)
00183
00184