Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelView.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 { ActionViewItem, IActionViewItemOptions } from '../../../../../base/browser/ui/actionbar/actionViewItems.js';
7
import { Action, IAction } from '../../../../../base/common/actions.js';
8
import { Event } from '../../../../../base/common/event.js';
9
import { localize, localize2 } from '../../../../../nls.js';
10
import { Action2, MenuId, registerAction2 } from '../../../../../platform/actions/common/actions.js';
11
import { ContextKeyExpr, IContextKeyService } from '../../../../../platform/contextkey/common/contextkey.js';
12
import { ExtensionIdentifier } from '../../../../../platform/extensions/common/extensions.js';
13
import { IInstantiationService, ServicesAccessor } from '../../../../../platform/instantiation/common/instantiation.js';
14
import { ThemeIcon } from '../../../../../base/common/themables.js';
15
import { NOTEBOOK_ACTIONS_CATEGORY, SELECT_KERNEL_ID } from '../controller/coreActions.js';
16
import { getNotebookEditorFromEditorPane, INotebookEditor } from '../notebookBrowser.js';
17
import { selectKernelIcon } from '../notebookIcons.js';
18
import { KernelPickerMRUStrategy, KernelQuickPickContext } from './notebookKernelQuickPickStrategy.js';
19
import { NotebookTextModel } from '../../common/model/notebookTextModel.js';
20
import { NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_KERNEL_COUNT } from '../../common/notebookContextKeys.js';
21
import { INotebookKernel, INotebookKernelHistoryService, INotebookKernelService } from '../../common/notebookKernelService.js';
22
import { IEditorService } from '../../../../services/editor/common/editorService.js';
23
24
function getEditorFromContext(editorService: IEditorService, context?: KernelQuickPickContext): INotebookEditor | undefined {
25
let editor: INotebookEditor | undefined;
26
if (context !== undefined && 'notebookEditorId' in context) {
27
const editorId = context.notebookEditorId;
28
const matchingEditor = editorService.visibleEditorPanes.find((editorPane) => {
29
const notebookEditor = getNotebookEditorFromEditorPane(editorPane);
30
return notebookEditor?.getId() === editorId;
31
});
32
editor = getNotebookEditorFromEditorPane(matchingEditor);
33
} else if (context !== undefined && 'notebookEditor' in context) {
34
editor = context?.notebookEditor;
35
} else {
36
editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane);
37
}
38
39
return editor;
40
}
41
42
function shouldSkip(
43
selected: INotebookKernel | undefined,
44
controllerId: string | undefined,
45
extensionId: string | undefined,
46
context: KernelQuickPickContext | undefined): boolean {
47
48
return !!(selected && (
49
(context && 'skipIfAlreadySelected' in context && context.skipIfAlreadySelected) ||
50
// target kernel is already selected
51
(controllerId && selected.id === controllerId && ExtensionIdentifier.equals(selected.extension, extensionId))
52
));
53
}
54
55
registerAction2(class extends Action2 {
56
constructor() {
57
super({
58
id: SELECT_KERNEL_ID,
59
category: NOTEBOOK_ACTIONS_CATEGORY,
60
title: localize2('notebookActions.selectKernel', 'Select Notebook Kernel'),
61
icon: selectKernelIcon,
62
f1: true,
63
precondition: NOTEBOOK_IS_ACTIVE_EDITOR,
64
menu: [{
65
id: MenuId.EditorTitle,
66
when: ContextKeyExpr.and(
67
NOTEBOOK_IS_ACTIVE_EDITOR,
68
ContextKeyExpr.notEquals('config.notebook.globalToolbar', true)
69
),
70
group: 'navigation',
71
order: -10
72
}, {
73
id: MenuId.NotebookToolbar,
74
when: ContextKeyExpr.equals('config.notebook.globalToolbar', true),
75
group: 'status',
76
order: -10
77
}, {
78
id: MenuId.InteractiveToolbar,
79
when: NOTEBOOK_KERNEL_COUNT.notEqualsTo(0),
80
group: 'status',
81
order: -10
82
}],
83
metadata: {
84
description: localize('notebookActions.selectKernel.args', "Notebook Kernel Args"),
85
args: [
86
{
87
name: 'kernelInfo',
88
description: 'The kernel info',
89
schema: {
90
'type': 'object',
91
'required': ['id', 'extension'],
92
'properties': {
93
'id': {
94
'type': 'string'
95
},
96
'extension': {
97
'type': 'string'
98
},
99
'notebookEditorId': {
100
'type': 'string'
101
}
102
}
103
}
104
}
105
]
106
},
107
});
108
}
109
110
async run(accessor: ServicesAccessor, context?: KernelQuickPickContext): Promise<boolean> {
111
const instantiationService = accessor.get(IInstantiationService);
112
const editorService = accessor.get(IEditorService);
113
114
const editor = getEditorFromContext(editorService, context);
115
116
if (!editor || !editor.hasModel()) {
117
return false;
118
}
119
120
let controllerId = context && 'id' in context ? context.id : undefined;
121
let extensionId = context && 'extension' in context ? context.extension : undefined;
122
123
if (controllerId && (typeof controllerId !== 'string' || typeof extensionId !== 'string')) {
124
// validate context: id & extension MUST be strings
125
controllerId = undefined;
126
extensionId = undefined;
127
}
128
129
const notebook = editor.textModel;
130
const notebookKernelService = accessor.get(INotebookKernelService);
131
const { selected } = notebookKernelService.getMatchingKernel(notebook);
132
133
if (shouldSkip(selected, controllerId, extensionId, context)) {
134
return true;
135
}
136
137
const wantedKernelId = controllerId ? `${extensionId}/${controllerId}` : undefined;
138
const strategy = instantiationService.createInstance(KernelPickerMRUStrategy);
139
return strategy.showQuickPick(editor, wantedKernelId);
140
}
141
});
142
143
export class NotebooKernelActionViewItem extends ActionViewItem {
144
145
private _kernelLabel?: HTMLAnchorElement;
146
147
constructor(
148
actualAction: IAction,
149
private readonly _editor: { onDidChangeModel: Event<void>; textModel: NotebookTextModel | undefined; scopedContextKeyService?: IContextKeyService } | INotebookEditor,
150
options: IActionViewItemOptions,
151
@INotebookKernelService private readonly _notebookKernelService: INotebookKernelService,
152
@INotebookKernelHistoryService private readonly _notebookKernelHistoryService: INotebookKernelHistoryService,
153
) {
154
const action = new Action('fakeAction', undefined, ThemeIcon.asClassName(selectKernelIcon), true, (event) => actualAction.run(event));
155
super(
156
undefined,
157
action,
158
{ ...options, label: false, icon: true }
159
);
160
this._register(action);
161
this._register(_editor.onDidChangeModel(this._update, this));
162
this._register(_notebookKernelService.onDidAddKernel(this._update, this));
163
this._register(_notebookKernelService.onDidRemoveKernel(this._update, this));
164
this._register(_notebookKernelService.onDidChangeNotebookAffinity(this._update, this));
165
this._register(_notebookKernelService.onDidChangeSelectedNotebooks(this._update, this));
166
this._register(_notebookKernelService.onDidChangeSourceActions(this._update, this));
167
this._register(_notebookKernelService.onDidChangeKernelDetectionTasks(this._update, this));
168
}
169
170
override render(container: HTMLElement): void {
171
this._update();
172
super.render(container);
173
container.classList.add('kernel-action-view-item');
174
this._kernelLabel = document.createElement('a');
175
container.appendChild(this._kernelLabel);
176
this.updateLabel();
177
}
178
179
protected override updateLabel() {
180
if (this._kernelLabel) {
181
this._kernelLabel.classList.add('kernel-label');
182
this._kernelLabel.innerText = this._action.label;
183
}
184
}
185
186
protected _update(): void {
187
const notebook = this._editor.textModel;
188
189
if (!notebook) {
190
this._resetAction();
191
return;
192
}
193
194
KernelPickerMRUStrategy.updateKernelStatusAction(notebook, this._action, this._notebookKernelService, this._notebookKernelHistoryService);
195
196
this.updateClass();
197
}
198
199
private _resetAction(): void {
200
this._action.enabled = false;
201
this._action.label = '';
202
this._action.class = '';
203
}
204
}
205
206