@jupyterlab/application
Version:
JupyterLab - Application
140 lines • 5.9 kB
JavaScript
/*
* Copyright (c) Jupyter Development Team.
* Distributed under the terms of the Modified BSD License.
*/
import { nullTranslator } from '@jupyterlab/translation';
/**
* Add a semantic commands to the application and take care
* of setting up the command changed signal.
*
* @param options Semantic command options
*/
export function addSemanticCommand(options) {
const { id, commands, shell, semanticCommands, default: defaultValues, overrides, trans } = options;
commands.addCommand(id, {
...createSemanticCommand({ commands, shell }, semanticCommands, defaultValues !== null && defaultValues !== void 0 ? defaultValues : {}, trans !== null && trans !== void 0 ? trans : nullTranslator.load('jupyterlab')),
...overrides
});
const commandList = Array.isArray(semanticCommands)
? semanticCommands
: [semanticCommands];
const onCommandChanged = (commands, args) => {
if (args.id) {
if (args.id === id && args.type === 'removed') {
commands.commandChanged.disconnect(onCommandChanged);
}
else {
const commandIds = commandList.reduce((agg, cmd) => agg.concat(cmd.ids), []);
if (commandIds.includes(args.id)) {
switch (args.type) {
case 'changed':
case 'many-changed':
commands.notifyCommandChanged(id);
break;
case 'removed':
for (const cmd of commandList) {
cmd.remove(args.id);
}
break;
}
}
}
}
};
commands.commandChanged.connect(onCommandChanged);
}
/**
* Create the command options from the given semantic commands list
* and the given default values.
*
* @param app Jupyter Application
* @param semanticCommands Single semantic command or a list of commands
* @param defaultValues Default values
* @param trans Translation bundle
* @returns Command options
*
* @deprecated Please use {@link addSemanticCommand}. This function will
* be removed of the public API in JupyterLab 5.
*/
export function createSemanticCommand(app, semanticCommands, defaultValues, trans) {
const { commands, shell } = app;
const commandList = Array.isArray(semanticCommands)
? semanticCommands
: [semanticCommands];
return {
label: concatenateTexts('label'),
caption: concatenateTexts('caption'),
isEnabled: () => {
var _a;
const isEnabled = reduceAttribute('isEnabled');
return ((isEnabled.length > 0 &&
!isEnabled.some(enabled => enabled === false)) ||
((_a = defaultValues.isEnabled) !== null && _a !== void 0 ? _a : false));
},
isToggled: () => {
var _a;
const isToggled = reduceAttribute('isToggled');
return (isToggled.some(enabled => enabled === true) ||
((_a = defaultValues.isToggled) !== null && _a !== void 0 ? _a : false));
},
isVisible: () => {
var _a;
const isVisible = reduceAttribute('isVisible');
return ((isVisible.length > 0 &&
!isVisible.some(visible => visible === false)) ||
((_a = defaultValues.isVisible) !== null && _a !== void 0 ? _a : true));
},
execute: async () => {
const widget = shell.currentWidget;
const commandIds = commandList.map(cmd => widget !== null ? cmd.getActiveCommandId(widget) : null);
const toExecute = commandIds.filter(commandId => commandId !== null && commands.isEnabled(commandId));
let result = null;
if (toExecute.length > 0) {
for (const commandId of toExecute) {
result = await commands.execute(commandId);
if (typeof result === 'boolean' && result === false) {
// If a command returns a boolean, assume it is the execution success status
// So break if it is false.
break;
}
}
}
else if (defaultValues.execute) {
result = await commands.execute(defaultValues.execute);
}
return result;
}
};
function reduceAttribute(attribute) {
const widget = shell.currentWidget;
const commandIds = commandList.map(cmd => widget !== null ? cmd.getActiveCommandId(widget) : null);
const attributes = commandIds
.filter(commandId => commandId !== null)
.map(commandId => commands[attribute](commandId));
return attributes;
}
function concatenateTexts(attribute) {
return () => {
var _a;
const texts = reduceAttribute(attribute).map((text, textIndex) => attribute == 'caption' && textIndex > 0
? text.toLocaleLowerCase()
: text);
switch (texts.length) {
case 0:
return (_a = defaultValues[attribute]) !== null && _a !== void 0 ? _a : '';
case 1:
return texts[0];
default: {
const hasEllipsis = texts.some(l => /…$/.test(l));
const main = texts
.slice(undefined, -1)
.map(l => l.replace(/…$/, ''))
.join(', ');
const end = texts.slice(-1)[0].replace(/…$/, '') + (hasEllipsis ? '…' : '');
return trans.__('%1 and %2', main, end);
}
}
};
}
}
//# sourceMappingURL=utils.js.map