Show More
@@ -0,0 +1,104 | |||
|
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 | # Needed to override preprocessor | |
|
25 | from .base import (Preprocessor) | |
|
26 | from IPython.utils.traitlets import Dict | |
|
27 | ||
|
28 | #----------------------------------------------------------------------------- | |
|
29 | # Classes | |
|
30 | #----------------------------------------------------------------------------- | |
|
31 | ||
|
32 | ||
|
33 | class HighlightMagicsPreprocessor(Preprocessor): | |
|
34 | """ | |
|
35 | Detects and tags code cells that use a different languages than Python. | |
|
36 | """ | |
|
37 | ||
|
38 | # list of magic language extensions and their associated pygment lexers | |
|
39 | languages = Dict( | |
|
40 | default_value={ | |
|
41 | '%%R': 'r', | |
|
42 | '%%bash': 'bash', | |
|
43 | '%%octave': 'octave', | |
|
44 | '%%perl': 'perl', | |
|
45 | '%%ruby': 'ruby'}, | |
|
46 | config=True, | |
|
47 | help=("Syntax highlighting for magic's extension languages. " | |
|
48 | "Each item associates a language magic extension such as %%R, " | |
|
49 | "with a pygments lexer such as r.")) | |
|
50 | ||
|
51 | def __init__(self, config=None, **kw): | |
|
52 | """Public constructor""" | |
|
53 | ||
|
54 | super(HighlightMagicsPreprocessor, self).__init__(config=config, **kw) | |
|
55 | ||
|
56 | # build a regular expression to catch language extensions and choose | |
|
57 | # an adequate pygments lexer | |
|
58 | any_language = "|".join(self.languages.keys()) | |
|
59 | self.re_magic_language = re.compile( | |
|
60 | r'^\s*({0})\s+'.format(any_language)) | |
|
61 | ||
|
62 | def which_magic_language(self, source): | |
|
63 | """ | |
|
64 | When a cell uses another language through a magic extension, | |
|
65 | the other language is returned. | |
|
66 | If no language magic is detected, this function returns None. | |
|
67 | ||
|
68 | Parameters | |
|
69 | ---------- | |
|
70 | source: str | |
|
71 | Source code of the cell to highlight | |
|
72 | """ | |
|
73 | ||
|
74 | m = self.re_magic_language.match(source) | |
|
75 | ||
|
76 | if m: | |
|
77 | # By construction of the re, the matched language must be in the | |
|
78 | # languages dictionnary | |
|
79 | assert(m.group(1) in self.languages) | |
|
80 | return self.languages[m.group(1)] | |
|
81 | else: | |
|
82 | return None | |
|
83 | ||
|
84 | def preprocess_cell(self, cell, resources, cell_index): | |
|
85 | """ | |
|
86 | Tags cells using a magic extension language | |
|
87 | ||
|
88 | Parameters | |
|
89 | ---------- | |
|
90 | cell : NotebookNode cell | |
|
91 | Notebook cell being processed | |
|
92 | resources : dictionary | |
|
93 | Additional resources used in the conversion process. Allows | |
|
94 | preprocessors to pass variables into the Jinja engine. | |
|
95 | cell_index : int | |
|
96 | Index of the cell being processed (see base.py) | |
|
97 | """ | |
|
98 | ||
|
99 | # Only tag code cells | |
|
100 | if hasattr(cell, "input") and cell.cell_type == "code": | |
|
101 | magic_language = self.which_magic_language(cell.input) | |
|
102 | if magic_language: | |
|
103 | cell['metadata']['magics_language'] = magic_language | |
|
104 | return cell, resources |
@@ -0,0 +1,68 | |||
|
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 class Exporter(LoggingConfigurable): | |||
|
68 | 68 | nbpreprocessors.CSSHTMLHeaderPreprocessor, |
|
69 | 69 | nbpreprocessors.RevealHelpPreprocessor, |
|
70 | 70 | nbpreprocessors.LatexPreprocessor, |
|
71 |
nbpreprocessors.SphinxPreprocessor |
|
|
71 | nbpreprocessors.SphinxPreprocessor, | |
|
72 | nbpreprocessors.HighlightMagicsPreprocessor], | |
|
72 | 73 | config=True, |
|
73 | 74 | help="""List of preprocessors available by default, by name, namespace, |
|
74 | 75 | instance, or type.""") |
@@ -46,7 +46,10 class HTMLExporter(TemplateExporter): | |||
|
46 | 46 | c = Config({ |
|
47 | 47 | 'CSSHTMLHeaderPreprocessor':{ |
|
48 | 48 | 'enabled':True |
|
49 |
} |
|
|
49 | }, | |
|
50 | 'HighlightMagicsPreprocessor': { | |
|
51 | 'enabled':True | |
|
52 | } | |
|
50 | 53 | }) |
|
51 | 54 | c.merge(super(HTMLExporter,self).default_config) |
|
52 | 55 | return c |
@@ -85,6 +85,9 class LatexExporter(TemplateExporter): | |||
|
85 | 85 | }, |
|
86 | 86 | 'SphinxPreprocessor': { |
|
87 | 87 | 'enabled':True |
|
88 | }, | |
|
89 | 'HighlightMagicsPreprocessor': { | |
|
90 | 'enabled':True | |
|
88 | 91 | } |
|
89 | 92 | }) |
|
90 | 93 | c.merge(super(LatexExporter,self).default_config) |
@@ -7,6 +7,7 from .revealhelp import RevealHelpPreprocessor | |||
|
7 | 7 | from .latex import LatexPreprocessor |
|
8 | 8 | from .sphinx import SphinxPreprocessor |
|
9 | 9 | from .csshtmlheader import CSSHTMLHeaderPreprocessor |
|
10 | from .highlightmagics import HighlightMagicsPreprocessor | |
|
10 | 11 | |
|
11 | 12 | # decorated function Preprocessors |
|
12 | 13 | from .coalescestreams import coalesce_streams |
General Comments 0
You need to be logged in to leave comments.
Login now