Show More
@@ -214,11 +214,11 b' class ConsoleWidget(QtGui.QPlainTextEdit):' | |||||
214 |
|
214 | |||
215 | elif key == QtCore.Qt.Key_Home: |
|
215 | elif key == QtCore.Qt.Key_Home: | |
216 | cursor.movePosition(QtGui.QTextCursor.StartOfLine) |
|
216 | cursor.movePosition(QtGui.QTextCursor.StartOfLine) | |
217 | start_pos = cursor.position() |
|
|||
218 | start_line = cursor.blockNumber() |
|
217 | start_line = cursor.blockNumber() | |
219 | if start_line == self._get_prompt_cursor().blockNumber(): |
|
218 | if start_line == self._get_prompt_cursor().blockNumber(): | |
220 |
start_pos |
|
219 | start_pos = self._prompt_pos | |
221 | else: |
|
220 | else: | |
|
221 | start_pos = cursor.position() | |||
222 | start_pos += len(self._continuation_prompt) |
|
222 | start_pos += len(self._continuation_prompt) | |
223 | if shift_down and self._in_buffer(position): |
|
223 | if shift_down and self._in_buffer(position): | |
224 | self._set_selection(position, start_pos) |
|
224 | self._set_selection(position, start_pos) | |
@@ -266,22 +266,7 b' class ConsoleWidget(QtGui.QPlainTextEdit):' | |||||
266 | make sense for a console widget. |
|
266 | make sense for a console widget. | |
267 | """ |
|
267 | """ | |
268 | cursor = self._get_end_cursor() |
|
268 | cursor = self._get_end_cursor() | |
269 | cursor.insertHtml(html) |
|
269 | self._insert_html(cursor, html) | |
270 |
|
||||
271 | # After appending HTML, the text document "remembers" the current |
|
|||
272 | # formatting, which means that subsequent calls to 'appendPlainText' |
|
|||
273 | # will be formatted similarly, a behavior that we do not want. To |
|
|||
274 | # prevent this, we make sure that the last character has no formatting. |
|
|||
275 | cursor.movePosition(QtGui.QTextCursor.Left, |
|
|||
276 | QtGui.QTextCursor.KeepAnchor) |
|
|||
277 | if cursor.selection().toPlainText().trimmed().isEmpty(): |
|
|||
278 | # If the last character is whitespace, it doesn't matter how it's |
|
|||
279 | # formatted, so just clear the formatting. |
|
|||
280 | cursor.setCharFormat(QtGui.QTextCharFormat()) |
|
|||
281 | else: |
|
|||
282 | # Otherwise, add an unformatted space. |
|
|||
283 | cursor.movePosition(QtGui.QTextCursor.Right) |
|
|||
284 | cursor.insertText(' ', QtGui.QTextCharFormat()) |
|
|||
285 |
|
270 | |||
286 | def appendPlainText(self, text): |
|
271 | def appendPlainText(self, text): | |
287 | """ Reimplemented to not append text as a new paragraph, which doesn't |
|
272 | """ Reimplemented to not append text as a new paragraph, which doesn't | |
@@ -712,6 +697,27 b' class ConsoleWidget(QtGui.QPlainTextEdit):' | |||||
712 | cursor.setPosition(position) |
|
697 | cursor.setPosition(position) | |
713 | return cursor |
|
698 | return cursor | |
714 |
|
699 | |||
|
700 | def _insert_html(self, cursor, html): | |||
|
701 | """ Insert HTML using the specified cursor in such a way that future | |||
|
702 | formatting is unaffected. | |||
|
703 | """ | |||
|
704 | cursor.insertHtml(html) | |||
|
705 | ||||
|
706 | # After inserting HTML, the text document "remembers" the current | |||
|
707 | # formatting, which means that subsequent calls adding plain text | |||
|
708 | # will result in similar formatting, a behavior that we do not want. To | |||
|
709 | # prevent this, we make sure that the last character has no formatting. | |||
|
710 | cursor.movePosition(QtGui.QTextCursor.Left, | |||
|
711 | QtGui.QTextCursor.KeepAnchor) | |||
|
712 | if cursor.selection().toPlainText().trimmed().isEmpty(): | |||
|
713 | # If the last character is whitespace, it doesn't matter how it's | |||
|
714 | # formatted, so just clear the formatting. | |||
|
715 | cursor.setCharFormat(QtGui.QTextCharFormat()) | |||
|
716 | else: | |||
|
717 | # Otherwise, add an unformatted space. | |||
|
718 | cursor.movePosition(QtGui.QTextCursor.Right) | |||
|
719 | cursor.insertText(' ', QtGui.QTextCharFormat()) | |||
|
720 | ||||
715 | def _prompt_started(self): |
|
721 | def _prompt_started(self): | |
716 | """ Called immediately after a new prompt is displayed. |
|
722 | """ Called immediately after a new prompt is displayed. | |
717 | """ |
|
723 | """ |
@@ -30,6 +30,10 b' class IPythonWidget(FrontendWidget):' | |||||
30 | .out-prompt-number { color: red; font-weight: bold; } |
|
30 | .out-prompt-number { color: red; font-weight: bold; } | |
31 | """ |
|
31 | """ | |
32 |
|
32 | |||
|
33 | # Default prompts. | |||
|
34 | in_prompt = '<br/>In [<span class="in-prompt-number">%i</span>]: ' | |||
|
35 | out_prompt = 'Out[<span class="out-prompt-number">%i</span>]: ' | |||
|
36 | ||||
33 | #--------------------------------------------------------------------------- |
|
37 | #--------------------------------------------------------------------------- | |
34 | # 'QObject' interface |
|
38 | # 'QObject' interface | |
35 | #--------------------------------------------------------------------------- |
|
39 | #--------------------------------------------------------------------------- | |
@@ -38,6 +42,7 b' class IPythonWidget(FrontendWidget):' | |||||
38 | super(IPythonWidget, self).__init__(parent) |
|
42 | super(IPythonWidget, self).__init__(parent) | |
39 |
|
43 | |||
40 | # Initialize protected variables. |
|
44 | # Initialize protected variables. | |
|
45 | self._previous_prompt_blocks = [] | |||
41 | self._prompt_count = 0 |
|
46 | self._prompt_count = 0 | |
42 |
|
47 | |||
43 | # Set a default stylesheet. |
|
48 | # Set a default stylesheet. | |
@@ -64,17 +69,29 b' class IPythonWidget(FrontendWidget):' | |||||
64 | def _show_interpreter_prompt(self): |
|
69 | def _show_interpreter_prompt(self): | |
65 | """ Reimplemented for IPython-style prompts. |
|
70 | """ Reimplemented for IPython-style prompts. | |
66 | """ |
|
71 | """ | |
|
72 | # Update old prompt numbers if necessary. | |||
|
73 | previous_prompt_number = self._prompt_count | |||
|
74 | if previous_prompt_number != self._prompt_count: | |||
|
75 | for i, (block, length) in enumerate(self._previous_prompt_blocks): | |||
|
76 | if block.isValid(): | |||
|
77 | cursor = QtGui.QTextCursor(block) | |||
|
78 | cursor.movePosition(QtGui.QTextCursor.Right, | |||
|
79 | QtGui.QTextCursor.KeepAnchor, length-1) | |||
|
80 | if i == 0: | |||
|
81 | prompt = self._make_in_prompt(previous_prompt_number) | |||
|
82 | else: | |||
|
83 | prompt = self._make_out_prompt(previous_prompt_number) | |||
|
84 | self._insert_html(cursor, prompt) | |||
|
85 | self._previous_prompt_blocks = [] | |||
|
86 | ||||
|
87 | # Show a new prompt. | |||
67 | self._prompt_count += 1 |
|
88 | self._prompt_count += 1 | |
68 | prompt_template = '<span class="in-prompt">%s</span>' |
|
89 | self._show_prompt(self._make_in_prompt(self._prompt_count), html=True) | |
69 | prompt_body = '<br/>In [<span class="in-prompt-number">%i</span>]: ' |
|
90 | self._save_prompt_block() | |
70 | prompt = (prompt_template % prompt_body) % self._prompt_count |
|
|||
71 | self._show_prompt(prompt, html=True) |
|
|||
72 |
|
91 | |||
73 | # Update continuation prompt to reflect (possibly) new prompt length. |
|
92 | # Update continuation prompt to reflect (possibly) new prompt length. | |
74 | cont_prompt_chars = '...: ' |
|
93 | self._set_continuation_prompt( | |
75 | space_count = len(self._prompt.lstrip()) - len(cont_prompt_chars) |
|
94 | self._make_continuation_prompt(self._prompt), html=True) | |
76 | cont_prompt_body = ' ' * space_count + cont_prompt_chars |
|
|||
77 | self._continuation_prompt_html = prompt_template % cont_prompt_body |
|
|||
78 |
|
95 | |||
79 | #------ Signal handlers ---------------------------------------------------- |
|
96 | #------ Signal handlers ---------------------------------------------------- | |
80 |
|
97 | |||
@@ -96,10 +113,9 b' class IPythonWidget(FrontendWidget):' | |||||
96 | def _handle_pyout(self, omsg): |
|
113 | def _handle_pyout(self, omsg): | |
97 | """ Reimplemented for IPython-style "display hook". |
|
114 | """ Reimplemented for IPython-style "display hook". | |
98 | """ |
|
115 | """ | |
99 | prompt_template = '<span class="out-prompt">%s</span>' |
|
116 | self.appendHtml(self._make_out_prompt(self._prompt_count)) | |
100 | prompt_body = 'Out[<span class="out-prompt-number">%i</span>]: ' |
|
117 | self._save_prompt_block() | |
101 | prompt = (prompt_template % prompt_body) % self._prompt_count |
|
118 | ||
102 | self.appendHtml(prompt) |
|
|||
103 | self.appendPlainText(omsg['content']['data'] + '\n') |
|
119 | self.appendPlainText(omsg['content']['data'] + '\n') | |
104 |
|
120 | |||
105 | #--------------------------------------------------------------------------- |
|
121 | #--------------------------------------------------------------------------- | |
@@ -135,6 +151,38 b' class IPythonWidget(FrontendWidget):' | |||||
135 | else: |
|
151 | else: | |
136 | self._highlighter.set_style(syntax_style) |
|
152 | self._highlighter.set_style(syntax_style) | |
137 |
|
153 | |||
|
154 | #--------------------------------------------------------------------------- | |||
|
155 | # 'IPythonWidget' protected interface | |||
|
156 | #--------------------------------------------------------------------------- | |||
|
157 | ||||
|
158 | def _make_in_prompt(self, number): | |||
|
159 | """ Given a prompt number, returns an HTML In prompt. | |||
|
160 | """ | |||
|
161 | body = self.in_prompt % number | |||
|
162 | return '<span class="in-prompt">%s</span>' % body | |||
|
163 | ||||
|
164 | def _make_continuation_prompt(self, prompt): | |||
|
165 | """ Given a plain text version of an In prompt, returns an HTML | |||
|
166 | continuation prompt. | |||
|
167 | """ | |||
|
168 | end_chars = '...: ' | |||
|
169 | space_count = len(prompt.lstrip('\n')) - len(end_chars) | |||
|
170 | body = ' ' * space_count + end_chars | |||
|
171 | return '<span class="in-prompt">%s</span>' % body | |||
|
172 | ||||
|
173 | def _make_out_prompt(self, number): | |||
|
174 | """ Given a prompt number, returns an HTML Out prompt. | |||
|
175 | """ | |||
|
176 | body = self.out_prompt % number | |||
|
177 | return '<span class="out-prompt">%s</span>' % body | |||
|
178 | ||||
|
179 | def _save_prompt_block(self): | |||
|
180 | """ Assuming a prompt has just been written at the end of the buffer, | |||
|
181 | store the QTextBlock that contains it and its length. | |||
|
182 | """ | |||
|
183 | block = self.document().lastBlock() | |||
|
184 | self._previous_prompt_blocks.append((block, block.length())) | |||
|
185 | ||||
138 |
|
186 | |||
139 | if __name__ == '__main__': |
|
187 | if __name__ == '__main__': | |
140 | from IPython.frontend.qt.kernelmanager import QtKernelManager |
|
188 | from IPython.frontend.qt.kernelmanager import QtKernelManager |
General Comments 0
You need to be logged in to leave comments.
Login now