Commit 654d7568 authored by Antoine Beaupré's avatar Antoine Beaupré

ubuntu-like search engine prototype

parent c7c82b6b
......@@ -267,7 +267,7 @@ class ManpageRenderer(object):
'''abstract class to store the manpage regex pattern'''
#: default pattern for manpages
pattern = r'/(?P<path>man/(?:\w+/)?man[1-9]/.+\.[1-9]\w*(?:\.gz))?$'
pattern = r'/(?:(?P<suite>\w+)/)?(?P<path>man/(?:\w+/)?man[1-9]/(?P<name>.+)\.(?P<section>[1-9]\w*)(?:\.gz))?$'
class W3mRenderer(CommandRenderer, ManpageRenderer):
# coding: utf-8
'''search engine for debmans'''
# Copyright (C) 2016 Antoine Beaupré <[email protected]>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# GNU Affero General Public License for more details.
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <>.
from __future__ import division, absolute_import
from __future__ import print_function
import re
import click
from flask import Flask
app = Flask(__name__)
from jinja2 import Template
from debmans.utils import find_static_file
from debmans.renderer import find_files, ManpageRenderer
def hello_world():
return 'Hello, World!'
def search(pattern):
'''respond to searches requests
.. todo:: messy use of Jinja directly because Flask expects
templates to be in templates/ here. just follow the
convention in `the flask manual
.. todo:: Flask also expects static files to be in static/, so we
should copy them there instead of at the root
.. todo:: unit test this:
.. note:: inspired by
with open(find_static_file('static/template.html'), 'r') as tmpl:
r = Template('utf-8'))
# XXX: this is getting a tad ridiculous now
# we shouldn't have to hack at the pattern like this
# there is a similar problem in dispatch - maybe file list
# should include the match pattern?
pattern = re.sub('\(\?P<name>[^)]*\)',
pattern, # XXX: wildcard or not?
app.logger.debug('searching for pattern: %s', pattern)
patterns = {}
# XXX: this doesn't belong here? should be command-level patterns
patterns[re.compile(pattern)] = None
# XXX: not sure this is the best structure
manpages = {} # suite -> (name, section)
i = 0
for path in find_files(app.config['output'], patterns):
i += 1
# XXX: again
m =, path)
assert m
suite ='suite')
name ='name')
section ='section')
if section not in manpages:
manpages[section] = set()
app.logger.debug('found manpage %s (%s) in %s', name, section, suite)
manpages[section].add((name, suite))
# XXX: should extend the normal template instead
# see
# XXX: this should also know about all sections, probably?
t = Template('''
{% for section, mans in manpages.iteritems() %}
{% for man, suite in mans %}
<td>{{ man }} ({{suite}})</td>
{% endfor %}
content = '%d manuals found' % i
content += t.render(manpages=manpages)
#for suite, mans in manpages.iteritems():
# content += 'suite: %s' % suite
# for man, sect in mans:
# app.logger.debug('go man: %s', man)
# content += 'man: %s sect %s' % (man, sect)
return r.render(content=content, suites={})
def devsearch(obj):
'''search the given output directory
.. todo:: this should probably replace serve
obviously, a production setup would not have this as a click
command, but as a CGI or WSGI app. see:
simplest is probably to provide WSGI and CGI shims. WSGI works
well in apache (and also works in Nginx) according to this:
and CGI works everywhere.
see also: nginx+uWSGI vs Apache - why we switched.
def main(output):
# XXX: not sure this is right, see
app.config['output'] = output
if __name__ == '__main__':
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment