diff --git a/packages/application-extension/schema/shortcuts.json b/packages/application-extension/schema/shortcuts.json new file mode 100644 index 0000000000..ee5c51cb77 --- /dev/null +++ b/packages/application-extension/schema/shortcuts.json @@ -0,0 +1,16 @@ +{ + "jupyter.lab.setting-icon": "notebook-ui-components:jupyter", + "jupyter.lab.setting-icon-label": "Jupyter Notebook shortcuts", + "title": "Jupyter Notebook Shortcuts", + "description": "Keyboard shortcuts for Jupyter Notebook", + "jupyter.lab.shortcuts": [ + { + "args": {}, + "command": "notebook:toggle-cell-outputs", + "keys": ["O"], + "selector": ".jp-Notebook.jp-mod-commandMode" + } + ], + "additionalProperties": false, + "type": "object" +} diff --git a/packages/application-extension/src/index.ts b/packages/application-extension/src/index.ts index 6a6c432330..39ab42862f 100644 --- a/packages/application-extension/src/index.ts +++ b/packages/application-extension/src/index.ts @@ -996,6 +996,20 @@ const sidePanelVisibility: JupyterFrontEndPlugin = { }, }; +/** + * A plugin for defining keyboard shortcuts specific to the notebook application. + */ +const shortcuts: JupyterFrontEndPlugin = { + id: '@jupyter-notebook/application-extension:shortcuts', + description: + 'A plugin for defining keyboard shortcuts specific to the notebook application.', + autoStart: true, + activate: (app: JupyterFrontEnd) => { + // for now this plugin is mostly useful for defining keyboard shortcuts + // specific to the notebook application + }, +}; + /** * The default tree route resolver plugin. */ @@ -1175,6 +1189,7 @@ const plugins: JupyterFrontEndPlugin[] = [ rendermime, shell, sidePanelVisibility, + shortcuts, splash, status, tabTitle, diff --git a/ui-tests/test/notebook.spec.ts b/ui-tests/test/notebook.spec.ts index 9ecab41844..de1223ca61 100644 --- a/ui-tests/test/notebook.spec.ts +++ b/ui-tests/test/notebook.spec.ts @@ -223,4 +223,31 @@ test.describe('Notebook', () => { await expect(page.locator('.jp-LogConsole')).toBeVisible(); }); + + test('Toggle cell outputs with the O keyboard shortcut', async ({ + page, + tmpPath, + }) => { + const notebook = 'autoscroll.ipynb'; + await page.contents.uploadFile( + path.resolve(__dirname, `./notebooks/${notebook}`), + `${tmpPath}/${notebook}` + ); + await page.goto(`notebooks/${tmpPath}/${notebook}`); + + await waitForKernelReady(page); + + // run the two cells + await page.keyboard.press('Shift+Enter'); + await page.keyboard.press('ControlOrMeta+Enter'); + + await page.keyboard.press('Escape'); + await page.keyboard.press('O'); + + await page.waitForSelector('.jp-OutputPlaceholder', { state: 'visible' }); + + await page.keyboard.press('O'); + + await page.waitForSelector('.jp-OutputPlaceholder', { state: 'hidden' }); + }); });