Skip to content

Commit 7757abc

Browse files
committed
Merge branch 'main' into overwrite-fix
2 parents 8e8313d + e930915 commit 7757abc

File tree

15 files changed

+367
-45
lines changed

15 files changed

+367
-45
lines changed

README.md

Lines changed: 51 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,62 @@
1-
# VS Code
1+
# Source Academy & VS Code
22

3-
Experimental project for running Source Academy within Visual Studio Code.
3+
<p align="center">
4+
<img src="./assets/icon.png" width="150">
5+
</p>
46

5-
## How to use
7+
A Visual Studio Code extension for integration with [Source Academy](https://about.sourceacademy.org), an online experiential environment for computational thinking.
68

7-
TODO: Add instructions
9+
It is available in the VS Code [Extension Marketplace](https://marketplace.visualstudio.com/items?itemName=source-academy.source-academy).
810

9-
## Notes to developers
11+
## Features
1012

11-
### Running the extension in dev mode
13+
- View, edit, and submit assessments
14+
- Syntax highlighting for Source
15+
- Integration with our [language server for Source](https://github.com/source-academy/source-lsp), which provides smart features such as:
16+
- Error checking
17+
- Code completion
18+
- Hover documentation
1219

13-
1. Setup the project
14-
```
15-
yarn
16-
```
17-
1. Compile
18-
```
19-
yarn compile
20-
```
21-
1. Run the extension in debug mode by opening the root folder a VSCode window, then "Start Debugging" (or press F5).
20+
## Installing
2221

23-
### Publishing the extension
22+
If you don't have VS Code installed yet, download it from [here](https://code.visualstudio.com/docs/setup/setup-overview) first.
2423

25-
For a new release, update the version in `package.json` and tag the commit. Push the commit and the tag to the repo,
26-
which will trigger GitHub Actions to build and publish the extension to Releases tab and the Marketplace.
24+
From within VS Code,
25+
26+
1. Click on the Extensions icon on the left sidebar or the `View: Show Extensions` command (`Ctrl+Shift+X`).
27+
2. Search for "Source Academy" and install it.
28+
29+
We'd recommend also installing the [Error Lens](https://marketplace.visualstudio.com/items?itemName=usernamehw.errorlens) extension
30+
to show diagnostic messages more prominently.
31+
32+
## Getting started
33+
34+
_If you don't have an existing Source Academy account, you can try out our public frontend. See section [Changing the frontend](#changing-the-frontend)._
35+
36+
After installing the extension,
37+
38+
1. Click on the newly-added Source Academy icon on the left sidebar.
39+
2. Launch the Source Academy panel.
40+
41+
<img src="./docs/images/launch-panel-from-sidebar.png" width="600">
42+
43+
Alternatively, use the `Source Academy: Show the Source Academy Panel` command.
44+
45+
Once the panel loads, you'll be prompted to log in. Afterwards, begin coding by opening any assessment.
46+
47+
### Changing the frontend
48+
49+
To use a different Source Academy frontend, modify the Frontend Base URL setting:
50+
51+
1. Press `Ctrl + ,` to open VS Code's settings page, then search for `frontendBaseUrl`.
52+
2. Enter a valid URL.
53+
54+
Example value (public frontend):
2755

2856
```
29-
npm version (major|minor|patch)
30-
git push origin main --tags
57+
https://sourceacademy.org
3158
```
59+
60+
## For developers
61+
62+
Check out our [developer guide](./docs/developer-guide.md) for instructions to setup and run the extension from source.

assets/icon.png

399 Bytes
Loading

assets/icon.svg

Lines changed: 50 additions & 0 deletions
Loading

docs/developer-guide.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Developer Guide
2+
3+
## Running the extension in dev mode
4+
5+
1. Setup the project
6+
```
7+
yarn
8+
```
9+
1. Compile
10+
```
11+
yarn build
12+
```
13+
1. Run the extension in debug mode by opening the root folder a VS Code window, then "Start Debugging" (or press F5).
14+
15+
## Publishing the extension
16+
17+
For a new release, update the version in `package.json` and tag the commit. Push the commit and the tag to the repo,
18+
which will trigger GitHub Actions to build and publish the extension to Releases tab and the Marketplace.
19+
20+
```
21+
npm version (major|minor|patch)
22+
git push origin main --tags
23+
```
99.5 KB
Loading

package.json

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
{
22
"name": "source-academy",
3-
"version": "0.2.0",
3+
"version": "0.3.1",
44
"publisher": "source-academy",
55
"license": "Apache-2.0",
66
"displayName": "Source Academy",
77
"description": "VS Code extension for Source Academy",
8-
"repository": "https://github.com/source-academy/vscode",
8+
"repository": {
9+
"type": "git",
10+
"url": "https://github.com/source-academy/vscode"
11+
},
912
"categories": [
1013
"Programming Languages",
1114
"Education"
@@ -37,6 +40,11 @@
3740
"type": "string",
3841
"default": "https://frontend.cloud.heyzec.dedyn.io",
3942
"description": "URL to the Source Academy frontend"
43+
},
44+
"source-academy.workspaceFolder": {
45+
"type": "string",
46+
"default": ".sourceacademy",
47+
"description": "Location to store code locally. If not absolute, it will be relative to the home directory."
4048
}
4149
}
4250
},
@@ -47,8 +55,8 @@
4755
".sjs"
4856
],
4957
"icon": {
50-
"light": "assets/icon.png",
51-
"dark": "assets/icon.png"
58+
"light": "assets/icon.svg",
59+
"dark": "assets/icon.svg"
5260
},
5361
"configuration": "./language-configuration.json"
5462
}
@@ -65,6 +73,31 @@
6573
"command": "source-academy.eval-editor",
6674
"key": "shift+enter"
6775
}
76+
],
77+
"views": {
78+
"source-academy": [
79+
{
80+
"id": "assessments",
81+
"name": "Assessments",
82+
"icon": "assets/icon.svg",
83+
"contextualTitle": "Source Academy"
84+
}
85+
]
86+
},
87+
"viewsContainers": {
88+
"activitybar": [
89+
{
90+
"id": "source-academy",
91+
"title": "Source Academy",
92+
"icon": "assets/icon.svg"
93+
}
94+
]
95+
},
96+
"viewsWelcome": [
97+
{
98+
"view": "assessments",
99+
"contents": "Launch the Source Academy panel to begin coding.\n[Launch!](command:source-academy.show-panel)\nNavigate to Missions page to populate this panel."
100+
}
68101
]
69102
},
70103
"scripts-info": {

src/commands/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as vscode from "vscode";
22
import { runLanguagePicker } from "./language";
33
import { evalEditor } from "./evalEditor";
44
import { showPanel } from "./showPanel";
5+
import { navigate } from "./navigate";
56

67
const EXTENSION_ID = "source-academy";
78

@@ -11,8 +12,9 @@ const EXTENSION_ID = "source-academy";
1112
*/
1213
const commands = (context: vscode.ExtensionContext) => ({
1314
pick: () => runLanguagePicker(context),
14-
"show-panel": () => showPanel(context),
15+
"show-panel": (route?: string) => showPanel(context, route),
1516
"eval-editor": () => evalEditor(context),
17+
navigate: (route: string) => navigate(context, route),
1618
});
1719

1820
/**

src/commands/navigate.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import * as vscode from "vscode";
2+
import { sendToFrontendWrapped } from "./showPanel";
3+
import Messages from "../utils/messages";
4+
5+
export async function navigate(
6+
context: vscode.ExtensionContext,
7+
route: string,
8+
) {
9+
const didNavigate = await sendToFrontendWrapped(Messages.Navigate(route));
10+
if (!didNavigate) {
11+
vscode.commands.executeCommand("source-academy.show-panel", route);
12+
}
13+
}

src/commands/showPanel.tsx

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ import { setWebviewContent } from "../utils/webview";
1212
import config from "../utils/config";
1313
import { Editor } from "../utils/editor";
1414
import { FRONTEND_ELEMENT_ID } from "../constants";
15-
import { client } from "../extension";
15+
import { client, SOURCE_ACADEMY_ICON_URI } from "../extension";
1616
import _ from "lodash";
17+
import { treeDataProvider } from "../treeview";
1718

1819
let panel: vscode.WebviewPanel | null = null;
1920
// This needs to be a reference to active
@@ -93,14 +94,23 @@ async function handleMessage(
9394
// }
9495
// activeEditor.replace(message.code, "Text");
9596
// break;
97+
case MessageTypeNames.NotifyAssessmentsOverview:
98+
const { assessmentOverviews, courseId } = message;
99+
context.globalState.update("assessmentOverviews", assessmentOverviews);
100+
context.globalState.update("courseId", courseId);
101+
treeDataProvider.refresh();
102+
break;
96103
}
97104
console.log(`${Date.now()} Finish handleMessage: ${message.type}`);
98105
}
99106

100107
handling = false;
101108
}
102109

103-
export async function showPanel(context: vscode.ExtensionContext) {
110+
export async function showPanel(
111+
context: vscode.ExtensionContext,
112+
route?: string,
113+
) {
104114
let language: string | undefined = context.workspaceState.get("language");
105115
if (!language) {
106116
language = LANGUAGES.SOURCE_1;
@@ -125,7 +135,8 @@ export async function showPanel(context: vscode.ExtensionContext) {
125135
context.subscriptions,
126136
);
127137

128-
const frontendUrl = new URL("/playground", config.frontendBaseUrl).href;
138+
const iframeUrl = new URL(route ?? "/playground", config.frontendBaseUrl)
139+
.href;
129140

130141
// equivalent to panel.webview.html = ...
131142
setWebviewContent(
@@ -139,7 +150,7 @@ export async function showPanel(context: vscode.ExtensionContext) {
139150
>
140151
<iframe
141152
id={FRONTEND_ELEMENT_ID}
142-
src={frontendUrl}
153+
src={iframeUrl}
143154
width="100%"
144155
height="100%"
145156
// @ts-ignore
@@ -149,18 +160,16 @@ export async function showPanel(context: vscode.ExtensionContext) {
149160
</div>,
150161
);
151162

152-
panel.iconPath = vscode.Uri.joinPath(
153-
context.extensionUri,
154-
"assets",
155-
"icon.png",
156-
);
163+
panel.iconPath = SOURCE_ACADEMY_ICON_URI;
157164
}
158165

159166
// TODO: Move this to a util file
160167
export async function sendToFrontendWrapped(message: MessageType) {
168+
// TODO: This returning of status code shouldn't be necessary after refactor
161169
if (!panel) {
162170
console.error("ERROR: panel is not set");
163-
return;
171+
return false;
164172
}
165173
sendToFrontend(panel, message);
174+
return true;
166175
}

src/extension.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
// The module 'vscode' contains the VS Code extensibility API
22
// Import the module and reference it with the alias vscode in your code below
33
import * as vscode from "vscode";
4+
import { setupTreeView } from "./treeview";
45
import { setupStatusBar } from "./statusbar/status";
5-
import { evalEditor } from "./commands/evalEditor";
66
import { registerAllCommands } from "./commands";
77
import { activateLspClient, deactivateLspClient } from "./lsp/client";
88
import { LanguageClient } from "vscode-languageclient/node";
9+
import { canonicaliseLocation } from "./utils/misc";
10+
import config from "./utils/config";
911

1012
// TODO: Don't expose this object directly, create an interface via a wrapper class
1113
export let client: LanguageClient;
1214

15+
export let SOURCE_ACADEMY_ICON_URI: vscode.Uri;
16+
1317
// This method is called when your extension is activated
1418
// Your extension is activated the very first time the command is executed
1519
export function activate(context: vscode.ExtensionContext) {
20+
setupTreeView(context);
1621
registerAllCommands(context);
1722

1823
context.subscriptions.push(setupStatusBar(context));
@@ -25,6 +30,27 @@ export function activate(context: vscode.ExtensionContext) {
2530
const info = context.globalState.get("info") ?? {};
2631

2732
client.sendRequest("source/publishInfo", info);
33+
34+
SOURCE_ACADEMY_ICON_URI = vscode.Uri.joinPath(
35+
context.extensionUri,
36+
"assets",
37+
"icon.svg",
38+
);
39+
40+
// TODO: Prompt the user to make this folder the default, and then set back to the config store.
41+
42+
// Update user's workspace settings to associate .js to Source
43+
const workspaceFolder = canonicaliseLocation(config.workspaceFolder);
44+
if (
45+
vscode.workspace.workspaceFolders
46+
?.map((wf) => wf.uri.fsPath)
47+
.includes(workspaceFolder)
48+
) {
49+
const workspaceConfig = vscode.workspace.getConfiguration();
50+
workspaceConfig.update("files.associations", {
51+
"*.js": "source",
52+
});
53+
}
2854
}
2955

3056
// This method is called when your extension is deactivated

0 commit comments

Comments
 (0)