Skip to content

Commit 7b32739

Browse files
authored
feat: reset button (#50)
* chore: remove old code * refactor: cleanup code * refactor: avoid nullable in Editor * refactor: make private * feat: update code on reset
1 parent 64323eb commit 7b32739

File tree

3 files changed

+58
-70
lines changed

3 files changed

+58
-70
lines changed

src/utils/editor.ts

Lines changed: 44 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -8,38 +8,46 @@ import { sendToFrontendWrapped } from "../commands/showPanel";
88
import { canonicaliseLocation } from "./misc";
99
import { codeAddPrepend, codeRemovePrepend } from "./editorUtils";
1010

11+
/**
12+
* Represents a VS Code editor associated with a Source Academy question.
13+
* Abstracts low level calling of VS Code APIs.
14+
*/
1115
export class Editor {
12-
editor?: vscode.TextEditor;
16+
private editor: vscode.TextEditor;
17+
private onChangeCallback?: (editor: Editor) => void;
18+
19+
// Data associated with TextEditor
20+
prepend: string;
21+
uri: string;
22+
23+
// Metadata relating to this question
1324
workspaceLocation: VscWorkspaceLocation;
1425
assessmentName: string;
1526
questionId: number;
16-
assessmentType: string | null = null;
17-
onChangeCallback?: (editor: Editor) => void;
18-
code: string | null = null;
19-
uri: string | null = null;
2027

21-
// For debugging purposes
22-
replaceTime: number = 0;
23-
nBursty: number = 0;
24-
25-
constructor(
28+
private constructor(
29+
editor: vscode.TextEditor,
30+
prepend: string,
31+
uri: string,
2632
workspaceLocation: VscWorkspaceLocation,
2733
assessmentName: string,
2834
questionId: number,
2935
) {
36+
this.editor = editor;
37+
this.prepend = prepend;
38+
this.uri = uri;
3039
this.workspaceLocation = workspaceLocation;
3140
this.assessmentName = assessmentName;
32-
this.assessmentType = this.assessmentType;
3341
this.questionId = questionId;
3442
}
3543

3644
/** For debugging purposes */
37-
log(text: string) {
38-
console.log(`${this.editor?.document.fileName.split("/").at(-1)} ${text}`);
45+
private log(text: string) {
46+
console.log(`${this.editor.document.fileName.split("/").at(-1)} ${text}`);
3947
}
4048

4149
getText() {
42-
return this.editor?.document.getText();
50+
return this.editor.document.getText();
4351
}
4452

4553
// TODO: This method is too loaded, it's not obvious it also shows the editor
@@ -50,19 +58,12 @@ export class Editor {
5058
prepend: string = "",
5159
initialCode: string = "",
5260
): Promise<Editor> {
53-
const self = new Editor(workspaceLocation, assessmentName, questionId);
54-
self.assessmentName = assessmentName;
55-
self.questionId = questionId;
56-
5761
const workspaceFolder = canonicaliseLocation(config.workspaceFolder);
58-
5962
const filePath = path.join(
6063
workspaceFolder,
6164
`${assessmentName}_${questionId}.js`,
6265
);
63-
6466
const uri = vscode.Uri.file(filePath);
65-
self.uri = uri.toString();
6667

6768
const contents = codeAddPrepend(initialCode, prepend);
6869

@@ -72,9 +73,6 @@ export class Editor {
7273
.then(
7374
(localCode) => {
7475
if (localCode !== contents) {
75-
self.log(
76-
"EXTENSION: Conflict detected between local and remote, prompting user to choose one",
77-
);
7876
vscode.window
7977
.showInformationMessage(
8078
[
@@ -87,15 +85,14 @@ export class Editor {
8785
.then(async (answer) => {
8886
// By default the code displayed is the local one
8987
if (answer === "Yes") {
90-
self.log("EXTENSION: Saving program from server to file");
9188
await vscode.workspace.fs.writeFile(
9289
uri,
9390
new TextEncoder().encode(contents),
9491
);
9592
} else if (answer === undefined) {
9693
// Modal cancelled
9794
const message = Messages.Text(
98-
self.workspaceLocation,
95+
workspaceLocation,
9996
codeRemovePrepend(localCode),
10097
);
10198
sendToFrontendWrapped(message);
@@ -104,7 +101,6 @@ export class Editor {
104101
}
105102
},
106103
async () => {
107-
self.log(`Opening file failed, creating at ${filePath}`);
108104
await vscode.workspace.fs.writeFile(
109105
uri,
110106
new TextEncoder().encode(contents),
@@ -116,79 +112,58 @@ export class Editor {
116112
preview: false,
117113
viewColumn: vscode.ViewColumn.One,
118114
});
115+
116+
// Programmatically set the language
119117
vscode.languages.setTextDocumentLanguage(editor.document, "source");
118+
119+
// Collapse the prepend section
120120
editor.selection = new vscode.Selection(
121121
editor.document.positionAt(0),
122122
editor.document.positionAt(1),
123123
);
124124
vscode.commands.executeCommand("editor.fold");
125125

126-
self.editor = editor;
126+
// Create wrapper
127+
const self = new Editor(
128+
editor,
129+
prepend,
130+
uri.toString(),
131+
workspaceLocation,
132+
assessmentName,
133+
questionId,
134+
);
135+
136+
// Register callback when contents changed
127137
vscode.workspace.onDidChangeTextDocument(
128138
(e: vscode.TextDocumentChangeEvent) => {
129139
if (!self.onChangeCallback) {
130140
return;
131141
}
132-
const text = editor.document.getText();
133142
if (e.contentChanges.length === 0) {
134143
self.log(`EXTENSION: Editor's code did not change, ignoring`);
135144
return;
136145
}
137-
if (Date.now() - self.replaceTime < 1000) {
138-
self.log(
139-
`EXTENSION: Ignoring change event, ${Date.now() - self.replaceTime}ms since last replace`,
140-
);
141-
return;
142-
}
143-
self.log(`EXTENSION: Editor's code changed!`);
144146
self.onChangeCallback(self);
145-
self.code = text;
146147
},
147148
);
149+
148150
return self;
149151
}
150152

151-
async replace(code: string, tag: string = "") {
152-
if (!this.editor) {
153-
return;
154-
}
155-
this.log(`EXTENSION: Editor's replace called by ${tag}: <<${code}>>`);
156-
if (this.nBursty > 5) {
157-
if (Date.now() - this.replaceTime < 5000) {
158-
this.log(`EXTENSION: TOO BURSTY`);
159-
return;
160-
}
161-
this.nBursty = 0;
162-
}
163-
if (Date.now() - this.replaceTime < 1000) {
164-
this.nBursty++;
165-
}
166-
// this.disableCallback = true;
153+
async replace(code: string) {
167154
const editor = this.editor;
168-
// Don't replace if the code is the same
155+
const contents = codeAddPrepend(code, this.prepend);
156+
157+
// In some sense, simulate a select all and paste
169158
editor.edit((editBuilder) => {
170159
editBuilder.replace(
171160
new vscode.Range(
172161
editor.document.positionAt(0),
173162
editor.document.positionAt(editor.document.getText().length),
174163
),
175-
code,
164+
contents,
176165
);
177166
});
178-
let retry = 0;
179-
while (editor.document.getText() !== code) {
180-
await new Promise((r) => setTimeout(r, 100));
181-
this.log(
182-
`EXTENSION: Editor's not replace yet, lets wait: ${editor.document.getText()}`,
183-
);
184-
retry++;
185-
if (retry > 11) {
186-
this.log(`EXTENSION: Editor's replace wait limit reached`);
187-
break;
188-
}
189-
}
190-
this.code = code;
191-
this.replaceTime = Date.now();
192167
}
193168

194169
onChange(

src/utils/messageHandler.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ export class MessageHandler {
147147
}
148148
if (editor !== this.activeEditor) {
149149
console.log(
150-
`EXTENSION: Editor ${editor.assessmentName}_${editor.questionId}_${editor.assessmentType} is no longer active, skipping onChange`,
150+
`EXTENSION: Editor ${editor.assessmentName}_${editor.questionId} is no longer active, skipping onChange`,
151151
);
152152
}
153153
const message = Messages.Text(
@@ -167,6 +167,12 @@ export class MessageHandler {
167167
context.globalState.update("courseId", courseId);
168168
treeDataProvider.refresh();
169169
break;
170+
case MessageTypeNames.ResetEditor:
171+
if (this.activeEditor) {
172+
this.activeEditor.replace(message.initialCode);
173+
this.panel?.reveal(vscode.ViewColumn.Two);
174+
}
175+
break;
170176
}
171177
console.log(`${Date.now()} Finish handleMessage: ${message.type}`);
172178
}

src/utils/messages.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ const Messages = createMessages({
4848
EvalEditor: (workspaceLocation: VscWorkspaceLocation) => ({
4949
workspaceLocation: workspaceLocation,
5050
}),
51+
ResetEditor: (
52+
workspaceLocation: VscWorkspaceLocation,
53+
initialCode: string,
54+
) => ({
55+
workspaceLocation,
56+
initialCode,
57+
}),
5158
NotifyAssessmentsOverview: (
5259
assessmentOverviews: VscAssessmentOverview[],
5360
courseId: number,

0 commit comments

Comments
 (0)