Bug 1255876 - Overriding the diff chunk generator to take into account explicit per-extension overrides; r=glob
MozReview-Commit-ID: ImDLT2T4yMj
--- a/pylib/pygments_override/pygments_override/extension.py
+++ b/pylib/pygments_override/pygments_override/extension.py
@@ -1,11 +1,46 @@
+import logging
+
from reviewboard.extensions.base import Extension
+from reviewboard.diffviewer.chunk_generator import (
+ get_diff_chunk_generator_class,
+ set_diff_chunk_generator_class
+)
+
+from pygments_override.overridable_chunk_generator import (
+ OverridableDiffChunkGenerator
+)
+
+
+logger = logging.getLogger(__name__)
+
class PygmentsOverride(Extension):
metadata = {
'Name': 'pygments-override',
'Summary': 'Customize Pygments for specific file extensions',
}
+ default_settings = {'overrides': ''}
+
+ is_configurable = True
+
def initialize(self):
- # Your extension initialization is done here.
- pass
+ self._original_chunk_generator_class = get_diff_chunk_generator_class()
+ set_diff_chunk_generator_class(OverridableDiffChunkGenerator)
+ logger.info('overridable diff chunk generator class set!')
+
+ def shutdown(self):
+ set_diff_chunk_generator_class(self._original_chunk_generator_class)
+ logger.info('original diff chunk generator class restored!')
+ super(PygmentsOverride, self).shutdown()
+
+ def get_overrides_map(self):
+ overrides = self.settings['overrides'].splitlines()
+ valid_overrides = [override for override in overrides
+ if '=' in override]
+ if valid_overrides != overrides:
+ invalid_overrides = set(overrides) - set(valid_overrides)
+ formatted_list = '\n'.join(invalid_overrides)
+ logger.error('ignoring malformed overrides:\n%s ' % formatted_list)
+
+ return dict([override.split('=') for override in valid_overrides])
new file mode 100644
--- /dev/null
+++ b/pylib/pygments_override/pygments_override/overridable_chunk_generator.py
@@ -0,0 +1,57 @@
+import logging
+from os.path import splitext
+
+from pygments import highlight
+from pygments.lexers import guess_lexer_for_filename, get_lexer_by_name
+
+from reviewboard.extensions.base import get_extension_manager
+from reviewboard.diffviewer.diffutils import split_line_endings
+from reviewboard.diffviewer.chunk_generator import (
+ get_diff_chunk_generator_class,
+ NoWrapperHtmlFormatter
+)
+
+
+logger = logging.getLogger(__name__)
+
+DiffChunkGenerator = get_diff_chunk_generator_class()
+
+
+class OverridableDiffChunkGenerator(DiffChunkGenerator):
+ """A chunk generator which overrides syntax highlighting."""
+
+ def _apply_pygments(self, data, filename):
+ """Applies Pygments syntax-highlighting to a file's contents.
+
+ Syntax highlight obeys a explicitly provided list of preferences by
+ extension or it is derived from the contents of the file.
+
+ The resulting HTML will be returned as a list of lines.
+ """
+ lexer = self._get_preferred_lexer(
+ filename, stripln=False, encoding='utf-8')
+ logger.debug('preferred lexer for %s: %s' % (filename, lexer))
+ if not lexer:
+ lexer = guess_lexer_for_filename(
+ filename, data, stripnl=False,
+ encoding='utf-8')
+
+ lexer.add_filter('codetagify')
+
+ return split_line_endings(highlight(data, lexer,
+ NoWrapperHtmlFormatter()))
+
+ def _get_preferred_lexer(self, filename, **options):
+ ext = splitext(filename)[1]
+ lexername = get_overrides().get(ext, None)
+ try:
+ lexer = get_lexer_by_name(lexername, **options)
+ except:
+ lexer = None
+ return lexer
+
+
+def get_overrides():
+ extension = get_extension_manager().get_enabled_extension(
+ 'pygments_override.extension.PygmentsOverride')
+ return extension.get_overrides_map()