Path: blob/main/src/vs/workbench/contrib/notebook/browser/controller/insertCellActions.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { Codicon } from '../../../../../base/common/codicons.js';6import { KeyCode, KeyMod } from '../../../../../base/common/keyCodes.js';7import { ILanguageService } from '../../../../../editor/common/languages/language.js';8import { localize } from '../../../../../nls.js';9import { IAction2Options, MenuId, MenuRegistry, registerAction2 } from '../../../../../platform/actions/common/actions.js';10import { ContextKeyExpr } from '../../../../../platform/contextkey/common/contextkey.js';11import { InputFocusedContext } from '../../../../../platform/contextkey/common/contextkeys.js';12import { ServicesAccessor } from '../../../../../platform/instantiation/common/instantiation.js';13import { KeybindingWeight } from '../../../../../platform/keybinding/common/keybindingsRegistry.js';14import { insertCell } from './cellOperations.js';15import { INotebookActionContext, NotebookAction } from './coreActions.js';16import { NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_EDITOR_EDITABLE } from '../../common/notebookContextKeys.js';17import { CellViewModel } from '../viewModel/notebookViewModelImpl.js';18import { CellKind, NotebookSetting } from '../../common/notebookCommon.js';19import { CTX_NOTEBOOK_CHAT_OUTER_FOCUS_POSITION } from './chat/notebookChatContext.js';20import { INotebookKernelHistoryService } from '../../common/notebookKernelService.js';2122const INSERT_CODE_CELL_ABOVE_COMMAND_ID = 'notebook.cell.insertCodeCellAbove';23const INSERT_CODE_CELL_BELOW_COMMAND_ID = 'notebook.cell.insertCodeCellBelow';24const INSERT_CODE_CELL_ABOVE_AND_FOCUS_CONTAINER_COMMAND_ID = 'notebook.cell.insertCodeCellAboveAndFocusContainer';25const INSERT_CODE_CELL_BELOW_AND_FOCUS_CONTAINER_COMMAND_ID = 'notebook.cell.insertCodeCellBelowAndFocusContainer';26const INSERT_CODE_CELL_AT_TOP_COMMAND_ID = 'notebook.cell.insertCodeCellAtTop';27const INSERT_MARKDOWN_CELL_ABOVE_COMMAND_ID = 'notebook.cell.insertMarkdownCellAbove';28const INSERT_MARKDOWN_CELL_BELOW_COMMAND_ID = 'notebook.cell.insertMarkdownCellBelow';29const INSERT_MARKDOWN_CELL_AT_TOP_COMMAND_ID = 'notebook.cell.insertMarkdownCellAtTop';3031export function insertNewCell(accessor: ServicesAccessor, context: INotebookActionContext, kind: CellKind, direction: 'above' | 'below', focusEditor: boolean) {32let newCell: CellViewModel | null = null;33if (context.ui) {34context.notebookEditor.focus();35}3637const languageService = accessor.get(ILanguageService);38const kernelHistoryService = accessor.get(INotebookKernelHistoryService);3940if (context.cell) {41const idx = context.notebookEditor.getCellIndex(context.cell);42newCell = insertCell(languageService, context.notebookEditor, idx, kind, direction, undefined, true, kernelHistoryService);43} else {44const focusRange = context.notebookEditor.getFocus();45const next = Math.max(focusRange.end - 1, 0);46newCell = insertCell(languageService, context.notebookEditor, next, kind, direction, undefined, true, kernelHistoryService);47}4849return newCell;50}5152export abstract class InsertCellCommand extends NotebookAction {53constructor(54desc: Readonly<IAction2Options>,55private kind: CellKind,56private direction: 'above' | 'below',57private focusEditor: boolean58) {59super(desc);60}6162async runWithContext(accessor: ServicesAccessor, context: INotebookActionContext): Promise<void> {63const newCell = await insertNewCell(accessor, context, this.kind, this.direction, this.focusEditor);6465if (newCell) {66await context.notebookEditor.focusNotebookCell(newCell, this.focusEditor ? 'editor' : 'container');67}68}69}7071registerAction2(class InsertCodeCellAboveAction extends InsertCellCommand {72constructor() {73super(74{75id: INSERT_CODE_CELL_ABOVE_COMMAND_ID,76title: localize('notebookActions.insertCodeCellAbove', "Insert Code Cell Above"),77keybinding: {78primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Enter,79when: ContextKeyExpr.and(NOTEBOOK_CELL_LIST_FOCUSED, InputFocusedContext.toNegated()),80weight: KeybindingWeight.WorkbenchContrib81},82menu: {83id: MenuId.NotebookCellInsert,84order: 085}86},87CellKind.Code,88'above',89true);90}91});92939495registerAction2(class InsertCodeCellAboveAndFocusContainerAction extends InsertCellCommand {96constructor() {97super(98{99id: INSERT_CODE_CELL_ABOVE_AND_FOCUS_CONTAINER_COMMAND_ID,100title: localize('notebookActions.insertCodeCellAboveAndFocusContainer', "Insert Code Cell Above and Focus Container")101},102CellKind.Code,103'above',104false);105}106});107108registerAction2(class InsertCodeCellBelowAction extends InsertCellCommand {109constructor() {110super(111{112id: INSERT_CODE_CELL_BELOW_COMMAND_ID,113title: localize('notebookActions.insertCodeCellBelow', "Insert Code Cell Below"),114keybinding: {115primary: KeyMod.CtrlCmd | KeyCode.Enter,116when: ContextKeyExpr.and(NOTEBOOK_CELL_LIST_FOCUSED, InputFocusedContext.toNegated(), CTX_NOTEBOOK_CHAT_OUTER_FOCUS_POSITION.isEqualTo('')),117weight: KeybindingWeight.WorkbenchContrib118},119menu: {120id: MenuId.NotebookCellInsert,121order: 1122}123},124CellKind.Code,125'below',126true);127}128});129130registerAction2(class InsertCodeCellBelowAndFocusContainerAction extends InsertCellCommand {131constructor() {132super(133{134id: INSERT_CODE_CELL_BELOW_AND_FOCUS_CONTAINER_COMMAND_ID,135title: localize('notebookActions.insertCodeCellBelowAndFocusContainer', "Insert Code Cell Below and Focus Container"),136},137CellKind.Code,138'below',139false);140}141});142143144registerAction2(class InsertMarkdownCellAboveAction extends InsertCellCommand {145constructor() {146super(147{148id: INSERT_MARKDOWN_CELL_ABOVE_COMMAND_ID,149title: localize('notebookActions.insertMarkdownCellAbove', "Insert Markdown Cell Above"),150menu: {151id: MenuId.NotebookCellInsert,152order: 2153}154},155CellKind.Markup,156'above',157true);158}159});160161registerAction2(class InsertMarkdownCellBelowAction extends InsertCellCommand {162constructor() {163super(164{165id: INSERT_MARKDOWN_CELL_BELOW_COMMAND_ID,166title: localize('notebookActions.insertMarkdownCellBelow', "Insert Markdown Cell Below"),167menu: {168id: MenuId.NotebookCellInsert,169order: 3170}171},172CellKind.Markup,173'below',174true);175}176});177178179registerAction2(class InsertCodeCellAtTopAction extends NotebookAction {180constructor() {181super(182{183id: INSERT_CODE_CELL_AT_TOP_COMMAND_ID,184title: localize('notebookActions.insertCodeCellAtTop', "Add Code Cell At Top"),185f1: false186});187}188189override async run(accessor: ServicesAccessor, context?: INotebookActionContext): Promise<void> {190context = context ?? this.getEditorContextFromArgsOrActive(accessor);191if (context) {192this.runWithContext(accessor, context);193}194}195196async runWithContext(accessor: ServicesAccessor, context: INotebookActionContext): Promise<void> {197const languageService = accessor.get(ILanguageService);198const kernelHistoryService = accessor.get(INotebookKernelHistoryService);199const newCell = insertCell(languageService, context.notebookEditor, 0, CellKind.Code, 'above', undefined, true, kernelHistoryService);200201if (newCell) {202await context.notebookEditor.focusNotebookCell(newCell, 'editor');203}204}205});206207registerAction2(class InsertMarkdownCellAtTopAction extends NotebookAction {208constructor() {209super(210{211id: INSERT_MARKDOWN_CELL_AT_TOP_COMMAND_ID,212title: localize('notebookActions.insertMarkdownCellAtTop', "Add Markdown Cell At Top"),213f1: false214});215}216217override async run(accessor: ServicesAccessor, context?: INotebookActionContext): Promise<void> {218context = context ?? this.getEditorContextFromArgsOrActive(accessor);219if (context) {220this.runWithContext(accessor, context);221}222}223224async runWithContext(accessor: ServicesAccessor, context: INotebookActionContext): Promise<void> {225const languageService = accessor.get(ILanguageService);226const kernelHistoryService = accessor.get(INotebookKernelHistoryService);227228const newCell = insertCell(languageService, context.notebookEditor, 0, CellKind.Markup, 'above', undefined, true, kernelHistoryService);229230if (newCell) {231await context.notebookEditor.focusNotebookCell(newCell, 'editor');232}233}234});235236MenuRegistry.appendMenuItem(MenuId.NotebookCellBetween, {237command: {238id: INSERT_CODE_CELL_BELOW_COMMAND_ID,239title: '$(add) ' + localize('notebookActions.menu.insertCode', "Code"),240tooltip: localize('notebookActions.menu.insertCode.tooltip', "Add Code Cell")241},242order: 0,243group: 'inline',244when: ContextKeyExpr.and(245NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true),246ContextKeyExpr.notEquals('config.notebook.experimental.insertToolbarAlignment', 'left')247)248});249250MenuRegistry.appendMenuItem(MenuId.NotebookCellBetween, {251command: {252id: INSERT_CODE_CELL_BELOW_COMMAND_ID,253title: localize('notebookActions.menu.insertCode.minimalToolbar', "Add Code"),254icon: Codicon.add,255tooltip: localize('notebookActions.menu.insertCode.tooltip', "Add Code Cell")256},257order: 0,258group: 'inline',259when: ContextKeyExpr.and(260NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true),261ContextKeyExpr.equals('config.notebook.experimental.insertToolbarAlignment', 'left')262)263});264265MenuRegistry.appendMenuItem(MenuId.NotebookToolbar, {266command: {267id: INSERT_CODE_CELL_BELOW_COMMAND_ID,268icon: Codicon.add,269title: localize('notebookActions.menu.insertCode.ontoolbar', "Code"),270tooltip: localize('notebookActions.menu.insertCode.tooltip', "Add Code Cell")271},272order: -5,273group: 'navigation/add',274when: ContextKeyExpr.and(275NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true),276ContextKeyExpr.notEquals('config.notebook.insertToolbarLocation', 'betweenCells'),277ContextKeyExpr.notEquals('config.notebook.insertToolbarLocation', 'hidden')278)279});280281MenuRegistry.appendMenuItem(MenuId.NotebookCellListTop, {282command: {283id: INSERT_CODE_CELL_AT_TOP_COMMAND_ID,284title: '$(add) ' + localize('notebookActions.menu.insertCode', "Code"),285tooltip: localize('notebookActions.menu.insertCode.tooltip', "Add Code Cell")286},287order: 0,288group: 'inline',289when: ContextKeyExpr.and(290NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true),291ContextKeyExpr.notEquals('config.notebook.experimental.insertToolbarAlignment', 'left')292)293});294295MenuRegistry.appendMenuItem(MenuId.NotebookCellListTop, {296command: {297id: INSERT_CODE_CELL_AT_TOP_COMMAND_ID,298title: localize('notebookActions.menu.insertCode.minimaltoolbar', "Add Code"),299icon: Codicon.add,300tooltip: localize('notebookActions.menu.insertCode.tooltip', "Add Code Cell")301},302order: 0,303group: 'inline',304when: ContextKeyExpr.and(305NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true),306ContextKeyExpr.equals('config.notebook.experimental.insertToolbarAlignment', 'left')307)308});309310311MenuRegistry.appendMenuItem(MenuId.NotebookCellBetween, {312command: {313id: INSERT_MARKDOWN_CELL_BELOW_COMMAND_ID,314title: '$(add) ' + localize('notebookActions.menu.insertMarkdown', "Markdown"),315tooltip: localize('notebookActions.menu.insertMarkdown.tooltip', "Add Markdown Cell")316},317order: 1,318group: 'inline',319when: ContextKeyExpr.and(320NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true),321ContextKeyExpr.notEquals('config.notebook.experimental.insertToolbarAlignment', 'left')322)323});324325MenuRegistry.appendMenuItem(MenuId.NotebookToolbar, {326command: {327id: INSERT_MARKDOWN_CELL_BELOW_COMMAND_ID,328icon: Codicon.add,329title: localize('notebookActions.menu.insertMarkdown.ontoolbar', "Markdown"),330tooltip: localize('notebookActions.menu.insertMarkdown.tooltip', "Add Markdown Cell")331},332order: -5,333group: 'navigation/add',334when: ContextKeyExpr.and(335NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true),336ContextKeyExpr.notEquals('config.notebook.insertToolbarLocation', 'betweenCells'),337ContextKeyExpr.notEquals('config.notebook.insertToolbarLocation', 'hidden'),338ContextKeyExpr.notEquals(`config.${NotebookSetting.globalToolbarShowLabel}`, false),339ContextKeyExpr.notEquals(`config.${NotebookSetting.globalToolbarShowLabel}`, 'never')340)341});342343MenuRegistry.appendMenuItem(MenuId.NotebookCellListTop, {344command: {345id: INSERT_MARKDOWN_CELL_AT_TOP_COMMAND_ID,346title: '$(add) ' + localize('notebookActions.menu.insertMarkdown', "Markdown"),347tooltip: localize('notebookActions.menu.insertMarkdown.tooltip', "Add Markdown Cell")348},349order: 1,350group: 'inline',351when: ContextKeyExpr.and(352NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true),353ContextKeyExpr.notEquals('config.notebook.experimental.insertToolbarAlignment', 'left')354)355});356357358