highlightmagics.py 3.1 KB

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