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