From 5fa19fa0d90e0a360ed7e7b20b50b6171bdbd000 Mon Sep 17 00:00:00 2001 From: Aliaksandr Dubrouski Date: Sun, 29 Dec 2013 20:45:49 +0300 Subject: [PATCH 1/4] Adds pygments library for html formatting of the plain text result preview --- webui.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/webui.py b/webui.py index 3e77257..b443a0d 100755 --- a/webui.py +++ b/webui.py @@ -27,6 +27,15 @@ from recoll import rclconfig except: import rclconfig +# import pygments +try: + haspygments = True + from pygments import highlight + from pygments.lexers import guess_lexer + from pygments.formatters import HtmlFormatter +except: + haspygments = False + print "No pygments library found - source code highlight is not available" #}}} #{{{ settings # settings defaults @@ -255,11 +264,20 @@ def preview(resnum): doc = rclq.fetchone() xt = rclextract.Extractor(doc) tdoc = xt.textextract(doc.ipath) + result = tdoc.text if tdoc.mimetype == 'text/html': bottle.response.content_type = 'text/html; charset=utf-8' + else if haspygments: + lexer = guess_lexer(tdoc.text) + if None != lexer: + bottle.response.content_type = 'text/html; charset=utf-8' + formatter = HtmlFormatter(linenos=True, cssclass="source",full=True) + result = highlight(tdoc.text, lexer, formatter) + else: + bottle.response.content_type = 'text/plain; charset=utf-8' else: bottle.response.content_type = 'text/plain; charset=utf-8' - return tdoc.text + return result #}}} #{{{ download @bottle.route('/download/') From cbb824c94e745e985c1ce2e93b859c7824163920 Mon Sep 17 00:00:00 2001 From: Aliaksandr Dubrouski Date: Mon, 6 Jan 2014 04:23:48 +0300 Subject: [PATCH 2/4] Adds new view template for pygments configuration --- views/settings.tpl | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/views/settings.tpl b/views/settings.tpl index 3d24214..6c88ab0 100644 --- a/views/settings.tpl +++ b/views/settings.tpl @@ -17,6 +17,20 @@ Folder depth (number of levels of the folder dropdown)
+ %if haspygments: + Enable pygments (enables source file syntax highlight in preview if True) + + %if highlight: + Use MIME-type to guess lexer rather filename + (uses mime-based guess on how to preview file content) +
+ Configure pygments options + %end +
+ %else: + No pygments library found (Install pygments to enable source file syntax highlight in preview) +
+ %end Locations
%for d in dirs: {{d}} From 37225b54255a83e6aaf1fd930cacddf783e6b836 Mon Sep 17 00:00:00 2001 From: Aliaksandr Dubrouski Date: Mon, 6 Jan 2014 04:26:07 +0300 Subject: [PATCH 3/4] Adds new strategy for lexer guess based on the mime type first then on filename, adds configuration and defaults for preview mode. --- webui.py | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 74 insertions(+), 9 deletions(-) diff --git a/webui.py b/webui.py index b443a0d..26da2a6 100755 --- a/webui.py +++ b/webui.py @@ -32,6 +32,9 @@ haspygments = True from pygments import highlight from pygments.lexers import guess_lexer + from pygments.lexers import get_lexer_for_filename + from pygments.lexers import get_lexer_for_mimetype + from pygments.lexers import ClassNotFound from pygments.formatters import HtmlFormatter except: haspygments = False @@ -47,6 +50,30 @@ 'maxchars': 500, 'maxresults': 0, 'perpage': 25, + 'highlight': True and haspygments, + 'haspygments': haspygments, + 'usemime': False +} +# preview defaults +PREVIEW = { + 'hl_lines': [1,], # + 'nowrap': False, # If set to True, don't wrap the tokens at all, not even inside a
 tag. This disables most other options (default: False).
+    'full'  : True, # Tells the formatter to output a "full" document, i.e. a complete self-contained document (default: False).
+    'title' : '',    # If full is true, the title that should be used to caption the document (default: '').
+    'style' : 'default', # The style to use, can be a string or a Style subclass (default: 'default'). This option has no effect if the cssfile and noclobber_cssfile option are given and the file specified in cssfile exists.
+    'linenos': 'table', # If set to 'table', output line numbers as a table with two cells, one containing the line numbers, the other the whole code. This is copy-and-paste-friendly, but may cause alignment problems with some browsers or fonts. If set to 'inline', the line numbers will be integrated in the 
 tag that contains the code (that setting is new in Pygments 0.8). For compatibility with Pygments 0.7 and earlier, every true value except 'inline' means the same as 'table' (in particular, that means also True).
+    'linenostart': 1,# The line number for the first line (default: 1).
+    'linenostep': 1,# If set to a number n > 1, only every nth line number is printed.
+    'linenospecial': 0,# If set to a number n > 0, every nth line number is given the CSS class "special" (default: 0).
+    'lineanchors': '',
+    'linespans': '',
+    'anchorlinenos': False, # If set to True, will wrap line numbers in  tags. Used in combination with linenos and lineanchors.
+    'nobackground': False,# If set to True, the formatter won't output the background color for the wrapping element.
+    'cssclass': 'source', # CSS class for the wrapping 
tag (default: 'highlight'). + 'classprefix': '', # Inline CSS styles for the wrapping
tag (default: ''). + 'encoding': 'utf-8', + 'outencoding': 'utf-8', + 'options': "style='inline'" } # sort fields/labels @@ -125,6 +152,14 @@ def get_config(): config['mounts'][d] = select([bottle.request.get_cookie(name), 'file://%s' % d], [None, '']) return config #}}} +#{{{ +def get_preview_config(): + config = {} + for k, v in PREVIEW.items(): + value = select([bottle.request.get_cookie(k), v]) + config[k] = type(v)(value) if str(v) != value else v + return config +#}}} #{{{ get_dirs def get_dirs(tops, depth): v = [] @@ -244,10 +279,15 @@ def results(): config['maxresults'] = nres if config['perpage'] == 0: config['perpage'] = nres - return { 'res': res, 'time': timer, 'query': query, 'dirs': - get_dirs(config['dirs'], config['dirdepth']), - 'qs': qs, 'sorts': SORTS, 'config': config, - 'query_string': bottle.request.query_string, 'nres': nres, + return { 'res': res, + 'time': timer, + 'query': query, + 'dirs': get_dirs(config['dirs'], config['dirdepth']), + 'qs': qs, + 'sorts': SORTS, + 'config': config, + 'query_string': bottle.request.query_string, + 'nres': nres, 'hasrclextract': hasrclextract } #}}} #{{{ preview @@ -265,13 +305,25 @@ def preview(resnum): xt = rclextract.Extractor(doc) tdoc = xt.textextract(doc.ipath) result = tdoc.text + cfg = get_config() if tdoc.mimetype == 'text/html': bottle.response.content_type = 'text/html; charset=utf-8' - else if haspygments: - lexer = guess_lexer(tdoc.text) + elif haspygments and cfg['highlight']: + try: + if cfg['usemime']: + try: + lexer = get_lexer_for_mimetype(doc.mimetype) + except ClassNotFound: + lexer = get_lexer_for_filename(doc.url) + else: + lexer = get_lexer_for_filename(doc.url) + except ClassNotFound: + print "No lexer found for %s with mime type '%s'" % (doc.url,doc.mimetype) + lexer = None if None != lexer: bottle.response.content_type = 'text/html; charset=utf-8' - formatter = HtmlFormatter(linenos=True, cssclass="source",full=True) + # depending on the lexer type apply the config for formatted output + formatter = HtmlFormatter(**get_preview_config()) result = highlight(tdoc.text, lexer, formatter) else: bottle.response.content_type = 'text/plain; charset=utf-8' @@ -346,14 +398,27 @@ def get_csv(): def settings(): return get_config() +@bottle.route('/pygments') +@bottle.view('pygments') +def pygments(): + return get_preview_config() if haspygments else {} + @bottle.route('/set') def set(): config = get_config() for k, v in DEFAULTS.items(): - bottle.response.set_cookie(k, str(bottle.request.query.get(k)), max_age=3153600000) + bottle.response.set_cookie(k, str(bottle.request.query.get(k)), max_age=3153600000, domain='localhost') for d in config['dirs']: cookie_name = 'mount_%s' % urllib.quote(d, '') - bottle.response.set_cookie(cookie_name, str(bottle.request.query.get('mount_%s' % d)), max_age=3153600000) + bottle.response.set_cookie(cookie_name, str(bottle.request.query.get('mount_%s' % d)), max_age=3153600000, domain='localhost') + bottle.redirect('./') + +@bottle.route('/setpygments') +def setpygments(): + for k, v in PREVIEW.items(): + update = select([bottle.request.query.get(k),v]) + bottle.response.set_cookie(k, str(update), max_age=3153600000, domain='') + # update config raw options bottle.redirect('./') #}}} #{{{ osd From e9c8ba091c1ce3a68d0981a34e0c284c820ee752 Mon Sep 17 00:00:00 2001 From: Aliaksandr Dubrouski Date: Tue, 7 Jan 2014 15:52:28 +0300 Subject: [PATCH 4/4] Configuration for pygments --- views/pygments.tpl | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 views/pygments.tpl diff --git a/views/pygments.tpl b/views/pygments.tpl new file mode 100644 index 0000000..d0ee817 --- /dev/null +++ b/views/pygments.tpl @@ -0,0 +1,28 @@ +%include header title=" / pygments" + +%include footer \ No newline at end of file