@@ -5,10 +5,10 @@ import {
5
5
} from 'vscode'
6
6
7
7
import {
8
- asWorksheetRunParams , WorksheetRunRequest , WorksheetRunParams , WorksheetRunResult ,
8
+ asWorksheetRunParams , WorksheetRunRequest , WorksheetRunResult ,
9
9
WorksheetPublishOutputParams , WorksheetPublishOutputNotification
10
10
} from './protocol'
11
- import { BaseLanguageClient , DocumentSelector } from 'vscode-languageclient'
11
+ import { BaseLanguageClient } from 'vscode-languageclient'
12
12
import { Disposable } from 'vscode-jsonrpc'
13
13
14
14
/**
@@ -23,11 +23,26 @@ export const worksheetRunKey = "dotty.worksheet.run"
23
23
*/
24
24
export const worksheetCancelKey = "dotty.worksheet.cancel"
25
25
26
+ /**
27
+ * A wrapper around the information that VSCode needs to display text decorations.
28
+ *
29
+ * @param decorationType The styling options of this decoration
30
+ * @param decorationOptions The options of this decoraiton.
31
+ */
32
+ class Decoration {
33
+ constructor ( readonly decorationType : vscode . TextEditorDecorationType ,
34
+ readonly decorationOptions : vscode . DecorationOptions ) {
35
+ }
36
+ }
37
+
26
38
/** A worksheet managed by vscode */
27
39
class Worksheet implements Disposable {
28
40
41
+ /** The version of this document the last time it was run */
42
+ private runVersion : number = - 1
43
+
29
44
/** All decorations that have been added so far */
30
- private decorationTypes : vscode . TextEditorDecorationType [ ] = [ ]
45
+ private decorations : Decoration [ ] = [ ]
31
46
32
47
/** The number of blank lines that have been inserted to fit the output so far. */
33
48
private insertedLines : number = 0
@@ -62,9 +77,11 @@ class Worksheet implements Disposable {
62
77
63
78
/** Remove all decorations, and resets this worksheet. */
64
79
private reset ( ) : void {
65
- this . decorationTypes . forEach ( decoration => decoration . dispose ( ) )
80
+ this . decorations . forEach ( decoration => decoration . decorationType . dispose ( ) )
81
+ this . decorations = [ ]
66
82
this . insertedLines = 0
67
83
this . decoratedLines . clear ( )
84
+ this . runVersion = - 1
68
85
this . margin = this . longestLine ( ) + 5
69
86
}
70
87
@@ -112,6 +129,7 @@ class Worksheet implements Disposable {
112
129
const edit = new vscode . WorkspaceEdit ( )
113
130
edit . set ( this . document . uri , textEdits )
114
131
vscode . workspace . applyEdit ( edit ) . then ( editSucceeded => {
132
+ this . runVersion = this . document . version
115
133
if ( editSucceeded && ! token . isCancellationRequested )
116
134
resolve ( vscode . window . withProgress ( {
117
135
location : ProgressLocation . Window ,
@@ -135,7 +153,8 @@ class Worksheet implements Disposable {
135
153
}
136
154
137
155
/**
138
- * Parse and display the result of running part of this worksheet.
156
+ * Parse and display the result of running part of this worksheet. The result is saved so that it
157
+ * can be restored if this buffer is closed.
139
158
*
140
159
* @param lineNumber The number of the line in the source that produced the result.
141
160
* @param runResult The result itself.
@@ -144,7 +163,7 @@ class Worksheet implements Disposable {
144
163
* @return A `Thenable` that will insert necessary lines to fit the output
145
164
* and display the decorations upon completion.
146
165
*/
147
- public displayResult ( lineNumber : number , runResult : string , editor : vscode . TextEditor ) {
166
+ public displayAndSaveResult ( lineNumber : number , runResult : string , editor : vscode . TextEditor ) {
148
167
const resultLines = runResult . trim ( ) . split ( / \r \n | \r | \n / g)
149
168
150
169
// The line where the next decoration should be put.
@@ -160,23 +179,41 @@ class Worksheet implements Disposable {
160
179
const editPos = new vscode . Position ( actualLine + 1 , 0 ) // add after the line
161
180
addNewLinesEdit . insert ( editor . document . uri , editPos , "\n" . repeat ( linesToInsert ) )
162
181
this . insertedLines += linesToInsert
182
+ // Increase the `runVersion`, because the text edit will increase the document's version
183
+ this . runVersion += 1
163
184
}
164
185
165
186
return vscode . workspace . applyEdit ( addNewLinesEdit ) . then ( _ => {
166
187
for ( let line of resultLines ) {
167
188
const decorationPosition = new vscode . Position ( actualLine , 0 )
168
189
const decorationMargin = this . margin - editor . document . lineAt ( actualLine ) . text . length
169
190
const decorationType = this . createDecoration ( decorationMargin , line )
170
- this . decorationTypes . push ( decorationType )
191
+ const decorationOptions = { range : new vscode . Range ( decorationPosition , decorationPosition ) , hoverMessage : line }
192
+ const decoration = new Decoration ( decorationType , decorationOptions )
193
+
171
194
this . decoratedLines . add ( actualLine )
195
+ this . decorations . push ( decoration )
172
196
173
- const decoration = { range : new vscode . Range ( decorationPosition , decorationPosition ) , hoverMessage : line }
174
- editor . setDecorations ( decorationType , [ decoration ] )
197
+ editor . setDecorations ( decorationType , [ decorationOptions ] )
175
198
actualLine += 1
176
199
}
177
200
} )
178
201
}
179
202
203
+ /**
204
+ * Restore the decorations that belong to this worksheet in `editor`. If the document has been
205
+ * changed, since the last run of the worksheet, the decorations won't be added.
206
+ *
207
+ * @param editor The editor where to display the decorations.
208
+ */
209
+ public restoreDecorations ( editor : vscode . TextEditor ) {
210
+ if ( editor . document . version == this . runVersion ) {
211
+ this . decorations . forEach ( decoration => {
212
+ editor . setDecorations ( decoration . decorationType , [ decoration . decorationOptions ] )
213
+ } )
214
+ }
215
+ }
216
+
180
217
/**
181
218
* Create a new `TextEditorDecorationType` showing `text`. The decoration
182
219
* will appear `margin` characters after the end of the line.
@@ -307,6 +344,14 @@ export class WorksheetProvider implements Disposable {
307
344
this . worksheets . delete ( document )
308
345
}
309
346
} ) ,
347
+ vscode . window . onDidChangeActiveTextEditor ( editor => {
348
+ if ( editor ) {
349
+ const worksheet = this . worksheetFor ( editor . document )
350
+ if ( worksheet ) {
351
+ worksheet . restoreDecorations ( editor )
352
+ }
353
+ }
354
+ } ) ,
310
355
vscode . commands . registerCommand ( worksheetRunKey , ( ) => {
311
356
this . callOnActiveWorksheet ( w => w . run ( ) )
312
357
} ) ,
@@ -375,7 +420,7 @@ export class WorksheetProvider implements Disposable {
375
420
if ( editor ) {
376
421
const worksheet = this . worksheetFor ( editor . document )
377
422
if ( worksheet ) {
378
- worksheet . displayResult ( output . line - 1 , output . content , editor )
423
+ worksheet . displayAndSaveResult ( output . line - 1 , output . content , editor )
379
424
}
380
425
}
381
426
}
0 commit comments