From d94c69f4104ec744c798a1f7092738b8a7b59b6b Mon Sep 17 00:00:00 2001 From: Michael Lively Date: Thu, 21 Nov 2024 14:43:47 -0800 Subject: [PATCH] Add markdown cell toolbar entry for run in section (#234387) * add markdown cell toolbar entry for run in section * remove unnecesasry context key and --- .../contrib/outline/notebookOutline.ts | 21 ++++--- .../browser/controller/coreActions.ts | 1 + .../browser/controller/executeActions.ts | 4 ++ .../browser/controller/sectionActions.ts | 60 +++++++++++++------ .../viewParts/notebookEditorStickyScroll.ts | 4 +- 5 files changed, 61 insertions(+), 29 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/outline/notebookOutline.ts b/src/vs/workbench/contrib/notebook/browser/contrib/outline/notebookOutline.ts index b0409762b8d90..7df78960c43d4 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/outline/notebookOutline.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/outline/notebookOutline.ts @@ -44,7 +44,7 @@ import { Action2, IMenu, IMenuService, MenuId, MenuItemAction, MenuRegistry, reg import { ContextKeyExpr, IContextKeyService, RawContextKey } from '../../../../../../platform/contextkey/common/contextkey.js'; import { MenuEntryActionViewItem, getActionBarActions } from '../../../../../../platform/actions/browser/menuEntryActionViewItem.js'; import { IAction } from '../../../../../../base/common/actions.js'; -import { NotebookSectionArgs } from '../../controller/sectionActions.js'; +import { NotebookOutlineEntryArgs } from '../../controller/sectionActions.js'; import { MarkupCellViewModel } from '../../viewModel/markupCellViewModel.js'; import { Delayer, disposableTimeout } from '../../../../../../base/common/async.js'; import { IOutlinePane } from '../../../../outline/browser/outline.js'; @@ -153,8 +153,12 @@ class NotebookOutlineRenderer implements ITreeRenderer void) | undefined; @@ -218,13 +222,13 @@ class NotebookOutlineRenderer implements ITreeRenderer { if (dropdownIsVisible) { - const actions = getOutlineToolbarActions(menu, { notebookEditor: this._editor, outlineEntry: entry }); + const actions = getOutlineToolbarActions(menu, { notebookEditor: editor, outlineEntry: entry }); deferredUpdate = () => toolbar.setActions(actions.primary, actions.secondary); return; } - const actions = getOutlineToolbarActions(menu, { notebookEditor: this._editor, outlineEntry: entry }); + const actions = getOutlineToolbarActions(menu, { notebookEditor: editor, outlineEntry: entry }); toolbar.setActions(actions.primary, actions.secondary); })); @@ -249,9 +253,8 @@ class NotebookOutlineRenderer implements ITreeRenderer /^inline/.test(g)); +function getOutlineToolbarActions(menu: IMenu, args?: NotebookOutlineEntryArgs): { primary: IAction[]; secondary: IAction[] } { + return getActionBarActions(menu.getActions({ shouldForwardArgs: true, arg: args }), g => /^inline/.test(g)); } class NotebookOutlineAccessibility implements IListAccessibilityProvider { diff --git a/src/vs/workbench/contrib/notebook/browser/controller/coreActions.ts b/src/vs/workbench/contrib/notebook/browser/controller/coreActions.ts index 567ae7a8ede3c..6d986184bad3d 100644 --- a/src/vs/workbench/contrib/notebook/browser/controller/coreActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/controller/coreActions.ts @@ -34,6 +34,7 @@ export const NOTEBOOK_EDITOR_WIDGET_ACTION_WEIGHT = KeybindingWeight.EditorContr export const NOTEBOOK_OUTPUT_WEBVIEW_ACTION_WEIGHT = KeybindingWeight.WorkbenchContrib + 1; // higher than Workbench contribution (such as Notebook List View), etc export const enum CellToolbarOrder { + RunSection, EditCell, ExecuteAboveCells, ExecuteCellAndBelow, diff --git a/src/vs/workbench/contrib/notebook/browser/controller/executeActions.ts b/src/vs/workbench/contrib/notebook/browser/controller/executeActions.ts index bcb4fcc526adb..57fc0cfc08f95 100644 --- a/src/vs/workbench/contrib/notebook/browser/controller/executeActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/controller/executeActions.ts @@ -56,6 +56,10 @@ export const executeThisCellCondition = ContextKeyExpr.and( executeCondition, NOTEBOOK_CELL_EXECUTING.toNegated()); +export const executeSectionCondition = ContextKeyExpr.and( + NOTEBOOK_CELL_TYPE.isEqualTo('markup'), +); + function renderAllMarkdownCells(context: INotebookActionContext): void { for (let i = 0; i < context.notebookEditor.getLength(); i++) { const cell = context.notebookEditor.cellAt(i); diff --git a/src/vs/workbench/contrib/notebook/browser/controller/sectionActions.ts b/src/vs/workbench/contrib/notebook/browser/controller/sectionActions.ts index f51e058a09fae..91dff4b7014a6 100644 --- a/src/vs/workbench/contrib/notebook/browser/controller/sectionActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/controller/sectionActions.ts @@ -9,20 +9,22 @@ import { ContextKeyExpr } from '../../../../../platform/contextkey/common/contex import { ServicesAccessor } from '../../../../../platform/instantiation/common/instantiation.js'; import { NotebookOutlineContext } from '../contrib/outline/notebookOutline.js'; import { FoldingController } from './foldingController.js'; -import { CellFoldingState, INotebookEditor } from '../notebookBrowser.js'; +import { CellFoldingState, ICellViewModel, INotebookEditor } from '../notebookBrowser.js'; import * as icons from '../notebookIcons.js'; import { OutlineEntry } from '../viewModel/OutlineEntry.js'; import { CellKind } from '../../common/notebookCommon.js'; import { OutlineTarget } from '../../../../services/outline/browser/outline.js'; +import { CELL_TITLE_CELL_GROUP_ID, CellToolbarOrder } from './coreActions.js'; +import { executeSectionCondition } from './executeActions.js'; -export type NotebookSectionArgs = { - notebookEditor: INotebookEditor | undefined; +export type NotebookOutlineEntryArgs = { + notebookEditor: INotebookEditor; outlineEntry: OutlineEntry; }; -export type ValidNotebookSectionArgs = { +export type NotebookCellArgs = { notebookEditor: INotebookEditor; - outlineEntry: OutlineEntry; + cell: ICellViewModel; }; export class NotebookRunSingleCellInSection extends Action2 { @@ -51,8 +53,8 @@ export class NotebookRunSingleCellInSection extends Action2 { }); } - override async run(_accessor: ServicesAccessor, context: NotebookSectionArgs): Promise { - if (!checkSectionContext(context)) { + override async run(_accessor: ServicesAccessor, context: any): Promise { + if (!checkOutlineEntryContext(context)) { return; } @@ -69,7 +71,7 @@ export class NotebookRunCellsInSection extends Action2 { mnemonicTitle: localize({ key: 'mirunCellsInSection', comment: ['&& denotes a mnemonic'] }, "&&Run Cells In Section"), }, shortTitle: localize('runCellsInSection', "Run Cells In Section"), - // icon: icons.executeBelowIcon, // TODO @Yoyokrazy replace this with new icon later + icon: icons.executeIcon, // TODO @Yoyokrazy replace this with new icon later menu: [ { id: MenuId.NotebookStickyScrollContext, @@ -86,17 +88,27 @@ export class NotebookRunCellsInSection extends Action2 { NotebookOutlineContext.CellHasChildren, NotebookOutlineContext.CellHasHeader, ) + }, + { + id: MenuId.NotebookCellTitle, + order: CellToolbarOrder.RunSection, + group: CELL_TITLE_CELL_GROUP_ID, + when: executeSectionCondition } ] }); } - override async run(_accessor: ServicesAccessor, context: NotebookSectionArgs): Promise { - if (!checkSectionContext(context)) { + override async run(_accessor: ServicesAccessor, context: any): Promise { + let cell: ICellViewModel; + if (checkOutlineEntryContext(context)) { + cell = context.outlineEntry.cell; + } else if (checkNotebookCellContext(context)) { + cell = context.cell; + } else { return; } - const cell = context.outlineEntry.cell; const idx = context.notebookEditor.getViewModel()?.getCellIndex(cell); if (idx === undefined) { return; @@ -137,8 +149,8 @@ export class NotebookFoldSection extends Action2 { }); } - override async run(_accessor: ServicesAccessor, context: NotebookSectionArgs): Promise { - if (!checkSectionContext(context)) { + override async run(_accessor: ServicesAccessor, context: any): Promise { + if (!checkOutlineEntryContext(context)) { return; } @@ -181,8 +193,8 @@ export class NotebookExpandSection extends Action2 { }); } - override async run(_accessor: ServicesAccessor, context: NotebookSectionArgs): Promise { - if (!checkSectionContext(context)) { + override async run(_accessor: ServicesAccessor, context: any): Promise { + if (!checkOutlineEntryContext(context)) { return; } @@ -200,15 +212,27 @@ export class NotebookExpandSection extends Action2 { } /** - * Take in context args and check if they exist + * Take in context args and check if they exist. True if action is run from notebook sticky scroll context menu or + * notebook outline context menu. * - * @param context - Notebook Section Context containing a notebook editor and outline entry + * @param context - Notebook Outline Context containing a notebook editor and outline entry * @returns true if context is valid, false otherwise */ -function checkSectionContext(context: NotebookSectionArgs): context is ValidNotebookSectionArgs { +function checkOutlineEntryContext(context: any): context is NotebookOutlineEntryArgs { return !!(context && context.notebookEditor && context.outlineEntry); } +/** + * Take in context args and check if they exist. True if action is run from a cell toolbar menu (potentially from the + * notebook cell container or cell editor context menus, but not tested or implemented atm) + * + * @param context - Notebook Outline Context containing a notebook editor and outline entry + * @returns true if context is valid, false otherwise + */ +function checkNotebookCellContext(context: any): context is NotebookCellArgs { + return !!(context && context.notebookEditor && context.cell); +} + registerAction2(NotebookRunSingleCellInSection); registerAction2(NotebookRunCellsInSection); registerAction2(NotebookFoldSection); diff --git a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorStickyScroll.ts b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorStickyScroll.ts index f742c0f3e67a4..c2e6f78366e21 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorStickyScroll.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorStickyScroll.ts @@ -21,7 +21,7 @@ import { foldingCollapsedIcon, foldingExpandedIcon } from '../../../../../editor import { MarkupCellViewModel } from '../viewModel/markupCellViewModel.js'; import { FoldingController } from '../controller/foldingController.js'; import { NotebookOptionsChangeEvent } from '../notebookOptions.js'; -import { NotebookSectionArgs } from '../controller/sectionActions.js'; +import { NotebookOutlineEntryArgs } from '../controller/sectionActions.js'; import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js'; import { INotebookCellOutlineDataSourceFactory } from '../viewModel/notebookOutlineDataSourceFactory.js'; @@ -175,7 +175,7 @@ export class NotebookStickyScroll extends Disposable { return; } - const args: NotebookSectionArgs = { + const args: NotebookOutlineEntryArgs = { outlineEntry: selectedOutlineEntry, notebookEditor: this.notebookEditor, };