@@ -5,10 +5,10 @@ import {
55} from 'vscode'
66
77import {
8- asWorksheetRunParams , WorksheetRunRequest , WorksheetRunParams , WorksheetRunResult ,
8+ asWorksheetRunParams , WorksheetRunRequest , WorksheetRunResult ,
99 WorksheetPublishOutputParams , WorksheetPublishOutputNotification
1010} from './protocol'
11- import { BaseLanguageClient , DocumentSelector } from 'vscode-languageclient'
11+ import { BaseLanguageClient } from 'vscode-languageclient'
1212import { Disposable } from 'vscode-jsonrpc'
1313
1414/**
@@ -23,11 +23,26 @@ export const worksheetRunKey = "dotty.worksheet.run"
2323 */
2424export const worksheetCancelKey = "dotty.worksheet.cancel"
2525
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+
2638/** A worksheet managed by vscode */
2739class Worksheet implements Disposable {
2840
41+ /** The version of this document the last time it was run */
42+ private runVersion : number = - 1
43+
2944 /** All decorations that have been added so far */
30- private decorationTypes : vscode . TextEditorDecorationType [ ] = [ ]
45+ private decorations : Decoration [ ] = [ ]
3146
3247 /** The number of blank lines that have been inserted to fit the output so far. */
3348 private insertedLines : number = 0
@@ -62,9 +77,11 @@ class Worksheet implements Disposable {
6277
6378 /** Remove all decorations, and resets this worksheet. */
6479 private reset ( ) : void {
65- this . decorationTypes . forEach ( decoration => decoration . dispose ( ) )
80+ this . decorations . forEach ( decoration => decoration . decorationType . dispose ( ) )
81+ this . decorations = [ ]
6682 this . insertedLines = 0
6783 this . decoratedLines . clear ( )
84+ this . runVersion = - 1
6885 this . margin = this . longestLine ( ) + 5
6986 }
7087
@@ -112,6 +129,7 @@ class Worksheet implements Disposable {
112129 const edit = new vscode . WorkspaceEdit ( )
113130 edit . set ( this . document . uri , textEdits )
114131 vscode . workspace . applyEdit ( edit ) . then ( editSucceeded => {
132+ this . runVersion = this . document . version
115133 if ( editSucceeded && ! token . isCancellationRequested )
116134 resolve ( vscode . window . withProgress ( {
117135 location : ProgressLocation . Window ,
@@ -135,7 +153,8 @@ class Worksheet implements Disposable {
135153 }
136154
137155 /**
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.
139158 *
140159 * @param lineNumber The number of the line in the source that produced the result.
141160 * @param runResult The result itself.
@@ -144,7 +163,7 @@ class Worksheet implements Disposable {
144163 * @return A `Thenable` that will insert necessary lines to fit the output
145164 * and display the decorations upon completion.
146165 */
147- public displayResult ( lineNumber : number , runResult : string , editor : vscode . TextEditor ) {
166+ public displayAndSaveResult ( lineNumber : number , runResult : string , editor : vscode . TextEditor ) {
148167 const resultLines = runResult . trim ( ) . split ( / \r \n | \r | \n / g)
149168
150169 // The line where the next decoration should be put.
@@ -160,23 +179,41 @@ class Worksheet implements Disposable {
160179 const editPos = new vscode . Position ( actualLine + 1 , 0 ) // add after the line
161180 addNewLinesEdit . insert ( editor . document . uri , editPos , "\n" . repeat ( linesToInsert ) )
162181 this . insertedLines += linesToInsert
182+ // Increase the `runVersion`, because the text edit will increase the document's version
183+ this . runVersion += 1
163184 }
164185
165186 return vscode . workspace . applyEdit ( addNewLinesEdit ) . then ( _ => {
166187 for ( let line of resultLines ) {
167188 const decorationPosition = new vscode . Position ( actualLine , 0 )
168189 const decorationMargin = this . margin - editor . document . lineAt ( actualLine ) . text . length
169190 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+
171194 this . decoratedLines . add ( actualLine )
195+ this . decorations . push ( decoration )
172196
173- const decoration = { range : new vscode . Range ( decorationPosition , decorationPosition ) , hoverMessage : line }
174- editor . setDecorations ( decorationType , [ decoration ] )
197+ editor . setDecorations ( decorationType , [ decorationOptions ] )
175198 actualLine += 1
176199 }
177200 } )
178201 }
179202
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+
180217 /**
181218 * Create a new `TextEditorDecorationType` showing `text`. The decoration
182219 * will appear `margin` characters after the end of the line.
@@ -307,6 +344,14 @@ export class WorksheetProvider implements Disposable {
307344 this . worksheets . delete ( document )
308345 }
309346 } ) ,
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+ } ) ,
310355 vscode . commands . registerCommand ( worksheetRunKey , ( ) => {
311356 this . callOnActiveWorksheet ( w => w . run ( ) )
312357 } ) ,
@@ -375,7 +420,7 @@ export class WorksheetProvider implements Disposable {
375420 if ( editor ) {
376421 const worksheet = this . worksheetFor ( editor . document )
377422 if ( worksheet ) {
378- worksheet . displayResult ( output . line - 1 , output . content , editor )
423+ worksheet . displayAndSaveResult ( output . line - 1 , output . content , editor )
379424 }
380425 }
381426 }
0 commit comments