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" +
+
+ Source file encoding Specify the encoding of the file being previewed + + + Display line numbers in the source file +
+ If set to 'table', output line numbers as a table with two cells, one containing the line numbers, the other the whole code. + + + Start line numbers from The line number for the first line (default: 1) + + + Line number step If set to a number n > 1, only every nth line number is printed. + +
+ + for more options available see http://pygments.org/docs/formatters/#common-options +
+ Pygments raw options (pass key-value pairs of pygments options separated by ,) + +
+ + +
+
+%include footer \ No newline at end of file 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}} diff --git a/webui.py b/webui.py index 3e77257..26da2a6 100755 --- a/webui.py +++ b/webui.py @@ -27,6 +27,18 @@ from recoll import rclconfig except: import rclconfig +# import pygments +try: + 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 + print "No pygments library found - source code highlight is not available" #}}} #{{{ settings # settings defaults @@ -38,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 @@ -116,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 = [] @@ -235,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 @@ -255,11 +304,32 @@ def preview(resnum): doc = rclq.fetchone() 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' + 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' + # 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' else: bottle.response.content_type = 'text/plain; charset=utf-8' - return tdoc.text + return result #}}} #{{{ download @bottle.route('/download/') @@ -328,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