ipython_console_highlighting.py
98 lines
| 3.4 KiB
| text/x-python
|
PythonLexer
Fernando Perez
|
r1850 | """reST directive for syntax-highlighting ipython interactive sessions. | ||
""" | ||||
#----------------------------------------------------------------------------- | ||||
# Needed modules | ||||
# Standard library | ||||
import re | ||||
# Third party | ||||
Fernando Perez
|
r1694 | from pygments.lexer import Lexer, do_insertions | ||
Fernando Perez
|
r1850 | from pygments.lexers.agile import (PythonConsoleLexer, PythonLexer, | ||
PythonTracebackLexer) | ||||
Fernando Perez
|
r1694 | from pygments.token import Comment, Generic | ||
Fernando Perez
|
r1850 | |||
Fernando Perez
|
r1694 | from sphinx import highlighting | ||
Fernando Perez
|
r1850 | |||
#----------------------------------------------------------------------------- | ||||
# Global constants | ||||
Fernando Perez
|
r1694 | line_re = re.compile('.*?\n') | ||
Fernando Perez
|
r1850 | #----------------------------------------------------------------------------- | ||
# Code begins - classes and functions | ||||
Fernando Perez
|
r1694 | class IPythonConsoleLexer(Lexer): | ||
""" | ||||
For IPython console output or doctests, such as: | ||||
.. sourcecode:: ipython | ||||
In [1]: a = 'foo' | ||||
In [2]: a | ||||
Out[2]: 'foo' | ||||
In [3]: print a | ||||
foo | ||||
In [4]: 1 / 0 | ||||
Fernando Perez
|
r1850 | |||
Notes: | ||||
- Tracebacks are not currently supported. | ||||
- It assumes the default IPython prompts, not customized ones. | ||||
Fernando Perez
|
r1694 | """ | ||
Fernando Perez
|
r1850 | |||
Fernando Perez
|
r1694 | name = 'IPython console session' | ||
aliases = ['ipython'] | ||||
mimetypes = ['text/x-ipython-console'] | ||||
input_prompt = re.compile("(In \[[0-9]+\]: )|( \.\.\.+:)") | ||||
output_prompt = re.compile("(Out\[[0-9]+\]: )|( \.\.\.+:)") | ||||
continue_prompt = re.compile(" \.\.\.+:") | ||||
tb_start = re.compile("\-+") | ||||
def get_tokens_unprocessed(self, text): | ||||
pylexer = PythonLexer(**self.options) | ||||
tblexer = PythonTracebackLexer(**self.options) | ||||
curcode = '' | ||||
insertions = [] | ||||
for match in line_re.finditer(text): | ||||
line = match.group() | ||||
input_prompt = self.input_prompt.match(line) | ||||
continue_prompt = self.continue_prompt.match(line.rstrip()) | ||||
output_prompt = self.output_prompt.match(line) | ||||
if line.startswith("#"): | ||||
insertions.append((len(curcode), | ||||
[(0, Comment, line)])) | ||||
elif input_prompt is not None: | ||||
insertions.append((len(curcode), | ||||
[(0, Generic.Prompt, input_prompt.group())])) | ||||
curcode += line[input_prompt.end():] | ||||
elif continue_prompt is not None: | ||||
insertions.append((len(curcode), | ||||
[(0, Generic.Prompt, continue_prompt.group())])) | ||||
curcode += line[continue_prompt.end():] | ||||
elif output_prompt is not None: | ||||
insertions.append((len(curcode), | ||||
[(0, Generic.Output, output_prompt.group())])) | ||||
curcode += line[output_prompt.end():] | ||||
else: | ||||
if curcode: | ||||
for item in do_insertions(insertions, | ||||
pylexer.get_tokens_unprocessed(curcode)): | ||||
yield item | ||||
curcode = '' | ||||
insertions = [] | ||||
yield match.start(), Generic.Output, line | ||||
if curcode: | ||||
for item in do_insertions(insertions, | ||||
pylexer.get_tokens_unprocessed(curcode)): | ||||
yield item | ||||
Fernando Perez
|
r1850 | #----------------------------------------------------------------------------- | ||
# Register the extension as a valid pygments lexer | ||||
Fernando Perez
|
r1694 | highlighting.lexers['ipython'] = IPythonConsoleLexer() | ||