##// END OF EJS Templates
First cut at safe appending in the Qt console.
epatters -
Show More
@@ -718,36 +718,46 b' class ConsoleWidget(Configurable, QtGui.QWidget):'
718 # 'ConsoleWidget' protected interface
718 # 'ConsoleWidget' protected interface
719 #--------------------------------------------------------------------------
719 #--------------------------------------------------------------------------
720
720
721 def _append_html(self, html):
721 def _append_custom(self, insert, input, before_prompt=False):
722 """ Appends html at the end of the console buffer.
722 """ A low-level method for appending content to the end of the buffer.
723
724 If 'before_prompt' is enabled, the content will be inserted before the
725 current prompt, if there is one.
723 """
726 """
724 cursor = self._get_end_cursor()
727 # Determine where to insert the content.
725 self._insert_html(cursor, html)
728 cursor = self._control.textCursor()
729 if before_prompt and not self._executing:
730 cursor.setPosition(self._prompt_pos)
731 cursor.movePosition(QtGui.QTextCursor.Left, n=len(self._prompt))
732 else:
733 cursor.movePosition(QtGui.QTextCursor.End)
734 start_pos = cursor.position()
726
735
727 def _append_html_fetching_plain_text(self, html):
736 # Perform the insertion.
728 """ Appends 'html', then returns the plain text version of it.
737 result = insert(cursor, input)
729 """
738
730 cursor = self._get_end_cursor()
739 # Adjust the prompt position if we have inserted before it. This is safe
731 return self._insert_html_fetching_plain_text(cursor, html)
740 # because buffer truncation is disabled when not executing.
741 if before_prompt and not self._executing:
742 self._prompt_pos += cursor.position() - start_pos
743
744 return result
732
745
733 def _append_plain_text(self, text):
746 def _append_html(self, html, before_prompt=False):
734 """ Appends plain text at the end of the console buffer, processing
747 """ Appends HTML at the end of the console buffer.
735 ANSI codes if enabled.
736 """
748 """
737 cursor = self._get_end_cursor()
749 self._append_custom(self._insert_html, html, before_prompt)
738 self._insert_plain_text(cursor, text)
739
750
740 def _append_plain_text_keeping_prompt(self, text):
751 def _append_html_fetching_plain_text(self, html, before_prompt=False):
741 """ Writes 'text' after the current prompt, then restores the old prompt
752 """ Appends HTML, then returns the plain text version of it.
742 with its old input buffer.
743 """
753 """
744 input_buffer = self.input_buffer
754 return self._append_custom(self._insert_html_fetching_plain_text,
745 self._append_plain_text('\n')
755 html, before_prompt)
746 self._prompt_finished()
747
756
748 self._append_plain_text(text)
757 def _append_plain_text(self, text, before_prompt=False):
749 self._show_prompt()
758 """ Appends plain text, processing ANSI codes if enabled.
750 self.input_buffer = input_buffer
759 """
760 self._append_custom(self._insert_plain_text, text, before_prompt)
751
761
752 def _cancel_text_completion(self):
762 def _cancel_text_completion(self):
753 """ If text completion is progress, cancel it.
763 """ If text completion is progress, cancel it.
@@ -372,14 +372,8 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):'
372 """ Handle display hook output.
372 """ Handle display hook output.
373 """
373 """
374 if not self._hidden and self._is_from_this_session(msg):
374 if not self._hidden and self._is_from_this_session(msg):
375 data = msg['content']['data']
375 text = msg['content']['data']
376 if isinstance(data, basestring):
376 self._append_plain_text(text + '\n', before_prompt=True)
377 # plaintext data from pure Python kernel
378 text = data
379 else:
380 # formatted output from DisplayFormatter (IPython kernel)
381 text = data.get('text/plain', '')
382 self._append_plain_text(text + '\n')
383
377
384 def _handle_stream(self, msg):
378 def _handle_stream(self, msg):
385 """ Handle stdout, stderr, and stdin.
379 """ Handle stdout, stderr, and stdin.
@@ -390,7 +384,7 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):'
390 # widget's tab width.
384 # widget's tab width.
391 text = msg['content']['data'].expandtabs(8)
385 text = msg['content']['data'].expandtabs(8)
392
386
393 self._append_plain_text(text)
387 self._append_plain_text(text, before_prompt=True)
394 self._control.moveCursor(QtGui.QTextCursor.End)
388 self._control.moveCursor(QtGui.QTextCursor.End)
395
389
396 def _handle_shutdown_reply(self, msg):
390 def _handle_shutdown_reply(self, msg):
@@ -62,16 +62,16 b' class IPythonWidget(FrontendWidget):'
62 editor = Unicode(default_editor, config=True,
62 editor = Unicode(default_editor, config=True,
63 help="""
63 help="""
64 A command for invoking a system text editor. If the string contains a
64 A command for invoking a system text editor. If the string contains a
65 {filename} format specifier, it will be used. Otherwise, the filename will
65 {filename} format specifier, it will be used. Otherwise, the filename
66 be appended to the end the command.
66 will be appended to the end the command.
67 """)
67 """)
68
68
69 editor_line = Unicode(config=True,
69 editor_line = Unicode(config=True,
70 help="""
70 help="""
71 The editor command to use when a specific line number is requested. The
71 The editor command to use when a specific line number is requested. The
72 string should contain two format specifiers: {line} and {filename}. If
72 string should contain two format specifiers: {line} and {filename}. If
73 this parameter is not specified, the line number option to the %edit magic
73 this parameter is not specified, the line number option to the %edit
74 will be ignored.
74 magic will be ignored.
75 """)
75 """)
76
76
77 style_sheet = Unicode(config=True,
77 style_sheet = Unicode(config=True,
@@ -85,8 +85,9 b' class IPythonWidget(FrontendWidget):'
85
85
86 syntax_style = Str(config=True,
86 syntax_style = Str(config=True,
87 help="""
87 help="""
88 If not empty, use this Pygments style for syntax highlighting. Otherwise,
88 If not empty, use this Pygments style for syntax highlighting.
89 the style sheet is queried for Pygments style information.
89 Otherwise, the style sheet is queried for Pygments style
90 information.
90 """)
91 """)
91
92
92 # Prompts.
93 # Prompts.
@@ -187,20 +188,20 b' class IPythonWidget(FrontendWidget):'
187 prompt_number = content['execution_count']
188 prompt_number = content['execution_count']
188 data = content['data']
189 data = content['data']
189 if data.has_key('text/html'):
190 if data.has_key('text/html'):
190 self._append_plain_text(self.output_sep)
191 self._append_plain_text(self.output_sep, True)
191 self._append_html(self._make_out_prompt(prompt_number))
192 self._append_html(self._make_out_prompt(prompt_number), True)
192 html = data['text/html']
193 html = data['text/html']
193 self._append_plain_text('\n')
194 self._append_plain_text('\n', True)
194 self._append_html(html + self.output_sep2)
195 self._append_html(html + self.output_sep2, True)
195 elif data.has_key('text/plain'):
196 elif data.has_key('text/plain'):
196 self._append_plain_text(self.output_sep)
197 self._append_plain_text(self.output_sep, True)
197 self._append_html(self._make_out_prompt(prompt_number))
198 self._append_html(self._make_out_prompt(prompt_number), True)
198 text = data['text/plain']
199 text = data['text/plain']
199 # If the repr is multiline, make sure we start on a new line,
200 # If the repr is multiline, make sure we start on a new line,
200 # so that its lines are aligned.
201 # so that its lines are aligned.
201 if "\n" in text and not self.output_sep.endswith("\n"):
202 if "\n" in text and not self.output_sep.endswith("\n"):
202 self._append_plain_text('\n')
203 self._append_plain_text('\n', True)
203 self._append_plain_text(text + self.output_sep2)
204 self._append_plain_text(text + self.output_sep2, True)
204
205
205 def _handle_display_data(self, msg):
206 def _handle_display_data(self, msg):
206 """ The base handler for the ``display_data`` message.
207 """ The base handler for the ``display_data`` message.
@@ -216,19 +217,19 b' class IPythonWidget(FrontendWidget):'
216 # representation.
217 # representation.
217 if data.has_key('text/html'):
218 if data.has_key('text/html'):
218 html = data['text/html']
219 html = data['text/html']
219 self._append_html(html)
220 self._append_html(html, before_prompt=True)
220 elif data.has_key('text/plain'):
221 elif data.has_key('text/plain'):
221 text = data['text/plain']
222 text = data['text/plain']
222 self._append_plain_text(text)
223 self._append_plain_text(text, before_prompt=True)
223 # This newline seems to be needed for text and html output.
224 # This newline seems to be needed for text and html output.
224 self._append_plain_text(u'\n')
225 self._append_plain_text(u'\n', before_prompt=True)
225
226
226 def _started_channels(self):
227 def _started_channels(self):
227 """ Reimplemented to make a history request.
228 """ Reimplemented to make a history request.
228 """
229 """
229 super(IPythonWidget, self)._started_channels()
230 super(IPythonWidget, self)._started_channels()
230 self.kernel_manager.shell_channel.history(hist_access_type='tail', n=1000)
231 self.kernel_manager.shell_channel.history(hist_access_type='tail',
231
232 n=1000)
232 #---------------------------------------------------------------------------
233 #---------------------------------------------------------------------------
233 # 'ConsoleWidget' public interface
234 # 'ConsoleWidget' public interface
234 #---------------------------------------------------------------------------
235 #---------------------------------------------------------------------------
@@ -413,8 +414,8 b' class IPythonWidget(FrontendWidget):'
413 self.custom_edit_requested.emit(filename, line)
414 self.custom_edit_requested.emit(filename, line)
414 elif not self.editor:
415 elif not self.editor:
415 self._append_plain_text('No default editor available.\n'
416 self._append_plain_text('No default editor available.\n'
416 'Specify a GUI text editor in the `IPythonWidget.editor` configurable\n'
417 'Specify a GUI text editor in the `IPythonWidget.editor` '
417 'to enable the %edit magic')
418 'configurable to enable the %edit magic')
418 else:
419 else:
419 try:
420 try:
420 filename = '"%s"' % filename
421 filename = '"%s"' % filename
General Comments 0
You need to be logged in to leave comments. Login now