@@ -38,6 +38,10 @@ type KernelPick = IQuickPickItem & { kernel: INotebookKernel };
3838function 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+ }
4145type SourcePick = IQuickPickItem & { action : ISourceAction } ;
4246function isSourcePick ( item : QuickPickInput < IQuickPickItem > ) : item is SourcePick {
4347 return 'action' in item ;
@@ -50,7 +54,7 @@ type KernelSourceQuickPickItem = IQuickPickItem & { command: Command };
5054function 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 ;
5458const KERNEL_PICKER_UPDATE_DEBOUNCE = 200 ;
5559
5660export 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