##// END OF EJS Templates
Integrated new IPythonInputSplitter into IPythonWidget.
epatters -
Show More
@@ -1,188 +1,192 b''
1 1 # System library imports
2 2 from PyQt4 import QtCore, QtGui
3 3
4 4 # Local imports
5 from IPython.core.inputsplitter import IPythonInputSplitter
5 6 from IPython.core.usage import default_banner
6 7 from frontend_widget import FrontendWidget
7 8
8 9
9 10 class IPythonWidget(FrontendWidget):
10 11 """ A FrontendWidget for an IPython kernel.
11 12 """
12 13
13 14 # The default stylesheet: black text on a white background.
14 15 default_stylesheet = """
15 16 .error { color: red; }
16 17 .in-prompt { color: navy; }
17 18 .in-prompt-number { font-weight: bold; }
18 19 .out-prompt { color: darkred; }
19 20 .out-prompt-number { font-weight: bold; }
20 21 """
21 22
22 23 # A dark stylesheet: white text on a black background.
23 24 dark_stylesheet = """
24 25 QPlainTextEdit { background-color: black; color: white }
25 26 QFrame { border: 1px solid grey; }
26 27 .error { color: red; }
27 28 .in-prompt { color: lime; }
28 29 .in-prompt-number { color: lime; font-weight: bold; }
29 30 .out-prompt { color: red; }
30 31 .out-prompt-number { color: red; font-weight: bold; }
31 32 """
32 33
33 34 # Default prompts.
34 35 in_prompt = '<br/>In [<span class="in-prompt-number">%i</span>]: '
35 36 out_prompt = 'Out[<span class="out-prompt-number">%i</span>]: '
36 37
37 38 #---------------------------------------------------------------------------
38 39 # 'object' interface
39 40 #---------------------------------------------------------------------------
40 41
41 42 def __init__(self, *args, **kw):
42 43 super(IPythonWidget, self).__init__(*args, **kw)
43 44
44 # Initialize protected variables.
45 # FrontendWidget protected variables.
46 self._input_splitter = IPythonInputSplitter(input_mode='replace')
47
48 # IPythonWidget protected variables.
45 49 self._previous_prompt_blocks = []
46 50 self._prompt_count = 0
47 51
48 52 # Set a default stylesheet.
49 53 self.reset_styling()
50 54
51 55 #---------------------------------------------------------------------------
52 56 # 'BaseFrontendMixin' abstract interface
53 57 #---------------------------------------------------------------------------
54 58
55 59 def _handle_pyout(self, msg):
56 60 """ Reimplemented for IPython-style "display hook".
57 61 """
58 62 self._append_html(self._make_out_prompt(self._prompt_count))
59 63 self._save_prompt_block()
60 64
61 65 self._append_plain_text(msg['content']['data'] + '\n')
62 66
63 67 #---------------------------------------------------------------------------
64 68 # 'FrontendWidget' interface
65 69 #---------------------------------------------------------------------------
66 70
67 71 def execute_file(self, path, hidden=False):
68 72 """ Reimplemented to use the 'run' magic.
69 73 """
70 74 self.execute('run %s' % path, hidden=hidden)
71 75
72 76 #---------------------------------------------------------------------------
73 77 # 'FrontendWidget' protected interface
74 78 #---------------------------------------------------------------------------
75 79
76 80 def _get_banner(self):
77 81 """ Reimplemented to return IPython's default banner.
78 82 """
79 83 return default_banner
80 84
81 85 def _process_execute_error(self, msg):
82 86 """ Reimplemented for IPython-style traceback formatting.
83 87 """
84 88 content = msg['content']
85 89 traceback_lines = content['traceback'][:]
86 90 traceback = ''.join(traceback_lines)
87 91 traceback = traceback.replace(' ', '&nbsp;')
88 92 traceback = traceback.replace('\n', '<br/>')
89 93
90 94 ename = content['ename']
91 95 ename_styled = '<span class="error">%s</span>' % ename
92 96 traceback = traceback.replace(ename, ename_styled)
93 97
94 98 self._append_html(traceback)
95 99
96 100 def _show_interpreter_prompt(self):
97 101 """ Reimplemented for IPython-style prompts.
98 102 """
99 103 # Update old prompt numbers if necessary.
100 104 previous_prompt_number = self._prompt_count
101 105 if previous_prompt_number != self._prompt_count:
102 106 for i, (block, length) in enumerate(self._previous_prompt_blocks):
103 107 if block.isValid():
104 108 cursor = QtGui.QTextCursor(block)
105 109 cursor.movePosition(QtGui.QTextCursor.Right,
106 110 QtGui.QTextCursor.KeepAnchor, length-1)
107 111 if i == 0:
108 112 prompt = self._make_in_prompt(previous_prompt_number)
109 113 else:
110 114 prompt = self._make_out_prompt(previous_prompt_number)
111 115 self._insert_html(cursor, prompt)
112 116 self._previous_prompt_blocks = []
113 117
114 118 # Show a new prompt.
115 119 self._prompt_count += 1
116 120 self._show_prompt(self._make_in_prompt(self._prompt_count), html=True)
117 121 self._save_prompt_block()
118 122
119 123 # Update continuation prompt to reflect (possibly) new prompt length.
120 124 self._set_continuation_prompt(
121 125 self._make_continuation_prompt(self._prompt), html=True)
122 126
123 127 #---------------------------------------------------------------------------
124 128 # 'IPythonWidget' interface
125 129 #---------------------------------------------------------------------------
126 130
127 131 def reset_styling(self):
128 132 """ Restores the default IPythonWidget styling.
129 133 """
130 134 self.set_styling(self.default_stylesheet, syntax_style='default')
131 135 #self.set_styling(self.dark_stylesheet, syntax_style='monokai')
132 136
133 137 def set_styling(self, stylesheet, syntax_style=None):
134 138 """ Sets the IPythonWidget styling.
135 139
136 140 Parameters:
137 141 -----------
138 142 stylesheet : str
139 143 A CSS stylesheet. The stylesheet can contain classes for:
140 144 1. Qt: QPlainTextEdit, QFrame, QWidget, etc
141 145 2. Pygments: .c, .k, .o, etc (see PygmentsHighlighter)
142 146 3. IPython: .error, .in-prompt, .out-prompt, etc.
143 147
144 148 syntax_style : str or None [default None]
145 149 If specified, use the Pygments style with given name. Otherwise,
146 150 the stylesheet is queried for Pygments style information.
147 151 """
148 152 self.setStyleSheet(stylesheet)
149 153 self._control.document().setDefaultStyleSheet(stylesheet)
150 154 if self._page_control:
151 155 self._page_control.document().setDefaultStyleSheet(stylesheet)
152 156
153 157 if syntax_style is None:
154 158 self._highlighter.set_style_sheet(stylesheet)
155 159 else:
156 160 self._highlighter.set_style(syntax_style)
157 161
158 162 #---------------------------------------------------------------------------
159 163 # 'IPythonWidget' protected interface
160 164 #---------------------------------------------------------------------------
161 165
162 166 def _make_in_prompt(self, number):
163 167 """ Given a prompt number, returns an HTML In prompt.
164 168 """
165 169 body = self.in_prompt % number
166 170 return '<span class="in-prompt">%s</span>' % body
167 171
168 172 def _make_continuation_prompt(self, prompt):
169 173 """ Given a plain text version of an In prompt, returns an HTML
170 174 continuation prompt.
171 175 """
172 176 end_chars = '...: '
173 177 space_count = len(prompt.lstrip('\n')) - len(end_chars)
174 178 body = '&nbsp;' * space_count + end_chars
175 179 return '<span class="in-prompt">%s</span>' % body
176 180
177 181 def _make_out_prompt(self, number):
178 182 """ Given a prompt number, returns an HTML Out prompt.
179 183 """
180 184 body = self.out_prompt % number
181 185 return '<span class="out-prompt">%s</span>' % body
182 186
183 187 def _save_prompt_block(self):
184 188 """ Assuming a prompt has just been written at the end of the buffer,
185 189 store the QTextBlock that contains it and its length.
186 190 """
187 191 block = self._control.document().lastBlock()
188 192 self._previous_prompt_blocks.append((block, block.length()))
General Comments 0
You need to be logged in to leave comments. Login now