Skip to content

Commit d186d6f

Browse files
authored
select another kernel: support grouping. (microsoft#166753)
1 parent 2617166 commit d186d6f

File tree

1 file changed

+60
-14
lines changed

1 file changed

+60
-14
lines changed

src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelQuickPickStrategy.ts

Lines changed: 60 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ type KernelPick = IQuickPickItem & { kernel: INotebookKernel };
3838
function isKernelPick(item: QuickPickInput<IQuickPickItem>): item is KernelPick {
3939
return 'kernel' in item;
4040
}
41+
type GroupedKernelsPick = IQuickPickItem & { kernels: INotebookKernel[]; source: string };
42+
function isGroupedKernelsPick(item: QuickPickInput<IQuickPickItem>): item is GroupedKernelsPick {
43+
return 'kernels' in item;
44+
}
4145
type SourcePick = IQuickPickItem & { action: ISourceAction };
4246
function isSourcePick(item: QuickPickInput<IQuickPickItem>): item is SourcePick {
4347
return 'action' in item;
@@ -50,7 +54,7 @@ type KernelSourceQuickPickItem = IQuickPickItem & { command: Command };
5054
function isKernelSourceQuickPickItem(item: IQuickPickItem): item is KernelSourceQuickPickItem {
5155
return 'command' in item;
5256
}
53-
type KernelQuickPickItem = IQuickPickItem | InstallExtensionPick | KernelPick | SourcePick | KernelSourceQuickPickItem;
57+
type KernelQuickPickItem = IQuickPickItem | InstallExtensionPick | KernelPick | GroupedKernelsPick | SourcePick | KernelSourceQuickPickItem;
5458
const KERNEL_PICKER_UPDATE_DEBOUNCE = 200;
5559

5660
export type KernelQuickPickContext =
@@ -63,8 +67,8 @@ export interface IKernelPickerStrategy {
6367
showQuickPick(editor: IActiveNotebookEditor, wantedKernelId?: string): Promise<boolean>;
6468
}
6569

66-
function toQuickPick(kernel: INotebookKernel, selected: INotebookKernel | undefined) {
67-
const res = <KernelPick>{
70+
function toKernelQuickPick(kernel: INotebookKernel, selected: INotebookKernel | undefined) {
71+
const res: KernelPick = {
6872
kernel,
6973
picked: kernel.id === selected?.id,
7074
label: kernel.label,
@@ -417,7 +421,7 @@ export class KernelPickerFlatStrategy extends KernelPickerStrategyBase {
417421

418422
// Next display all of the kernels not marked as hidden grouped by categories or extensions.
419423
// If we don't have a kind, always display those at the bottom.
420-
const picks = all.filter(item => (!suggestions.includes(item) && !hidden.includes(item))).map(kernel => toQuickPick(kernel, selected));
424+
const picks = all.filter(item => (!suggestions.includes(item) && !hidden.includes(item))).map(kernel => toKernelQuickPick(kernel, selected));
421425
const kernelsPerCategory = groupBy(picks, (a, b) => compareIgnoreCase(a.kernel.kind || 'z', b.kernel.kind || 'z'));
422426
kernelsPerCategory.forEach(items => {
423427
quickPickItems.push({
@@ -461,15 +465,15 @@ export class KernelPickerFlatStrategy extends KernelPickerStrategyBase {
461465
});
462466

463467
// The title is already set to "Selected" so we don't need to set it again in description, thus passing in `undefined`.
464-
quickPickItems.push(toQuickPick(suggestions[0], undefined));
468+
quickPickItems.push(toKernelQuickPick(suggestions[0], undefined));
465469
return;
466470
}
467471

468472
quickPickItems.push({
469473
type: 'separator',
470474
label: localize('suggestedKernels', "Suggested")
471475
});
472-
quickPickItems.push(...suggestions.map(kernel => toQuickPick(kernel, selected)));
476+
quickPickItems.push(...suggestions.map(kernel => toKernelQuickPick(kernel, selected)));
473477
}
474478

475479
static updateKernelStatusAction(notebook: NotebookTextModel, action: IAction, notebookKernelService: INotebookKernelService, scopedContextKeyService?: IContextKeyService) {
@@ -543,7 +547,7 @@ export class KernelPickerMRUStrategy extends KernelPickerStrategyBase {
543547
@IExtensionsWorkbenchService _extensionWorkbenchService: IExtensionsWorkbenchService,
544548
@IExtensionService _extensionService: IExtensionService,
545549
@ICommandService _commandService: ICommandService,
546-
@INotebookKernelHistoryService private readonly _notebookKernelHistoryService: INotebookKernelHistoryService,
550+
@INotebookKernelHistoryService private readonly _notebookKernelHistoryService: INotebookKernelHistoryService
547551

548552
) {
549553
super(
@@ -564,7 +568,7 @@ export class KernelPickerMRUStrategy extends KernelPickerStrategyBase {
564568
let previousKind = '';
565569

566570
if (matchResult.selected) {
567-
const kernelItem = toQuickPick(matchResult.selected, matchResult.selected);
571+
const kernelItem = toKernelQuickPick(matchResult.selected, matchResult.selected);
568572
const kind = matchResult.selected.kind || '';
569573
if (kind) {
570574
previousKind = kind;
@@ -573,7 +577,7 @@ export class KernelPickerMRUStrategy extends KernelPickerStrategyBase {
573577
quickPickItems.push(kernelItem);
574578
}
575579

576-
matchResult.suggestions.filter(kernel => kernel.id !== matchResult.selected?.id).map(kernel => toQuickPick(kernel, matchResult.selected))
580+
matchResult.suggestions.filter(kernel => kernel.id !== matchResult.selected?.id).map(kernel => toKernelQuickPick(kernel, matchResult.selected))
577581
.forEach(kernel => {
578582
const kind = kernel.kernel.kind || '';
579583
if (kind && kind !== previousKind) {
@@ -663,6 +667,9 @@ export class KernelPickerMRUStrategy extends KernelPickerStrategyBase {
663667
} else if (isKernelPick(quickPick.selectedItems[0])) {
664668
await this._selecteKernel(notebook, quickPick.selectedItems[0].kernel);
665669
resolve(true);
670+
} else if (isGroupedKernelsPick(quickPick.selectedItems[0])) {
671+
await this._selectOneKernel(notebook, quickPick.selectedItems[0].source, quickPick.selectedItems[0].kernels);
672+
resolve(true);
666673
} else if (isSourcePick(quickPick.selectedItems[0])) {
667674
// selected explicilty, it should trigger the execution?
668675
quickPick.selectedItems[0].action.runAction();
@@ -674,11 +681,26 @@ export class KernelPickerMRUStrategy extends KernelPickerStrategyBase {
674681
quickPick.busy = false;
675682
const matchResult = this._getMatchingResult(notebook);
676683
const others = matchResult.all.filter(item => item.extension.value !== JUPYTER_EXTENSION_ID);
677-
quickPickItems.push(...others.map(kernel => ({
678-
label: kernel.label,
679-
detail: kernel.extension.value,
680-
kernel
681-
})));
684+
685+
// group controllers by extension
686+
for (const group of groupBy(others, (a, b) => a.extension.value === b.extension.value ? 0 : 1)) {
687+
const extension = this._extensionService.extensions.find(extension => extension.identifier.value === group[0].extension.value);
688+
const source = extension?.description ?? group[0].extension.value;
689+
if (group.length > 1) {
690+
quickPickItems.push({
691+
label: source,
692+
detail: localize('selectKernelFromExtensionDetail', "Kernels: {0}", group.map(kernel => kernel.label).join(', ')),
693+
kernels: group
694+
});
695+
} else {
696+
quickPickItems.push({
697+
label: group[0].label,
698+
detail: source,
699+
kernel: group[0]
700+
});
701+
}
702+
}
703+
682704
const validActions = actions.filter(action => action.command);
683705

684706
quickPickItems.push(...validActions.map(action => {
@@ -710,6 +732,30 @@ export class KernelPickerMRUStrategy extends KernelPickerStrategyBase {
710732
});
711733
}
712734

735+
private async _selectOneKernel(notebook: NotebookTextModel, source: string, kernels: INotebookKernel[]) {
736+
const quickPickItems: QuickPickInput<KernelPick>[] = kernels.map(kernel => toKernelQuickPick(kernel, undefined));
737+
const quickPick = this._quickInputService.createQuickPick<KernelQuickPickItem>();
738+
quickPick.items = quickPickItems;
739+
quickPick.canSelectMany = false;
740+
741+
quickPick.title = localize('selectKernelFromExtension', "Select Kernel from {0}", source);
742+
743+
quickPick.onDidAccept(async () => {
744+
if (quickPick.selectedItems && quickPick.selectedItems.length > 0 && isKernelPick(quickPick.selectedItems[0])) {
745+
await this._selecteKernel(notebook, quickPick.selectedItems[0].kernel);
746+
}
747+
748+
quickPick.hide();
749+
quickPick.dispose();
750+
});
751+
752+
quickPick.onDidHide(() => {
753+
quickPick.dispose();
754+
});
755+
756+
quickPick.show();
757+
}
758+
713759
private async _executeCommand<T>(notebook: NotebookTextModel, command: string | Command): Promise<T | undefined | void> {
714760
const id = typeof command === 'string' ? command : command.id;
715761
const args = typeof command === 'string' ? [] : command.arguments ?? [];

0 commit comments

Comments
 (0)