22// Licensed under the MIT License.
33
44import { injectable } from 'inversify' ;
5- import { workspace } from 'vscode' ;
5+ import { workspace , commands , window , QuickPickItem , WorkspaceEdit , NotebookEdit , NotebookRange } from 'vscode' ;
66import { IExtensionSyncActivationService } from '../../platform/activation/types' ;
77import { IExtensionContext } from '../../platform/common/types' ;
88import { inject } from 'inversify' ;
9- import { DeepnoteNotebookSerializer } from './deepnoteSerializer' ;
9+ import { DeepnoteNotebookSerializer , DeepnoteProject , DeepnoteNotebook } from './deepnoteSerializer' ;
10+ import { Commands } from '../../platform/common/constants' ;
1011
1112// Responsible for registering the Deepnote notebook serializer
1213@injectable ( )
@@ -16,8 +17,96 @@ export class DeepnoteActivationService implements IExtensionSyncActivationServic
1617 ) { }
1718
1819 public activate ( ) {
20+ const serializer = new DeepnoteNotebookSerializer ( ) ;
1921 this . extensionContext . subscriptions . push (
20- workspace . registerNotebookSerializer ( 'deepnote' , new DeepnoteNotebookSerializer ( ) )
22+ workspace . registerNotebookSerializer ( 'deepnote' , serializer )
2123 ) ;
24+
25+ // Register command to switch between notebooks
26+ this . extensionContext . subscriptions . push (
27+ commands . registerCommand ( Commands . SelectDeepnoteNotebook , ( ) => this . selectNotebook ( ) )
28+ ) ;
29+ }
30+
31+ private async selectNotebook ( ) {
32+ const activeEditor = window . activeNotebookEditor ;
33+ if ( ! activeEditor || activeEditor . notebook . notebookType !== 'deepnote' ) {
34+ window . showErrorMessage ( 'Please open a Deepnote file first' ) ;
35+ return ;
36+ }
37+
38+ const notebookUri = activeEditor . notebook . uri ;
39+ const rawContent = await workspace . fs . readFile ( notebookUri ) ;
40+ const contentString = Buffer . from ( rawContent ) . toString ( 'utf8' ) ;
41+
42+ try {
43+ const yaml = await import ( 'js-yaml' ) ;
44+ const deepnoteProject = yaml . load ( contentString ) as DeepnoteProject ;
45+
46+ if ( ! deepnoteProject . project ?. notebooks ) {
47+ window . showErrorMessage ( 'Invalid Deepnote file: no notebooks found' ) ;
48+ return ;
49+ }
50+
51+ if ( deepnoteProject . project . notebooks . length === 1 ) {
52+ window . showInformationMessage ( 'This Deepnote file contains only one notebook' ) ;
53+ return ;
54+ }
55+
56+ const currentNotebookId = activeEditor . notebook . metadata ?. deepnoteNotebookId ;
57+
58+ interface NotebookQuickPickItem extends QuickPickItem {
59+ notebook : DeepnoteNotebook ;
60+ }
61+
62+ const items : NotebookQuickPickItem [ ] = deepnoteProject . project . notebooks . map ( notebook => ( {
63+ label : notebook . name ,
64+ description : `${ notebook . blocks . length } cells${ notebook . id === currentNotebookId ? ' (current)' : '' } ` ,
65+ detail : `ID: ${ notebook . id } ${ notebook . workingDirectory ? ` | Working Directory: ${ notebook . workingDirectory } ` : '' } ` ,
66+ notebook
67+ } ) ) ;
68+
69+ const selectedItem = await window . showQuickPick ( items , {
70+ placeHolder : 'Select a notebook to switch to' ,
71+ title : 'Switch Notebook'
72+ } ) ;
73+
74+ if ( selectedItem && selectedItem . notebook . id !== currentNotebookId ) {
75+ // Create new cells from the selected notebook
76+ const serializer = new DeepnoteNotebookSerializer ( ) ;
77+ const cells = serializer . convertBlocksToCells ( selectedItem . notebook . blocks ) ;
78+
79+ // Create a workspace edit to replace all cells
80+ const edit = new WorkspaceEdit ( ) ;
81+ const notebookEdit = NotebookEdit . replaceCells (
82+ new NotebookRange ( 0 , activeEditor . notebook . cellCount ) ,
83+ cells
84+ ) ;
85+
86+ // Also update metadata to reflect the new notebook
87+ const metadataEdit = NotebookEdit . updateNotebookMetadata ( {
88+ ...activeEditor . notebook . metadata ,
89+ deepnoteNotebookId : selectedItem . notebook . id ,
90+ deepnoteNotebookName : selectedItem . notebook . name
91+ } ) ;
92+
93+ edit . set ( notebookUri , [ notebookEdit , metadataEdit ] ) ;
94+
95+ // Apply the edit
96+ const success = await workspace . applyEdit ( edit ) ;
97+
98+ if ( success ) {
99+ // Store the selected notebook ID for future reference
100+ const fileId = deepnoteProject . project . id ;
101+ DeepnoteNotebookSerializer . setSelectedNotebookForUri ( fileId , selectedItem . notebook . id ) ;
102+
103+ window . showInformationMessage ( `Switched to notebook: ${ selectedItem . notebook . name } ` ) ;
104+ } else {
105+ window . showErrorMessage ( 'Failed to switch notebook' ) ;
106+ }
107+ }
108+ } catch ( error ) {
109+ window . showErrorMessage ( `Error switching notebook: ${ error instanceof Error ? error . message : 'Unknown error' } ` ) ;
110+ }
22111 }
23112}
0 commit comments