Show More
@@ -0,0 +1,113 b'' | |||||
|
1 | """This preprocessor detect cells using a different language through | |||
|
2 | magic extensions such as `%%R` or `%%octave`. Cell's metadata is marked | |||
|
3 | so that the appropriate highlighter can be used in the `highlight` | |||
|
4 | filter. | |||
|
5 | """ | |||
|
6 | ||||
|
7 | #----------------------------------------------------------------------------- | |||
|
8 | # Copyright (c) 2013, the IPython Development Team. | |||
|
9 | # | |||
|
10 | # Distributed under the terms of the Modified BSD License. | |||
|
11 | # | |||
|
12 | # The full license is in the file COPYING.txt, distributed with this software. | |||
|
13 | #----------------------------------------------------------------------------- | |||
|
14 | ||||
|
15 | #----------------------------------------------------------------------------- | |||
|
16 | # Imports | |||
|
17 | #----------------------------------------------------------------------------- | |||
|
18 | ||||
|
19 | from __future__ import print_function, absolute_import | |||
|
20 | ||||
|
21 | import re | |||
|
22 | ||||
|
23 | # Our own imports | |||
|
24 | from .base import Preprocessor | |||
|
25 | from IPython.utils.traitlets import Dict | |||
|
26 | ||||
|
27 | #----------------------------------------------------------------------------- | |||
|
28 | # Classes | |||
|
29 | #----------------------------------------------------------------------------- | |||
|
30 | ||||
|
31 | ||||
|
32 | class HighlightMagicsPreprocessor(Preprocessor): | |||
|
33 | """ | |||
|
34 | Detects and tags code cells that use a different languages than Python. | |||
|
35 | """ | |||
|
36 | ||||
|
37 | # list of magic language extensions and their associated pygment lexers | |||
|
38 | default_languages = Dict( | |||
|
39 | default_value={ | |||
|
40 | '%%R': 'r', | |||
|
41 | '%%bash': 'bash', | |||
|
42 | '%%cython': 'cython', | |||
|
43 | '%%javascript': 'javascript', | |||
|
44 | '%%julia': 'julia', | |||
|
45 | '%%latex': 'latex', | |||
|
46 | '%%octave': 'octave', | |||
|
47 | '%%perl': 'perl', | |||
|
48 | '%%ruby': 'ruby', | |||
|
49 | '%%sh': 'sh'}) | |||
|
50 | ||||
|
51 | # user defined language extensions | |||
|
52 | languages = Dict( | |||
|
53 | config=True, | |||
|
54 | help=("Syntax highlighting for magic's extension languages. " | |||
|
55 | "Each item associates a language magic extension such as %%R, " | |||
|
56 | "with a pygments lexer such as r.")) | |||
|
57 | ||||
|
58 | def __init__(self, config=None, **kw): | |||
|
59 | """Public constructor""" | |||
|
60 | ||||
|
61 | super(HighlightMagicsPreprocessor, self).__init__(config=config, **kw) | |||
|
62 | ||||
|
63 | # Update the default languages dict with the user configured ones | |||
|
64 | self.default_languages.update(self.languages) | |||
|
65 | ||||
|
66 | # build a regular expression to catch language extensions and choose | |||
|
67 | # an adequate pygments lexer | |||
|
68 | any_language = "|".join(self.default_languages.keys()) | |||
|
69 | self.re_magic_language = re.compile( | |||
|
70 | r'^\s*({0})\s+'.format(any_language)) | |||
|
71 | ||||
|
72 | def which_magic_language(self, source): | |||
|
73 | """ | |||
|
74 | When a cell uses another language through a magic extension, | |||
|
75 | the other language is returned. | |||
|
76 | If no language magic is detected, this function returns None. | |||
|
77 | ||||
|
78 | Parameters | |||
|
79 | ---------- | |||
|
80 | source: str | |||
|
81 | Source code of the cell to highlight | |||
|
82 | """ | |||
|
83 | ||||
|
84 | m = self.re_magic_language.match(source) | |||
|
85 | ||||
|
86 | if m: | |||
|
87 | # By construction of the re, the matched language must be in the | |||
|
88 | # languages dictionary | |||
|
89 | return self.default_languages[m.group(1)] | |||
|
90 | else: | |||
|
91 | return None | |||
|
92 | ||||
|
93 | def preprocess_cell(self, cell, resources, cell_index): | |||
|
94 | """ | |||
|
95 | Tags cells using a magic extension language | |||
|
96 | ||||
|
97 | Parameters | |||
|
98 | ---------- | |||
|
99 | cell : NotebookNode cell | |||
|
100 | Notebook cell being processed | |||
|
101 | resources : dictionary | |||
|
102 | Additional resources used in the conversion process. Allows | |||
|
103 | preprocessors to pass variables into the Jinja engine. | |||
|
104 | cell_index : int | |||
|
105 | Index of the cell being processed (see base.py) | |||
|
106 | """ | |||
|
107 | ||||
|
108 | # Only tag code cells | |||
|
109 | if hasattr(cell, "input") and cell.cell_type == "code": | |||
|
110 | magic_language = self.which_magic_language(cell.input) | |||
|
111 | if magic_language: | |||
|
112 | cell['metadata']['magics_language'] = magic_language | |||
|
113 | return cell, resources |
@@ -0,0 +1,68 b'' | |||||
|
1 | """ | |||
|
2 | Module with tests for the HighlightMagics preprocessor | |||
|
3 | """ | |||
|
4 | ||||
|
5 | #----------------------------------------------------------------------------- | |||
|
6 | # Copyright (c) 2013, the IPython Development Team. | |||
|
7 | # | |||
|
8 | # Distributed under the terms of the Modified BSD License. | |||
|
9 | # | |||
|
10 | # The full license is in the file COPYING.txt, distributed with this software. | |||
|
11 | #----------------------------------------------------------------------------- | |||
|
12 | ||||
|
13 | #----------------------------------------------------------------------------- | |||
|
14 | # Imports | |||
|
15 | #----------------------------------------------------------------------------- | |||
|
16 | ||||
|
17 | from .base import PreprocessorTestsBase | |||
|
18 | from ..highlightmagics import HighlightMagicsPreprocessor | |||
|
19 | ||||
|
20 | ||||
|
21 | #----------------------------------------------------------------------------- | |||
|
22 | # Class | |||
|
23 | #----------------------------------------------------------------------------- | |||
|
24 | ||||
|
25 | class TestHighlightMagics(PreprocessorTestsBase): | |||
|
26 | """Contains test functions for highlightmagics.py""" | |||
|
27 | ||||
|
28 | ||||
|
29 | def build_preprocessor(self): | |||
|
30 | """Make an instance of a preprocessor""" | |||
|
31 | preprocessor = HighlightMagicsPreprocessor() | |||
|
32 | preprocessor.enabled = True | |||
|
33 | return preprocessor | |||
|
34 | ||||
|
35 | def test_constructor(self): | |||
|
36 | """Can a HighlightMagicsPreprocessor be constructed?""" | |||
|
37 | self.build_preprocessor() | |||
|
38 | ||||
|
39 | def test_tagging(self): | |||
|
40 | """Test the HighlightMagicsPreprocessor tagging""" | |||
|
41 | nb = self.build_notebook() | |||
|
42 | res = self.build_resources() | |||
|
43 | preprocessor = self.build_preprocessor() | |||
|
44 | nb.worksheets[0].cells[0].input = """%%R -i x,y -o XYcoef | |||
|
45 | lm.fit <- lm(y~x) | |||
|
46 | par(mfrow=c(2,2)) | |||
|
47 | print(summary(lm.fit)) | |||
|
48 | plot(lm.fit) | |||
|
49 | XYcoef <- coef(lm.fit)""" | |||
|
50 | ||||
|
51 | nb, res = preprocessor(nb, res) | |||
|
52 | ||||
|
53 | assert('magics_language' in nb.worksheets[0].cells[0]['metadata']) | |||
|
54 | ||||
|
55 | self.assertEqual(nb.worksheets[0].cells[0]['metadata']['magics_language'], 'r') | |||
|
56 | ||||
|
57 | def test_no_false_positive(self): | |||
|
58 | """Test that HighlightMagicsPreprocessor does not tag false positives""" | |||
|
59 | nb = self.build_notebook() | |||
|
60 | res = self.build_resources() | |||
|
61 | preprocessor = self.build_preprocessor() | |||
|
62 | nb.worksheets[0].cells[0].input = """# this should not be detected | |||
|
63 | print(\""" | |||
|
64 | %%R -i x, y | |||
|
65 | \""")""" | |||
|
66 | nb, res = preprocessor(nb, res) | |||
|
67 | ||||
|
68 | assert('magics_language' not in nb.worksheets[0].cells[0]['metadata']) No newline at end of file |
@@ -68,7 +68,8 b' class Exporter(LoggingConfigurable):' | |||||
68 | nbpreprocessors.CSSHTMLHeaderPreprocessor, |
|
68 | nbpreprocessors.CSSHTMLHeaderPreprocessor, | |
69 | nbpreprocessors.RevealHelpPreprocessor, |
|
69 | nbpreprocessors.RevealHelpPreprocessor, | |
70 | nbpreprocessors.LatexPreprocessor, |
|
70 | nbpreprocessors.LatexPreprocessor, | |
71 |
nbpreprocessors.SphinxPreprocessor |
|
71 | nbpreprocessors.SphinxPreprocessor, | |
|
72 | nbpreprocessors.HighlightMagicsPreprocessor], | |||
72 | config=True, |
|
73 | config=True, | |
73 | help="""List of preprocessors available by default, by name, namespace, |
|
74 | help="""List of preprocessors available by default, by name, namespace, | |
74 | instance, or type.""") |
|
75 | instance, or type.""") |
@@ -46,7 +46,10 b' class HTMLExporter(TemplateExporter):' | |||||
46 | c = Config({ |
|
46 | c = Config({ | |
47 | 'CSSHTMLHeaderPreprocessor':{ |
|
47 | 'CSSHTMLHeaderPreprocessor':{ | |
48 | 'enabled':True |
|
48 | 'enabled':True | |
49 |
} |
|
49 | }, | |
|
50 | 'HighlightMagicsPreprocessor': { | |||
|
51 | 'enabled':True | |||
|
52 | } | |||
50 | }) |
|
53 | }) | |
51 | c.merge(super(HTMLExporter,self).default_config) |
|
54 | c.merge(super(HTMLExporter,self).default_config) | |
52 | return c |
|
55 | return c |
@@ -85,6 +85,9 b' class LatexExporter(TemplateExporter):' | |||||
85 | }, |
|
85 | }, | |
86 | 'SphinxPreprocessor': { |
|
86 | 'SphinxPreprocessor': { | |
87 | 'enabled':True |
|
87 | 'enabled':True | |
|
88 | }, | |||
|
89 | 'HighlightMagicsPreprocessor': { | |||
|
90 | 'enabled':True | |||
88 | } |
|
91 | } | |
89 | }) |
|
92 | }) | |
90 | c.merge(super(LatexExporter,self).default_config) |
|
93 | c.merge(super(LatexExporter,self).default_config) |
@@ -47,6 +47,9 b' class SlidesExporter(TemplateExporter):' | |||||
47 | 'RevealHelpPreprocessor':{ |
|
47 | 'RevealHelpPreprocessor':{ | |
48 | 'enabled':True, |
|
48 | 'enabled':True, | |
49 | }, |
|
49 | }, | |
|
50 | 'HighlightMagicsPreprocessor': { | |||
|
51 | 'enabled':True | |||
|
52 | } | |||
50 | }) |
|
53 | }) | |
51 | c.merge(super(SlidesExporter,self).default_config) |
|
54 | c.merge(super(SlidesExporter,self).default_config) | |
52 | return c |
|
55 | return c |
@@ -14,7 +14,7 b' from within Jinja templates.' | |||||
14 | # Imports |
|
14 | # Imports | |
15 | #----------------------------------------------------------------------------- |
|
15 | #----------------------------------------------------------------------------- | |
16 |
|
16 | |||
17 |
from |
|
17 | from pygments import highlight as pygements_highlight | |
18 | from pygments.lexers import get_lexer_by_name |
|
18 | from pygments.lexers import get_lexer_by_name | |
19 | from pygments.formatters import HtmlFormatter |
|
19 | from pygments.formatters import HtmlFormatter | |
20 | from pygments.formatters import LatexFormatter |
|
20 | from pygments.formatters import LatexFormatter | |
@@ -37,52 +37,66 b' __all__ = [' | |||||
37 | 'highlight2latex' |
|
37 | 'highlight2latex' | |
38 | ] |
|
38 | ] | |
39 |
|
39 | |||
40 |
|
40 | def highlight2html(source, language='ipython', metadata=None): | ||
41 | def highlight2html(source, language='ipython'): |
|
|||
42 | """ |
|
41 | """ | |
43 | Return a syntax-highlighted version of the input source as html output. |
|
42 | Return a syntax-highlighted version of the input source as html output. | |
44 |
|
43 | |||
45 | Parameters |
|
44 | Parameters | |
46 | ---------- |
|
45 | ---------- | |
47 | source : str |
|
46 | source : str | |
48 |
|
|
47 | source of the cell to highlight. | |
49 | language : str |
|
48 | language : str | |
50 | Language to highlight the syntax of. |
|
49 | Language to highlight the syntax of. | |
|
50 | metadata : NotebookNode cell metadata | |||
|
51 | metadata of the cell to highlight. | |||
51 | """ |
|
52 | """ | |
52 |
|
53 | |||
53 | return _pygment_highlight(source, HtmlFormatter(), language) |
|
54 | return _pygment_highlight(source, HtmlFormatter(), language, metadata) | |
54 |
|
55 | |||
55 |
|
56 | |||
56 | def highlight2latex(source, language='ipython'): |
|
57 | def highlight2latex(source, language='ipython', metadata=None): | |
57 | """ |
|
58 | """ | |
58 | Return a syntax-highlighted version of the input source as latex output. |
|
59 | Return a syntax-highlighted version of the input source as latex output. | |
59 |
|
60 | |||
60 | Parameters |
|
61 | Parameters | |
61 | ---------- |
|
62 | ---------- | |
62 | source : str |
|
63 | source : str | |
63 |
|
|
64 | source of the cell to highlight. | |
64 | language : str |
|
65 | language : str | |
65 | Language to highlight the syntax of. |
|
66 | Language to highlight the syntax of. | |
|
67 | metadata : NotebookNode cell metadata | |||
|
68 | metadata of the cell to highlight. | |||
66 | """ |
|
69 | """ | |
67 | return _pygment_highlight(source, LatexFormatter(), language) |
|
70 | return _pygment_highlight(source, LatexFormatter(), language, metadata) | |
|
71 | ||||
68 |
|
72 | |||
69 |
|
73 | |||
70 | def _pygment_highlight(source, output_formatter, language='ipython'): |
|
74 | def _pygment_highlight(source, output_formatter, language='ipython', metadata=None): | |
71 | """ |
|
75 | """ | |
72 | Return a syntax-highlighted version of the input source |
|
76 | Return a syntax-highlighted version of the input source | |
73 |
|
77 | |||
74 | Parameters |
|
78 | Parameters | |
75 | ---------- |
|
79 | ---------- | |
76 | source : str |
|
80 | source : str | |
77 |
|
|
81 | source of the cell to highlight. | |
78 | output_formatter : Pygments formatter |
|
82 | output_formatter : Pygments formatter | |
79 | language : str |
|
83 | language : str | |
80 | Language to highlight the syntax of. |
|
84 | Language to highlight the syntax of. | |
|
85 | metadata : NotebookNode cell metadata | |||
|
86 | metadata of the cell to highlight. | |||
81 | """ |
|
87 | """ | |
82 |
|
88 | |||
|
89 | # If the cell uses a magic extension language, | |||
|
90 | # use the magic language instead. | |||
|
91 | if language == 'ipython' \ | |||
|
92 | and metadata \ | |||
|
93 | and 'magics_language' in metadata: | |||
|
94 | ||||
|
95 | language = metadata['magics_language'] | |||
|
96 | ||||
83 | if language == 'ipython': |
|
97 | if language == 'ipython': | |
84 | lexer = IPythonLexer() |
|
98 | lexer = IPythonLexer() | |
85 | else: |
|
99 | else: | |
86 | lexer = get_lexer_by_name(language, stripall=True) |
|
100 | lexer = get_lexer_by_name(language, stripall=True) | |
87 |
|
101 | |||
88 |
return pygements_highlight(source, lexer, output_formatter) |
|
102 | return pygements_highlight(source, lexer, output_formatter) |
@@ -7,6 +7,7 b' from .revealhelp import RevealHelpPreprocessor' | |||||
7 | from .latex import LatexPreprocessor |
|
7 | from .latex import LatexPreprocessor | |
8 | from .sphinx import SphinxPreprocessor |
|
8 | from .sphinx import SphinxPreprocessor | |
9 | from .csshtmlheader import CSSHTMLHeaderPreprocessor |
|
9 | from .csshtmlheader import CSSHTMLHeaderPreprocessor | |
|
10 | from .highlightmagics import HighlightMagicsPreprocessor | |||
10 |
|
11 | |||
11 | # decorated function Preprocessors |
|
12 | # decorated function Preprocessors | |
12 | from .coalescestreams import coalesce_streams |
|
13 | from .coalescestreams import coalesce_streams |
@@ -36,7 +36,7 b' In [{{ cell.prompt_number }}]:' | |||||
36 |
|
36 | |||
37 | {% block input %} |
|
37 | {% block input %} | |
38 | <div class="input_area box-flex1"> |
|
38 | <div class="input_area box-flex1"> | |
39 | {{ cell.input | highlight2html }} |
|
39 | {{ cell.input | highlight2html(metadata=cell.metadata) }} | |
40 | </div> |
|
40 | </div> | |
41 | {%- endblock input %} |
|
41 | {%- endblock input %} | |
42 |
|
42 |
@@ -284,7 +284,7 b' Note: For best display, use latex syntax highlighting. =))' | |||||
284 | \vspace{-25pt} |
|
284 | \vspace{-25pt} | |
285 |
|
285 | |||
286 | % Add contents below. |
|
286 | % Add contents below. | |
287 | ((( cell.input | highlight2latex ))) |
|
287 | ((( cell.input | highlight2latex(metadata=cell.metadata) ))) | |
288 |
|
288 | |||
289 | ((* elif resources.sphinx.outputstyle == 'notebook' *)) |
|
289 | ((* elif resources.sphinx.outputstyle == 'notebook' *)) | |
290 | \vspace{6pt} |
|
290 | \vspace{6pt} | |
@@ -292,7 +292,7 b' Note: For best display, use latex syntax highlighting. =))' | |||||
292 | \vspace{-2.65\baselineskip} |
|
292 | \vspace{-2.65\baselineskip} | |
293 | \begin{ColorVerbatim} |
|
293 | \begin{ColorVerbatim} | |
294 | \vspace{-0.7\baselineskip} |
|
294 | \vspace{-0.7\baselineskip} | |
295 | ((( cell.input | highlight2latex ))) |
|
295 | ((( cell.input | highlight2latex(metadata=cell.metadata) ))) | |
296 | ((* if cell.input == None or cell.input == '' *)) |
|
296 | ((* if cell.input == None or cell.input == '' *)) | |
297 | \vspace{0.3\baselineskip} |
|
297 | \vspace{0.3\baselineskip} | |
298 | ((* else *)) |
|
298 | ((* else *)) |
General Comments 0
You need to be logged in to leave comments.
Login now