"""A file handler for plain text files."""
from os.path import join, splitext
from re import findall
from pygments import highlight
from pygments.lexers import guess_lexer_for_filename
from pygments.lexers.special import TextLexer
from pygments.lexers.configs import IniLexer
from pygments.formatters.html import HtmlFormatter
from pygments.util import ClassNotFound
from chrysalio.lib.utils import normalize_spaces, load_guessing_encoding
from chrysalio.helpers.literal import Literal
from ..lib.i18n import _
from ..lib.handler import LAYOUT_VIEW_PT, CHRYSALIO_JS, Handler
PLAIN_CSS = ('/ciowarehouse/css/handler_plain.css',)
# =============================================================================
[docs]def includeme(configurator):
"""Function to include CioWarehouse a handler.
:type configurator: pyramid.config.Configurator
:param configurator:
Object used to do configuration declaration within the application.
"""
Handler.register(configurator, HandlerPlain)
# =============================================================================
[docs]class HandlerPlain(Handler):
"""Class to manage a plain text file."""
uid = 'plain'
label = _('Generic plain text file handling')
extensions = (
'.txt', '.rst', '.rnc', '.tex', '.ini', '.py', '.css', '.xml', '.xsl',
'.regex', '.js', '.json', '.org', '.toml')
viewings = (
{'name': 'text', 'label': _('Text'),
'template': LAYOUT_VIEW_PT,
'css': PLAIN_CSS,
'js': CHRYSALIO_JS},
{'name': 'code', 'label': _('Code'),
'template': LAYOUT_VIEW_PT,
'css': PLAIN_CSS,
'js': CHRYSALIO_JS})
# -------------------------------------------------------------------------
[docs] def infos_complete_fields(
self, warehouse, path, abs_path, whoosh_fields, request=None):
"""Complete the ``whoosh_fields`` dictionary with information found
in the metadata file.
See: :meth:`.lib.handler.Handler.infos_complete_fields`
"""
super(HandlerPlain, self).infos_complete_fields(
warehouse, path, abs_path, whoosh_fields, request)
# Look for index field IDs to process
field_ids = self._remaining_fields(warehouse, whoosh_fields)
if not field_ids:
return
# Load file
content = load_guessing_encoding(abs_path)
if content is None: # pragma: nocover
self._log_error(
_('${w}/${p}: unknown encoding', {
'w': warehouse.uid, 'p': path}), request)
return
# Extract information
for field_id in field_ids:
indexer = self._indexers[field_id]
if indexer.get('argument'):
field = ' '.join(findall(indexer['argument'], content))
else:
field = content
if indexer.get('limit'):
field = normalize_spaces(field, indexer['limit'])
else:
field.strip()
if field:
whoosh_fields[field_id] = field
# -------------------------------------------------------------------------
[docs] def view(self, request, warehouse, content=None, ts_factory=None):
"""Return a string containing HTML to display the file.
See: :meth:`.lib.handler.Handler.view`
"""
path = join(*request.matchdict['path'])
if content is None:
content = load_guessing_encoding(join(warehouse.root, path))
if content is None: # pragma: nocover
self._log_error(
_('${w}/${p}: unknown encoding', {
'w': warehouse.uid, 'p': path}))
content = request.localizer.translate(_(
'${p}: unknown encoding ', {'p': path}))
viewing = self.current_rendering(request, warehouse, 'viewing')
try:
lexer = guess_lexer_for_filename(path, content)
except ClassNotFound:
lexer = IniLexer() \
if splitext(path)[1] == '.regex' else TextLexer()
content = highlight(content, lexer, HtmlFormatter())
return self._chameleon_render(
request, warehouse, viewing, ts_factory or _, {
'rendering_num': request.session[
'handlers'][self.uid]['viewing'],
'content': Literal(content)})