source: trunk/adm/website/sphinxext/ipython_console_highlighting.py @ 50

Last change on this file since 50 was 36, checked in by pinsard, 13 years ago

add end users website production

File size: 4.1 KB
Line 
1"""reST directive for syntax-highlighting ipython interactive sessions.
2
3XXX - See what improvements can be made based on the new (as of Sept 2009)
4'pycon' lexer for the python console.  At the very least it will give better
5highlighted tracebacks.
6"""
7
8#-----------------------------------------------------------------------------
9# Needed modules
10
11# Standard library
12import re
13
14# Third party
15from pygments.lexer import Lexer, do_insertions
16from pygments.lexers.agile import (PythonConsoleLexer, PythonLexer, 
17                                   PythonTracebackLexer)
18from pygments.token import Comment, Generic
19
20from sphinx import highlighting
21
22#-----------------------------------------------------------------------------
23# Global constants
24line_re = re.compile('.*?\n')
25
26#-----------------------------------------------------------------------------
27# Code begins - classes and functions
28
29class IPythonConsoleLexer(Lexer):
30    """
31    For IPython console output or doctests, such as:
32
33    .. sourcecode:: ipython
34
35      In [1]: a = 'foo'
36
37      In [2]: a
38      Out[2]: 'foo'
39
40      In [3]: print a
41      foo
42
43      In [4]: 1 / 0
44
45    Notes:
46
47      - Tracebacks are not currently supported.
48
49      - It assumes the default IPython prompts, not customized ones.
50    """
51   
52    name = 'IPython console session'
53    aliases = ['ipython']
54    mimetypes = ['text/x-ipython-console']
55    input_prompt = re.compile("(In \[[0-9]+\]: )|(   \.\.\.+:)")
56    output_prompt = re.compile("(Out\[[0-9]+\]: )|(   \.\.\.+:)")
57    continue_prompt = re.compile("   \.\.\.+:")
58    tb_start = re.compile("\-+")
59
60    def get_tokens_unprocessed(self, text):
61        pylexer = PythonLexer(**self.options)
62        tblexer = PythonTracebackLexer(**self.options)
63
64        curcode = ''
65        insertions = []
66        for match in line_re.finditer(text):
67            line = match.group()
68            input_prompt = self.input_prompt.match(line)
69            continue_prompt = self.continue_prompt.match(line.rstrip())
70            output_prompt = self.output_prompt.match(line)
71            if line.startswith("#"):
72                insertions.append((len(curcode),
73                                   [(0, Comment, line)]))
74            elif input_prompt is not None:
75                insertions.append((len(curcode),
76                                   [(0, Generic.Prompt, input_prompt.group())]))
77                curcode += line[input_prompt.end():]
78            elif continue_prompt is not None:
79                insertions.append((len(curcode),
80                                   [(0, Generic.Prompt, continue_prompt.group())]))
81                curcode += line[continue_prompt.end():]
82            elif output_prompt is not None:
83                # Use the 'error' token for output.  We should probably make
84                # our own token, but error is typicaly in a bright color like
85                # red, so it works fine for our output prompts.
86                insertions.append((len(curcode),
87                                   [(0, Generic.Error, output_prompt.group())]))
88                curcode += line[output_prompt.end():]
89            else:
90                if curcode:
91                    for item in do_insertions(insertions,
92                                              pylexer.get_tokens_unprocessed(curcode)):
93                        yield item
94                        curcode = ''
95                        insertions = []
96                yield match.start(), Generic.Output, line
97        if curcode:
98            for item in do_insertions(insertions,
99                                      pylexer.get_tokens_unprocessed(curcode)):
100                yield item
101
102
103def setup(app):
104    """Setup as a sphinx extension."""
105
106    # This is only a lexer, so adding it below to pygments appears sufficient.
107    # But if somebody knows that the right API usage should be to do that via
108    # sphinx, by all means fix it here.  At least having this setup.py
109    # suppresses the sphinx warning we'd get without it.
110    pass
111
112#-----------------------------------------------------------------------------
113# Register the extension as a valid pygments lexer
114highlighting.lexers['ipython'] = IPythonConsoleLexer()
Note: See TracBrowser for help on using the repository browser.