3
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
4
*--------------------------------------------------------------------------------------------*/
5
5
6
- import { VSBuffer } from 'vs/base/common/buffer' ;
7
6
import { Event } from 'vs/base/common/event' ;
8
7
import { IReference } from 'vs/base/common/lifecycle' ;
9
8
import * as paths from 'vs/base/common/path' ;
10
- import { isEqual } from 'vs/base/common/resources' ;
9
+ import { isEqual , joinPath } from 'vs/base/common/resources' ;
11
10
import { URI } from 'vs/base/common/uri' ;
11
+ import { PLAINTEXT_LANGUAGE_ID } from 'vs/editor/common/languages/modesRegistry' ;
12
12
import { IResolvedTextEditorModel , ITextModelService } from 'vs/editor/common/services/resolverService' ;
13
+ import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs' ;
13
14
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation' ;
14
- import { IUntypedEditorInput } from 'vs/workbench/common/editor' ;
15
+ import { EditorInputCapabilities , GroupIdentifier , ISaveOptions , IUntypedEditorInput } from 'vs/workbench/common/editor' ;
15
16
import { EditorInput } from 'vs/workbench/common/editor/editorInput' ;
16
17
import { IInteractiveDocumentService } from 'vs/workbench/contrib/interactive/browser/interactiveDocumentService' ;
17
18
import { IInteractiveHistoryService } from 'vs/workbench/contrib/interactive/browser/interactiveHistoryService' ;
18
- import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel' ;
19
- import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel' ;
20
- import { CellKind , ICellDto2 , IOutputDto , IResolvedNotebookEditorModel , NotebookCellCollapseState , NotebookCellInternalMetadata , NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon' ;
19
+ import { IResolvedNotebookEditorModel } from 'vs/workbench/contrib/notebook/common/notebookCommon' ;
21
20
import { ICompositeNotebookEditorInput , NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput' ;
21
+ import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService' ;
22
22
23
23
export class InteractiveEditorInput extends EditorInput implements ICompositeNotebookEditorInput {
24
- static create ( instantiationService : IInstantiationService , resource : URI , inputResource : URI , title ?: string ) {
25
- return instantiationService . createInstance ( InteractiveEditorInput , resource , inputResource , title ) ;
24
+ static create ( instantiationService : IInstantiationService , resource : URI , inputResource : URI , title ?: string , language ?: string ) {
25
+ return instantiationService . createInstance ( InteractiveEditorInput , resource , inputResource , title , language ) ;
26
26
}
27
27
28
28
static readonly ID : string = 'workbench.input.interactive' ;
@@ -37,6 +37,11 @@ export class InteractiveEditorInput extends EditorInput implements ICompositeNot
37
37
38
38
private _initTitle ?: string ;
39
39
40
+ get language ( ) {
41
+ return this . _inputModelRef ?. object . textEditorModel . getLanguageId ( ) ?? this . _initLanguage ;
42
+ }
43
+ private _initLanguage ?: string ;
44
+
40
45
private _notebookEditorInput : NotebookEditorInput ;
41
46
get notebookEditorInput ( ) {
42
47
return this . _notebookEditorInput ;
@@ -74,17 +79,20 @@ export class InteractiveEditorInput extends EditorInput implements ICompositeNot
74
79
resource : URI ,
75
80
inputResource : URI ,
76
81
title : string | undefined ,
82
+ languageId : string | undefined ,
77
83
@IInstantiationService instantiationService : IInstantiationService ,
78
84
@ITextModelService textModelService : ITextModelService ,
79
-
80
85
@IInteractiveDocumentService interactiveDocumentService : IInteractiveDocumentService ,
81
- @IInteractiveHistoryService historyService : IInteractiveHistoryService
86
+ @IInteractiveHistoryService historyService : IInteractiveHistoryService ,
87
+ @INotebookService private readonly _notebookService : INotebookService ,
88
+ @IFileDialogService private readonly _fileDialogService : IFileDialogService
82
89
) {
83
90
const input = NotebookEditorInput . create ( instantiationService , resource , 'interactive' , { } ) ;
84
91
super ( ) ;
85
92
this . _notebookEditorInput = input ;
86
93
this . _register ( this . _notebookEditorInput ) ;
87
94
this . _initTitle = title ;
95
+ this . _initLanguage = languageId ;
88
96
this . _resource = resource ;
89
97
this . _inputResource = inputResource ;
90
98
this . _inputResolver = null ;
@@ -113,8 +121,10 @@ export class InteractiveEditorInput extends EditorInput implements ICompositeNot
113
121
this . _register ( this . primary . onDidChangeCapabilities ( ( ) => this . _onDidChangeCapabilities . fire ( ) ) ) ;
114
122
}
115
123
116
- override isDirty ( ) {
117
- return false ;
124
+ override get capabilities ( ) : EditorInputCapabilities {
125
+ return EditorInputCapabilities . Untitled
126
+ | EditorInputCapabilities . Readonly
127
+ | EditorInputCapabilities . Scratchpad ;
118
128
}
119
129
120
130
private async _resolveEditorModel ( ) {
@@ -134,30 +144,58 @@ export class InteractiveEditorInput extends EditorInput implements ICompositeNot
134
144
return this . _inputResolver ;
135
145
}
136
146
137
- this . _inputResolver = this . _resolveEditorModel ( ) . then ( editorModel => {
138
- if ( this . _data ) {
139
- editorModel ?. notebook . reset ( this . _data . notebookData . cells . map ( ( cell : ISerializedCell ) => deserializeCell ( cell ) ) , this . _data . notebookData . metadata , this . _data . notebookData . transientOptions ) ;
140
- }
141
-
142
- return editorModel ;
143
- } ) ;
147
+ this . _inputResolver = this . _resolveEditorModel ( ) ;
144
148
145
149
return this . _inputResolver ;
146
150
}
147
151
148
- async resolveInput ( language : string ) {
152
+ async resolveInput ( language ? : string ) {
149
153
if ( this . _inputModelRef ) {
150
154
return this . _inputModelRef . object . textEditorModel ;
151
155
}
152
156
153
- this . _interactiveDocumentService . willCreateInteractiveDocument ( this . resource ! , this . inputResource , language ) ;
157
+ const resolvedLanguage = language ?? this . _initLanguage ?? PLAINTEXT_LANGUAGE_ID ;
158
+ this . _interactiveDocumentService . willCreateInteractiveDocument ( this . resource ! , this . inputResource , resolvedLanguage ) ;
154
159
this . _inputModelRef = await this . _textModelService . createModelReference ( this . inputResource ) ;
155
160
156
- if ( this . _data && this . _data . inputData ) {
157
- this . _inputModelRef . object . textEditorModel . setValue ( this . _data . inputData . value ) ;
161
+ return this . _inputModelRef . object . textEditorModel ;
162
+ }
163
+
164
+ override async save ( group : GroupIdentifier , options ?: ISaveOptions ) : Promise < EditorInput | IUntypedEditorInput | undefined > {
165
+ if ( this . _editorModelReference ) {
166
+
167
+ if ( this . hasCapability ( EditorInputCapabilities . Untitled ) ) {
168
+ return this . saveAs ( group , options ) ;
169
+ } else {
170
+ await this . _editorModelReference . save ( options ) ;
171
+ }
172
+
173
+ return this ;
158
174
}
159
175
160
- return this . _inputModelRef . object . textEditorModel ;
176
+ return undefined ;
177
+ }
178
+
179
+ override async saveAs ( group : GroupIdentifier , options ?: ISaveOptions ) : Promise < IUntypedEditorInput | undefined > {
180
+ if ( ! this . _editorModelReference ) {
181
+ return undefined ;
182
+ }
183
+
184
+ const provider = this . _notebookService . getContributedNotebookType ( 'interactive' ) ;
185
+
186
+ if ( ! provider ) {
187
+ return undefined ;
188
+ }
189
+
190
+ const filename = this . getName ( ) + '.ipynb' ;
191
+ const pathCandidate = joinPath ( await this . _fileDialogService . defaultFilePath ( ) , filename ) ;
192
+
193
+ const target = await this . _fileDialogService . pickFileToSave ( pathCandidate , options ?. availableFileSystems ) ;
194
+ if ( ! target ) {
195
+ return undefined ; // save cancelled
196
+ }
197
+
198
+ return await this . _editorModelReference . saveAs ( target ) ;
161
199
}
162
200
163
201
override matches ( otherInput : EditorInput | IUntypedEditorInput ) : boolean {
@@ -181,37 +219,6 @@ export class InteractiveEditorInput extends EditorInput implements ICompositeNot
181
219
return basename . substr ( 0 , basename . length - paths . extname ( p ) . length ) ;
182
220
}
183
221
184
- getSerialization ( ) : { notebookData : any | undefined ; inputData : any | undefined } {
185
- return {
186
- notebookData : this . _serializeNotebook ( this . _editorModelReference ?. notebook ) ,
187
- inputData : this . _inputModelRef ? {
188
- value : this . _inputModelRef . object . textEditorModel . getValue ( ) ,
189
- language : this . _inputModelRef . object . textEditorModel . getLanguageId ( )
190
- } : undefined
191
- } ;
192
- }
193
-
194
- private _data : { notebookData : any | undefined ; inputData : any | undefined } | undefined ;
195
-
196
- async restoreSerialization ( data : { notebookData : any | undefined ; inputData : any | undefined } | undefined ) {
197
- this . _data = data ;
198
- }
199
-
200
- private _serializeNotebook ( notebook ?: NotebookTextModel ) {
201
- if ( ! notebook ) {
202
- return undefined ;
203
- }
204
-
205
- const cells = notebook . cells . map ( cell => serializeCell ( cell ) ) ;
206
-
207
- return {
208
- cells : cells ,
209
- metadata : notebook . metadata ,
210
- transientOptions : notebook . transientOptions
211
- } ;
212
- }
213
-
214
-
215
222
override dispose ( ) {
216
223
// we support closing the interactive window without prompt, so the editor model should not be dirty
217
224
this . _editorModelReference ?. revert ( { soft : true } ) ;
@@ -229,74 +236,3 @@ export class InteractiveEditorInput extends EditorInput implements ICompositeNot
229
236
return this . _historyService ;
230
237
}
231
238
}
232
-
233
- /**
234
- * Serialization of interactive notebook.
235
- * This is not placed in notebook land as regular notebooks are handled by file service directly.
236
- */
237
-
238
- interface ISerializedOutputItem {
239
- readonly mime : string ;
240
- readonly data : number [ ] ;
241
- }
242
-
243
- interface ISerializedCellOutput {
244
- outputs : ISerializedOutputItem [ ] ;
245
- metadata ?: Record < string , any > ;
246
- outputId : string ;
247
- }
248
-
249
- export interface ISerializedCell {
250
- source : string ;
251
- language : string ;
252
- mime : string | undefined ;
253
- cellKind : CellKind ;
254
- outputs : ISerializedCellOutput [ ] ;
255
- metadata ?: NotebookCellMetadata ;
256
- internalMetadata ?: NotebookCellInternalMetadata ;
257
- collapseState ?: NotebookCellCollapseState ;
258
- }
259
-
260
- function serializeCell ( cell : NotebookCellTextModel ) : ISerializedCell {
261
- return {
262
- cellKind : cell . cellKind ,
263
- language : cell . language ,
264
- metadata : cell . metadata ,
265
- mime : cell . mime ,
266
- outputs : cell . outputs . map ( output => serializeCellOutput ( output ) ) ,
267
- source : cell . getValue ( )
268
- } ;
269
- }
270
-
271
- function deserializeCell ( cell : ISerializedCell ) : ICellDto2 {
272
- return {
273
- cellKind : cell . cellKind ,
274
- source : cell . source ,
275
- language : cell . language ,
276
- metadata : cell . metadata ,
277
- mime : cell . mime ,
278
- outputs : cell . outputs . map ( ( output ) => deserializeCellOutput ( output ) )
279
- } ;
280
- }
281
-
282
- function serializeCellOutput ( output : IOutputDto ) : ISerializedCellOutput {
283
- return {
284
- outputId : output . outputId ,
285
- outputs : output . outputs . map ( ot => ( {
286
- mime : ot . mime ,
287
- data : ot . data . buffer ? Array . from ( ot . data . buffer ) : [ ]
288
- } ) ) ,
289
- metadata : output . metadata
290
- } ;
291
- }
292
-
293
- function deserializeCellOutput ( output : ISerializedCellOutput ) : IOutputDto {
294
- return {
295
- outputId : output . outputId ,
296
- outputs : output . outputs . map ( ot => ( {
297
- mime : ot . mime ,
298
- data : VSBuffer . fromByteArray ( ot . data )
299
- } ) ) ,
300
- metadata : output . metadata
301
- } ;
302
- }
0 commit comments