mirror of
https://github.com/wassname/jupyter_contrib_nbextensions.git
synced 2026-09-09 11:25:07 +08:00
updated code_prettify to use the shared library
This commit is contained in:
+33
-192
@@ -1,35 +1,27 @@
|
||||
// Copyright (c) Jupyter-Contrib Team.
|
||||
// Distributed under the terms of the Modified BSD License.
|
||||
// Authors: @jfbercher and @jcb91
|
||||
|
||||
define(function(require, exports, module) {
|
||||
'use strict';
|
||||
|
||||
var $ = require('jquery');
|
||||
var Jupyter = require('base/js/namespace');
|
||||
var events = require('base/js/events');
|
||||
var utils = require('base/js/utils');
|
||||
var ConfigSection = require('services/config').ConfigSection;
|
||||
var CodeCell = require('notebook/js/codecell').CodeCell;
|
||||
var kernel_exec_on_cell = require('nbextensions/code_prettify/kernel_exec_on_cell')
|
||||
|
||||
var mod_name = 'code_prettify';
|
||||
var mod_log_prefix = '[' + mod_name + ']';
|
||||
var mod_edit_shortcuts = {};
|
||||
var mod_cmd_shortcuts = {};
|
||||
var default_kernel_config = {
|
||||
library: '',
|
||||
prefix: '',
|
||||
postfix: '',
|
||||
replacements_json_to_kernel: [],
|
||||
trim_formatted_text: true
|
||||
};
|
||||
|
||||
// gives default settings
|
||||
var cfg = {
|
||||
add_toolbar_button: true,
|
||||
hotkey: 'Ctrl-L',
|
||||
prettify_all_hotkey: 'Ctrl-Shift-L',
|
||||
process_all_hotkey: 'Ctrl-Shift-L',
|
||||
register_hotkey: true,
|
||||
show_alerts_for_errors: true,
|
||||
extension_name: 'code_prettify',
|
||||
extension_label: 'Code prettify',
|
||||
extension_icon: 'fa-legal'
|
||||
};
|
||||
|
||||
cfg.kernel_config_map = { // map of parameters for supported kernels
|
||||
@@ -54,199 +46,48 @@ define(function(require, exports, module) {
|
||||
// before it is parsed into an object
|
||||
cfg.kernel_config_map_json = JSON.stringify(cfg.kernel_config_map);
|
||||
|
||||
/**
|
||||
* return a Promise which will resolve/reject based on the kernel message
|
||||
* type.
|
||||
* The returned promise will be
|
||||
* - resolved if the message was not an error
|
||||
* - rejected using the message's error text if msg.msg_type is "error"
|
||||
*/
|
||||
function convert_error_msg_to_broken_promise (msg) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
if (msg.msg_type == 'error') {
|
||||
return reject(mod_log_prefix + '\n Error: ' + msg.content.ename + '\n' + msg.content.evalue);
|
||||
}
|
||||
return resolve(msg);
|
||||
});
|
||||
}
|
||||
function assign_hotkeys_from_config(cfg) {
|
||||
|
||||
function get_kernel_config() {
|
||||
var kernelLanguage = Jupyter.notebook.metadata.kernelspec.language.toLowerCase();
|
||||
var kernel_config = cfg.kernel_config_map[kernelLanguage];
|
||||
// true => deep
|
||||
return $.extend(true, {}, default_kernel_config, kernel_config);
|
||||
}
|
||||
var cfg_code_prettify = cfg;
|
||||
var mod_edit_shortcuts = {};
|
||||
var mod_cmd_shortcuts = {};
|
||||
|
||||
function transform_json_string_to_kernel_string (str, kernel_config) {
|
||||
for (var ii=0; ii<kernel_config.replacements_json_to_kernel.length; ii++) {
|
||||
var from = kernel_config.replacements_json_to_kernel[ii][0];
|
||||
var to = kernel_config.replacements_json_to_kernel[ii][1];
|
||||
str = str.replace(from, to);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* construct functions as callbacks for the autoformat cell promise. This
|
||||
* is necessary because javascript lacks loop scoping, so if we don't use
|
||||
* this IIFE pattern, cell_index & cell are passed by reference, and every
|
||||
* callback ends up using the same value
|
||||
*/
|
||||
function construct_cell_callbacks (cell_index, cell) {
|
||||
var on_success = function (formatted_text) {
|
||||
cell.set_text(formatted_text);
|
||||
};
|
||||
var on_failure = function (reason) {
|
||||
console.warn(
|
||||
mod_log_prefix,
|
||||
'error prettifying cell', cell_index + ':\n',
|
||||
reason
|
||||
);
|
||||
if (cfg.show_alerts_for_errors) {
|
||||
alert(reason);
|
||||
}
|
||||
};
|
||||
return [on_success, on_failure];
|
||||
}
|
||||
|
||||
function autoformat_cells (indices) {
|
||||
if (indices === undefined) {
|
||||
indices = Jupyter.notebook.get_selected_cells_indices();
|
||||
}
|
||||
var kernel_config = get_kernel_config();
|
||||
for (var ii=0; ii<indices.length; ii++) {
|
||||
var cell_index = indices[ii];
|
||||
var cell = Jupyter.notebook.get_cell(cell_index);
|
||||
if (!(cell instanceof CodeCell)) {
|
||||
continue;
|
||||
}
|
||||
// IIFE because otherwise cell_index & cell are passed by reference
|
||||
var callbacks = construct_cell_callbacks(cell_index, cell);
|
||||
autoformat_text(cell.get_text(), kernel_config).then(callbacks[0], callbacks[1]);
|
||||
}
|
||||
}
|
||||
|
||||
function autoformat_text (text, kernel_config) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
kernel_config = kernel_config || get_kernel_config();
|
||||
var kernel_str = transform_json_string_to_kernel_string(
|
||||
JSON.stringify(text), kernel_config);
|
||||
Jupyter.notebook.kernel.execute(
|
||||
kernel_config.prefix + kernel_str + kernel_config.postfix,
|
||||
{iopub: {output: function (msg) {
|
||||
return resolve(convert_error_msg_to_broken_promise(msg).then(
|
||||
function on_success (msg) {
|
||||
// print goes to stream text => msg.content.text
|
||||
var formatted_text = String(JSON.parse(msg.content.text));
|
||||
if (kernel_config.trim_formatted_text) {
|
||||
formatted_text = formatted_text.trim();
|
||||
}
|
||||
return formatted_text;
|
||||
}
|
||||
));
|
||||
}}},
|
||||
{silent: false}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function add_toolbar_button () {
|
||||
if ($('#code_prettify_button').length < 1) {
|
||||
Jupyter.toolbar.add_buttons_group([{
|
||||
'label': 'Code prettify',
|
||||
'icon': 'fa-legal',
|
||||
'callback': function (evt) { autoformat_cells(); },
|
||||
'id': 'code_prettify_button'
|
||||
}]);
|
||||
}
|
||||
}
|
||||
|
||||
function assign_hotkeys_from_config () {
|
||||
mod_edit_shortcuts[cfg.hotkey] = {
|
||||
help: "code prettify",
|
||||
help_index: 'yf',
|
||||
handler: function (evt) { autoformat_cells(); },
|
||||
handler: function(evt) {
|
||||
return kernel_exec_on_cell.autoformat_cells(cfg_code_prettify);
|
||||
},
|
||||
};
|
||||
mod_edit_shortcuts[cfg.prettify_all_hotkey] = {
|
||||
|
||||
mod_edit_shortcuts[cfg.process_all_hotkey] = {
|
||||
help: "code prettify the whole notebook",
|
||||
help_index: 'yf',
|
||||
handler: function (evt) {
|
||||
var indices = []; var N = Jupyter.notebook.ncells();
|
||||
for (var i = 0; i <= N; i++) {
|
||||
indices.push(i);
|
||||
}
|
||||
autoformat_cells(indices); },
|
||||
handler: function(evt) {
|
||||
return function() {
|
||||
var indices = [];
|
||||
var N = Jupyter.notebook.ncells();
|
||||
for (var i = 0; i <= N; i++) {
|
||||
indices.push(i);
|
||||
}
|
||||
kernel_exec_on_cell.autoformat_cells(cfg_code_prettify, indices);
|
||||
}
|
||||
}(),
|
||||
};
|
||||
mod_cmd_shortcuts[cfg.prettify_all_hotkey] = mod_edit_shortcuts[cfg.prettify_all_hotkey]
|
||||
}
|
||||
|
||||
function setup_for_new_kernel () {
|
||||
var kernelLanguage = Jupyter.notebook.metadata.kernelspec.language.toLowerCase();
|
||||
var kernel_config = cfg.kernel_config_map[kernelLanguage];
|
||||
if (kernel_config === undefined) {
|
||||
$('#code_prettify_button').remove();
|
||||
alert(mod_log_prefix + " Sorry, can't use kernel language " + kernelLanguage + ".\n" +
|
||||
"Configurations are currently only defined for the following languages:\n" +
|
||||
', '.join(Object.keys(cfg.kernel_config_map)) + "\n" +
|
||||
"See readme for more details.");
|
||||
} else {
|
||||
if (cfg.add_toolbar_button) {
|
||||
add_toolbar_button();
|
||||
}
|
||||
if (cfg.register_hotkey) {
|
||||
Jupyter.keyboard_manager.edit_shortcuts.add_shortcuts(mod_edit_shortcuts);
|
||||
Jupyter.keyboard_manager.command_shortcuts.add_shortcuts(mod_cmd_shortcuts);
|
||||
}
|
||||
Jupyter.notebook.kernel.execute(
|
||||
kernel_config.library,
|
||||
{ iopub: { output: convert_error_msg_to_broken_promise } },
|
||||
{ silent: false }
|
||||
);
|
||||
mod_cmd_shortcuts[cfg.process_all_hotkey] = mod_edit_shortcuts[cfg.process_all_hotkey]
|
||||
if (cfg.register_hotkey) {
|
||||
Jupyter.keyboard_manager.edit_shortcuts.add_shortcuts(mod_edit_shortcuts);
|
||||
Jupyter.keyboard_manager.command_shortcuts.add_shortcuts(mod_cmd_shortcuts);
|
||||
}
|
||||
}
|
||||
|
||||
function load_notebook_extension () {
|
||||
var base_url = utils.get_body_data("baseUrl");
|
||||
var conf_section = new ConfigSection('notebook', {base_url: base_url});
|
||||
// first, load config
|
||||
conf_section.load()
|
||||
// now update default config with that loaded from server
|
||||
.then(function on_success (config_data) {
|
||||
$.extend(true, cfg, config_data[mod_name]);
|
||||
}, function on_error (err) {
|
||||
console.warn(mod_log_prefix, 'error loading config:', err);
|
||||
})
|
||||
// next parse json config values
|
||||
.then(function on_success () {
|
||||
var parsed_kernel_cfg = JSON.parse(cfg.kernel_config_map_json);
|
||||
$.extend(cfg.kernel_config_map, parsed_kernel_cfg);
|
||||
})
|
||||
// if we failed to parse the json values in the config
|
||||
// using catch pattern, we attempt to continue anyway using defaults
|
||||
.catch(function on_error (err) {
|
||||
console.warn(
|
||||
mod_log_prefix, 'error parsing config variable',
|
||||
mod_name + '.kernel_config_map_json to a json object:',
|
||||
err
|
||||
);
|
||||
})
|
||||
// now do things which required the config to be loaded
|
||||
.then(function on_success () {
|
||||
assign_hotkeys_from_config(); // initialize hotkey
|
||||
// kernel may already have been loaded before we get here, in which
|
||||
// case we've missed the kernel_ready.Kernel event, so try this
|
||||
if (typeof Jupyter.notebook.kernel !== "undefined" && Jupyter.notebook.kernel !== null) {
|
||||
setup_for_new_kernel();
|
||||
console.log("Executing kernel_exec_on_cell load_ipython")
|
||||
kernel_exec_on_cell.main(mod_name, mod_log_prefix, cfg);
|
||||
//kernel_exec_on_cell.
|
||||
assign_hotkeys_from_config(kernel_exec_on_cell.bigCfg['code_prettify']);
|
||||
}
|
||||
|
||||
// on kernel_ready.Kernel, a new kernel has been started
|
||||
events.on("kernel_ready.Kernel", function(event, data) {
|
||||
console.log(mod_log_prefix, 'restarting for new kernel_ready.Kernel event');
|
||||
setup_for_new_kernel();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
load_ipython_extension: load_notebook_extension
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user