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