Skip to content

Commit 701e8ea

Browse files
committed
vscode: Add Worksheet class
It is used to represent the worksheets managed by vscode, instead of having several global variables.
1 parent 471a059 commit 701e8ea

File tree

1 file changed

+74
-77
lines changed

1 file changed

+74
-77
lines changed

vscode-dotty/src/worksheet.ts

Lines changed: 74 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,40 @@
1-
'use strict'
2-
31
import * as vscode from 'vscode'
42
import { LanguageClient } from 'vscode-languageclient'
53

6-
/** All decorations that have been added so far */
7-
let worksheetDecorationTypes: Map<vscode.TextDocument, vscode.TextEditorDecorationType[]> = new Map<vscode.TextDocument, vscode.TextEditorDecorationType[]>()
4+
/** A worksheet managed by vscode */
5+
class Worksheet {
6+
7+
constructor(document: vscode.TextDocument) {
8+
this.document = document
9+
}
10+
11+
/** The text document that this worksheet represents. */
12+
readonly document: vscode.TextDocument
813

9-
/** The number of blank lines that have been inserted to fit the output so far. */
10-
let worksheetInsertedLines: Map<vscode.TextDocument, number> = new Map<vscode.TextDocument, number>()
14+
/** All decorations that have been added so far */
15+
decorationTypes: vscode.TextEditorDecorationType[] = []
1116

12-
/** The minimum margin to add so that the decoration is shown after all text. */
13-
let worksheetMargin: Map<vscode.TextDocument, number> = new Map<vscode.TextDocument, number>()
17+
/** The number of blank lines that have been inserted to fit the output so far. */
18+
insertedLines: number = 0
1419

15-
/** Whether the given worksheet has finished evaluating. */
16-
let worksheetFinished: Map<vscode.TextDocument, boolean> = new Map<vscode.TextDocument, boolean>()
20+
/** The minimum margin to add so that the decoration is shown after all text. */
21+
margin: number = 0
22+
23+
/** Whether this worksheet has finished evaluating. */
24+
finished: boolean = false
25+
26+
/** Remove all decorations and resets this worksheet. */
27+
reset() {
28+
this.decorationTypes.forEach(decoration => decoration.dispose())
29+
this.insertedLines = 0
30+
this.margin = longestLine(this.document) + 5
31+
this.finished = false
32+
}
33+
34+
}
35+
36+
/** All the worksheets */
37+
let worksheets: Map<vscode.TextDocument, Worksheet> = new Map<vscode.TextDocument, Worksheet>()
1738

1839
/**
1940
* The command key for evaluating a worksheet. Exposed to users as
@@ -47,9 +68,9 @@ export function isWorksheet(document: vscode.TextDocument): boolean {
4768
export function evaluateCommand() {
4869
const editor = vscode.window.activeTextEditor
4970
if (editor) {
50-
const document = editor.document
51-
if (isWorksheet(document)) {
52-
showWorksheetProgress(document)
71+
const worksheet = worksheets.get(editor.document)
72+
if (worksheet) {
73+
showWorksheetProgress(worksheet)
5374
}
5475
}
5576
}
@@ -69,19 +90,20 @@ export function worksheetSave(client: LanguageClient) {
6990
const editor = vscode.window.activeTextEditor
7091
if (editor) {
7192
const document = editor.document
72-
if (isWorksheet(document)) {
73-
if (document.isDirty) document.save()
74-
else {
75-
_prepareWorksheet(document).then(_ => {
76-
if (document.isDirty) document.save()
77-
else {
78-
client.sendNotification("textDocument/didSave", {
79-
textDocument: { uri: document.uri.toString() }
80-
})
81-
showWorksheetProgress(document)
82-
}
83-
})
84-
}
93+
const worksheet = worksheets.get(document) || new Worksheet(document)
94+
worksheets.set(document, worksheet)
95+
96+
if (document.isDirty) document.save()
97+
else {
98+
_prepareWorksheet(worksheet).then(_ => {
99+
if (document.isDirty) document.save()
100+
else {
101+
client.sendNotification("textDocument/didSave", {
102+
textDocument: { uri: document.uri.toString() }
103+
})
104+
showWorksheetProgress(worksheet)
105+
}
106+
})
85107
}
86108
}
87109
}
@@ -96,26 +118,18 @@ export function worksheetSave(client: LanguageClient) {
96118
* @param event `TextDocumentWillSaveEvent`.
97119
*/
98120
export function prepareWorksheet(event: vscode.TextDocumentWillSaveEvent) {
99-
const document = event.document
100-
const setup = _prepareWorksheet(document)
101-
event.waitUntil(setup)
121+
const worksheet = worksheets.get(event.document)
122+
if (worksheet) {
123+
const setup = _prepareWorksheet(worksheet)
124+
event.waitUntil(setup)
125+
}
102126
}
103127

104-
function _prepareWorksheet(document: vscode.TextDocument) {
105-
if (isWorksheet(document)) {
106-
return removeRedundantBlankLines(document)
107-
.then(_ => {
108-
removeDecorations(document)
109-
worksheetMargin.set(document, longestLine(document) + 5)
110-
worksheetInsertedLines.set(document, 0)
111-
worksheetFinished.set(document, false)
112-
})
113-
} else {
114-
return Promise.resolve()
115-
}
128+
function _prepareWorksheet(worksheet: Worksheet) {
129+
return removeRedundantBlankLines(worksheet.document).then(_ => worksheet.reset())
116130
}
117131

118-
function showWorksheetProgress(document: vscode.TextDocument) {
132+
function showWorksheetProgress(worksheet: Worksheet) {
119133
return vscode.window.withProgress({
120134
location: vscode.ProgressLocation.Notification,
121135
title: "Evaluating worksheet",
@@ -125,10 +139,7 @@ function showWorksheetProgress(document: vscode.TextDocument) {
125139
vscode.commands.executeCommand(worksheetCancelEvaluationKey)
126140
})
127141

128-
function isFinished() {
129-
return worksheetFinished.get(document) || false
130-
}
131-
return wait(isFinished, 500)
142+
return wait(() => worksheet.finished, 500)
132143
})
133144
}
134145

@@ -172,11 +183,15 @@ export function worksheetHandleMessage(message: string) {
172183
})
173184

174185
if (editor) {
175-
let payload = message.slice(editor.document.uri.toString().length)
176-
if (payload == "FINISHED") {
177-
worksheetFinished.set(editor.document, true)
178-
} else {
179-
worksheetDisplayResult(payload, editor)
186+
const worksheet = worksheets.get(editor.document)
187+
188+
if (worksheet) {
189+
let payload = message.slice(editor.document.uri.toString().length)
190+
if (payload == "FINISHED") {
191+
worksheet.finished = true
192+
} else {
193+
worksheetDisplayResult(payload, worksheet, editor)
194+
}
180195
}
181196
}
182197
}
@@ -222,16 +237,6 @@ function longestLine(document: vscode.TextDocument) {
222237
return maxLength
223238
}
224239

225-
/**
226-
* Remove all decorations added by worksheet evaluation.
227-
*/
228-
function removeDecorations(document: vscode.TextDocument) {
229-
const decorationTypes = worksheetDecorationTypes.get(document) || []
230-
decorationTypes.forEach(decoration =>
231-
decoration.dispose()
232-
)
233-
}
234-
235240
/**
236241
* Remove the repeated blank lines in the source.
237242
*
@@ -293,31 +298,24 @@ function removeRedundantBlankLines(document: vscode.TextDocument) {
293298
*
294299
* @see worksheetCreateDecoration
295300
*
296-
* @param message The message to parse.
297-
* @param ed The editor where to display the result.
301+
* @param message The message to parse.
302+
* @param worksheet The worksheet that receives the result.
303+
* @param editor The editor where to display the result.
298304
* @return A `Thenable` that will insert necessary lines to fit the output
299305
* and display the decorations upon completion.
300306
*/
301-
function worksheetDisplayResult(message: string, editor: vscode.TextEditor) {
307+
function worksheetDisplayResult(message: string, worksheet: Worksheet, editor: vscode.TextEditor) {
302308

303309
const colonIndex = message.indexOf(":")
304310
const lineNumber = parseInt(message.slice(0, colonIndex)) - 1 // lines are 0-indexed
305311
const evalResult = message.slice(colonIndex + 1)
306312
const resultLines = evalResult.trim().split(/\r\n|\r|\n/g)
307-
const margin = worksheetMargin.get(editor.document) || 0
308-
309-
let insertedLines = worksheetInsertedLines.get(editor.document) || 0
310-
311-
let decorationTypes = worksheetDecorationTypes.get(editor.document)
312-
if (!decorationTypes) {
313-
decorationTypes = []
314-
worksheetDecorationTypes.set(editor.document, decorationTypes)
315-
}
313+
const margin = worksheet.margin
316314

317315
// The line where the next decoration should be put.
318316
// It's the number of the line that produced the output, plus the number
319317
// of lines that we've inserted so far.
320-
let actualLine = lineNumber + insertedLines
318+
let actualLine = lineNumber + worksheet.insertedLines
321319

322320
// If the output has more than one line, we need to insert blank lines
323321
// below the line that produced the output to fit the output.
@@ -326,16 +324,15 @@ function worksheetDisplayResult(message: string, editor: vscode.TextEditor) {
326324
const linesToInsert = resultLines.length - 1
327325
const editPos = new vscode.Position(actualLine + 1, 0) // add after the line
328326
addNewLinesEdit.insert(editor.document.uri, editPos, "\n".repeat(linesToInsert))
329-
insertedLines += linesToInsert
330-
worksheetInsertedLines.set(editor.document, insertedLines)
327+
worksheet.insertedLines += linesToInsert
331328
}
332329

333330
return vscode.workspace.applyEdit(addNewLinesEdit).then(_ => {
334331
for (let line of resultLines) {
335332
const decorationPosition = new vscode.Position(actualLine, 0)
336333
const decorationMargin = margin - editor.document.lineAt(actualLine).text.length
337334
const decorationType = worksheetCreateDecoration(decorationMargin, line)
338-
if (decorationTypes) decorationTypes.push(decorationType)
335+
worksheet.decorationTypes.push(decorationType)
339336

340337
const decoration = { range: new vscode.Range(decorationPosition, decorationPosition), hoverMessage: line }
341338
editor.setDecorations(decorationType, [decoration])

0 commit comments

Comments
 (0)