diff --git a/IPython/qt/console/frontend_widget.py b/IPython/qt/console/frontend_widget.py index 222db04..309de99 100644 --- a/IPython/qt/console/frontend_widget.py +++ b/IPython/qt/console/frontend_widget.py @@ -197,6 +197,9 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin): self._local_kernel = kw.get('local_kernel', FrontendWidget._local_kernel) + # Whether or not a clear_output call is pending new output. + self._pending_clearoutput = False + #--------------------------------------------------------------------------- # 'ConsoleWidget' public interface #--------------------------------------------------------------------------- @@ -339,6 +342,14 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin): #--------------------------------------------------------------------------- # 'BaseFrontendMixin' abstract interface #--------------------------------------------------------------------------- + def _handle_clear_output(self, msg): + """Handle clear output messages.""" + if not self._hidden and self._is_from_this_session(msg): + wait = msg['content'].get('wait', True) + if wait: + self._pending_clearoutput = True + else: + self.clear_output() def _handle_complete_reply(self, rep): """ Handle replies for tab completion. @@ -520,6 +531,7 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin): """ self.log.debug("pyout: %s", msg.get('content', '')) if not self._hidden and self._is_from_this_session(msg): + self.flush_clearoutput() text = msg['content']['data'] self._append_plain_text(text + '\n', before_prompt=True) @@ -528,13 +540,8 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin): """ self.log.debug("stream: %s", msg.get('content', '')) if not self._hidden and self._is_from_this_session(msg): - # Most consoles treat tabs as being 8 space characters. Convert tabs - # to spaces so that output looks as expected regardless of this - # widget's tab width. - text = msg['content']['data'].expandtabs(8) - - self._append_plain_text(text, before_prompt=True) - self._control.moveCursor(QtGui.QTextCursor.End) + self.flush_clearoutput() + self.append_stream(msg['content']['data']) def _handle_shutdown_reply(self, msg): """ Handle shutdown signal, only if from other console. @@ -685,6 +692,31 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin): before_prompt=True ) + def append_stream(self, text): + """Appends text to the output stream.""" + # Most consoles treat tabs as being 8 space characters. Convert tabs + # to spaces so that output looks as expected regardless of this + # widget's tab width. + text = text.expandtabs(8) + + print([ord(c) for c in text]) + self._append_plain_text(text, before_prompt=True) + self._control.moveCursor(QtGui.QTextCursor.End) + + def flush_clearoutput(self): + """If a clearoutput is pending, execute it.""" + if self._pending_clearoutput: + self._pending_clearoutput = False + self.clear_output() + + def clear_output(self): + """Clear the output area.""" + cursor = self._control.textCursor() + cursor.beginEditBlock() + cursor.movePosition(cursor.StartOfLine, cursor.KeepAnchor) + cursor.insertText('') + cursor.endEditBlock() + #--------------------------------------------------------------------------- # 'FrontendWidget' protected interface #--------------------------------------------------------------------------- diff --git a/IPython/qt/console/ipython_widget.py b/IPython/qt/console/ipython_widget.py index 962fd86..423877a 100644 --- a/IPython/qt/console/ipython_widget.py +++ b/IPython/qt/console/ipython_widget.py @@ -140,7 +140,6 @@ class IPythonWidget(FrontendWidget): #--------------------------------------------------------------------------- # 'BaseFrontendMixin' abstract interface #--------------------------------------------------------------------------- - def _handle_complete_reply(self, rep): """ Reimplemented to support IPython's improved completion machinery. """ @@ -223,6 +222,7 @@ class IPythonWidget(FrontendWidget): """ self.log.debug("pyout: %s", msg.get('content', '')) if not self._hidden and self._is_from_this_session(msg): + self.flush_clearoutput() content = msg['content'] prompt_number = content.get('execution_count', 0) data = content['data'] @@ -250,6 +250,7 @@ class IPythonWidget(FrontendWidget): # eventually will as this allows all frontends to monitor the display # data. But we need to figure out how to handle this in the GUI. if not self._hidden and self._is_from_this_session(msg): + self.flush_clearoutput() source = msg['content']['source'] data = msg['content']['data'] metadata = msg['content']['metadata'] diff --git a/IPython/qt/console/rich_ipython_widget.py b/IPython/qt/console/rich_ipython_widget.py index 4da9855..a21c45d 100644 --- a/IPython/qt/console/rich_ipython_widget.py +++ b/IPython/qt/console/rich_ipython_widget.py @@ -114,6 +114,7 @@ class RichIPythonWidget(IPythonWidget): """ Overridden to handle rich data types, like SVG. """ if not self._hidden and self._is_from_this_session(msg): + self.flush_clearoutput() content = msg['content'] prompt_number = content.get('execution_count', 0) data = content['data'] @@ -140,6 +141,7 @@ class RichIPythonWidget(IPythonWidget): """ Overridden to handle rich data types, like SVG. """ if not self._hidden and self._is_from_this_session(msg): + self.flush_clearoutput() source = msg['content']['source'] data = msg['content']['data'] metadata = msg['content']['metadata']