// Extended code execution commands and more define([ 'base/js/namespace', 'jquery', 'require', 'base/js/events', 'services/config', 'base/js/utils', 'notebook/js/codecell' ], function(Jupyter, $, requirejs, events, configmod, utils, codecell) { "use strict"; var run_list = []; /* list of cells to be run */ // define default config parameter values var params = { run_cells_above: 'Alt-a', run_cells_below: 'Alt-b', toggle_marker: 'Alt-t', mark_all_codecells: 'Alt-m', unmark_all_codecells: 'Alt-u', run_marked_cells: 'Alt-r', run_all_cells: 'Alt-x', run_all_cells_ignore_errors: 'Alt-f', stop_execution: 'Ctrl-c', marked_color: '#20f224', scheduled_color: '#00def0', run_color: '#f30a2d' }; /** * Add event if user clicks on codemirror gutter * */ function add_gutter_events() { var ncells = Jupyter.notebook.ncells(); var cells = Jupyter.notebook.get_cells(); for (var i = 0; i < ncells; i++) { var cell = cells[i]; if ((cell.cell_type === "code")) { cell.code_mirror.on("gutterClick", changeEvent); if (is_marked(cell)) { var g = cell.code_mirror.getGutterElement(); $(g).css({ "background-color": params.marked_color }); } } } } /* * Initialize toolbar and gutter after config was loaded */ function initialize() { $.extend(true, params, Jupyter.notebook.config.data.runtools); add_gutter_events(); /* Add run control buttons to toolbar */ $(Jupyter.toolbar.add_buttons_group([ Jupyter.keyboard_manager.actions.register ({ help: 'Toggle Runtools Toolbar', icon: 'fa-cogs', handler: toggle_toolbar }, 'toggle-runtools-toolbar', 'runtools') ])).find('.btn').attr('id', 'toggle_runtools').css({ 'outline': 'none' }); /* Add keyboard shortcuts */ var add_command_shortcuts = {}; add_command_shortcuts[params["run_cells_above"]] = { help: 'Run cells above', help_index: 'xa', handler: function() { execute_cells_above(); return false; } }; add_command_shortcuts[params["run_cells_below"]] = { help: 'Run cells below', help_index: 'aa', handler: function() { execute_cells_below(); return false; } }; add_command_shortcuts[params["toggle_marker"]] = { help: 'Toggle marker', help_index: 'mt', handler: function() { toggle_marker(); return false; } }; add_command_shortcuts[params["mark_all_codecells"]] = { help: 'Mark all codecells', help_index: 'ma', handler: function() { mark_all(); return false; } }; add_command_shortcuts[params["unmark_all_codecells"]] = { help: 'Unmark all codecells', help_index: 'mu', handler: function() { mark_none(); return false; } }; add_command_shortcuts[params["run_marked_cells"]] = { help: 'Run marked cells', help_index: 'rm', handler: function() { run_marked_cells(); return false; } }; add_command_shortcuts[params["run_all_cells"]] = { help: 'Run all cells', help_index: 'ra', handler: function() { var pos = Jupyter.notebook.element.scrollTop(); execute_all_cells(); Jupyter.notebook.element.animate({ scrollTop: pos }, 100); return false; } }; add_command_shortcuts[params["run_all_cells_ignore_errors"]] = { help: 'Run all cells - ignore errors', help_index: 'rf', handler: function() { run_all_cells_ignore_errors(); return false; } }; Jupyter.keyboard_manager.command_shortcuts.add_shortcuts(add_command_shortcuts); Jupyter.keyboard_manager.edit_shortcuts.add_shortcuts(add_command_shortcuts); events.on('finished_execute.CodeCell', finished_execute_event); } /** * Hide or show a cell * * @param cell * @param io 'i' for cell input, 'o' for cell output * @param showme {Boolean} show (true) or hide (false) cell */ function showCell(cell, io, showme) { if (io === 'i') { if (showme === true) { cell.element.find("div.input").show(); cell.metadata.hide_input = false; } else { cell.element.find("div.input").hide(); cell.metadata.hide_input = true; } } else { if (showme === true) { cell.element.find('div.output').show(); cell.metadata.hide_output = false; } else { cell.element.find('div.output').hide(); cell.metadata.hide_output = true; } } } function _show_input_output_of_marked(show, char) { var cells = Jupyter.notebook.get_cells(); var ncells = cells.length; for (var i = 0; i < ncells; i++) { var _cell = cells[i]; if (is_marked(_cell)) showCell(_cell, char, show); } } /** * Hide or show input of all marked code cells * * @param show {Boolean} show (true) or hide (false) code cells */ function show_input(show) { _show_input_output_of_marked(show, 'i'); } /** * Hide or show output area of all marked code cells * * @param {Boolean} show show (true) or hide (false) */ function show_output(show) { _show_input_output_of_marked(show, 'o'); } /** * Execute next cell in run list, if it is still marked * */ function execute_next_marked_cell() { var cells = Jupyter.notebook.get_cells(); var end = cells.length; while (run_list.length > 0) { var runcell = run_list.shift(); for (var i = 0; i < end; i++) { if (runcell === cells[i]) { if (runcell.metadata.run_control !== undefined && runcell.metadata.run_control.marked === true) { var g = runcell.code_mirror.getGutterElement(); $(g).css({ "background-color": params.run_color }); runcell.execute(); return; } } } } } function _execute_without_selecting(idx_start, idx_end, stop_on_error) { // notebook.execute_cells alters selection, this doesn't var cells = Jupyter.notebook.get_cells(); idx_start = idx_start !== undefined ? idx_start : 0; idx_end = idx_end !== undefined ? idx_end : cells.length; for (var ii = idx_start; ii < idx_end; ii++) { cells[ii].execute(stop_on_error); } } function execute_cells_above() { _execute_without_selecting(0, Jupyter.notebook.get_selected_index()); } function execute_cells_below() { _execute_without_selecting(Jupyter.notebook.get_selected_index(), undefined); } function execute_all_cells(stop_on_error) { _execute_without_selecting(0, undefined, stop_on_error); } /** * Run code cells marked in metadata * */ function run_marked_cells() { var cells = Jupyter.notebook.get_cells(); var end = cells.length; run_list = []; /* Show all marked cells as scheduled to be run with new gutter background color */ for (var i = 0; i < end; i++) { var cell = cells[i]; if (cell instanceof codecell.CodeCell) { var last_line = cell.code_mirror.lastLine(); var cell_empty = ( last_line === 0 && cell.code_mirror.getLine(last_line) === ""); if (cell.metadata.run_control !== undefined && cell_empty === false) { if (cell.metadata.run_control.marked === true) { var g = cell.code_mirror.getGutterElement(); $(g).css({ "background-color": params.scheduled_color }); run_list.push(cell); } } } } execute_next_marked_cell(); } /* * Execute next cell in run_list when notified execution of last cell has been finished * @param evt Event * @param data Cell that has finished executing */ var finished_execute_event = function(evt, data) { var cell = data.cell; /* Reset gutter color no non-queued state */ if (is_marked(cell)) { var g = cell.code_mirror.getGutterElement(); $(g).css({ "background-color": params.marked_color }); } execute_next_marked_cell(); }; /** * * @param cell * @param value */ function setCell(cell, value) { if (!(cell instanceof codecell.CodeCell)) return; if (cell.metadata.run_control === undefined) cell.metadata.run_control = {}; if (cell.metadata.run_control.marked === undefined) cell.metadata.run_control.marked = false; if (value === undefined) value = !cell.metadata.run_control.marked; var g = cell.code_mirror.getGutterElement(); if (value === false) { cell.metadata.run_control.marked = false; $(g).css({ "background-color": "" }); } else { cell.metadata.run_control.marked = true; $(g).css({ "background-color": params.marked_color }); } } function setCellsMarked(cells, value) { var ncells = cells.length; for (var i = 0; i < ncells; i++) { setCell(cells[i], value); } } /** * Toggle code cell marker */ function toggle_marker() { setCellsMarked(Jupyter.notebook.get_selected_cells(), undefined); } /** * */ function mark_all() { setCellsMarked(Jupyter.notebook.get_cells(), true); } /** * */ function mark_none() { setCellsMarked(Jupyter.notebook.get_cells(), false); } /** * * @param cell notebook cell instance * @param state {string} state to be display [ '', 'locked', 'executed', 'modified' ] */ function set_cell_state(cell, state) { var icon = ""; if (state === 'locked') { icon = '