Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/notebook/browser/controller/insertCellActions.ts
5240 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 { Codicon } from '../../../../../base/common/codicons.js';
7
import { KeyCode, KeyMod } from '../../../../../base/common/keyCodes.js';
8
import { ILanguageService } from '../../../../../editor/common/languages/language.js';
9
import { localize } from '../../../../../nls.js';
10
import { IAction2Options, MenuId, MenuRegistry, registerAction2 } from '../../../../../platform/actions/common/actions.js';
11
import { ContextKeyExpr } from '../../../../../platform/contextkey/common/contextkey.js';
12
import { InputFocusedContext } from '../../../../../platform/contextkey/common/contextkeys.js';
13
import { ServicesAccessor } from '../../../../../platform/instantiation/common/instantiation.js';
14
import { KeybindingWeight } from '../../../../../platform/keybinding/common/keybindingsRegistry.js';
15
import { insertCell } from './cellOperations.js';
16
import { INotebookActionContext, NotebookAction } from './coreActions.js';
17
import { NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_EDITOR_EDITABLE } from '../../common/notebookContextKeys.js';
18
import { CellViewModel } from '../viewModel/notebookViewModelImpl.js';
19
import { CellKind, NotebookSetting } from '../../common/notebookCommon.js';
20
import { INotebookKernelHistoryService } from '../../common/notebookKernelService.js';
21
22
const INSERT_CODE_CELL_ABOVE_COMMAND_ID = 'notebook.cell.insertCodeCellAbove';
23
const INSERT_CODE_CELL_BELOW_COMMAND_ID = 'notebook.cell.insertCodeCellBelow';
24
const INSERT_CODE_CELL_ABOVE_AND_FOCUS_CONTAINER_COMMAND_ID = 'notebook.cell.insertCodeCellAboveAndFocusContainer';
25
const INSERT_CODE_CELL_BELOW_AND_FOCUS_CONTAINER_COMMAND_ID = 'notebook.cell.insertCodeCellBelowAndFocusContainer';
26
const INSERT_CODE_CELL_AT_TOP_COMMAND_ID = 'notebook.cell.insertCodeCellAtTop';
27
const INSERT_MARKDOWN_CELL_ABOVE_COMMAND_ID = 'notebook.cell.insertMarkdownCellAbove';
28
const INSERT_MARKDOWN_CELL_BELOW_COMMAND_ID = 'notebook.cell.insertMarkdownCellBelow';
29
const INSERT_MARKDOWN_CELL_AT_TOP_COMMAND_ID = 'notebook.cell.insertMarkdownCellAtTop';
30
31
export function insertNewCell(accessor: ServicesAccessor, context: INotebookActionContext, kind: CellKind, direction: 'above' | 'below', focusEditor: boolean) {
32
let newCell: CellViewModel | null = null;
33
if (context.ui) {
34
context.notebookEditor.focus();
35
}
36
37
const languageService = accessor.get(ILanguageService);
38
const kernelHistoryService = accessor.get(INotebookKernelHistoryService);
39
40
if (context.cell) {
41
const idx = context.notebookEditor.getCellIndex(context.cell);
42
newCell = insertCell(languageService, context.notebookEditor, idx, kind, direction, undefined, true, kernelHistoryService);
43
} else {
44
const focusRange = context.notebookEditor.getFocus();
45
const next = Math.max(focusRange.end - 1, 0);
46
newCell = insertCell(languageService, context.notebookEditor, next, kind, direction, undefined, true, kernelHistoryService);
47
}
48
49
return newCell;
50
}
51
52
export abstract class InsertCellCommand extends NotebookAction {
53
constructor(
54
desc: Readonly<IAction2Options>,
55
private kind: CellKind,
56
private direction: 'above' | 'below',
57
private focusEditor: boolean
58
) {
59
super(desc);
60
}
61
62
async runWithContext(accessor: ServicesAccessor, context: INotebookActionContext): Promise<void> {
63
const newCell = await insertNewCell(accessor, context, this.kind, this.direction, this.focusEditor);
64
65
if (newCell) {
66
await context.notebookEditor.focusNotebookCell(newCell, this.focusEditor ? 'editor' : 'container');
67
}
68
}
69
}
70
71
registerAction2(class InsertCodeCellAboveAction extends InsertCellCommand {
72
constructor() {
73
super(
74
{
75
id: INSERT_CODE_CELL_ABOVE_COMMAND_ID,
76
title: localize('notebookActions.insertCodeCellAbove', "Insert Code Cell Above"),
77
keybinding: {
78
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Enter,
79
when: ContextKeyExpr.and(NOTEBOOK_CELL_LIST_FOCUSED, InputFocusedContext.toNegated()),
80
weight: KeybindingWeight.WorkbenchContrib
81
},
82
menu: {
83
id: MenuId.NotebookCellInsert,
84
order: 0
85
}
86
},
87
CellKind.Code,
88
'above',
89
true);
90
}
91
});
92
93
94
95
registerAction2(class InsertCodeCellAboveAndFocusContainerAction extends InsertCellCommand {
96
constructor() {
97
super(
98
{
99
id: INSERT_CODE_CELL_ABOVE_AND_FOCUS_CONTAINER_COMMAND_ID,
100
title: localize('notebookActions.insertCodeCellAboveAndFocusContainer', "Insert Code Cell Above and Focus Container")
101
},
102
CellKind.Code,
103
'above',
104
false);
105
}
106
});
107
108
registerAction2(class InsertCodeCellBelowAction extends InsertCellCommand {
109
constructor() {
110
super(
111
{
112
id: INSERT_CODE_CELL_BELOW_COMMAND_ID,
113
title: localize('notebookActions.insertCodeCellBelow', "Insert Code Cell Below"),
114
keybinding: {
115
primary: KeyMod.CtrlCmd | KeyCode.Enter,
116
when: ContextKeyExpr.and(NOTEBOOK_CELL_LIST_FOCUSED, InputFocusedContext.toNegated()),
117
weight: KeybindingWeight.WorkbenchContrib
118
},
119
menu: {
120
id: MenuId.NotebookCellInsert,
121
order: 1
122
}
123
},
124
CellKind.Code,
125
'below',
126
true);
127
}
128
});
129
130
registerAction2(class InsertCodeCellBelowAndFocusContainerAction extends InsertCellCommand {
131
constructor() {
132
super(
133
{
134
id: INSERT_CODE_CELL_BELOW_AND_FOCUS_CONTAINER_COMMAND_ID,
135
title: localize('notebookActions.insertCodeCellBelowAndFocusContainer', "Insert Code Cell Below and Focus Container"),
136
},
137
CellKind.Code,
138
'below',
139
false);
140
}
141
});
142
143
144
registerAction2(class InsertMarkdownCellAboveAction extends InsertCellCommand {
145
constructor() {
146
super(
147
{
148
id: INSERT_MARKDOWN_CELL_ABOVE_COMMAND_ID,
149
title: localize('notebookActions.insertMarkdownCellAbove', "Insert Markdown Cell Above"),
150
menu: {
151
id: MenuId.NotebookCellInsert,
152
order: 2
153
}
154
},
155
CellKind.Markup,
156
'above',
157
true);
158
}
159
});
160
161
registerAction2(class InsertMarkdownCellBelowAction extends InsertCellCommand {
162
constructor() {
163
super(
164
{
165
id: INSERT_MARKDOWN_CELL_BELOW_COMMAND_ID,
166
title: localize('notebookActions.insertMarkdownCellBelow', "Insert Markdown Cell Below"),
167
menu: {
168
id: MenuId.NotebookCellInsert,
169
order: 3
170
}
171
},
172
CellKind.Markup,
173
'below',
174
true);
175
}
176
});
177
178
179
registerAction2(class InsertCodeCellAtTopAction extends NotebookAction {
180
constructor() {
181
super(
182
{
183
id: INSERT_CODE_CELL_AT_TOP_COMMAND_ID,
184
title: localize('notebookActions.insertCodeCellAtTop', "Add Code Cell At Top"),
185
f1: false
186
});
187
}
188
189
override async run(accessor: ServicesAccessor, context?: INotebookActionContext): Promise<void> {
190
context = context ?? this.getEditorContextFromArgsOrActive(accessor);
191
if (context) {
192
this.runWithContext(accessor, context);
193
}
194
}
195
196
async runWithContext(accessor: ServicesAccessor, context: INotebookActionContext): Promise<void> {
197
const languageService = accessor.get(ILanguageService);
198
const kernelHistoryService = accessor.get(INotebookKernelHistoryService);
199
const newCell = insertCell(languageService, context.notebookEditor, 0, CellKind.Code, 'above', undefined, true, kernelHistoryService);
200
201
if (newCell) {
202
await context.notebookEditor.focusNotebookCell(newCell, 'editor');
203
}
204
}
205
});
206
207
registerAction2(class InsertMarkdownCellAtTopAction extends NotebookAction {
208
constructor() {
209
super(
210
{
211
id: INSERT_MARKDOWN_CELL_AT_TOP_COMMAND_ID,
212
title: localize('notebookActions.insertMarkdownCellAtTop', "Add Markdown Cell At Top"),
213
f1: false
214
});
215
}
216
217
override async run(accessor: ServicesAccessor, context?: INotebookActionContext): Promise<void> {
218
context = context ?? this.getEditorContextFromArgsOrActive(accessor);
219
if (context) {
220
this.runWithContext(accessor, context);
221
}
222
}
223
224
async runWithContext(accessor: ServicesAccessor, context: INotebookActionContext): Promise<void> {
225
const languageService = accessor.get(ILanguageService);
226
const kernelHistoryService = accessor.get(INotebookKernelHistoryService);
227
228
const newCell = insertCell(languageService, context.notebookEditor, 0, CellKind.Markup, 'above', undefined, true, kernelHistoryService);
229
230
if (newCell) {
231
await context.notebookEditor.focusNotebookCell(newCell, 'editor');
232
}
233
}
234
});
235
236
MenuRegistry.appendMenuItem(MenuId.NotebookCellBetween, {
237
command: {
238
id: INSERT_CODE_CELL_BELOW_COMMAND_ID,
239
title: '$(add) ' + localize('notebookActions.menu.insertCode', "Code"),
240
tooltip: localize('notebookActions.menu.insertCode.tooltip', "Add Code Cell")
241
},
242
order: 0,
243
group: 'inline',
244
when: ContextKeyExpr.and(
245
NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true),
246
ContextKeyExpr.notEquals('config.notebook.experimental.insertToolbarAlignment', 'left')
247
)
248
});
249
250
MenuRegistry.appendMenuItem(MenuId.NotebookCellBetween, {
251
command: {
252
id: INSERT_CODE_CELL_BELOW_COMMAND_ID,
253
title: localize('notebookActions.menu.insertCode.minimalToolbar', "Add Code"),
254
icon: Codicon.add,
255
tooltip: localize('notebookActions.menu.insertCode.tooltip', "Add Code Cell")
256
},
257
order: 0,
258
group: 'inline',
259
when: ContextKeyExpr.and(
260
NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true),
261
ContextKeyExpr.equals('config.notebook.experimental.insertToolbarAlignment', 'left')
262
)
263
});
264
265
MenuRegistry.appendMenuItem(MenuId.NotebookToolbar, {
266
command: {
267
id: INSERT_CODE_CELL_BELOW_COMMAND_ID,
268
icon: Codicon.add,
269
title: localize('notebookActions.menu.insertCode.ontoolbar', "Code"),
270
tooltip: localize('notebookActions.menu.insertCode.tooltip', "Add Code Cell")
271
},
272
order: -5,
273
group: 'navigation/add',
274
when: ContextKeyExpr.and(
275
NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true),
276
ContextKeyExpr.notEquals('config.notebook.insertToolbarLocation', 'betweenCells'),
277
ContextKeyExpr.notEquals('config.notebook.insertToolbarLocation', 'hidden')
278
)
279
});
280
281
MenuRegistry.appendMenuItem(MenuId.NotebookCellListTop, {
282
command: {
283
id: INSERT_CODE_CELL_AT_TOP_COMMAND_ID,
284
title: '$(add) ' + localize('notebookActions.menu.insertCode', "Code"),
285
tooltip: localize('notebookActions.menu.insertCode.tooltip', "Add Code Cell")
286
},
287
order: 0,
288
group: 'inline',
289
when: ContextKeyExpr.and(
290
NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true),
291
ContextKeyExpr.notEquals('config.notebook.experimental.insertToolbarAlignment', 'left')
292
)
293
});
294
295
MenuRegistry.appendMenuItem(MenuId.NotebookCellListTop, {
296
command: {
297
id: INSERT_CODE_CELL_AT_TOP_COMMAND_ID,
298
title: localize('notebookActions.menu.insertCode.minimaltoolbar', "Add Code"),
299
icon: Codicon.add,
300
tooltip: localize('notebookActions.menu.insertCode.tooltip', "Add Code Cell")
301
},
302
order: 0,
303
group: 'inline',
304
when: ContextKeyExpr.and(
305
NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true),
306
ContextKeyExpr.equals('config.notebook.experimental.insertToolbarAlignment', 'left')
307
)
308
});
309
310
311
MenuRegistry.appendMenuItem(MenuId.NotebookCellBetween, {
312
command: {
313
id: INSERT_MARKDOWN_CELL_BELOW_COMMAND_ID,
314
title: '$(add) ' + localize('notebookActions.menu.insertMarkdown', "Markdown"),
315
tooltip: localize('notebookActions.menu.insertMarkdown.tooltip', "Add Markdown Cell")
316
},
317
order: 1,
318
group: 'inline',
319
when: ContextKeyExpr.and(
320
NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true),
321
ContextKeyExpr.notEquals('config.notebook.experimental.insertToolbarAlignment', 'left')
322
)
323
});
324
325
MenuRegistry.appendMenuItem(MenuId.NotebookToolbar, {
326
command: {
327
id: INSERT_MARKDOWN_CELL_BELOW_COMMAND_ID,
328
icon: Codicon.add,
329
title: localize('notebookActions.menu.insertMarkdown.ontoolbar', "Markdown"),
330
tooltip: localize('notebookActions.menu.insertMarkdown.tooltip', "Add Markdown Cell")
331
},
332
order: -5,
333
group: 'navigation/add',
334
when: ContextKeyExpr.and(
335
NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true),
336
ContextKeyExpr.notEquals('config.notebook.insertToolbarLocation', 'betweenCells'),
337
ContextKeyExpr.notEquals('config.notebook.insertToolbarLocation', 'hidden'),
338
ContextKeyExpr.notEquals(`config.${NotebookSetting.globalToolbarShowLabel}`, false),
339
ContextKeyExpr.notEquals(`config.${NotebookSetting.globalToolbarShowLabel}`, 'never')
340
)
341
});
342
343
MenuRegistry.appendMenuItem(MenuId.NotebookCellListTop, {
344
command: {
345
id: INSERT_MARKDOWN_CELL_AT_TOP_COMMAND_ID,
346
title: '$(add) ' + localize('notebookActions.menu.insertMarkdown', "Markdown"),
347
tooltip: localize('notebookActions.menu.insertMarkdown.tooltip', "Add Markdown Cell")
348
},
349
order: 1,
350
group: 'inline',
351
when: ContextKeyExpr.and(
352
NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true),
353
ContextKeyExpr.notEquals('config.notebook.experimental.insertToolbarAlignment', 'left')
354
)
355
});
356
357