Path: blob/main/src/vs/workbench/contrib/notebook/browser/controller/sectionActions.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 { localize, localize2 } from '../../../../../nls.js';6import { Action2, MenuId, registerAction2 } from '../../../../../platform/actions/common/actions.js';7import { ContextKeyExpr } from '../../../../../platform/contextkey/common/contextkey.js';8import { ServicesAccessor } from '../../../../../platform/instantiation/common/instantiation.js';9import { NotebookOutlineContext } from '../contrib/outline/notebookOutline.js';10import { FoldingController } from './foldingController.js';11import { CellEditState, CellFoldingState, ICellViewModel, INotebookEditor } from '../notebookBrowser.js';12import * as icons from '../notebookIcons.js';13import { OutlineEntry } from '../viewModel/OutlineEntry.js';14import { CellKind } from '../../common/notebookCommon.js';15import { OutlineTarget } from '../../../../services/outline/browser/outline.js';16import { CELL_TITLE_CELL_GROUP_ID, CellToolbarOrder } from './coreActions.js';17import { executeSectionCondition } from './executeActions.js';1819export type NotebookOutlineEntryArgs = {20notebookEditor: INotebookEditor;21outlineEntry: OutlineEntry;22};2324export type NotebookCellArgs = {25notebookEditor: INotebookEditor;26cell: ICellViewModel;27};2829export class NotebookRunSingleCellInSection extends Action2 {30constructor() {31super({32id: 'notebook.section.runSingleCell',33title: {34...localize2('runCell', "Run Cell"),35mnemonicTitle: localize({ key: 'mirunCell', comment: ['&& denotes a mnemonic'] }, "&&Run Cell"),36},37shortTitle: localize('runCell', "Run Cell"),38icon: icons.executeIcon,39menu: [40{41id: MenuId.NotebookOutlineActionMenu,42group: 'inline',43order: 1,44when: ContextKeyExpr.and(45NotebookOutlineContext.CellKind.isEqualTo(CellKind.Code),46NotebookOutlineContext.OutlineElementTarget.isEqualTo(OutlineTarget.OutlinePane),47NotebookOutlineContext.CellHasChildren.toNegated(),48NotebookOutlineContext.CellHasHeader.toNegated(),49)50}51]52});53}5455override async run(_accessor: ServicesAccessor, context: any): Promise<void> {56if (!checkOutlineEntryContext(context)) {57return;58}5960context.notebookEditor.executeNotebookCells([context.outlineEntry.cell]);61}62}6364export class NotebookRunCellsInSection extends Action2 {65constructor() {66super({67id: 'notebook.section.runCells',68title: {69...localize2('runCellsInSection', "Run Cells In Section"),70mnemonicTitle: localize({ key: 'mirunCellsInSection', comment: ['&& denotes a mnemonic'] }, "&&Run Cells In Section"),71},72shortTitle: localize('runCellsInSection', "Run Cells In Section"),73icon: icons.executeIcon, // TODO @Yoyokrazy replace this with new icon later74menu: [75{76id: MenuId.NotebookStickyScrollContext,77group: 'notebookExecution',78order: 179},80{81id: MenuId.NotebookOutlineActionMenu,82group: 'inline',83order: 1,84when: ContextKeyExpr.and(85NotebookOutlineContext.CellKind.isEqualTo(CellKind.Markup),86NotebookOutlineContext.OutlineElementTarget.isEqualTo(OutlineTarget.OutlinePane),87NotebookOutlineContext.CellHasChildren,88NotebookOutlineContext.CellHasHeader,89)90},91{92id: MenuId.NotebookCellTitle,93order: CellToolbarOrder.RunSection,94group: CELL_TITLE_CELL_GROUP_ID,95when: executeSectionCondition96}97]98});99}100101override async run(_accessor: ServicesAccessor, context: any): Promise<void> {102let cell: ICellViewModel;103if (checkOutlineEntryContext(context)) {104cell = context.outlineEntry.cell;105} else if (checkNotebookCellContext(context)) {106cell = context.cell;107} else {108return;109}110111if (cell.getEditState() === CellEditState.Editing) {112const foldingController = context.notebookEditor.getContribution<FoldingController>(FoldingController.id);113foldingController.recompute();114}115116const cellIdx = context.notebookEditor.getViewModel()?.getCellIndex(cell);117if (cellIdx === undefined) {118return;119}120const sectionIdx = context.notebookEditor.getViewModel()?.getFoldingStartIndex(cellIdx);121if (sectionIdx === undefined) {122return;123}124const length = context.notebookEditor.getViewModel()?.getFoldedLength(sectionIdx);125if (length === undefined) {126return;127}128129const cells = context.notebookEditor.getCellsInRange({ start: sectionIdx, end: sectionIdx + length + 1 });130context.notebookEditor.executeNotebookCells(cells);131}132}133134export class NotebookFoldSection extends Action2 {135constructor() {136super({137id: 'notebook.section.foldSection',138title: {139...localize2('foldSection', "Fold Section"),140mnemonicTitle: localize({ key: 'mifoldSection', comment: ['&& denotes a mnemonic'] }, "&&Fold Section"),141},142shortTitle: localize('foldSection', "Fold Section"),143menu: [144{145id: MenuId.NotebookOutlineActionMenu,146group: 'notebookFolding',147order: 2,148when: ContextKeyExpr.and(149NotebookOutlineContext.CellKind.isEqualTo(CellKind.Markup),150NotebookOutlineContext.OutlineElementTarget.isEqualTo(OutlineTarget.OutlinePane),151NotebookOutlineContext.CellHasChildren,152NotebookOutlineContext.CellHasHeader,153NotebookOutlineContext.CellFoldingState.isEqualTo(CellFoldingState.Expanded)154)155}156]157});158}159160override async run(_accessor: ServicesAccessor, context: any): Promise<void> {161if (!checkOutlineEntryContext(context)) {162return;163}164165this.toggleFoldRange(context.outlineEntry, context.notebookEditor);166}167168private toggleFoldRange(entry: OutlineEntry, notebookEditor: INotebookEditor) {169const foldingController = notebookEditor.getContribution<FoldingController>(FoldingController.id);170const index = entry.index;171const headerLevel = entry.level;172const newFoldingState = CellFoldingState.Collapsed;173174foldingController.setFoldingStateDown(index, newFoldingState, headerLevel);175}176}177178export class NotebookExpandSection extends Action2 {179constructor() {180super({181id: 'notebook.section.expandSection',182title: {183...localize2('expandSection', "Expand Section"),184mnemonicTitle: localize({ key: 'miexpandSection', comment: ['&& denotes a mnemonic'] }, "&&Expand Section"),185},186shortTitle: localize('expandSection', "Expand Section"),187menu: [188{189id: MenuId.NotebookOutlineActionMenu,190group: 'notebookFolding',191order: 2,192when: ContextKeyExpr.and(193NotebookOutlineContext.CellKind.isEqualTo(CellKind.Markup),194NotebookOutlineContext.OutlineElementTarget.isEqualTo(OutlineTarget.OutlinePane),195NotebookOutlineContext.CellHasChildren,196NotebookOutlineContext.CellHasHeader,197NotebookOutlineContext.CellFoldingState.isEqualTo(CellFoldingState.Collapsed)198)199}200]201});202}203204override async run(_accessor: ServicesAccessor, context: any): Promise<void> {205if (!checkOutlineEntryContext(context)) {206return;207}208209this.toggleFoldRange(context.outlineEntry, context.notebookEditor);210}211212private toggleFoldRange(entry: OutlineEntry, notebookEditor: INotebookEditor) {213const foldingController = notebookEditor.getContribution<FoldingController>(FoldingController.id);214const index = entry.index;215const headerLevel = entry.level;216const newFoldingState = CellFoldingState.Expanded;217218foldingController.setFoldingStateDown(index, newFoldingState, headerLevel);219}220}221222/**223* Take in context args and check if they exist. True if action is run from notebook sticky scroll context menu or224* notebook outline context menu.225*226* @param context - Notebook Outline Context containing a notebook editor and outline entry227* @returns true if context is valid, false otherwise228*/229function checkOutlineEntryContext(context: any): context is NotebookOutlineEntryArgs {230return !!(context && context.notebookEditor && context.outlineEntry);231}232233/**234* Take in context args and check if they exist. True if action is run from a cell toolbar menu (potentially from the235* notebook cell container or cell editor context menus, but not tested or implemented atm)236*237* @param context - Notebook Outline Context containing a notebook editor and outline entry238* @returns true if context is valid, false otherwise239*/240function checkNotebookCellContext(context: any): context is NotebookCellArgs {241return !!(context && context.notebookEditor && context.cell);242}243244registerAction2(NotebookRunSingleCellInSection);245registerAction2(NotebookRunCellsInSection);246registerAction2(NotebookFoldSection);247registerAction2(NotebookExpandSection);248249250