Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/notebook/browser/controller/sectionActions.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { localize, localize2 } from '../../../../../nls.js';
7
import { Action2, MenuId, registerAction2 } from '../../../../../platform/actions/common/actions.js';
8
import { ContextKeyExpr } from '../../../../../platform/contextkey/common/contextkey.js';
9
import { ServicesAccessor } from '../../../../../platform/instantiation/common/instantiation.js';
10
import { NotebookOutlineContext } from '../contrib/outline/notebookOutline.js';
11
import { FoldingController } from './foldingController.js';
12
import { CellEditState, CellFoldingState, ICellViewModel, INotebookEditor } from '../notebookBrowser.js';
13
import * as icons from '../notebookIcons.js';
14
import { OutlineEntry } from '../viewModel/OutlineEntry.js';
15
import { CellKind } from '../../common/notebookCommon.js';
16
import { OutlineTarget } from '../../../../services/outline/browser/outline.js';
17
import { CELL_TITLE_CELL_GROUP_ID, CellToolbarOrder } from './coreActions.js';
18
import { executeSectionCondition } from './executeActions.js';
19
20
export type NotebookOutlineEntryArgs = {
21
notebookEditor: INotebookEditor;
22
outlineEntry: OutlineEntry;
23
};
24
25
export type NotebookCellArgs = {
26
notebookEditor: INotebookEditor;
27
cell: ICellViewModel;
28
};
29
30
export class NotebookRunSingleCellInSection extends Action2 {
31
constructor() {
32
super({
33
id: 'notebook.section.runSingleCell',
34
title: {
35
...localize2('runCell', "Run Cell"),
36
mnemonicTitle: localize({ key: 'mirunCell', comment: ['&& denotes a mnemonic'] }, "&&Run Cell"),
37
},
38
shortTitle: localize('runCell', "Run Cell"),
39
icon: icons.executeIcon,
40
menu: [
41
{
42
id: MenuId.NotebookOutlineActionMenu,
43
group: 'inline',
44
order: 1,
45
when: ContextKeyExpr.and(
46
NotebookOutlineContext.CellKind.isEqualTo(CellKind.Code),
47
NotebookOutlineContext.OutlineElementTarget.isEqualTo(OutlineTarget.OutlinePane),
48
NotebookOutlineContext.CellHasChildren.toNegated(),
49
NotebookOutlineContext.CellHasHeader.toNegated(),
50
)
51
}
52
]
53
});
54
}
55
56
override async run(_accessor: ServicesAccessor, context: any): Promise<void> {
57
if (!checkOutlineEntryContext(context)) {
58
return;
59
}
60
61
context.notebookEditor.executeNotebookCells([context.outlineEntry.cell]);
62
}
63
}
64
65
export class NotebookRunCellsInSection extends Action2 {
66
constructor() {
67
super({
68
id: 'notebook.section.runCells',
69
title: {
70
...localize2('runCellsInSection', "Run Cells In Section"),
71
mnemonicTitle: localize({ key: 'mirunCellsInSection', comment: ['&& denotes a mnemonic'] }, "&&Run Cells In Section"),
72
},
73
shortTitle: localize('runCellsInSection', "Run Cells In Section"),
74
icon: icons.executeIcon, // TODO @Yoyokrazy replace this with new icon later
75
menu: [
76
{
77
id: MenuId.NotebookStickyScrollContext,
78
group: 'notebookExecution',
79
order: 1
80
},
81
{
82
id: MenuId.NotebookOutlineActionMenu,
83
group: 'inline',
84
order: 1,
85
when: ContextKeyExpr.and(
86
NotebookOutlineContext.CellKind.isEqualTo(CellKind.Markup),
87
NotebookOutlineContext.OutlineElementTarget.isEqualTo(OutlineTarget.OutlinePane),
88
NotebookOutlineContext.CellHasChildren,
89
NotebookOutlineContext.CellHasHeader,
90
)
91
},
92
{
93
id: MenuId.NotebookCellTitle,
94
order: CellToolbarOrder.RunSection,
95
group: CELL_TITLE_CELL_GROUP_ID,
96
when: executeSectionCondition
97
}
98
]
99
});
100
}
101
102
override async run(_accessor: ServicesAccessor, context: any): Promise<void> {
103
let cell: ICellViewModel;
104
if (checkOutlineEntryContext(context)) {
105
cell = context.outlineEntry.cell;
106
} else if (checkNotebookCellContext(context)) {
107
cell = context.cell;
108
} else {
109
return;
110
}
111
112
if (cell.getEditState() === CellEditState.Editing) {
113
const foldingController = context.notebookEditor.getContribution<FoldingController>(FoldingController.id);
114
foldingController.recompute();
115
}
116
117
const cellIdx = context.notebookEditor.getViewModel()?.getCellIndex(cell);
118
if (cellIdx === undefined) {
119
return;
120
}
121
const sectionIdx = context.notebookEditor.getViewModel()?.getFoldingStartIndex(cellIdx);
122
if (sectionIdx === undefined) {
123
return;
124
}
125
const length = context.notebookEditor.getViewModel()?.getFoldedLength(sectionIdx);
126
if (length === undefined) {
127
return;
128
}
129
130
const cells = context.notebookEditor.getCellsInRange({ start: sectionIdx, end: sectionIdx + length + 1 });
131
context.notebookEditor.executeNotebookCells(cells);
132
}
133
}
134
135
export class NotebookFoldSection extends Action2 {
136
constructor() {
137
super({
138
id: 'notebook.section.foldSection',
139
title: {
140
...localize2('foldSection', "Fold Section"),
141
mnemonicTitle: localize({ key: 'mifoldSection', comment: ['&& denotes a mnemonic'] }, "&&Fold Section"),
142
},
143
shortTitle: localize('foldSection', "Fold Section"),
144
menu: [
145
{
146
id: MenuId.NotebookOutlineActionMenu,
147
group: 'notebookFolding',
148
order: 2,
149
when: ContextKeyExpr.and(
150
NotebookOutlineContext.CellKind.isEqualTo(CellKind.Markup),
151
NotebookOutlineContext.OutlineElementTarget.isEqualTo(OutlineTarget.OutlinePane),
152
NotebookOutlineContext.CellHasChildren,
153
NotebookOutlineContext.CellHasHeader,
154
NotebookOutlineContext.CellFoldingState.isEqualTo(CellFoldingState.Expanded)
155
)
156
}
157
]
158
});
159
}
160
161
override async run(_accessor: ServicesAccessor, context: any): Promise<void> {
162
if (!checkOutlineEntryContext(context)) {
163
return;
164
}
165
166
this.toggleFoldRange(context.outlineEntry, context.notebookEditor);
167
}
168
169
private toggleFoldRange(entry: OutlineEntry, notebookEditor: INotebookEditor) {
170
const foldingController = notebookEditor.getContribution<FoldingController>(FoldingController.id);
171
const index = entry.index;
172
const headerLevel = entry.level;
173
const newFoldingState = CellFoldingState.Collapsed;
174
175
foldingController.setFoldingStateDown(index, newFoldingState, headerLevel);
176
}
177
}
178
179
export class NotebookExpandSection extends Action2 {
180
constructor() {
181
super({
182
id: 'notebook.section.expandSection',
183
title: {
184
...localize2('expandSection', "Expand Section"),
185
mnemonicTitle: localize({ key: 'miexpandSection', comment: ['&& denotes a mnemonic'] }, "&&Expand Section"),
186
},
187
shortTitle: localize('expandSection', "Expand Section"),
188
menu: [
189
{
190
id: MenuId.NotebookOutlineActionMenu,
191
group: 'notebookFolding',
192
order: 2,
193
when: ContextKeyExpr.and(
194
NotebookOutlineContext.CellKind.isEqualTo(CellKind.Markup),
195
NotebookOutlineContext.OutlineElementTarget.isEqualTo(OutlineTarget.OutlinePane),
196
NotebookOutlineContext.CellHasChildren,
197
NotebookOutlineContext.CellHasHeader,
198
NotebookOutlineContext.CellFoldingState.isEqualTo(CellFoldingState.Collapsed)
199
)
200
}
201
]
202
});
203
}
204
205
override async run(_accessor: ServicesAccessor, context: any): Promise<void> {
206
if (!checkOutlineEntryContext(context)) {
207
return;
208
}
209
210
this.toggleFoldRange(context.outlineEntry, context.notebookEditor);
211
}
212
213
private toggleFoldRange(entry: OutlineEntry, notebookEditor: INotebookEditor) {
214
const foldingController = notebookEditor.getContribution<FoldingController>(FoldingController.id);
215
const index = entry.index;
216
const headerLevel = entry.level;
217
const newFoldingState = CellFoldingState.Expanded;
218
219
foldingController.setFoldingStateDown(index, newFoldingState, headerLevel);
220
}
221
}
222
223
/**
224
* Take in context args and check if they exist. True if action is run from notebook sticky scroll context menu or
225
* notebook outline context menu.
226
*
227
* @param context - Notebook Outline Context containing a notebook editor and outline entry
228
* @returns true if context is valid, false otherwise
229
*/
230
function checkOutlineEntryContext(context: any): context is NotebookOutlineEntryArgs {
231
return !!(context && context.notebookEditor && context.outlineEntry);
232
}
233
234
/**
235
* Take in context args and check if they exist. True if action is run from a cell toolbar menu (potentially from the
236
* notebook cell container or cell editor context menus, but not tested or implemented atm)
237
*
238
* @param context - Notebook Outline Context containing a notebook editor and outline entry
239
* @returns true if context is valid, false otherwise
240
*/
241
function checkNotebookCellContext(context: any): context is NotebookCellArgs {
242
return !!(context && context.notebookEditor && context.cell);
243
}
244
245
registerAction2(NotebookRunSingleCellInSection);
246
registerAction2(NotebookRunCellsInSection);
247
registerAction2(NotebookFoldSection);
248
registerAction2(NotebookExpandSection);
249
250