highlightmagics.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  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. # Copyright (c) Jupyter Development Team.
  7. # Distributed under the terms of the Modified BSD License.
  8. from __future__ import print_function, absolute_import
  9. import re
  10. from .base import Preprocessor
  11. from traitlets import Dict
  12. class HighlightMagicsPreprocessor(Preprocessor):
  13. """
  14. Detects and tags code cells that use a different languages than Python.
  15. """
  16. # list of magic language extensions and their associated pygment lexers
  17. default_languages = Dict({
  18. '%%R': 'r',
  19. '%%bash': 'bash',
  20. '%%cython': 'cython',
  21. '%%javascript': 'javascript',
  22. '%%julia': 'julia',
  23. '%%latex': 'latex',
  24. '%%octave': 'octave',
  25. '%%perl': 'perl',
  26. '%%ruby': 'ruby',
  27. '%%sh': 'sh',
  28. })
  29. # user defined language extensions
  30. languages = Dict(
  31. help=("Syntax highlighting for magic's extension languages. "
  32. "Each item associates a language magic extension such as %%R, "
  33. "with a pygments lexer such as r.")
  34. ).tag(config=True)
  35. def __init__(self, config=None, **kw):
  36. """Public constructor"""
  37. super(HighlightMagicsPreprocessor, self).__init__(config=config, **kw)
  38. # Update the default languages dict with the user configured ones
  39. self.default_languages.update(self.languages)
  40. # build a regular expression to catch language extensions and choose
  41. # an adequate pygments lexer
  42. any_language = "|".join(self.default_languages.keys())
  43. self.re_magic_language = re.compile(
  44. r'^\s*({0})\s+'.format(any_language))
  45. def which_magic_language(self, source):
  46. """
  47. When a cell uses another language through a magic extension,
  48. the other language is returned.
  49. If no language magic is detected, this function returns None.
  50. Parameters
  51. ----------
  52. source: str
  53. Source code of the cell to highlight
  54. """
  55. m = self.re_magic_language.match(source)
  56. if m:
  57. # By construction of the re, the matched language must be in the
  58. # languages dictionary
  59. return self.default_languages[m.group(1)]
  60. else:
  61. return None
  62. def preprocess_cell(self, cell, resources, cell_index):
  63. """
  64. Tags cells using a magic extension language
  65. Parameters
  66. ----------
  67. cell : NotebookNode cell
  68. Notebook cell being processed
  69. resources : dictionary
  70. Additional resources used in the conversion process. Allows
  71. preprocessors to pass variables into the Jinja engine.
  72. cell_index : int
  73. Index of the cell being processed (see base.py)
  74. """
  75. # Only tag code cells
  76. if cell.cell_type == "code":
  77. magic_language = self.which_magic_language(cell.source)
  78. if magic_language:
  79. cell['metadata']['magics_language'] = magic_language
  80. return cell, resources