Skip to content

Commit

Permalink
Added Keybindings to notebook editor (#13497)
Browse files Browse the repository at this point in the history
* Fixed context keys for notebook editor contexts
    this makes commands from jupyter available

Signed-off-by: Jonah Iden <jonah.iden@typefox.io>

* smaller fix and removed unnecessary change

Signed-off-by: Jonah Iden <jonah.iden@typefox.io>

* fixed build

Signed-off-by: Jonah Iden <jonah.iden@typefox.io>

* review comments

Signed-off-by: Jonah Iden <jonah.iden@typefox.io>

* fixed context key management for notebook main toolbar

Signed-off-by: Jonah Iden <jonah.iden@typefox.io>

* refactored notebook context key management

Signed-off-by: Jonah Iden <jonah.iden@typefox.io>

* contextKey scope refactor and markdown close editor keybinding

Signed-off-by: Jonah Iden <jonah.iden@typefox.io>

* more keybindings

Signed-off-by: Jonah Iden <jonah.iden@typefox.io>

* added insert cell commands

Signed-off-by: Jonah Iden <jonah.iden@typefox.io>

* smaller fixes, refactoring, changing cell type command

Signed-off-by: Jonah Iden <jonah.iden@typefox.io>

* review changes

remove unused inject

* remove unneccessary import

Signed-off-by: Jonah Iden <jonah.iden@typefox.io>

* update cell context when selecte cell has been replaced

Signed-off-by: Jonah Iden <jonah.iden@typefox.io>

---------

Signed-off-by: Jonah Iden <jonah.iden@typefox.io>
  • Loading branch information
jonah-iden authored Mar 19, 2024
1 parent d76ec39 commit 3e16157
Show file tree
Hide file tree
Showing 18 changed files with 392 additions and 165 deletions.
3 changes: 3 additions & 0 deletions packages/core/src/browser/keybinding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,9 @@ export class KeybindingRegistry {

isEnabledInScope(binding: common.Keybinding, target: HTMLElement | undefined): boolean {
const context = binding.context && this.contexts[binding.context];
if (binding.command && !this.commandRegistry.isEnabled(binding.command, binding.args)) {
return false;
}
if (context && !context.isEnabled(binding)) {
return false;
}
Expand Down
1 change: 1 addition & 0 deletions packages/notebook/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"@theia/editor": "1.47.0",
"@theia/filesystem": "1.47.0",
"@theia/monaco": "1.47.0",
"@theia/monaco-editor-core": "1.83.101",
"react-perfect-scrollbar": "^1.5.8",
"tslib": "^2.6.2"
},
Expand Down
38 changes: 38 additions & 0 deletions packages/notebook/src/browser/contributions/cell-operations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// *****************************************************************************
// Copyright (C) 2023 TypeFox and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************

import { CellEditType, CellKind } from '../../common';
import { NotebookCellModel } from '../view-model/notebook-cell-model';
import { NotebookModel } from '../view-model/notebook-model';

/**
* a collection of different reusable notbook cell operations
*/

export function changeCellType(notebookModel: NotebookModel, cell: NotebookCellModel, type: CellKind): void {
if (cell.cellKind === type) {
return;
}
notebookModel.applyEdits([{
editType: CellEditType.Replace,
index: notebookModel.cells.indexOf(cell),
count: 1,
cells: [{
...cell.getData(),
cellKind: type
}]
}], true);
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@

import { Command, CommandContribution, CommandHandler, CommandRegistry, CompoundMenuNodeRole, MenuContribution, MenuModelRegistry, nls } from '@theia/core';
import { inject, injectable } from '@theia/core/shared/inversify';
import { ApplicationShell, codicon, CommonCommands } from '@theia/core/lib/browser';
import { ApplicationShell, codicon, CommonCommands, KeybindingContribution, KeybindingRegistry } from '@theia/core/lib/browser';
import { NotebookModel } from '../view-model/notebook-model';
import { NotebookService } from '../service/notebook-service';
import { CellEditType, CellKind, NotebookCommand } from '../../common';
import { NotebookKernelQuickPickService } from '../service/notebook-kernel-quick-pick-service';
import { NotebookExecutionService } from '../service/notebook-execution-service';
import { NotebookEditorWidget } from '../notebook-editor-widget';
import { NotebookEditorWidgetService } from '../service/notebook-editor-widget-service';
import { NOTEBOOK_CELL_FOCUSED, NOTEBOOK_EDITOR_FOCUSED } from './notebook-context-keys';

export namespace NotebookCommands {
export const ADD_NEW_CELL_COMMAND = Command.toDefaultLocalizedCommand({
Expand Down Expand Up @@ -59,10 +61,20 @@ export namespace NotebookCommands {
category: 'Notebook',
iconClass: codicon('clear-all')
});

export const CHANGE_SELECTED_CELL = Command.toDefaultLocalizedCommand({
id: 'notebook.change-selected-cell',
category: 'Notebook',
});
}

export enum CellChangeDirection {
Up = 'up',
Down = 'down'
}

@injectable()
export class NotebookActionsContribution implements CommandContribution, MenuContribution {
export class NotebookActionsContribution implements CommandContribution, MenuContribution, KeybindingContribution {

@inject(NotebookService)
protected notebookService: NotebookService;
Expand All @@ -76,10 +88,22 @@ export class NotebookActionsContribution implements CommandContribution, MenuCon
@inject(ApplicationShell)
protected shell: ApplicationShell;

@inject(NotebookEditorWidgetService)
protected notebookEditorWidgetService: NotebookEditorWidgetService;

registerCommands(commands: CommandRegistry): void {
commands.registerCommand(NotebookCommands.ADD_NEW_CELL_COMMAND, {
execute: (notebookModel: NotebookModel, cellKind: CellKind, index?: number) => {
const insertIndex = index ?? (notebookModel.selectedCell ? notebookModel.cells.indexOf(notebookModel.selectedCell) : 0);
execute: (notebookModel: NotebookModel, cellKind: CellKind = CellKind.Markup, index?: number | 'above' | 'below') => {
notebookModel = notebookModel ?? this.notebookEditorWidgetService.focusedEditor?.model;

let insertIndex: number = 0;
if (index && index >= 0) {
insertIndex = index as number;
} else if (notebookModel.selectedCell && typeof index === 'string') {
// if index is -1 insert below otherwise at the index of the selected cell which is above the selected.
insertIndex = notebookModel.cells.indexOf(notebookModel.selectedCell) + (index === 'below' ? 1 : 0);
}

let firstCodeCell;
if (cellKind === CellKind.Code) {
firstCodeCell = notebookModel.cells.find(cell => cell.cellKind === CellKind.Code);
Expand All @@ -101,11 +125,11 @@ export class NotebookActionsContribution implements CommandContribution, MenuCon
});

commands.registerCommand(NotebookCommands.ADD_NEW_MARKDOWN_CELL_COMMAND, this.editableCommandHandler(
notebookModel => commands.executeCommand(NotebookCommands.ADD_NEW_CELL_COMMAND.id, notebookModel, CellKind.Markup)
notebookModel => commands.executeCommand(NotebookCommands.ADD_NEW_CELL_COMMAND.id, notebookModel, CellKind.Markup, 'below')
));

commands.registerCommand(NotebookCommands.ADD_NEW_CODE_CELL_COMMAND, this.editableCommandHandler(
notebookModel => commands.executeCommand(NotebookCommands.ADD_NEW_CELL_COMMAND.id, notebookModel, CellKind.Code)
notebookModel => commands.executeCommand(NotebookCommands.ADD_NEW_CELL_COMMAND.id, notebookModel, CellKind.Code, 'below')
));

commands.registerCommand(NotebookCommands.SELECT_KERNEL_COMMAND, this.editableCommandHandler(
Expand All @@ -120,6 +144,24 @@ export class NotebookActionsContribution implements CommandContribution, MenuCon
notebookModel => notebookModel.cells.forEach(cell => cell.spliceNotebookCellOutputs({ start: 0, deleteCount: cell.outputs.length, newOutputs: [] }))
));

commands.registerCommand(NotebookCommands.CHANGE_SELECTED_CELL,
{
execute: (change: number | CellChangeDirection) => {
const model = this.notebookEditorWidgetService.focusedEditor?.model;
if (model && typeof change === 'number') {
model.setSelectedCell(model.cells[change]);
} else if (model && model.selectedCell) {
const currentIndex = model.cells.indexOf(model.selectedCell);
if (change === CellChangeDirection.Up && currentIndex > 0) {
model.setSelectedCell(model.cells[currentIndex - 1]);
} else if (change === CellChangeDirection.Down && currentIndex < model.cells.length - 1) {
model.setSelectedCell(model.cells[currentIndex + 1]);
}
}
}
}
);

commands.registerHandler(CommonCommands.UNDO.id, {
isEnabled: () => {
const widget = this.shell.activeWidget;
Expand All @@ -134,6 +176,7 @@ export class NotebookActionsContribution implements CommandContribution, MenuCon
},
execute: () => (this.shell.activeWidget as NotebookEditorWidget).redo()
});

}

protected editableCommandHandler(execute: (notebookModel: NotebookModel) => void): CommandHandler {
Expand Down Expand Up @@ -179,6 +222,23 @@ export class NotebookActionsContribution implements CommandContribution, MenuCon
// other items
}

registerKeybindings(keybindings: KeybindingRegistry): void {
keybindings.registerKeybindings(
{
command: NotebookCommands.CHANGE_SELECTED_CELL.id,
keybinding: 'up',
args: CellChangeDirection.Up,
when: `!editorTextFocus && ${NOTEBOOK_EDITOR_FOCUSED} && ${NOTEBOOK_CELL_FOCUSED}`
},
{
command: NotebookCommands.CHANGE_SELECTED_CELL.id,
keybinding: 'down',
args: CellChangeDirection.Down,
when: `!editorTextFocus && ${NOTEBOOK_EDITOR_FOCUSED} && ${NOTEBOOK_CELL_FOCUSED}`
},
);
}

}

export namespace NotebookMenus {
Expand Down
Loading

0 comments on commit 3e16157

Please sign in to comment.