changeset 2651:2003e3685733

Improved search GUI - Added information about contenttype and item size in the items metadata. Also added color coding for various stuff like green for metadata, yellow for search term suggestions, blue for item names. Also added search options to help in search - search all revisions or the latest ones, sort search results by time - newer first, older first or default, search items of particular contenttype(s). Also removed the second search bar in the upper right corner in search page.
author Ajitesh Gupta <ajgupta93@gmail.com>
date Thu, 26 Jun 2014 04:09:07 +0530
parents 4385775cf3a1
children 9645576dd44d
files MoinMoin/apps/frontend/views.py MoinMoin/constants/contenttypes.py MoinMoin/search/__init__.py MoinMoin/static/js/search.js MoinMoin/templates/ajaxsearch.html MoinMoin/templates/base.html MoinMoin/templates/search.html MoinMoin/themes/__init__.py MoinMoin/themes/basic/static/css/basic.css MoinMoin/themes/basic/static/custom-less/basic.less MoinMoin/themes/basic/static/custom-less/moin-variables.less MoinMoin/themes/basic/templates/layout.html MoinMoin/themes/foobar/static/css/common.css MoinMoin/themes/foobar/static/css/stylus/main.styl MoinMoin/themes/modernized/static/css/common.css MoinMoin/themes/modernized/static/css/stylus/main.styl make.py
diffstat 17 files changed, 330 insertions(+), 86 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/apps/frontend/views.py	Thu Jun 26 02:13:49 2014 +0530
+++ b/MoinMoin/apps/frontend/views.py	Thu Jun 26 04:09:07 2014 +0530
@@ -38,6 +38,7 @@
 import pytz
 from babel import Locale
 
+from whoosh import sorting
 from whoosh.query import Term, Prefix, And, Or, DateRange, Every
 from whoosh.analysis import StandardAnalyzer
 
@@ -58,6 +59,7 @@
 from MoinMoin.constants.namespaces import *
 from MoinMoin.constants.itemtypes import ITEMTYPE_DEFAULT, ITEMTYPE_TICKET
 from MoinMoin.constants.chartypes import CHARS_UPPER, CHARS_LOWER
+from MoinMoin.constants.contenttypes import *
 from MoinMoin.util import crypto
 from MoinMoin.util.interwiki import url_for_item, split_fqname, CompositeName
 from MoinMoin.search import SearchForm
@@ -266,15 +268,74 @@
         return transcluded_names
 
 
+def add_file_filters(_filter, filetypes):
+    """
+    Add various terms to the filter for the search query for the selected file types
+    in the search options.
+
+    :param _filter: the current filter
+    :param filetypes: list of selected filetypes
+    :returns: the required _filter for the search query
+    """
+    if filetypes:
+        alltypes = "all" in filetypes
+        contenttypes = []
+        files_filter = []
+        if alltypes or "markup" in filetypes:
+            contenttypes.append(CONTENTTYPE_MARKUP)
+        if alltypes or "text" in filetypes:
+            contenttypes.append(CONTENTTYPE_TEXT)
+        if alltypes or "image" in filetypes:
+            contenttypes.append(CONTENTTYPE_IMAGE)
+        if alltypes or "audio" in filetypes:
+            contenttypes.append(CONTENTTYPE_AUDIO)
+        if alltypes or "video" in filetypes:
+            contenttypes.append(CONTENTTYPE_VIDEO)
+        if alltypes or "drawing" in filetypes:
+            contenttypes.append(CONTENTTYPE_DRAWING)
+        if alltypes or "other" in filetypes:
+            contenttypes.append(CONTENTTYPE_OTHER)
+        for ctype in contenttypes:
+            for itemtype in ctype:
+                files_filter.append(Term("contenttype", itemtype))
+        files_filter = Or(files_filter)
+        _filter.append(files_filter)
+        _filter = And(_filter)
+    return _filter
+
+
+def add_facets(facets, time_sorting):
+    """
+    Adds various facets for the search features.
+
+    :param facets: current facets
+    :param time_sorting: defines the sorting order and can have one of the following 3 values :
+                     1. default - default search
+                     2. old - sort old items first
+                     3. new - sort new items first
+    :returns: required facets for the search query
+    """
+    if time_sorting == "new":
+        facets.append(sorting.FieldFacet("mtime", reverse=True))
+    elif time_sorting == "old":
+        facets.append(sorting.FieldFacet("mtime", reverse=False))
+    return facets
+
+
 @frontend.route('/+search/<itemname:item_name>', methods=['GET', 'POST'])
 @frontend.route('/+search', defaults=dict(item_name=u''), methods=['GET', 'POST'])
 def search(item_name):
     search_form = SearchForm.from_flat(request.values)
     ajax = True if request.args.get('boolajax') else False
     valid = search_form.validate()
+    time_sorting = False
+    filetypes = []
     if ajax:
         query = request.args.get('q')
-        history = request.args.get('history')
+        history = request.args.get('history') == "true"
+        time_sorting = request.args.get('time_sorting')
+        filetypes = request.args.get('filetypes')
+        filetypes = filetypes.split(',')[:-1]  # To remove the extra u'' at the end of the list
     else:
         query = search_form['q'].value
         history = bool(request.values.get('history'))
@@ -288,7 +349,8 @@
         qp = flaskg.storage.query_parser([NAME_EXACT, NAME, SUMMARY, CONTENT, CONTENTNGRAM], idx_name=idx_name)
         q = qp.parse(query)
 
-        _filter = None
+        _filter = []
+        _filter = add_file_filters(_filter, filetypes)
         if item_name:  # Only search this item and subitems
             prefix_name = item_name + u'/'
             terms = [Term(NAME_EXACT, item_name), Prefix(NAME_EXACT, prefix_name), ]
@@ -318,8 +380,10 @@
 
         with flaskg.storage.indexer.ix[idx_name].searcher() as searcher:
             # terms is set to retrieve list of terms which matched, in the searchtemplate, for highlight.
+            facets = []
+            facets = add_facets(facets, time_sorting)
             flaskg.clock.start('search')
-            results = searcher.search(q, filter=_filter, limit=100, terms=True)
+            results = searcher.search(q, filter=_filter, limit=100, terms=True, sortedby=facets)
             flaskg.clock.stop('search')
             flaskg.clock.start('search suggestions')
             name_suggestions = [word for word, score in results.key_terms(NAME, docs=20, numterms=10)]
--- a/MoinMoin/constants/contenttypes.py	Thu Jun 26 02:13:49 2014 +0530
+++ b/MoinMoin/constants/contenttypes.py	Thu Jun 26 04:09:07 2014 +0530
@@ -21,6 +21,91 @@
 CONTENTTYPE_DEFAULT = u'application/octet-stream'
 CONTENTTYPE_NONEXISTENT = u'application/x-nonexistent'
 
+CONTENTTYPE_MARKUP = [
+    u'text/x.moin.wiki;charset=utf-8',
+    u'text/x-mediawiki;charset=utf-8',
+    u'text/x.moin.creole;charset=utf-8',
+    u'text/x-markdown;charset=utf-8',
+    u'text/x-rst;charset=utf-8',
+    u'text/html;charset=utf-8',
+    u'application/docbook+xml;charset=utf-8',
+]
+
+CONTENTTYPE_TEXT = [
+    u'text/plain;charset=utf-8',
+    u'text/x-diff;charset=utf-8',
+    u'text/x-python;charset=utf-8',
+    u'text/csv;charset=utf-8',
+    u'text/x-irclog;charset=utf-8',
+]
+
+CONTENTTYPE_IMAGE = [
+    u'image/svg+xml',
+    u'image/png',
+    u'image/jpeg',
+    u'image/gif',
+]
+
+CONTENTTYPE_AUDIO = [
+    u'audio/wave',
+    u'audio/ogg',
+    u'audio/mpeg',
+    u'audio/webm',
+]
+
+CONTENTTYPE_VIDEO = [
+    u'video/ogg',
+    u'video/webm',
+    u'video/mp4',
+]
+
+CONTENTTYPE_DRAWING = [
+    u'application/x-twikidraw',
+    u'application/x-anywikidraw',
+    u'application/x-svgdraw',
+]
+
+CONTENTTYPE_OTHER = [
+    u'application/octet-stream',
+    u'application/x-tar',
+    u'application/x-gtar',
+    u'application/zip',
+    u'application/pdf',
+]
+
+CONTENTTYPES_MAP = {
+    u'text/x.moin.wiki;charset=utf-8': 'Wiki (Moinmoin)',
+    u'text/x-mediawiki;charset=utf-8': 'Wiki (MediaWiki)',
+    u'text/x.moin.creole;charset=utf-8': 'Wiki (Creole)',
+    u'text/x-markdown;charset=utf-8': 'Markdown',
+    u'text/x-rst;charset=utf-8': 'ReST',
+    u'text/html;charset=utf-8': 'HTML',
+    u'application/docbook+xml;charset=utf-8': 'DocBook',
+    u'text/plain;charset=utf-8': 'Plain Text',
+    u'text/x-diff;charset=utf-8': 'Diff/Patch',
+    u'text/x-python;charset=utf-8': 'Python Code',
+    u'text/csv;charset=utf-8': 'CSV',
+    u'text/x-irclog;charset=utf-8': 'IRC Log',
+    u'image/svg+xml': 'SVG Image',
+    u'image/png': 'PNG Image',
+    u'image/jpeg': 'JPEG Image',
+    u'image/gif': 'GIF Image',
+    u'audio/wave': 'WAV Audio',
+    u'audio/ogg': 'OGG Audio',
+    u'audio/mpeg': 'MP3 Audio',
+    u'audio/webm': 'WebM Audio',
+    u'video/ogg': 'OGG Video',
+    u'video/webm': 'WebM Video',
+    u'video/mp4': 'MP4 Video',
+    u'application/x-twikidraw': 'TDRAW',
+    u'application/x-anywikidraw': 'ADRAW',
+    u'application/x-svgdraw': 'SVGDRAW',
+    u'application/octet-stream': 'Binary File',
+    u'application/x-tar': 'TAR',
+    u'application/x-gtar': 'TGZ',
+    u'application/zip': 'ZIP',
+    u'application/pdf': 'PDF',
+}
 
 GROUP_MARKUP_TEXT = 'markup text items'
 GROUP_OTHER_TEXT = 'other text items'
--- a/MoinMoin/search/__init__.py	Thu Jun 26 02:13:49 2014 +0530
+++ b/MoinMoin/search/__init__.py	Thu Jun 26 04:09:07 2014 +0530
@@ -28,7 +28,6 @@
 
 class SearchForm(Form):
     q = Search
-    history = InlineCheckbox.using(label=L_('search all revisions'))
     submit_label = L_('Search')
 
     validators = [ValidSearch()]
--- a/MoinMoin/static/js/search.js	Thu Jun 26 02:13:49 2014 +0530
+++ b/MoinMoin/static/js/search.js	Thu Jun 26 04:09:07 2014 +0530
@@ -5,23 +5,39 @@
         return false;
     });
 
-    // hide form submit button
-    $('#moin-long-searchform .button').hide();
+    $(document).on("click", "#moin-long-searchform .button", (function(){
+        $('#moin-search-query').keyup();
+    }));
 
-    function ajaxify(query, allrevs) {
+    $(document).on("click", "label", (function(){
+        $('#moin-search-query').keyup();
+    }));
+
+    $(document).on("click", ".moin-search-option-bar", (function(){
+        $('.moin-searchoptions').toggleClass('hidden');
+    }));
+
+    $('.moin-loginsettings').addClass('navbar-right');
+
+    function ajaxify(query, allrevs, time_sorting, filetypes) {
         $.ajax({
             type: "GET",
             url: "/+search",
-            data: { q: query, history: allrevs, boolajax: true }
+            data: { q: query, history: allrevs, time_sorting: time_sorting, filetypes: filetypes, boolajax: true }
         }).done(function( html ) {
             $('#finalresults').html(html)
         });
     }
+
     $('#moin-search-query').keyup(function() {
-        var allrev = false;
-        if($('[name="history"]').prop('checked')){
-            allrev = true;
-        }
-        ajaxify($(this).val(), allrev);
+        var allrev;
+        var mtime = false;
+        var filetypes= '';
+        allrev = $('[name="history"]:checked').val() === "all";
+        time_sorting = $('[name="modified_time"]:checked').val();
+        $('[name="itemtype"]:checked').each(function() {
+            filetypes += $(this).val() + ',';
+        });
+        ajaxify($(this).val(), allrev, time_sorting, filetypes);
     });
 });
--- a/MoinMoin/templates/ajaxsearch.html	Thu Jun 26 02:13:49 2014 +0530
+++ b/MoinMoin/templates/ajaxsearch.html	Thu Jun 26 04:09:07 2014 +0530
@@ -1,40 +1,40 @@
-<br/>
-{% if omitted_words %}
-  <p>{{ _("common words in query: %(termlist)s", termlist=omitted_words) }}</p>
-{% endif %}
-<br/>
 {% if results is defined %}
-    <p class="searchstats">
-        {% if results %}
-        {{ _("%(result_len)d results found (%(runtime).3f secs).",
-              result_len=results|length, runtime=results.runtime
-            )
-        }}
-        {% else %}
-        {{ _("No results found (%(runtime).3f secs).", runtime=results.runtime) }}
-        {% endif %}
-    </p>
+    {% if omitted_words %}
+        <p>{{ _("Common words in query: %(termlist)s", termlist=omitted_words) }}</p>
     {% endif %}
-
     {% if results is defined %}
         {% if word_suggestions %}
-            <p>{{ _("input suggestions: %(termlist)s", termlist=word_suggestions) }}</p>
+            <p class="moin-suggestions">{{ _("Input suggestions : ") }}</p><p class="moin-suggestion-terms">{{ _(" %(termlist)s", termlist=word_suggestions) }}</p><br>
         {% endif %}
         {% if name_suggestions or content_suggestions %}
-            <p>{{ _("name term suggestions: %(termlist)s", termlist=name_suggestions) }}</p>
-            <p>{{ _("content term suggestions: %(termlist)s", termlist=content_suggestions) }}</p>
+            <p class="moin-suggestions">{{ _("Name term suggestions : ") }}</p><p class="moin-suggestion-terms">{{ _( " %(termlist)s", termlist=name_suggestions) }}</p><br>
+            <p class="moin-suggestions">{{ _("Content term suggestions : ") }}</p><p class="moin-suggestion-terms">{{ _(" %(termlist)s", termlist=content_suggestions) }}</p><br><br>
         {% endif %}
+        <p class="searchstats">
+            {% if results %}
+            {{ _("%(result_len)d results found (%(runtime).3f secs).",
+                  result_len=results|length, runtime=results.runtime
+                )
+            }}
+            {% else %}
+            {{ _("No results found (%(runtime).3f secs).", runtime=results.runtime) }}
+            {% endif %}
+        </p>
         {% if results %}
             <div class="searchresults">
                 <table>
                     {% for result in results %}
                         {% if result['wikiname'] == cfg.interwikiname %}
                             <tr>
-                                <td class="moin-wordbreak">{{ result.pos + 1 }}
-                                    {% if history %}
-                                        <a href="{{ url_for_item(item_name=result['revid'], wiki_name='Self', namespace=result['namespace'], field='revid') }}"><b>{{ result['name'] | join(' | ')}}</b></a>
+                                <td class="moin-wordbreak">
+                                    {% if result['name'] %}
+                                        {% if history %}
+                                            <a href="{{ url_for_item(item_name=result['revid'], wiki_name='Self', namespace=result['namespace'], field='revid') }}"><b>{{ result['name'] | join(' | ')}}</b></a>
+                                        {% else %}
+                                            <a href="{{ url_for_item(item_name=result['name'][0], wiki_name='Self', namespace=result['namespace']) }}"><b>{{ result['name'] | join(' | ')}}</b></a>
+                                        {% endif %}
                                     {% else %}
-                                        <a href="{{ url_for_item(item_name=result['name'][0], wiki_name='Self', namespace=result['namespace']) }}"><b>{{ result['name'] | join(' | ')}}</b></a>
+                                        <a href="{{ url_for_item(item_name=result['revid'], wiki_name='Self', namespace=result['namespace'], field='revid') }}"><b>Item ID : {{ result['itemid'] }}</b></a>
                                     {% endif %}
                                 </td>
                             </tr>
@@ -45,23 +45,23 @@
                                     </td>
                                 </tr>
                             {% endif %}
-                            <tr>
+                            <tr class="moin-search-meta">
                                 <td>
-                                    <p class="info searchhitinfobar">{{ _("Revision: %(revid)s Last Change: %(mtime)s", revid=result['revid']|shorten_id, mtime=result['mtime']|datetimeformat) }}</p>
+                                    <p class="info searchhitinfobar">{{ _("Revision: %(revid)s - %(size)s - %(mtime)s - %(type)s", type=(result['contenttype']|shorten_ctype), mtime=result['mtime']|datetimeformat, size=result['size']|filesizeformat, revid=result['revid']|shorten_id) }}</p>
                                 </td>
                             </tr>
                             <tr>
                                 <td>
-                                    {% if user.may.read(result['name']) %}
-                                        <p class="info foundtext">{{ result.highlights('content')|safe }}</p>
+                                    {% if user.may.read(get_fqname(item_name=results['itemid'],field='ITEMID',namespace=results['namespace'])) %}
+                                        <p class="info foundtext">{{ result.highlights('content')|safe }}</p><br>
                                     {% else %}
-                                        <p class="info foundtext">{{ _("You don't have read permission for this item.") }}</p>
+                                        <p class="info foundtext">{{ _("You don't have read permission for this item.") }}</p><br>
                                     {% endif %}
                                 </td>
                             </tr>
                         {% else %}
                             <tr>
-                                <td class="moin-wordbreak">{{ result.pos + 1 }}
+                                <td class="moin-wordbreak">
                                 <a class="moin-interwiki" href="{{ url_for_item(item_name=result['name'], wiki_name=result['wikiname'], rev=result['revid']) }}"><b>{{ "%s:%s" % (result['wikiname'], result['name']) }}</b></a>
                                 </td>
                             </tr>
@@ -70,4 +70,5 @@
                 </table>
             </div>
         {% endif %}
+    {% endif %}
 {% endif %}
--- a/MoinMoin/templates/base.html	Thu Jun 26 02:13:49 2014 +0530
+++ b/MoinMoin/templates/base.html	Thu Jun 26 04:09:07 2014 +0530
@@ -53,6 +53,7 @@
 
     {% block theme_stylesheets %}
     <link media="all" rel="stylesheet" href="{{ theme_static('css/common.css') }}" />
+    <link media="all" rel="stylesheet" href="{{ url_for('static', filename='css/common.css') }}" />
     {% endblock %}
     {{ stylesheets }}
     {% if user.valid and user.css_url -%}
--- a/MoinMoin/templates/search.html	Thu Jun 26 02:13:49 2014 +0530
+++ b/MoinMoin/templates/search.html	Thu Jun 26 04:09:07 2014 +0530
@@ -10,13 +10,53 @@
 {% endblock %}
 
 {% block content %}
+    <h1>{{_("Search")}}</h1>
     {{ gen.form.open(medium_search_form, id='moin-long-searchform', method='get', action=url_for('frontend.search', item_name=item_name)) }}
         <p>
         {{ forms.render(medium_search_form['q']) }}
         {{ forms.render_submit(medium_search_form) }}
         </p>
+        <div class="moin-search-option-bar"><h4 style="display:inline-block">Search Options</h4><span class="icon-chevron-down"></span></div>
+        <div class="moin-searchoptions hidden">
+            <table>
+                <tr colspan="4">
+                    <th width="20%">Revisions</td>
+                    <th width="20%">Sort By Time</td>
+                    <th width="60%" colspan="3">Content Types</td>
+                </tr>
+                <tr>
+                    <td>
+                        <label id="moin-option"><input type="radio" name="history" value="latest" checked="checked"> Latest</label><br>
+                        <label id="moin-option"><input type="radio" name="history" value="all"> All</label><br>
+                    </td>
+                    <td>
+                        <form>
+                            <label id="moin-option"><input type="radio" name="modified_time" value="default" checked="checked"> Default</label><br>
+                            <label id="moin-option"><input type="radio" name="modified_time" value="old"> Older First</label><br>
+                            <label id="moin-option"><input type="radio" name="modified_time" value="new"> Newer First</label><br>
+                        </form>
+                    </td>
+                    <form>
+                        <td>
+                            <label id="moin-option"><input type="checkbox" name="itemtype" value="markup"> Markup Text</label><br>
+                            <label id="moin-option"><input type="checkbox" name="itemtype" value="text"> Other Text</label><br>
+                            <label id="moin-option"><input type="checkbox" name="itemtype" value="image"> Image</label><br>
+                        </td>
+                        <td>
+                            <label id="moin-option"><input type="checkbox" name="itemtype" value="audio"> Audio</label><br>
+                            <label id="moin-option"><input type="checkbox" name="itemtype" value="video"> Video</label><br>
+                            <label id="moin-option"><input type="checkbox" name="itemtype" value="drawing"> Drawing</label><br>
+                        </td>
+                        <td>
+                            <label id="moin-option"><input type="checkbox" name="itemtype" value="other"> Other</label><br>
+                            <label id="moin-option"><input type="checkbox" name="itemtype" value="unknown"> Unknown</label><br>
+                            <label id="moin-option"><input type="checkbox" name="itemtype" value="all" checked="checked"> All</label><br>
+                        </td>
+                   </form>
+                </tr>
+            </table>
+        </div>
         <p>
-        {{ forms.render(medium_search_form['history']) }}
         {{ forms.render_errors(medium_search_form) }}
         </p>
     {{ gen.form.close() }}
--- a/MoinMoin/themes/__init__.py	Thu Jun 26 02:13:49 2014 +0530
+++ b/MoinMoin/themes/__init__.py	Thu Jun 26 04:09:07 2014 +0530
@@ -23,9 +23,10 @@
 from MoinMoin.i18n import _, L_, N_
 from MoinMoin import wikiutil, user
 from MoinMoin.constants.keys import USERID, ADDRESS, HOSTNAME, REVID, ITEMID, NAME_EXACT
+from MoinMoin.constants.contenttypes import CONTENTTYPES_MAP
 from MoinMoin.constants.namespaces import NAMESPACE_DEFAULT, NAMESPACE_USERPROFILES, NAMESPACE_ALL
 from MoinMoin.search import SearchForm
-from MoinMoin.util.interwiki import split_interwiki, getInterwikiHome, is_local_wiki, is_known_wiki, url_for_item, CompositeName, split_fqname
+from MoinMoin.util.interwiki import split_interwiki, getInterwikiHome, is_local_wiki, is_known_wiki, url_for_item, CompositeName, split_fqname, get_fqname
 from MoinMoin.util.crypto import cache_key
 from MoinMoin.util.forms import make_generator
 from MoinMoin.util.clock import timed
@@ -573,24 +574,6 @@
 }
 
 
-# TODO: Update dictionary with more content-types
-def shorten_content_type(contenttype):
-    """
-    Shorten content-types
-
-    Shortens the content-type to terms that normal users understand.
-
-    :param name: contenttype, unicode
-    :rtype: unicode
-    :returns: shortened version of contenttype
-    """
-    ctype = contenttype.split(';')[0]
-    if ctype in CONTENTTYPE_SHORTEN:
-        return CONTENTTYPE_SHORTEN[ctype]
-    else:
-        return "Unknown"
-
-
 def shorten_id(name, length=7):
     """
     Shorten IDs to specified length
@@ -639,13 +622,24 @@
     return timegm(dt.timetuple())
 
 
+def shorten_ctype(contenttype):
+    """
+    Returns user understandable terms for contenttype.
+
+    :param contenttype: contains the long form of the contenttype
+    :rtype: unicode
+    :returns: user understandable version of contenttype
+    """
+    return CONTENTTYPES_MAP.get(contenttype, "Unknown")
+
+
 def setup_jinja_env():
     app.jinja_env.filters['shorten_fqname'] = shorten_fqname
     app.jinja_env.filters['shorten_item_name'] = shorten_item_name
     app.jinja_env.filters['shorten_id'] = shorten_id
     app.jinja_env.filters['contenttype_to_class'] = contenttype_to_class
     app.jinja_env.filters['json_dumps'] = dumps
-    app.jinja_env.filters['shorten_ctype'] = shorten_content_type
+    app.jinja_env.filters['shorten_ctype'] = shorten_ctype
     # please note that these filters are installed by flask-babel:
     # datetimeformat, dateformat, timeformat, timedeltaformat
 
@@ -664,6 +658,7 @@
         'cfg': app.cfg,
         'item_name': u'@NONAMEGIVEN',  # XXX can we just use u'' ?
         'url_for_item': url_for_item,
+        'get_fqname': get_fqname,
         'get_editor_info': lambda meta: get_editor_info(meta),
         'utctimestamp': lambda dt: utctimestamp(dt),
         'gen': make_generator(),
--- a/MoinMoin/themes/basic/static/css/basic.css	Thu Jun 26 02:13:49 2014 +0530
+++ b/MoinMoin/themes/basic/static/css/basic.css	Thu Jun 26 04:09:07 2014 +0530
@@ -6619,6 +6619,17 @@
   position: absolute;
   width: 100%;
 }
+.moin-search-option-bar {
+  padding-left: 10px;
+  border: 1px solid #555555;
+  background-color: #1b436d;
+  color: #c8ddf1;
+  border-radius: 5px;
+}
+.moin-search-option-bar > span {
+  float: right;
+  padding: 10px;
+}
 @media (min-width: 768px) {
   .container {
     min-height: 100%;
--- a/MoinMoin/themes/basic/static/custom-less/basic.less	Thu Jun 26 02:13:49 2014 +0530
+++ b/MoinMoin/themes/basic/static/custom-less/basic.less	Thu Jun 26 04:09:07 2014 +0530
@@ -317,6 +317,17 @@
   position: absolute;
   width: 100%;
 }
+.moin-search-option-bar {
+  padding-left: 10px;
+  border: 1px solid @gray;
+  background-color: @search_option_bar_color;
+  color: @search_option_bar_text_color;
+  border-radius: 5px;
+  > span {
+    float: right;
+    padding: 10px;
+  }
+}
 // set min-width to prevent search box from floating off window to right
 @media (min-width: 768px) {
   .container {
--- a/MoinMoin/themes/basic/static/custom-less/moin-variables.less	Thu Jun 26 02:13:49 2014 +0530
+++ b/MoinMoin/themes/basic/static/custom-less/moin-variables.less	Thu Jun 26 04:09:07 2014 +0530
@@ -23,3 +23,9 @@
 
 // Darker-Navbar and List heading background
 @navbar-bg: #eee;
+
+// Search
+// -------------------------
+@searchstats_color:              #808080;
+@search_option_bar_color:        #1b436d;
+@search_option_bar_text_color:   #c8ddf1;
--- a/MoinMoin/themes/basic/templates/layout.html	Thu Jun 26 02:13:49 2014 +0530
+++ b/MoinMoin/themes/basic/templates/layout.html	Thu Jun 26 04:09:07 2014 +0530
@@ -78,7 +78,7 @@
                                         {% endif %}
                                     </div>
                                 </div>
-                                <div class="col-lg-6">
+                                <div class="col-lg-6 moin-loginsettings">
                                     <div class="moin-navbar-collapse navbar-collapse collapse in" id="target">
                                         <ul class="nav navbar-nav moin-pull-right">
 
--- a/MoinMoin/themes/foobar/static/css/common.css	Thu Jun 26 02:13:49 2014 +0530
+++ b/MoinMoin/themes/foobar/static/css/common.css	Thu Jun 26 04:09:07 2014 +0530
@@ -354,10 +354,9 @@
 .searchresults dt{margin-top:1em;font-weight:normal}
 .searchresults dd,.searchresults p{font-size:.85em}
 .searchresults td{border-width:0}
-.searchresults p.info{margin-left:2%}
-.searchresults .searchhitinfobar{margin-left:15px;margin-top:0}
-.searchresults .foundtext{margin-left:15px;margin-top:0}
-p.searchstats{font-size:.8em;text-align:right;width:100%;padding:2px}
+.searchresults .searchhitinfobar{margin-top:0;display:inline}
+.searchresults .foundtext{margin-top:0}
+p.searchstats{font-size:.8em;width:100%;padding-left:14px}
 p.searchhint{background-color:#f4f4f4;border:1px solid #9d9d9b;padding:2px}
 .searchpages{margin-left:auto;margin-right:auto;}
 .searchpages tr,.searchpages td{border:0;padding:5px;margin:0;text-align:center;vertical-align:middle;color:#000;font-weight:bold;font-size:1.05em}
@@ -453,5 +452,8 @@
 #moin-main-container{min-height:100%;position:relative}
 #moin-main-box{margin-bottom:60px}
 #moin-footer{position:absolute;bottom:5px;width:98%}
+.moin-search-option-bar{width:75%;padding-left:14px;}
+.moin-search-option-bar span{float:right;padding:10px}
+.moin-suggestions{padding-left:14px}
 @media print{#moin-global-tray,#moin-local-panel,#moin-footer,#moin-searchform{display:none}
 }
--- a/MoinMoin/themes/foobar/static/css/stylus/main.styl	Thu Jun 26 02:13:49 2014 +0530
+++ b/MoinMoin/themes/foobar/static/css/stylus/main.styl	Thu Jun 26 04:09:07 2014 +0530
@@ -800,22 +800,18 @@
         font-size 0.85em
     td
         border-width 0
-    p.info
-        margin-left 2%
 
 .searchresults .searchhitinfobar
-    margin-left 15px
     margin-top 0
+    display inline
 
 .searchresults .foundtext
-    margin-left 15px
     margin-top 0
 
 p.searchstats
     font-size 0.8em
-    text-align right
     width 100%
-    padding 2px
+    padding-left 14px
 
 p.searchhint
     background-color page_color
@@ -1171,6 +1167,16 @@
     bottom 5px
     width 98%
 
+.moin-search-option-bar
+    width 75%
+    padding-left 14px
+    span
+        float right
+        padding 10px
+
+.moin-suggestions
+    padding-left 14px
+
 /* fix tests -- currently checking <big> and <small> */
 @media print
     #moin-global-tray
--- a/MoinMoin/themes/modernized/static/css/common.css	Thu Jun 26 02:13:49 2014 +0530
+++ b/MoinMoin/themes/modernized/static/css/common.css	Thu Jun 26 04:09:07 2014 +0530
@@ -306,10 +306,9 @@
 .searchresults dt{margin-top:1em;font-weight:normal}
 .searchresults dd,.searchresults p{font-size:.85em}
 .searchresults td{border-width:0}
-.searchresults p.info{margin-left:2%}
-.searchresults .searchhitinfobar{margin-left:15px;margin-top:0}
-.searchresults .foundtext{margin-left:15px;margin-top:0}
-p.searchstats{font-size:.8em;text-align:right;width:100%;padding:2px}
+.searchresults .searchhitinfobar{margin-top:0;display:inline}
+.searchresults .foundtext{margin-top:0}
+p.searchstats{font-size:.8em;width:100%;padding-left:14px}
 p.searchhint{background-color:#eef1f6;border:1px solid #4e7da9;padding:2px}
 .searchpages{margin-left:auto;margin-right:auto}
 .searchpages tr,.searchpages td{border:0;padding:5px;margin:0;text-align:center;vertical-align:middle;color:#000;font-weight:bold;font-size:1.05em}
@@ -520,6 +519,9 @@
 #moin-main-wrapper{position:relative;min-height:100%}
 #moin-page{padding-bottom:105px}
 #moin-footer{position:absolute;width:100%;bottom:0}
+.moin-search-option-bar{width:75%;padding-left:14px;}
+.moin-search-option-bar span{float:right;padding:10px}
+.moin-suggestions{padding-left:14px}
 @media print{html{font-family:serif;font-size:12pt;width:100%}
 body,#moin-page,#moin-content-data{margin:0;padding:0}
 a,a:visited,a.moin-nonexistent{color:#939393;text-decoration:none}
--- a/MoinMoin/themes/modernized/static/css/stylus/main.styl	Thu Jun 26 02:13:49 2014 +0530
+++ b/MoinMoin/themes/modernized/static/css/stylus/main.styl	Thu Jun 26 04:09:07 2014 +0530
@@ -511,22 +511,17 @@
 .searchresults td
     border-width 0
 
-.searchresults p.info
-    margin-left 2%
-
 .searchresults .searchhitinfobar
-    margin-left 15px
     margin-top 0
+    display inline
 
 .searchresults .foundtext
-    margin-left 15px
     margin-top 0
 
 p.searchstats
     font-size 0.8em
-    text-align right
     width 100%
-    padding 2px
+    padding-left 14px
 
 p.searchhint
     background-color table_bg_color
@@ -1556,6 +1551,16 @@
     width 100%
     bottom 0
 
+.moin-search-option-bar
+    width 75%
+    padding-left 14px
+    span
+        float right
+        padding 10px
+
+.moin-suggestions
+    padding-left 14px
+
 @media print
     html
         font-family serif
--- a/make.py	Thu Jun 26 02:13:49 2014 +0530
+++ b/make.py	Thu Jun 26 04:09:07 2014 +0530
@@ -378,7 +378,7 @@
             data_loc = '{0};{1}'.format(bootstrap_loc, pygments_loc)
         else:
             data_loc = '{0}:{1}'.format(bootstrap_loc, pygments_loc)
-        include = '--include-path=' + data_loc        
+        include = '--include-path=' + data_loc
         command = 'cd MoinMoin/themes/basic/static/custom-less{0}lessc {1} basic.less ../css/basic.css'.format(SEP, include)
         result = subprocess.call(command, shell=True)
         if result == 0: