Show More
@@ -253,6 +253,14 b" define(['require'" | |||
|
253 | 253 | env.notebook.delete_cell(); |
|
254 | 254 | } |
|
255 | 255 | }, |
|
256 | 'toggle-unsolicited-message-display':{ | |
|
257 | help: 'toggle display from external clients', | |
|
258 | icon: 'fa-sitemap', | |
|
259 | help_index: 'gb', | |
|
260 | handler: function (env) { | |
|
261 | env.notebook.toggle_ignore_unsolicited_msgs(); | |
|
262 | } | |
|
263 | }, | |
|
256 | 264 | 'interrupt-kernel':{ |
|
257 | 265 | icon: 'fa-stop', |
|
258 | 266 | help_index : 'ha', |
@@ -95,6 +95,7 b' define([' | |||
|
95 | 95 | 'space' : 'ipython.scroll-down', |
|
96 | 96 | 'down' : 'ipython.select-next-cell', |
|
97 | 97 | 'i,i' : 'ipython.interrupt-kernel', |
|
98 | 'e': 'ipython.toggle-unsolicited-message-display', | |
|
98 | 99 | '0,0' : 'ipython.restart-kernel', |
|
99 | 100 | 'd,d' : 'ipython.delete-cell', |
|
100 | 101 | 'esc': 'ipython.close-pager', |
@@ -278,6 +278,9 b' define([' | |||
|
278 | 278 | }); |
|
279 | 279 | |
|
280 | 280 | // Kernel |
|
281 | this.element.find('#toggle_unsolicited').click(function() { | |
|
282 | IPython.notebook.toggle_ignore_unsolicited_msgs(); | |
|
283 | }); | |
|
281 | 284 | this.element.find('#int_kernel').click(function () { |
|
282 | 285 | that.notebook.kernel.interrupt(); |
|
283 | 286 | }); |
@@ -135,6 +135,7 b' define([' | |||
|
135 | 135 | this.undelete_below = false; |
|
136 | 136 | this.paste_enabled = false; |
|
137 | 137 | this.writable = false; |
|
138 | this.ignore_unsolicited_msgs = false; | |
|
138 | 139 | // It is important to start out in command mode to match the intial mode |
|
139 | 140 | // of the KeyboardManager. |
|
140 | 141 | this.mode = 'command'; |
@@ -1562,6 +1563,60 b' define([' | |||
|
1562 | 1563 | this.get_selected_cell().toggle_line_numbers(); |
|
1563 | 1564 | }; |
|
1564 | 1565 | |
|
1566 | // Support for displaying input and output messages from other iPy clients. | |
|
1567 | ||
|
1568 | /** | |
|
1569 | * Toggles the ability to display input/output message events from | |
|
1570 | * externally connected clients (i.e. other iPython shells, vim-ipython, | |
|
1571 | * etc). | |
|
1572 | * | |
|
1573 | * @method toggle_ignore_unsolicited_msgs | |
|
1574 | */ | |
|
1575 | Notebook.prototype.toggle_ignore_unsolicited_msgs = function () { | |
|
1576 | this.ignore_unsolicited_msgs = !this.ignore_unsolicited_msgs; | |
|
1577 | this.events.trigger('toggle_unsolicited_msgs.Notebook', | |
|
1578 | [this.ignore_unsolicited_msgs]); | |
|
1579 | return this.ignore_unsolicited_msgs; | |
|
1580 | }; | |
|
1581 | ||
|
1582 | /** | |
|
1583 | * Handles the display of unsolicited messages, i.e. inputs or outputs that | |
|
1584 | * were generated by a client other than this notebook. New messages are | |
|
1585 | * displayed at the bottom of the notebook. | |
|
1586 | * | |
|
1587 | * @method handle_unsolicited_msg | |
|
1588 | */ | |
|
1589 | Notebook.prototype.handle_unsolicited_msg = function(msg) { | |
|
1590 | if (this.ignore_unsolicited_msgs) { | |
|
1591 | return; | |
|
1592 | } | |
|
1593 | if (msg.msg_type == 'execute_input') { | |
|
1594 | var cell = this.insert_cell_at_bottom('code'); | |
|
1595 | if (cell) { | |
|
1596 | var cell_index = this.ncells() - 1; | |
|
1597 | cell.last_msg_id = msg.parent_header.msg_id; | |
|
1598 | cell.set_text(msg.content.code); | |
|
1599 | cell._handle_execute_reply(msg); | |
|
1600 | this.scroll_to_cell(cell_index); | |
|
1601 | this.select(cell_index); | |
|
1602 | } | |
|
1603 | } else { | |
|
1604 | /* Find the input cell that corresponds with the output, then add | |
|
1605 | * the contents to the cell's output area. | |
|
1606 | */ | |
|
1607 | var count = this.ncells(); | |
|
1608 | while (count--) { | |
|
1609 | var cell = this.get_cell(count); | |
|
1610 | if (cell && cell.last_msg_id == msg.parent_header.msg_id) { | |
|
1611 | cell.output_area.handle_output(msg); | |
|
1612 | this.scroll_to_cell(count); | |
|
1613 | this.select(count); | |
|
1614 | break; | |
|
1615 | } | |
|
1616 | } | |
|
1617 | } | |
|
1618 | }; | |
|
1619 | ||
|
1565 | 1620 | /** |
|
1566 | 1621 | * Set the codemirror mode for all code cells, including the default for |
|
1567 | 1622 | * new code cells. |
@@ -1639,6 +1694,7 b' define([' | |||
|
1639 | 1694 | cell.set_kernel(this.session.kernel); |
|
1640 | 1695 | } |
|
1641 | 1696 | } |
|
1697 | this.kernel.unsolicited_msg_callback = $.proxy(this.handle_unsolicited_msg, this); | |
|
1642 | 1698 | }; |
|
1643 | 1699 | Notebook.prototype._session_start_failed = function (jqxhr, status, error){ |
|
1644 | 1700 | this._session_starting = false; |
@@ -279,6 +279,11 b' define([' | |||
|
279 | 279 | nnw.warning(error.message || "Notebook copy failed"); |
|
280 | 280 | }); |
|
281 | 281 | |
|
282 | this.events.on('toggle_unsolicited_msgs.Notebook', function(evt, ignored) { | |
|
283 | var msg = (ignored? "Ignoring": "Showing") + " I/O from external clients"; | |
|
284 | nnw.set_message(msg, 1000); | |
|
285 | }); | |
|
286 | ||
|
282 | 287 | // Checkpoint events |
|
283 | 288 | this.events.on('checkpoint_created.Notebook', function (evt, data) { |
|
284 | 289 | var msg = "Checkpoint created"; |
@@ -47,6 +47,7 b' define([' | |||
|
47 | 47 | this.session_id = utils.uuid(); |
|
48 | 48 | this._msg_callbacks = {}; |
|
49 | 49 | this.info_reply = {}; // kernel_info_reply stored here after starting |
|
50 | this.unsolicited_msg_callback = null; | |
|
50 | 51 | |
|
51 | 52 | if (typeof(WebSocket) !== 'undefined') { |
|
52 | 53 | this.WebSocket = WebSocket; |
@@ -136,6 +137,7 b' define([' | |||
|
136 | 137 | this._iopub_handlers = {}; |
|
137 | 138 | this.register_iopub_handler('status', $.proxy(this._handle_status_message, this)); |
|
138 | 139 | this.register_iopub_handler('clear_output', $.proxy(this._handle_clear_output, this)); |
|
140 | this.register_iopub_handler('execute_input', $.proxy(this._handle_input_message, this)); | |
|
139 | 141 | |
|
140 | 142 | for (var i=0; i < output_msg_types.length; i++) { |
|
141 | 143 | this.register_iopub_handler(output_msg_types[i], $.proxy(this._handle_output_message, this)); |
@@ -994,6 +996,11 b' define([' | |||
|
994 | 996 | Kernel.prototype._handle_output_message = function (msg) { |
|
995 | 997 | var callbacks = this.get_callbacks_for_msg(msg.parent_header.msg_id); |
|
996 | 998 | if (!callbacks || !callbacks.iopub) { |
|
999 | if (this.unsolicited_msg_callback) { | |
|
1000 | // The message came from another client. Let the UI decide what | |
|
1001 | // to do with it. | |
|
1002 | this.unsolicited_msg_callback(msg); | |
|
1003 | } | |
|
997 | 1004 | return; |
|
998 | 1005 | } |
|
999 | 1006 | var callback = callbacks.iopub.output; |
@@ -1003,6 +1010,20 b' define([' | |||
|
1003 | 1010 | }; |
|
1004 | 1011 | |
|
1005 | 1012 | /** |
|
1013 | * Handle an input message (execute_input). | |
|
1014 | * | |
|
1015 | * @function _handle_input message | |
|
1016 | */ | |
|
1017 | Kernel.prototype._handle_input_message = function (msg) { | |
|
1018 | var callbacks = this.get_callbacks_for_msg(msg.parent_header.msg_id); | |
|
1019 | if (!callbacks && this.unsolicited_msg_callback) { | |
|
1020 | // The message came from another client. Let the UI decide what to | |
|
1021 | // do with it. | |
|
1022 | this.unsolicited_msg_callback(msg); | |
|
1023 | } | |
|
1024 | }; | |
|
1025 | ||
|
1026 | /** | |
|
1006 | 1027 | * Dispatch IOPub messages to respective handlers. Each message |
|
1007 | 1028 | * type should have a handler. |
|
1008 | 1029 | * |
@@ -228,6 +228,9 b' class="notebook_app"' | |||
|
228 | 228 | </li> |
|
229 | 229 | <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Kernel</a> |
|
230 | 230 | <ul id="kernel_menu" class="dropdown-menu"> |
|
231 | <li id="toggle_unsolicited" | |
|
232 | title="Toggle display of unsolicited messages."> | |
|
233 | <a href="#">Show/ignore unsolicited messages.</a></li> | |
|
231 | 234 | <li id="int_kernel" |
|
232 | 235 | title="Send KeyboardInterrupt (CTRL-C) to the Kernel"> |
|
233 | 236 | <a href="#">Interrupt</a> |
General Comments 0
You need to be logged in to leave comments.
Login now