123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682 |
- // Copyright (c) Jupyter Development Team.
- // Distributed under the terms of the Modified BSD License.
- /**
- * @packageDocumentation
- * @module notebook-extension
- */
- import {
- ILayoutRestorer,
- JupyterFrontEnd,
- JupyterFrontEndPlugin
- } from '@jupyterlab/application';
- import {
- Dialog,
- ICommandPalette,
- ISessionContextDialogs,
- MainAreaWidget,
- sessionContextDialogs,
- showDialog,
- WidgetTracker
- } from '@jupyterlab/apputils';
- import { Cell, CodeCell, ICellModel, MarkdownCell } from '@jupyterlab/cells';
- import { IEditorServices } from '@jupyterlab/codeeditor';
- import { PageConfig, URLExt } from '@jupyterlab/coreutils';
- import { IDocumentManager } from '@jupyterlab/docmanager';
- import { IFileBrowserFactory } from '@jupyterlab/filebrowser';
- import { ILauncher } from '@jupyterlab/launcher';
- import {
- IEditMenu,
- IFileMenu,
- IHelpMenu,
- IKernelMenu,
- IMainMenu,
- IRunMenu,
- IViewMenu
- } from '@jupyterlab/mainmenu';
- import * as nbformat from '@jupyterlab/nbformat';
- import {
- CommandEditStatus,
- INotebookTools,
- INotebookTracker,
- INotebookWidgetFactory,
- Notebook,
- NotebookActions,
- NotebookModelFactory,
- NotebookPanel,
- NotebookTools,
- NotebookTracker,
- NotebookTrustStatus,
- NotebookWidgetFactory,
- StaticNotebook
- } from '@jupyterlab/notebook';
- import {
- IObservableList,
- IObservableUndoableList
- } from '@jupyterlab/observables';
- import { IPropertyInspectorProvider } from '@jupyterlab/property-inspector';
- import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
- import { ISettingRegistry } from '@jupyterlab/settingregistry';
- import { IStateDB } from '@jupyterlab/statedb';
- import { IStatusBar } from '@jupyterlab/statusbar';
- import { ITranslator, nullTranslator } from '@jupyterlab/translation';
- import { buildIcon, notebookIcon } from '@jupyterlab/ui-components';
- import { ArrayExt } from '@lumino/algorithm';
- import { CommandRegistry } from '@lumino/commands';
- import {
- JSONExt,
- JSONObject,
- JSONValue,
- ReadonlyJSONValue,
- ReadonlyPartialJSONObject,
- UUID
- } from '@lumino/coreutils';
- import { DisposableSet } from '@lumino/disposable';
- import { Message, MessageLoop } from '@lumino/messaging';
- import { Menu, Panel } from '@lumino/widgets';
- import { logNotebookOutput } from './nboutput';
- /**
- * The command IDs used by the notebook plugin.
- */
- namespace CommandIDs {
- export const createNew = 'notebook:create-new';
- export const interrupt = 'notebook:interrupt-kernel';
- export const restart = 'notebook:restart-kernel';
- export const restartClear = 'notebook:restart-clear-output';
- export const restartAndRunToSelected = 'notebook:restart-and-run-to-selected';
- export const restartRunAll = 'notebook:restart-run-all';
- export const reconnectToKernel = 'notebook:reconnect-to-kernel';
- export const changeKernel = 'notebook:change-kernel';
- export const createConsole = 'notebook:create-console';
- export const createOutputView = 'notebook:create-output-view';
- export const clearAllOutputs = 'notebook:clear-all-cell-outputs';
- export const closeAndShutdown = 'notebook:close-and-shutdown';
- export const trust = 'notebook:trust';
- export const exportToFormat = 'notebook:export-to-format';
- export const run = 'notebook:run-cell';
- export const runAndAdvance = 'notebook:run-cell-and-select-next';
- export const runAndInsert = 'notebook:run-cell-and-insert-below';
- export const runInConsole = 'notebook:run-in-console';
- export const runAll = 'notebook:run-all-cells';
- export const runAllAbove = 'notebook:run-all-above';
- export const runAllBelow = 'notebook:run-all-below';
- export const renderAllMarkdown = 'notebook:render-all-markdown';
- export const toCode = 'notebook:change-cell-to-code';
- export const toMarkdown = 'notebook:change-cell-to-markdown';
- export const toRaw = 'notebook:change-cell-to-raw';
- export const cut = 'notebook:cut-cell';
- export const copy = 'notebook:copy-cell';
- export const pasteAbove = 'notebook:paste-cell-above';
- export const pasteBelow = 'notebook:paste-cell-below';
- export const pasteAndReplace = 'notebook:paste-and-replace-cell';
- export const moveUp = 'notebook:move-cell-up';
- export const moveDown = 'notebook:move-cell-down';
- export const clearOutputs = 'notebook:clear-cell-output';
- export const deleteCell = 'notebook:delete-cell';
- export const insertAbove = 'notebook:insert-cell-above';
- export const insertBelow = 'notebook:insert-cell-below';
- export const selectAbove = 'notebook:move-cursor-up';
- export const selectBelow = 'notebook:move-cursor-down';
- export const extendAbove = 'notebook:extend-marked-cells-above';
- export const extendTop = 'notebook:extend-marked-cells-top';
- export const extendBelow = 'notebook:extend-marked-cells-below';
- export const extendBottom = 'notebook:extend-marked-cells-bottom';
- export const selectAll = 'notebook:select-all';
- export const deselectAll = 'notebook:deselect-all';
- export const editMode = 'notebook:enter-edit-mode';
- export const merge = 'notebook:merge-cells';
- export const mergeAbove = 'notebook:merge-cell-above';
- export const mergeBelow = 'notebook:merge-cell-below';
- export const split = 'notebook:split-cell-at-cursor';
- export const commandMode = 'notebook:enter-command-mode';
- export const toggleAllLines = 'notebook:toggle-all-cell-line-numbers';
- export const undoCellAction = 'notebook:undo-cell-action';
- export const redoCellAction = 'notebook:redo-cell-action';
- export const markdown1 = 'notebook:change-cell-to-heading-1';
- export const markdown2 = 'notebook:change-cell-to-heading-2';
- export const markdown3 = 'notebook:change-cell-to-heading-3';
- export const markdown4 = 'notebook:change-cell-to-heading-4';
- export const markdown5 = 'notebook:change-cell-to-heading-5';
- export const markdown6 = 'notebook:change-cell-to-heading-6';
- export const hideCode = 'notebook:hide-cell-code';
- export const showCode = 'notebook:show-cell-code';
- export const hideAllCode = 'notebook:hide-all-cell-code';
- export const showAllCode = 'notebook:show-all-cell-code';
- export const hideOutput = 'notebook:hide-cell-outputs';
- export const showOutput = 'notebook:show-cell-outputs';
- export const hideAllOutputs = 'notebook:hide-all-cell-outputs';
- export const showAllOutputs = 'notebook:show-all-cell-outputs';
- export const enableOutputScrolling = 'notebook:enable-output-scrolling';
- export const disableOutputScrolling = 'notebook:disable-output-scrolling';
- export const selectLastRunCell = 'notebook:select-last-run-cell';
- export const replaceSelection = 'notebook:replace-selection';
- export const toggleCollapseCmd = 'Collapsible_Headings:Toggle_Collapse';
- export const collapseAllCmd = 'Collapsible_Headings:Collapse_All';
- export const expandAllCmd = 'Collapsible_Headings:Expand_All';
- }
- /**
- * The name of the factory that creates notebooks.
- */
- const FACTORY = 'Notebook';
- /**
- * The exluded Export To ...
- * (returned from nbconvert's export list)
- */
- const FORMAT_EXCLUDE = ['notebook', 'python', 'custom'];
- /**
- * The notebook widget tracker provider.
- */
- const trackerPlugin: JupyterFrontEndPlugin<INotebookTracker> = {
- id: '@jupyterlab/notebook-extension:tracker',
- provides: INotebookTracker,
- requires: [INotebookWidgetFactory, ITranslator],
- optional: [
- ICommandPalette,
- IFileBrowserFactory,
- ILauncher,
- ILayoutRestorer,
- IMainMenu,
- ISettingRegistry,
- ISessionContextDialogs
- ],
- activate: activateNotebookHandler,
- autoStart: true
- };
- /**
- * The notebook cell factory provider.
- */
- const factory: JupyterFrontEndPlugin<NotebookPanel.IContentFactory> = {
- id: '@jupyterlab/notebook-extension:factory',
- provides: NotebookPanel.IContentFactory,
- requires: [IEditorServices],
- autoStart: true,
- activate: (app: JupyterFrontEnd, editorServices: IEditorServices) => {
- const editorFactory = editorServices.factoryService.newInlineEditor;
- return new NotebookPanel.ContentFactory({ editorFactory });
- }
- };
- /**
- * The notebook tools extension.
- */
- const tools: JupyterFrontEndPlugin<INotebookTools> = {
- activate: activateNotebookTools,
- provides: INotebookTools,
- id: '@jupyterlab/notebook-extension:tools',
- autoStart: true,
- requires: [INotebookTracker, IEditorServices, IStateDB, ITranslator],
- optional: [IPropertyInspectorProvider]
- };
- /**
- * A plugin providing a CommandEdit status item.
- */
- export const commandEditItem: JupyterFrontEndPlugin<void> = {
- id: '@jupyterlab/notebook-extension:mode-status',
- autoStart: true,
- requires: [INotebookTracker, ITranslator],
- optional: [IStatusBar],
- activate: (
- app: JupyterFrontEnd,
- tracker: INotebookTracker,
- translator: ITranslator,
- statusBar: IStatusBar | null
- ) => {
- if (!statusBar) {
- // Automatically disable if statusbar missing
- return;
- }
- const { shell } = app;
- const item = new CommandEditStatus(translator);
- // Keep the status item up-to-date with the current notebook.
- tracker.currentChanged.connect(() => {
- const current = tracker.currentWidget;
- item.model.notebook = current && current.content;
- });
- statusBar.registerStatusItem('@jupyterlab/notebook-extension:mode-status', {
- item,
- align: 'right',
- rank: 4,
- isActive: () =>
- !!shell.currentWidget &&
- !!tracker.currentWidget &&
- shell.currentWidget === tracker.currentWidget
- });
- }
- };
- /**
- * A plugin providing export commands in the main menu and command palette
- */
- export const exportPlugin: JupyterFrontEndPlugin<void> = {
- id: '@jupyterlab/notebook-extension:export',
- autoStart: true,
- requires: [ITranslator, INotebookTracker],
- optional: [IMainMenu, ICommandPalette],
- activate: (
- app: JupyterFrontEnd,
- translator: ITranslator,
- tracker: INotebookTracker,
- mainMenu: IMainMenu | null,
- palette: ICommandPalette | null
- ) => {
- const trans = translator.load('jupyterlab');
- const { commands, shell } = app;
- const services = app.serviceManager;
- const isEnabled = (): boolean => {
- return Private.isEnabled(shell, tracker);
- };
- commands.addCommand(CommandIDs.exportToFormat, {
- label: args => {
- const formatLabel = args['label'] as string;
- return args['isPalette']
- ? trans.__('Export Notebook: %1', formatLabel)
- : formatLabel;
- },
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (!current) {
- return;
- }
- const url = PageConfig.getNBConvertURL({
- format: args['format'] as string,
- download: true,
- path: current.context.path
- });
- const child = window.open('', '_blank');
- const { context } = current;
- if (child) {
- child.opener = null;
- }
- if (context.model.dirty && !context.model.readOnly) {
- return context.save().then(() => {
- child?.location.assign(url);
- });
- }
- return new Promise<void>(resolve => {
- child?.location.assign(url);
- resolve(undefined);
- });
- },
- isEnabled
- });
- // Add a notebook group to the File menu.
- let exportTo: Menu | null | undefined;
- if (mainMenu) {
- exportTo = mainMenu.fileMenu.items.find(
- item =>
- item.type === 'submenu' &&
- item.submenu?.id === 'jp-mainmenu-file-notebookexport'
- )?.submenu;
- }
- void services.nbconvert.getExportFormats().then(response => {
- if (response) {
- const formatLabels: any = Private.getFormatLabels(translator);
- // Convert export list to palette and menu items.
- const formatList = Object.keys(response);
- formatList.forEach(function (key) {
- const capCaseKey = trans.__(key[0].toUpperCase() + key.substr(1));
- const labelStr = formatLabels[key] ? formatLabels[key] : capCaseKey;
- let args = {
- format: key,
- label: labelStr,
- isPalette: false
- };
- if (FORMAT_EXCLUDE.indexOf(key) === -1) {
- if (exportTo) {
- exportTo.addItem({
- command: CommandIDs.exportToFormat,
- args: args
- });
- }
- if (palette) {
- args = {
- format: key,
- label: labelStr,
- isPalette: true
- };
- const category = trans.__('Notebook Operations');
- palette.addItem({
- command: CommandIDs.exportToFormat,
- category,
- args
- });
- }
- }
- });
- }
- });
- }
- };
- /**
- * A plugin that adds a notebook trust status item to the status bar.
- */
- export const notebookTrustItem: JupyterFrontEndPlugin<void> = {
- id: '@jupyterlab/notebook-extension:trust-status',
- autoStart: true,
- requires: [INotebookTracker, ITranslator],
- optional: [IStatusBar],
- activate: (
- app: JupyterFrontEnd,
- tracker: INotebookTracker,
- tranlator: ITranslator,
- statusBar: IStatusBar | null
- ) => {
- if (!statusBar) {
- // Automatically disable if statusbar missing
- return;
- }
- const { shell } = app;
- const item = new NotebookTrustStatus(tranlator);
- // Keep the status item up-to-date with the current notebook.
- tracker.currentChanged.connect(() => {
- const current = tracker.currentWidget;
- item.model.notebook = current && current.content;
- });
- statusBar.registerStatusItem(
- '@jupyterlab/notebook-extension:trust-status',
- {
- item,
- align: 'right',
- rank: 3,
- isActive: () =>
- !!shell.currentWidget &&
- !!tracker.currentWidget &&
- shell.currentWidget === tracker.currentWidget
- }
- );
- }
- };
- /**
- * The notebook widget factory provider.
- */
- const widgetFactoryPlugin: JupyterFrontEndPlugin<NotebookWidgetFactory.IFactory> = {
- id: '@jupyterlab/notebook-extension:widget-factory',
- provides: INotebookWidgetFactory,
- requires: [
- NotebookPanel.IContentFactory,
- IEditorServices,
- IRenderMimeRegistry,
- ISessionContextDialogs,
- ITranslator
- ],
- activate: activateWidgetFactory,
- autoStart: true
- };
- /**
- * The cloned output provider.
- */
- const clonedOutputsPlugin: JupyterFrontEndPlugin<void> = {
- id: '@jupyterlab/notebook-extension:cloned-outputs',
- requires: [IDocumentManager, INotebookTracker, ITranslator],
- optional: [ILayoutRestorer],
- activate: activateClonedOutputs,
- autoStart: true
- };
- /**
- * A plugin for code consoles functionalities.
- */
- const codeConsolePlugin: JupyterFrontEndPlugin<void> = {
- id: '@jupyterlab/notebook-extension:code-console',
- requires: [INotebookTracker, ITranslator],
- activate: activateCodeConsole,
- autoStart: true
- };
- /**
- * Export the plugins as default.
- */
- const plugins: JupyterFrontEndPlugin<any>[] = [
- factory,
- trackerPlugin,
- exportPlugin,
- tools,
- commandEditItem,
- notebookTrustItem,
- widgetFactoryPlugin,
- logNotebookOutput,
- clonedOutputsPlugin,
- codeConsolePlugin
- ];
- export default plugins;
- /**
- * Activate the notebook tools extension.
- */
- function activateNotebookTools(
- app: JupyterFrontEnd,
- tracker: INotebookTracker,
- editorServices: IEditorServices,
- state: IStateDB,
- translator: ITranslator,
- inspectorProvider: IPropertyInspectorProvider | null
- ): INotebookTools {
- const trans = translator.load('jupyterlab');
- const id = 'notebook-tools';
- const notebookTools = new NotebookTools({ tracker, translator });
- const activeCellTool = new NotebookTools.ActiveCellTool();
- const slideShow = NotebookTools.createSlideShowSelector(translator);
- const editorFactory = editorServices.factoryService.newInlineEditor;
- const cellMetadataEditor = new NotebookTools.CellMetadataEditorTool({
- editorFactory,
- collapsed: false,
- translator
- });
- const notebookMetadataEditor = new NotebookTools.NotebookMetadataEditorTool({
- editorFactory,
- translator
- });
- const services = app.serviceManager;
- // Create message hook for triggers to save to the database.
- const hook = (sender: any, message: Message): boolean => {
- switch (message.type) {
- case 'activate-request':
- void state.save(id, { open: true });
- break;
- case 'after-hide':
- case 'close-request':
- void state.remove(id);
- break;
- default:
- break;
- }
- return true;
- };
- const optionsMap: { [key: string]: JSONValue } = {};
- optionsMap.None = null;
- void services.nbconvert.getExportFormats().then(response => {
- if (response) {
- /**
- * The excluded Cell Inspector Raw NbConvert Formats
- * (returned from nbconvert's export list)
- */
- const rawFormatExclude = [
- 'pdf',
- 'slides',
- 'script',
- 'notebook',
- 'custom'
- ];
- let optionValueArray: any = [
- [trans.__('PDF'), 'pdf'],
- [trans.__('Slides'), 'slides'],
- [trans.__('Script'), 'script'],
- [trans.__('Notebook'), 'notebook'],
- [trans.__('Custom'), 'custom']
- ];
- // convert exportList to palette and menu items
- const formatList = Object.keys(response);
- const formatLabels = Private.getFormatLabels(translator);
- formatList.forEach(function (key) {
- if (rawFormatExclude.indexOf(key) === -1) {
- const altOption = trans.__(key[0].toUpperCase() + key.substr(1));
- const option = formatLabels[key] ? formatLabels[key] : altOption;
- const mimeTypeValue = response[key].output_mimetype;
- optionValueArray.push([option, mimeTypeValue]);
- }
- });
- const nbConvert = NotebookTools.createNBConvertSelector(
- optionValueArray,
- translator
- );
- notebookTools.addItem({ tool: nbConvert, section: 'common', rank: 3 });
- }
- });
- notebookTools.title.icon = buildIcon;
- notebookTools.title.caption = trans.__('Notebook Tools');
- notebookTools.id = id;
- notebookTools.addItem({ tool: activeCellTool, section: 'common', rank: 1 });
- notebookTools.addItem({ tool: slideShow, section: 'common', rank: 2 });
- notebookTools.addItem({
- tool: cellMetadataEditor,
- section: 'advanced',
- rank: 1
- });
- notebookTools.addItem({
- tool: notebookMetadataEditor,
- section: 'advanced',
- rank: 2
- });
- MessageLoop.installMessageHook(notebookTools, hook);
- if (inspectorProvider) {
- tracker.widgetAdded.connect((sender, panel) => {
- const inspector = inspectorProvider.register(panel);
- inspector.render(notebookTools);
- });
- }
- return notebookTools;
- }
- /**
- * Activate the notebook widget factory.
- */
- function activateWidgetFactory(
- app: JupyterFrontEnd,
- contentFactory: NotebookPanel.IContentFactory,
- editorServices: IEditorServices,
- rendermime: IRenderMimeRegistry,
- sessionContextDialogs: ISessionContextDialogs,
- translator: ITranslator
- ): NotebookWidgetFactory.IFactory {
- const factory = new NotebookWidgetFactory({
- name: FACTORY,
- fileTypes: ['notebook'],
- modelName: 'notebook',
- defaultFor: ['notebook'],
- preferKernel: true,
- canStartKernel: true,
- rendermime: rendermime,
- contentFactory,
- editorConfig: StaticNotebook.defaultEditorConfig,
- notebookConfig: StaticNotebook.defaultNotebookConfig,
- mimeTypeService: editorServices.mimeTypeService,
- sessionDialogs: sessionContextDialogs,
- translator: translator
- });
- app.docRegistry.addWidgetFactory(factory);
- return factory;
- }
- /**
- * Activate the plugin to create and track cloned outputs.
- */
- function activateClonedOutputs(
- app: JupyterFrontEnd,
- docManager: IDocumentManager,
- notebookTracker: INotebookTracker,
- translator: ITranslator,
- restorer: ILayoutRestorer | null
- ): void {
- const trans = translator.load('jupyterlab');
- const clonedOutputs = new WidgetTracker<
- MainAreaWidget<Private.ClonedOutputArea>
- >({
- namespace: 'cloned-outputs'
- });
- if (restorer) {
- void restorer.restore(clonedOutputs, {
- command: CommandIDs.createOutputView,
- args: widget => ({
- path: widget.content.path,
- index: widget.content.index
- }),
- name: widget => `${widget.content.path}:${widget.content.index}`,
- when: notebookTracker.restored // After the notebook widgets (but not contents).
- });
- }
- const { commands, shell } = app;
- const isEnabledAndSingleSelected = (): boolean => {
- return Private.isEnabledAndSingleSelected(shell, notebookTracker);
- };
- commands.addCommand(CommandIDs.createOutputView, {
- label: trans.__('Create New View for Output'),
- execute: async args => {
- let cell: CodeCell | undefined;
- let current: NotebookPanel | undefined | null;
- // If we are given a notebook path and cell index, then
- // use that, otherwise use the current active cell.
- const path = args.path as string | undefined | null;
- let index = args.index as number | undefined | null;
- if (path && index !== undefined && index !== null) {
- current = docManager.findWidget(path, FACTORY) as NotebookPanel;
- if (!current) {
- return;
- }
- } else {
- current = notebookTracker.currentWidget;
- if (!current) {
- return;
- }
- cell = current.content.activeCell as CodeCell;
- index = current.content.activeCellIndex;
- }
- // Create a MainAreaWidget
- const content = new Private.ClonedOutputArea({
- notebook: current,
- cell,
- index,
- translator
- });
- const widget = new MainAreaWidget({ content });
- current.context.addSibling(widget, {
- ref: current.id,
- mode: 'split-bottom'
- });
- const updateCloned = () => {
- void clonedOutputs.save(widget);
- };
- current.context.pathChanged.connect(updateCloned);
- current.context.model?.cells.changed.connect(updateCloned);
- // Add the cloned output to the output widget tracker.
- void clonedOutputs.add(widget);
- // Remove the output view if the parent notebook is closed.
- current.content.disposed.connect(() => {
- current!.context.pathChanged.disconnect(updateCloned);
- current!.context.model?.cells.changed.disconnect(updateCloned);
- widget.dispose();
- });
- },
- isEnabled: isEnabledAndSingleSelected
- });
- }
- /**
- * Activate the plugin to add code console functionalities
- */
- function activateCodeConsole(
- app: JupyterFrontEnd,
- tracker: INotebookTracker,
- translator: ITranslator
- ): void {
- const trans = translator.load('jupyterlab');
- const { commands, shell } = app;
- const isEnabled = (): boolean => Private.isEnabled(shell, tracker);
- commands.addCommand(CommandIDs.createConsole, {
- label: trans.__('New Console for Notebook'),
- execute: args => {
- const current = tracker.currentWidget;
- if (!current) {
- return;
- }
- return Private.createConsole(
- commands,
- current,
- args['activate'] as boolean
- );
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.runInConsole, {
- label: trans.__('Run Selected Text or Current Line in Console'),
- execute: async args => {
- // Default to not activating the notebook (thereby putting the notebook
- // into command mode)
- const current = tracker.currentWidget;
- if (!current) {
- return;
- }
- const { context, content } = current;
- const cell = content.activeCell;
- const metadata = cell?.model.metadata.toJSON();
- const path = context.path;
- // ignore action in non-code cell
- if (!cell || cell.model.type !== 'code') {
- return;
- }
- let code: string;
- const editor = cell.editor;
- const selection = editor.getSelection();
- const { start, end } = selection;
- const selected = start.column !== end.column || start.line !== end.line;
- if (selected) {
- // Get the selected code from the editor.
- const start = editor.getOffsetAt(selection.start);
- const end = editor.getOffsetAt(selection.end);
- code = editor.model.value.text.substring(start, end);
- } else {
- // no selection, find the complete statement around the current line
- const cursor = editor.getCursorPosition();
- const srcLines = editor.model.value.text.split('\n');
- let curLine = selection.start.line;
- while (
- curLine < editor.lineCount &&
- !srcLines[curLine].replace(/\s/g, '').length
- ) {
- curLine += 1;
- }
- // if curLine > 0, we first do a search from beginning
- let fromFirst = curLine > 0;
- let firstLine = 0;
- let lastLine = firstLine + 1;
- // eslint-disable-next-line
- while (true) {
- code = srcLines.slice(firstLine, lastLine).join('\n');
- const reply = await current.context.sessionContext.session?.kernel?.requestIsComplete(
- {
- // ipython needs an empty line at the end to correctly identify completeness of indented code
- code: code + '\n\n'
- }
- );
- if (reply?.content.status === 'complete') {
- if (curLine < lastLine) {
- // we find a block of complete statement containing the current line, great!
- while (
- lastLine < editor.lineCount &&
- !srcLines[lastLine].replace(/\s/g, '').length
- ) {
- lastLine += 1;
- }
- editor.setCursorPosition({
- line: lastLine,
- column: cursor.column
- });
- break;
- } else {
- // discard the complete statement before the current line and continue
- firstLine = lastLine;
- lastLine = firstLine + 1;
- }
- } else if (lastLine < editor.lineCount) {
- // if incomplete and there are more lines, add the line and check again
- lastLine += 1;
- } else if (fromFirst) {
- // we search from the first line and failed, we search again from current line
- firstLine = curLine;
- lastLine = curLine + 1;
- fromFirst = false;
- } else {
- // if we have searched both from first line and from current line and we
- // cannot find anything, we submit the current line.
- code = srcLines[curLine];
- while (
- curLine + 1 < editor.lineCount &&
- !srcLines[curLine + 1].replace(/\s/g, '').length
- ) {
- curLine += 1;
- }
- editor.setCursorPosition({
- line: curLine + 1,
- column: cursor.column
- });
- break;
- }
- }
- }
- if (!code) {
- return;
- }
- await commands.execute('console:open', {
- activate: false,
- insertMode: 'split-bottom',
- path
- });
- await commands.execute('console:inject', {
- activate: false,
- code,
- path,
- metadata
- });
- },
- isEnabled
- });
- }
- /**
- * Activate the notebook handler extension.
- */
- function activateNotebookHandler(
- app: JupyterFrontEnd,
- factory: NotebookWidgetFactory.IFactory,
- translator: ITranslator,
- palette: ICommandPalette | null,
- browserFactory: IFileBrowserFactory | null,
- launcher: ILauncher | null,
- restorer: ILayoutRestorer | null,
- mainMenu: IMainMenu | null,
- settingRegistry: ISettingRegistry | null,
- sessionDialogs: ISessionContextDialogs | null
- ): INotebookTracker {
- const trans = translator.load('jupyterlab');
- const services = app.serviceManager;
- const { commands } = app;
- const tracker = new NotebookTracker({ namespace: 'notebook' });
- // Fetch settings if possible.
- const fetchSettings = settingRegistry
- ? settingRegistry.load(trackerPlugin.id)
- : Promise.reject(new Error(`No setting registry for ${trackerPlugin.id}`));
- // Handle state restoration.
- if (restorer) {
- fetchSettings
- .then(settings => {
- updateConfig(settings);
- settings.changed.connect(() => {
- updateConfig(settings);
- });
- })
- .catch((reason: Error) => {
- console.warn(reason.message);
- updateTracker({
- editorConfig: factory.editorConfig,
- notebookConfig: factory.notebookConfig,
- kernelShutdown: factory.shutdownOnClose
- });
- });
- void restorer.restore(tracker, {
- command: 'docmanager:open',
- args: panel => ({ path: panel.context.path, factory: FACTORY }),
- name: panel => panel.context.path,
- when: services.ready
- });
- }
- const registry = app.docRegistry;
- registry.addModelFactory(new NotebookModelFactory({}));
- addCommands(app, tracker, translator, sessionDialogs);
- if (palette) {
- populatePalette(palette, translator);
- }
- let id = 0; // The ID counter for notebook panels.
- const ft = app.docRegistry.getFileType('notebook');
- factory.widgetCreated.connect((sender, widget) => {
- // If the notebook panel does not have an ID, assign it one.
- widget.id = widget.id || `notebook-${++id}`;
- // Set up the title icon
- widget.title.icon = ft?.icon;
- widget.title.iconClass = ft?.iconClass ?? '';
- widget.title.iconLabel = ft?.iconLabel ?? '';
- // Notify the widget tracker if restore data needs to update.
- widget.context.pathChanged.connect(() => {
- void tracker.save(widget);
- });
- // Add the notebook panel to the tracker.
- void tracker.add(widget);
- });
- /**
- * Update the settings of the current tracker.
- */
- function updateTracker(options: NotebookPanel.IConfig): void {
- tracker.forEach(widget => {
- widget.setConfig(options);
- });
- }
- /**
- * Update the setting values.
- */
- function updateConfig(settings: ISettingRegistry.ISettings): void {
- const code = {
- ...StaticNotebook.defaultEditorConfig.code,
- ...(settings.get('codeCellConfig').composite as JSONObject)
- };
- const markdown = {
- ...StaticNotebook.defaultEditorConfig.markdown,
- ...(settings.get('markdownCellConfig').composite as JSONObject)
- };
- const raw = {
- ...StaticNotebook.defaultEditorConfig.raw,
- ...(settings.get('rawCellConfig').composite as JSONObject)
- };
- factory.editorConfig = { code, markdown, raw };
- factory.notebookConfig = {
- scrollPastEnd: settings.get('scrollPastEnd').composite as boolean,
- defaultCell: settings.get('defaultCell').composite as nbformat.CellType,
- recordTiming: settings.get('recordTiming').composite as boolean,
- numberCellsToRenderDirectly: settings.get('numberCellsToRenderDirectly')
- .composite as number,
- renderCellOnIdle: settings.get('renderCellOnIdle').composite as boolean,
- observedTopMargin: settings.get('observedTopMargin').composite as string,
- observedBottomMargin: settings.get('observedBottomMargin')
- .composite as string,
- maxNumberOutputs: settings.get('maxNumberOutputs').composite as number
- };
- factory.shutdownOnClose = settings.get('kernelShutdown')
- .composite as boolean;
- updateTracker({
- editorConfig: factory.editorConfig,
- notebookConfig: factory.notebookConfig,
- kernelShutdown: factory.shutdownOnClose
- });
- }
- // Add main menu notebook menu.
- if (mainMenu) {
- populateMenus(app, mainMenu, tracker, translator, sessionDialogs);
- }
- // Utility function to create a new notebook.
- const createNew = (cwd: string, kernelName?: string) => {
- return commands
- .execute('docmanager:new-untitled', { path: cwd, type: 'notebook' })
- .then(model => {
- return commands.execute('docmanager:open', {
- path: model.path,
- factory: FACTORY,
- kernel: { name: kernelName }
- });
- });
- };
- // Add a command for creating a new notebook.
- commands.addCommand(CommandIDs.createNew, {
- label: args => {
- const kernelName = (args['kernelName'] as string) || '';
- if (args['isLauncher'] && args['kernelName'] && services.kernelspecs) {
- return (
- services.kernelspecs.specs?.kernelspecs[kernelName]?.display_name ??
- ''
- );
- }
- if (args['isPalette']) {
- return trans.__('New Notebook');
- }
- return trans.__('Notebook');
- },
- caption: trans.__('Create a new notebook'),
- icon: args => (args['isPalette'] ? undefined : notebookIcon),
- execute: args => {
- const cwd =
- (args['cwd'] as string) ||
- (browserFactory ? browserFactory.defaultBrowser.model.path : '');
- const kernelName = (args['kernelName'] as string) || '';
- return createNew(cwd, kernelName);
- }
- });
- // Add a launcher item if the launcher is available.
- if (launcher) {
- void services.ready.then(() => {
- let disposables: DisposableSet | null = null;
- const onSpecsChanged = () => {
- if (disposables) {
- disposables.dispose();
- disposables = null;
- }
- const specs = services.kernelspecs.specs;
- if (!specs) {
- return;
- }
- disposables = new DisposableSet();
- const baseUrl = PageConfig.getBaseUrl();
- for (const name in specs.kernelspecs) {
- const rank = name === specs.default ? 0 : Infinity;
- const spec = specs.kernelspecs[name]!;
- let kernelIconUrl = spec.resources['logo-64x64'];
- if (kernelIconUrl) {
- const index = kernelIconUrl.indexOf('kernelspecs');
- kernelIconUrl = URLExt.join(baseUrl, kernelIconUrl.slice(index));
- }
- disposables.add(
- launcher.add({
- command: CommandIDs.createNew,
- args: { isLauncher: true, kernelName: name },
- category: trans.__('Notebook'),
- rank,
- kernelIconUrl,
- metadata: {
- kernel: JSONExt.deepCopy(
- spec.metadata || {}
- ) as ReadonlyJSONValue
- }
- })
- );
- }
- };
- onSpecsChanged();
- services.kernelspecs.specsChanged.connect(onSpecsChanged);
- });
- }
- // Cell context menu groups
- app.contextMenu.addItem({
- type: 'separator',
- selector: '.jp-Notebook .jp-Cell',
- rank: 0
- });
- app.contextMenu.addItem({
- command: CommandIDs.cut,
- selector: '.jp-Notebook .jp-Cell',
- rank: 1
- });
- app.contextMenu.addItem({
- command: CommandIDs.copy,
- selector: '.jp-Notebook .jp-Cell',
- rank: 2
- });
- app.contextMenu.addItem({
- command: CommandIDs.pasteBelow,
- selector: '.jp-Notebook .jp-Cell',
- rank: 3
- });
- app.contextMenu.addItem({
- type: 'separator',
- selector: '.jp-Notebook .jp-Cell',
- rank: 4
- });
- app.contextMenu.addItem({
- command: CommandIDs.deleteCell,
- selector: '.jp-Notebook .jp-Cell',
- rank: 5
- });
- app.contextMenu.addItem({
- type: 'separator',
- selector: '.jp-Notebook .jp-Cell',
- rank: 6
- });
- app.contextMenu.addItem({
- command: CommandIDs.split,
- selector: '.jp-Notebook .jp-Cell',
- rank: 7
- });
- app.contextMenu.addItem({
- command: CommandIDs.merge,
- selector: '.jp-Notebook .jp-Cell',
- rank: 8
- });
- app.contextMenu.addItem({
- command: CommandIDs.mergeAbove,
- selector: '.jp-Notebook .jp-Cell',
- rank: 8
- });
- app.contextMenu.addItem({
- command: CommandIDs.mergeBelow,
- selector: '.jp-Notebook .jp-Cell',
- rank: 8
- });
- app.contextMenu.addItem({
- type: 'separator',
- selector: '.jp-Notebook .jp-Cell',
- rank: 9
- });
- // CodeCell context menu groups
- app.contextMenu.addItem({
- command: CommandIDs.createOutputView,
- selector: '.jp-Notebook .jp-CodeCell',
- rank: 10
- });
- app.contextMenu.addItem({
- type: 'separator',
- selector: '.jp-Notebook .jp-CodeCell',
- rank: 11
- });
- app.contextMenu.addItem({
- command: CommandIDs.clearOutputs,
- selector: '.jp-Notebook .jp-CodeCell',
- rank: 12
- });
- // Notebook context menu groups
- app.contextMenu.addItem({
- command: CommandIDs.clearAllOutputs,
- selector: '.jp-Notebook',
- rank: 0
- });
- app.contextMenu.addItem({
- type: 'separator',
- selector: '.jp-Notebook',
- rank: 1
- });
- app.contextMenu.addItem({
- command: CommandIDs.enableOutputScrolling,
- selector: '.jp-Notebook',
- rank: 2
- });
- app.contextMenu.addItem({
- command: CommandIDs.disableOutputScrolling,
- selector: '.jp-Notebook',
- rank: 3
- });
- app.contextMenu.addItem({
- type: 'separator',
- selector: '.jp-Notebook',
- rank: 4
- });
- app.contextMenu.addItem({
- command: CommandIDs.undoCellAction,
- selector: '.jp-Notebook',
- rank: 5
- });
- app.contextMenu.addItem({
- command: CommandIDs.redoCellAction,
- selector: '.jp-Notebook',
- rank: 6
- });
- app.contextMenu.addItem({
- command: CommandIDs.restart,
- selector: '.jp-Notebook',
- rank: 7
- });
- app.contextMenu.addItem({
- type: 'separator',
- selector: '.jp-Notebook',
- rank: 8
- });
- app.contextMenu.addItem({
- command: CommandIDs.createConsole,
- selector: '.jp-Notebook',
- rank: 9
- });
- return tracker;
- }
- // Get the current widget and activate unless the args specify otherwise.
- function getCurrent(
- tracker: INotebookTracker,
- shell: JupyterFrontEnd.IShell,
- args: ReadonlyPartialJSONObject
- ): NotebookPanel | null {
- const widget = tracker.currentWidget;
- const activate = args['activate'] !== false;
- if (activate && widget) {
- shell.activateById(widget.id);
- }
- return widget;
- }
- /**
- * Add the notebook commands to the application's command registry.
- */
- function addCommands(
- app: JupyterFrontEnd,
- tracker: NotebookTracker,
- translator: ITranslator,
- sessionDialogs: ISessionContextDialogs | null
- ): void {
- const trans = translator.load('jupyterlab');
- const { commands, shell } = app;
- sessionDialogs = sessionDialogs ?? sessionContextDialogs;
- const isEnabled = (): boolean => {
- return Private.isEnabled(shell, tracker);
- };
- const isEnabledAndSingleSelected = (): boolean => {
- return Private.isEnabledAndSingleSelected(shell, tracker);
- };
- const refreshCellCollapsed = (notebook: Notebook): void => {
- for (const cell of notebook.widgets) {
- if (cell instanceof MarkdownCell && cell.headingCollapsed) {
- NotebookActions.setHeadingCollapse(cell, true, notebook);
- NotebookActions.expandParent(cell, notebook);
- }
- }
- };
- const isEnabledAndHeadingSelected = (): boolean => {
- return Private.isEnabledAndHeadingSelected(shell, tracker);
- };
- // Set up collapse signal for each header cell in a notebook
- tracker.currentChanged.connect(
- (sender: INotebookTracker, panel: NotebookPanel) => {
- panel.content.model?.cells.changed.connect(
- (
- list: IObservableUndoableList<ICellModel>,
- args: IObservableList.IChangedArgs<ICellModel>
- ) => {
- const cell = panel.content.widgets[args.newIndex];
- if (
- cell instanceof MarkdownCell &&
- (args.type === 'add' || args.type === 'set')
- ) {
- cell.toggleCollapsedSignal.connect(
- (newCell: MarkdownCell, collapsing: boolean) => {
- NotebookActions.setHeadingCollapse(
- newCell,
- collapsing,
- panel.content
- );
- }
- );
- }
- // Might be overkill to refresh this every time, but
- // it helps to keep the collapse state consistent.
- refreshCellCollapsed(panel.content);
- }
- );
- panel.content.activeCellChanged.connect(
- (notebook: Notebook, cell: Cell) => {
- NotebookActions.expandParent(cell, notebook);
- }
- );
- }
- );
- commands.addCommand(CommandIDs.runAndAdvance, {
- label: trans.__('Run Selected Cells'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- const { context, content } = current;
- return NotebookActions.runAndAdvance(content, context.sessionContext);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.run, {
- label: trans.__("Run Selected Cells and Don't Advance"),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- const { context, content } = current;
- return NotebookActions.run(content, context.sessionContext);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.runAndInsert, {
- label: trans.__('Run Selected Cells and Insert Below'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- const { context, content } = current;
- return NotebookActions.runAndInsert(content, context.sessionContext);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.runAll, {
- label: trans.__('Run All Cells'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- const { context, content } = current;
- return NotebookActions.runAll(content, context.sessionContext);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.runAllAbove, {
- label: trans.__('Run All Above Selected Cell'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- const { context, content } = current;
- return NotebookActions.runAllAbove(content, context.sessionContext);
- }
- },
- isEnabled: () => {
- // Can't run above if there are multiple cells selected,
- // or if we are at the top of the notebook.
- return (
- isEnabledAndSingleSelected() &&
- tracker.currentWidget!.content.activeCellIndex !== 0
- );
- }
- });
- commands.addCommand(CommandIDs.runAllBelow, {
- label: trans.__('Run Selected Cell and All Below'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- const { context, content } = current;
- return NotebookActions.runAllBelow(content, context.sessionContext);
- }
- },
- isEnabled: () => {
- // Can't run below if there are multiple cells selected,
- // or if we are at the bottom of the notebook.
- return (
- isEnabledAndSingleSelected() &&
- tracker.currentWidget!.content.activeCellIndex !==
- tracker.currentWidget!.content.widgets.length - 1
- );
- }
- });
- commands.addCommand(CommandIDs.renderAllMarkdown, {
- label: trans.__('Render All Markdown Cells'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- const { context, content } = current;
- return NotebookActions.renderAllMarkdown(
- content,
- context.sessionContext
- );
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.restart, {
- label: trans.__('Restart Kernel…'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return sessionDialogs!.restart(current.sessionContext, translator);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.closeAndShutdown, {
- label: trans.__('Close and Shut Down'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (!current) {
- return;
- }
- const fileName = current.title.label;
- return showDialog({
- title: trans.__('Shut down the notebook?'),
- body: trans.__('Are you sure you want to close "%1"?', fileName),
- buttons: [Dialog.cancelButton(), Dialog.warnButton()]
- }).then(result => {
- if (result.button.accept) {
- return current.context.sessionContext.shutdown().then(() => {
- current.dispose();
- });
- }
- });
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.trust, {
- label: () => trans.__('Trust Notebook'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- const { context, content } = current;
- return NotebookActions.trust(content).then(() => context.save());
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.restartClear, {
- label: trans.__('Restart Kernel and Clear All Outputs…'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- const { content, sessionContext } = current;
- return sessionDialogs!.restart(sessionContext, translator).then(() => {
- NotebookActions.clearAllOutputs(content);
- });
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.restartAndRunToSelected, {
- label: trans.__('Restart Kernel and Run up to Selected Cell…'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- const { context, content } = current;
- return sessionDialogs!
- .restart(current.sessionContext, translator)
- .then(restarted => {
- if (restarted) {
- void NotebookActions.runAllAbove(
- content,
- context.sessionContext
- ).then(executed => {
- if (executed || content.activeCellIndex === 0) {
- void NotebookActions.run(content, context.sessionContext);
- }
- });
- }
- });
- }
- },
- isEnabled: isEnabledAndSingleSelected
- });
- commands.addCommand(CommandIDs.restartRunAll, {
- label: trans.__('Restart Kernel and Run All Cells…'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- const { context, content, sessionContext } = current;
- return sessionDialogs!
- .restart(sessionContext, translator)
- .then(restarted => {
- if (restarted) {
- void NotebookActions.runAll(content, context.sessionContext);
- }
- return restarted;
- });
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.clearAllOutputs, {
- label: trans.__('Clear All Outputs'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.clearAllOutputs(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.clearOutputs, {
- label: trans.__('Clear Outputs'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.clearOutputs(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.interrupt, {
- label: trans.__('Interrupt Kernel'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (!current) {
- return;
- }
- const kernel = current.context.sessionContext.session?.kernel;
- if (kernel) {
- return kernel.interrupt();
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.toCode, {
- label: trans.__('Change to Code Cell Type'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.changeCellType(current.content, 'code');
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.toMarkdown, {
- label: trans.__('Change to Markdown Cell Type'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.changeCellType(current.content, 'markdown');
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.toRaw, {
- label: trans.__('Change to Raw Cell Type'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.changeCellType(current.content, 'raw');
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.cut, {
- label: trans.__('Cut Cells'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.cut(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.copy, {
- label: trans.__('Copy Cells'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.copy(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.pasteBelow, {
- label: trans.__('Paste Cells Below'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.paste(current.content, 'below');
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.pasteAbove, {
- label: trans.__('Paste Cells Above'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.paste(current.content, 'above');
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.pasteAndReplace, {
- label: trans.__('Paste Cells and Replace'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.paste(current.content, 'replace');
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.deleteCell, {
- label: trans.__('Delete Cells'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.deleteCells(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.split, {
- label: trans.__('Split Cell'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.splitCell(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.merge, {
- label: trans.__('Merge Selected Cells'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.mergeCells(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.mergeAbove, {
- label: trans.__('Merge Cell Above'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.mergeCells(current.content, true);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.mergeBelow, {
- label: trans.__('Merge Cell Below'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.mergeCells(current.content, false);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.insertAbove, {
- label: trans.__('Insert Cell Above'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.insertAbove(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.insertBelow, {
- label: trans.__('Insert Cell Below'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.insertBelow(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.selectAbove, {
- label: trans.__('Select Cell Above'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.selectAbove(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.selectBelow, {
- label: trans.__('Select Cell Below'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.selectBelow(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.extendAbove, {
- label: trans.__('Extend Selection Above'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.extendSelectionAbove(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.extendTop, {
- label: trans.__('Extend Selection to Top'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.extendSelectionAbove(current.content, true);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.extendBelow, {
- label: trans.__('Extend Selection Below'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.extendSelectionBelow(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.extendBottom, {
- label: trans.__('Extend Selection to Bottom'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.extendSelectionBelow(current.content, true);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.selectAll, {
- label: trans.__('Select All Cells'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.selectAll(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.deselectAll, {
- label: trans.__('Deselect All Cells'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.deselectAll(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.moveUp, {
- label: trans.__('Move Cells Up'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.moveUp(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.moveDown, {
- label: trans.__('Move Cells Down'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.moveDown(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.toggleAllLines, {
- label: trans.__('Toggle All Line Numbers'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.toggleAllLineNumbers(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.commandMode, {
- label: trans.__('Enter Command Mode'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- current.content.mode = 'command';
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.editMode, {
- label: trans.__('Enter Edit Mode'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- current.content.mode = 'edit';
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.undoCellAction, {
- label: trans.__('Undo Cell Operation'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.undo(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.redoCellAction, {
- label: trans.__('Redo Cell Operation'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.redo(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.changeKernel, {
- label: trans.__('Change Kernel…'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return sessionDialogs!.selectKernel(
- current.context.sessionContext,
- translator
- );
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.reconnectToKernel, {
- label: trans.__('Reconnect To Kernel'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (!current) {
- return;
- }
- const kernel = current.context.sessionContext.session?.kernel;
- if (kernel) {
- return kernel.reconnect();
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.markdown1, {
- label: trans.__('Change to Heading 1'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.setMarkdownHeader(current.content, 1);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.markdown2, {
- label: trans.__('Change to Heading 2'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.setMarkdownHeader(current.content, 2);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.markdown3, {
- label: trans.__('Change to Heading 3'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.setMarkdownHeader(current.content, 3);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.markdown4, {
- label: trans.__('Change to Heading 4'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.setMarkdownHeader(current.content, 4);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.markdown5, {
- label: trans.__('Change to Heading 5'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.setMarkdownHeader(current.content, 5);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.markdown6, {
- label: trans.__('Change to Heading 6'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.setMarkdownHeader(current.content, 6);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.hideCode, {
- label: trans.__('Collapse Selected Code'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.hideCode(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.showCode, {
- label: trans.__('Expand Selected Code'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.showCode(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.hideAllCode, {
- label: trans.__('Collapse All Code'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.hideAllCode(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.showAllCode, {
- label: trans.__('Expand All Code'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.showAllCode(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.hideOutput, {
- label: trans.__('Collapse Selected Outputs'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.hideOutput(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.showOutput, {
- label: trans.__('Expand Selected Outputs'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.showOutput(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.hideAllOutputs, {
- label: trans.__('Collapse All Outputs'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.hideAllOutputs(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.showAllOutputs, {
- label: trans.__('Expand All Outputs'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.showAllOutputs(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.enableOutputScrolling, {
- label: trans.__('Enable Scrolling for Outputs'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.enableOutputScrolling(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.disableOutputScrolling, {
- label: trans.__('Disable Scrolling for Outputs'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.disableOutputScrolling(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.selectLastRunCell, {
- label: trans.__('Select current running or last run cell'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.selectLastRunCell(current.content);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.replaceSelection, {
- label: trans.__('Replace Selection in Notebook Cell'),
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- const text: string = (args['text'] as string) || '';
- if (current) {
- return NotebookActions.replaceSelection(current.content, text);
- }
- },
- isEnabled
- });
- commands.addCommand(CommandIDs.toggleCollapseCmd, {
- label: 'Toggle Collapse Notebook Heading',
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.toggleCurrentHeadingCollapse(current.content);
- }
- },
- isEnabled: isEnabledAndHeadingSelected
- });
- commands.addCommand(CommandIDs.collapseAllCmd, {
- label: 'Collapse All Cells',
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.collapseAll(current.content);
- }
- }
- });
- commands.addCommand(CommandIDs.expandAllCmd, {
- label: 'Expand All Headings',
- execute: args => {
- const current = getCurrent(tracker, shell, args);
- if (current) {
- return NotebookActions.expandAllHeadings(current.content);
- }
- }
- });
- }
- /**
- * Populate the application's command palette with notebook commands.
- */
- function populatePalette(
- palette: ICommandPalette,
- translator: ITranslator
- ): void {
- const trans = translator.load('jupyterlab');
- let category = trans.__('Notebook Operations');
- [
- CommandIDs.interrupt,
- CommandIDs.restart,
- CommandIDs.restartClear,
- CommandIDs.restartRunAll,
- CommandIDs.runAll,
- CommandIDs.renderAllMarkdown,
- CommandIDs.runAllAbove,
- CommandIDs.runAllBelow,
- CommandIDs.restartAndRunToSelected,
- CommandIDs.selectAll,
- CommandIDs.deselectAll,
- CommandIDs.clearAllOutputs,
- CommandIDs.toggleAllLines,
- CommandIDs.editMode,
- CommandIDs.commandMode,
- CommandIDs.changeKernel,
- CommandIDs.reconnectToKernel,
- CommandIDs.createConsole,
- CommandIDs.closeAndShutdown,
- CommandIDs.trust,
- CommandIDs.toggleCollapseCmd,
- CommandIDs.collapseAllCmd,
- CommandIDs.expandAllCmd
- ].forEach(command => {
- palette.addItem({ command, category });
- });
- palette.addItem({
- command: CommandIDs.createNew,
- category,
- args: { isPalette: true }
- });
- category = trans.__('Notebook Cell Operations');
- [
- CommandIDs.run,
- CommandIDs.runAndAdvance,
- CommandIDs.runAndInsert,
- CommandIDs.runInConsole,
- CommandIDs.clearOutputs,
- CommandIDs.toCode,
- CommandIDs.toMarkdown,
- CommandIDs.toRaw,
- CommandIDs.cut,
- CommandIDs.copy,
- CommandIDs.pasteBelow,
- CommandIDs.pasteAbove,
- CommandIDs.pasteAndReplace,
- CommandIDs.deleteCell,
- CommandIDs.split,
- CommandIDs.merge,
- CommandIDs.mergeAbove,
- CommandIDs.mergeBelow,
- CommandIDs.insertAbove,
- CommandIDs.insertBelow,
- CommandIDs.selectAbove,
- CommandIDs.selectBelow,
- CommandIDs.extendAbove,
- CommandIDs.extendTop,
- CommandIDs.extendBelow,
- CommandIDs.extendBottom,
- CommandIDs.moveDown,
- CommandIDs.moveUp,
- CommandIDs.undoCellAction,
- CommandIDs.redoCellAction,
- CommandIDs.markdown1,
- CommandIDs.markdown2,
- CommandIDs.markdown3,
- CommandIDs.markdown4,
- CommandIDs.markdown5,
- CommandIDs.markdown6,
- CommandIDs.hideCode,
- CommandIDs.showCode,
- CommandIDs.hideAllCode,
- CommandIDs.showAllCode,
- CommandIDs.hideOutput,
- CommandIDs.showOutput,
- CommandIDs.hideAllOutputs,
- CommandIDs.showAllOutputs,
- CommandIDs.enableOutputScrolling,
- CommandIDs.disableOutputScrolling
- ].forEach(command => {
- palette.addItem({ command, category });
- });
- }
- /**
- * Populates the application menus for the notebook.
- */
- function populateMenus(
- app: JupyterFrontEnd,
- mainMenu: IMainMenu,
- tracker: INotebookTracker,
- translator: ITranslator,
- sessionDialogs: ISessionContextDialogs | null
- ): void {
- const trans = translator.load('jupyterlab');
- const { commands } = app;
- sessionDialogs = sessionDialogs || sessionContextDialogs;
- // Add undo/redo hooks to the edit menu.
- mainMenu.editMenu.undoers.add({
- tracker,
- undo: widget => {
- widget.content.activeCell?.editor.undo();
- },
- redo: widget => {
- widget.content.activeCell?.editor.redo();
- }
- } as IEditMenu.IUndoer<NotebookPanel>);
- // Add a clearer to the edit menu
- mainMenu.editMenu.clearers.add({
- tracker,
- clearCurrentLabel: (n: number) => trans.__('Clear Output'),
- clearAllLabel: (n: number) => {
- return trans.__('Clear All Outputs');
- },
- clearCurrent: (current: NotebookPanel) => {
- return NotebookActions.clearOutputs(current.content);
- },
- clearAll: (current: NotebookPanel) => {
- return NotebookActions.clearAllOutputs(current.content);
- }
- } as IEditMenu.IClearer<NotebookPanel>);
- // Add a close and shutdown command to the file menu.
- mainMenu.fileMenu.closeAndCleaners.add({
- tracker,
- closeAndCleanupLabel: (n: number) =>
- trans.__('Close and Shutdown Notebook'),
- closeAndCleanup: (current: NotebookPanel) => {
- const fileName = current.title.label;
- return showDialog({
- title: trans.__('Shut down the Notebook?'),
- body: trans.__('Are you sure you want to close "%1"?', fileName),
- buttons: [Dialog.cancelButton(), Dialog.warnButton()]
- }).then(result => {
- if (result.button.accept) {
- return current.context.sessionContext.shutdown().then(() => {
- current.dispose();
- });
- }
- });
- }
- } as IFileMenu.ICloseAndCleaner<NotebookPanel>);
- // Add a kernel user to the Kernel menu
- mainMenu.kernelMenu.kernelUsers.add({
- tracker,
- interruptKernel: current => {
- const kernel = current.sessionContext.session?.kernel;
- if (kernel) {
- return kernel.interrupt();
- }
- return Promise.resolve(void 0);
- },
- reconnectToKernel: current => {
- const kernel = current.sessionContext.session?.kernel;
- if (kernel) {
- return kernel.reconnect();
- }
- return Promise.resolve(void 0);
- },
- restartKernelAndClearLabel: (n: number) =>
- trans.__('Restart Kernel and Clear All Outputs…'),
- restartKernel: current =>
- sessionDialogs!.restart(current.sessionContext, translator),
- restartKernelAndClear: current => {
- return sessionDialogs!
- .restart(current.sessionContext, translator)
- .then(restarted => {
- if (restarted) {
- NotebookActions.clearAllOutputs(current.content);
- }
- return restarted;
- });
- },
- changeKernel: current =>
- sessionDialogs!.selectKernel(current.sessionContext, translator),
- shutdownKernel: current => current.sessionContext.shutdown()
- } as IKernelMenu.IKernelUser<NotebookPanel>);
- // Add a console creator the the Kernel menu
- mainMenu.fileMenu.consoleCreators.add({
- tracker,
- createConsoleLabel: (n: number) => trans.__('New Console for Notebook'),
- createConsole: current => Private.createConsole(commands, current, true)
- } as IFileMenu.IConsoleCreator<NotebookPanel>);
- // Add an IEditorViewer to the application view menu
- mainMenu.viewMenu.editorViewers.add({
- tracker,
- toggleLineNumbers: widget => {
- NotebookActions.toggleAllLineNumbers(widget.content);
- },
- lineNumbersToggled: widget => {
- const config = widget.content.editorConfig;
- return !!(
- config.code.lineNumbers &&
- config.markdown.lineNumbers &&
- config.raw.lineNumbers
- );
- }
- } as IViewMenu.IEditorViewer<NotebookPanel>);
- // Add an ICodeRunner to the application run menu
- mainMenu.runMenu.codeRunners.add({
- tracker,
- runLabel: (n: number) => trans.__('Run Selected Cells'),
- runAllLabel: (n: number) => trans.__('Run All Cells'),
- restartAndRunAllLabel: (n: number) =>
- trans.__('Restart Kernel and Run All Cells…'),
- run: current => {
- const { context, content } = current;
- return NotebookActions.runAndAdvance(
- content,
- context.sessionContext
- ).then(() => void 0);
- },
- runAll: current => {
- const { context, content } = current;
- return NotebookActions.runAll(content, context.sessionContext).then(
- () => void 0
- );
- },
- restartAndRunAll: current => {
- const { context, content } = current;
- return sessionDialogs!
- .restart(context.sessionContext, translator)
- .then(restarted => {
- if (restarted) {
- void NotebookActions.runAll(content, context.sessionContext);
- }
- return restarted;
- });
- }
- } as IRunMenu.ICodeRunner<NotebookPanel>);
- // Add kernel information to the application help menu.
- mainMenu.helpMenu.kernelUsers.add({
- tracker,
- getKernel: current => current.sessionContext.session?.kernel
- } as IHelpMenu.IKernelUser<NotebookPanel>);
- }
- /**
- * A namespace for module private functionality.
- */
- namespace Private {
- /**
- * Create a console connected with a notebook kernel
- *
- * @param commands Commands registry
- * @param widget Notebook panel
- * @param activate Should the console be activated
- */
- export function createConsole(
- commands: CommandRegistry,
- widget: NotebookPanel,
- activate?: boolean
- ): Promise<void> {
- const options = {
- path: widget.context.path,
- preferredLanguage: widget.context.model.defaultKernelLanguage,
- activate: activate,
- ref: widget.id,
- insertMode: 'split-bottom'
- };
- return commands.execute('console:create', options);
- }
- /**
- * Whether there is an active notebook.
- */
- export function isEnabled(
- shell: JupyterFrontEnd.IShell,
- tracker: INotebookTracker
- ): boolean {
- return (
- tracker.currentWidget !== null &&
- tracker.currentWidget === shell.currentWidget
- );
- }
- /**
- * Whether there is an notebook active, with a single selected cell.
- */
- export function isEnabledAndSingleSelected(
- shell: JupyterFrontEnd.IShell,
- tracker: INotebookTracker
- ): boolean {
- if (!Private.isEnabled(shell, tracker)) {
- return false;
- }
- const { content } = tracker.currentWidget!;
- const index = content.activeCellIndex;
- // If there are selections that are not the active cell,
- // this command is confusing, so disable it.
- for (let i = 0; i < content.widgets.length; ++i) {
- if (content.isSelected(content.widgets[i]) && i !== index) {
- return false;
- }
- }
- return true;
- }
- /**
- * Whether there is an notebook active, with a single selected cell.
- */
- export function isEnabledAndHeadingSelected(
- shell: JupyterFrontEnd.IShell,
- tracker: INotebookTracker
- ): boolean {
- if (!Private.isEnabled(shell, tracker)) {
- return false;
- }
- const { content } = tracker.currentWidget!;
- const index = content.activeCellIndex;
- if (!(content.activeCell instanceof MarkdownCell)) {
- return false;
- }
- // If there are selections that are not the active cell,
- // this command is confusing, so disable it.
- for (let i = 0; i < content.widgets.length; ++i) {
- if (content.isSelected(content.widgets[i]) && i !== index) {
- return false;
- }
- }
- return true;
- }
- /**
- * The default Export To ... formats and their human readable labels.
- */
- export function getFormatLabels(
- translator: ITranslator
- ): { [k: string]: string } {
- translator = translator || nullTranslator;
- const trans = translator.load('jupyterlab');
- return {
- html: trans.__('HTML'),
- latex: trans.__('LaTeX'),
- markdown: trans.__('Markdown'),
- pdf: trans.__('PDF'),
- rst: trans.__('ReStructured Text'),
- script: trans.__('Executable Script'),
- slides: trans.__('Reveal.js Slides')
- };
- }
- /**
- * A widget hosting a cloned output area.
- */
- export class ClonedOutputArea extends Panel {
- constructor(options: ClonedOutputArea.IOptions) {
- super();
- const trans = (options.translator || nullTranslator).load('jupyterlab');
- this._notebook = options.notebook;
- this._index = options.index !== undefined ? options.index : -1;
- this._cell = options.cell || null;
- this.id = `LinkedOutputView-${UUID.uuid4()}`;
- this.title.label = 'Output View';
- this.title.icon = notebookIcon;
- this.title.caption = this._notebook.title.label
- ? trans.__('For Notebook: %1', this._notebook.title.label)
- : trans.__('For Notebook:');
- this.addClass('jp-LinkedOutputView');
- // Wait for the notebook to be loaded before
- // cloning the output area.
- void this._notebook.context.ready.then(() => {
- if (!this._cell) {
- this._cell = this._notebook.content.widgets[this._index] as CodeCell;
- }
- if (!this._cell || this._cell.model.type !== 'code') {
- this.dispose();
- return;
- }
- const clone = this._cell.cloneOutputArea();
- this.addWidget(clone);
- });
- }
- /**
- * The index of the cell in the notebook.
- */
- get index(): number {
- return this._cell
- ? ArrayExt.findFirstIndex(
- this._notebook.content.widgets,
- c => c === this._cell
- )
- : this._index;
- }
- /**
- * The path of the notebook for the cloned output area.
- */
- get path(): string {
- return this._notebook.context.path;
- }
- private _notebook: NotebookPanel;
- private _index: number;
- private _cell: CodeCell | null = null;
- }
- /**
- * ClonedOutputArea statics.
- */
- export namespace ClonedOutputArea {
- export interface IOptions {
- /**
- * The notebook associated with the cloned output area.
- */
- notebook: NotebookPanel;
- /**
- * The cell for which to clone the output area.
- */
- cell?: CodeCell;
- /**
- * If the cell is not available, provide the index
- * of the cell for when the notebook is loaded.
- */
- index?: number;
- /**
- * If the cell is not available, provide the index
- * of the cell for when the notebook is loaded.
- */
- translator?: ITranslator;
- }
- }
- }
|