diff --git a/IPython/core/display.py b/IPython/core/display.py index 724d164..4366c4e 100644 --- a/IPython/core/display.py +++ b/IPython/core/display.py @@ -657,15 +657,19 @@ class Image(DisplayObject): return unicode(s.split('.')[-1].lower()) -def clear_output(): - """Clear the output of the current cell receiving output.""" +def clear_output(wait=False): + """Clear the output of the current cell receiving output. + + Parameters + ---------- + wait : bool [default: false] + Wait to clear the output until new output is available to replace it.""" from IPython.core.interactiveshell import InteractiveShell if InteractiveShell.initialized(): - InteractiveShell.instance().display_pub.clear_output() + InteractiveShell.instance().display_pub.clear_output(wait) else: from IPython.utils import io print('\033[2K\r', file=io.stdout, end='') io.stdout.flush() print('\033[2K\r', file=io.stderr, end='') io.stderr.flush() - diff --git a/IPython/core/displaypub.py b/IPython/core/displaypub.py index f351730..fd253ba 100644 --- a/IPython/core/displaypub.py +++ b/IPython/core/displaypub.py @@ -108,7 +108,7 @@ class DisplayPublisher(Configurable): if 'text/plain' in data: print(data['text/plain'], file=io.stdout) - def clear_output(self): + def clear_output(self, wait=False): """Clear the output of the cell receiving output.""" print('\033[2K\r', file=io.stdout, end='') io.stdout.flush() @@ -123,8 +123,8 @@ class CapturingDisplayPublisher(DisplayPublisher): def publish(self, source, data, metadata=None): self.outputs.append((source, data, metadata)) - def clear_output(self): - super(CapturingDisplayPublisher, self).clear_output() + def clear_output(self, wait=False): + super(CapturingDisplayPublisher, self).clear_output(wait) if other: # empty the list, *do not* reassign a new list del self.outputs[:] diff --git a/IPython/html/static/notebook/js/codecell.js b/IPython/html/static/notebook/js/codecell.js index 3ccc9f8..a23094f 100644 --- a/IPython/html/static/notebook/js/codecell.js +++ b/IPython/html/static/notebook/js/codecell.js @@ -386,8 +386,8 @@ var IPython = (function (IPython) { }; - CodeCell.prototype.clear_output = function () { - this.output_area.clear_output(); + CodeCell.prototype.clear_output = function (wait) { + this.output_area.clear_output(wait); }; diff --git a/IPython/html/static/notebook/js/outputarea.js b/IPython/html/static/notebook/js/outputarea.js index d6b6fd0..9e6ddf3 100644 --- a/IPython/html/static/notebook/js/outputarea.js +++ b/IPython/html/static/notebook/js/outputarea.js @@ -31,7 +31,7 @@ var IPython = (function (IPython) { this.outputs = []; this.collapsed = false; this.scrolled = false; - this.clear_out_timeout = null; + this.clear_queued = null; if (prompt_area === undefined) { this.prompt_area = true; } else { @@ -289,6 +289,12 @@ var IPython = (function (IPython) { OutputArea.prototype.append_output = function (json, dynamic) { // If dynamic is true, javascript output will be eval'd. this.expand(); + + // Clear the output if clear is queued. + if (this.clear_queued) { + this.clear_output(false); + } + if (json.output_type === 'pyout') { this.append_pyout(json, dynamic); } else if (json.output_type === 'pyerr') { @@ -605,21 +611,32 @@ var IPython = (function (IPython) { OutputArea.prototype.handle_clear_output = function (content) { - this.clear_output(); + this.clear_output(content.wait); }; - OutputArea.prototype.clear_output = function() { - - // Fix the output div's height - var height = this.element.height(); - this.element.height(height); + OutputArea.prototype.clear_output = function(wait) { + if (wait) { - // clear all, no need for logic - this.element.html(""); - this.outputs = []; - this.unscroll_area(); - return; + // If a clear is queued, clear before adding another to the queue. + if (this.clear_queued) { + this.clear_output(false); + }; + + this.clear_queued = true; + } else { + this.clear_queued = false; + + // Fix the output div's height + var height = this.element.height(); + this.element.height(height); + + // clear all, no need for logic + this.element.html(""); + this.outputs = []; + this.unscroll_area(); + return; + }; }; diff --git a/IPython/kernel/zmq/zmqshell.py b/IPython/kernel/zmq/zmqshell.py index 5b0bfb0..df7f5a5 100644 --- a/IPython/kernel/zmq/zmqshell.py +++ b/IPython/kernel/zmq/zmqshell.py @@ -86,8 +86,8 @@ class ZMQDisplayPublisher(DisplayPublisher): parent=self.parent_header, ident=self.topic, ) - def clear_output(self): - content = {} + def clear_output(self, wait=False): + content = dict(wait=wait) print('\r', file=sys.stdout, end='') print('\r', file=sys.stderr, end='') diff --git a/docs/source/development/messaging.rst b/docs/source/development/messaging.rst index 8919b44..5fcd571 100644 --- a/docs/source/development/messaging.rst +++ b/docs/source/development/messaging.rst @@ -984,6 +984,20 @@ Message type: ``status``:: execution_state : ('busy', 'idle', 'starting') } +Clear output +------------ + +This message type is used to clear the output that is visible on the frontend. + +Message type: ``clear_output``:: + + content = { + + # Wait to clear the output until new output is available. Clears the + # existing output immediately before the new output is displayed. + # Useful for creating simple animations with minimal flickering. + 'wait' : bool, + } Messages on the stdin ROUTER/DEALER sockets ===========================================