101 lines
3.2 KiB
Python
101 lines
3.2 KiB
Python
|
"""This preprocessor detect cells using a different language through
|
||
|
magic extensions such as `%%R` or `%%octave`. Cell's metadata is marked
|
||
|
so that the appropriate highlighter can be used in the `highlight`
|
||
|
filter.
|
||
|
"""
|
||
|
|
||
|
# Copyright (c) Jupyter Development Team.
|
||
|
# Distributed under the terms of the Modified BSD License.
|
||
|
|
||
|
from __future__ import print_function, absolute_import
|
||
|
|
||
|
import re
|
||
|
|
||
|
from .base import Preprocessor
|
||
|
from traitlets import Dict
|
||
|
|
||
|
|
||
|
class HighlightMagicsPreprocessor(Preprocessor):
|
||
|
"""
|
||
|
Detects and tags code cells that use a different languages than Python.
|
||
|
"""
|
||
|
|
||
|
# list of magic language extensions and their associated pygment lexers
|
||
|
default_languages = Dict({
|
||
|
'%%R': 'r',
|
||
|
'%%bash': 'bash',
|
||
|
'%%cython': 'cython',
|
||
|
'%%javascript': 'javascript',
|
||
|
'%%julia': 'julia',
|
||
|
'%%latex': 'latex',
|
||
|
'%%octave': 'octave',
|
||
|
'%%perl': 'perl',
|
||
|
'%%ruby': 'ruby',
|
||
|
'%%sh': 'sh',
|
||
|
'%%sql': 'sql',
|
||
|
})
|
||
|
|
||
|
# user defined language extensions
|
||
|
languages = Dict(
|
||
|
help=("Syntax highlighting for magic's extension languages. "
|
||
|
"Each item associates a language magic extension such as %%R, "
|
||
|
"with a pygments lexer such as r.")
|
||
|
).tag(config=True)
|
||
|
|
||
|
def __init__(self, config=None, **kw):
|
||
|
"""Public constructor"""
|
||
|
|
||
|
super().__init__(config=config, **kw)
|
||
|
|
||
|
# Update the default languages dict with the user configured ones
|
||
|
self.default_languages.update(self.languages)
|
||
|
|
||
|
# build a regular expression to catch language extensions and choose
|
||
|
# an adequate pygments lexer
|
||
|
any_language = "|".join(self.default_languages.keys())
|
||
|
self.re_magic_language = re.compile(
|
||
|
r'^\s*({0})\s+'.format(any_language))
|
||
|
|
||
|
def which_magic_language(self, source):
|
||
|
"""
|
||
|
When a cell uses another language through a magic extension,
|
||
|
the other language is returned.
|
||
|
If no language magic is detected, this function returns None.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
source: str
|
||
|
Source code of the cell to highlight
|
||
|
"""
|
||
|
|
||
|
m = self.re_magic_language.match(source)
|
||
|
|
||
|
if m:
|
||
|
# By construction of the re, the matched language must be in the
|
||
|
# languages dictionary
|
||
|
return self.default_languages[m.group(1)]
|
||
|
else:
|
||
|
return None
|
||
|
|
||
|
def preprocess_cell(self, cell, resources, cell_index):
|
||
|
"""
|
||
|
Tags cells using a magic extension language
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
cell : NotebookNode cell
|
||
|
Notebook cell being processed
|
||
|
resources : dictionary
|
||
|
Additional resources used in the conversion process. Allows
|
||
|
preprocessors to pass variables into the Jinja engine.
|
||
|
cell_index : int
|
||
|
Index of the cell being processed (see base.py)
|
||
|
"""
|
||
|
|
||
|
# Only tag code cells
|
||
|
if cell.cell_type == "code":
|
||
|
magic_language = self.which_magic_language(cell.source)
|
||
|
if magic_language:
|
||
|
cell['metadata']['magics_language'] = magic_language
|
||
|
return cell, resources
|