/ concept-collection / numbl-web-ide
Sign in
concept-collection / numbl-web-ide
numbl-web-ide / src / ide.ts
87 lines · 2.9 KBBlameHistoryRaw
1import { attachGitHubSourceControl, createWorkbench, type Workbench, type WorkbenchTheme, type WorkspaceFileSystem } from 'minwebide';
2import { createMipSystem } from './numbl/mipSystem';
3import { createNumblRunner } from './numbl/runner';
4import { openProjectFileSystem, touchProject, type ProjectInfo } from './projects';
6export interface NumblWorkbench {
7 readonly workbench: Workbench;
8 dispose(): void;
9}
11/**
12 * Assembles the numbl workbench (mip system + runner) on a file system.
13 * Shared by project IDEs and GitHub repo IDEs; does not own `fs` — the
14 * caller disposes it.
15 */
16export async function openNumblWorkbench(container: HTMLElement, fs: WorkspaceFileSystem, workspaceName: string, theme: WorkbenchTheme): Promise<NumblWorkbench> {
17 const mip = await createMipSystem();
18 // fetch/refresh mip core in the background; runs await it (and say so
19 // in the output channel if they actually have to wait)
20 void mip.ensureCore().catch(() => { /* retried on the next run */ });
22 const workbench = createWorkbench(container, {
23 fileSystem: fs,
24 theme,
25 workspaceName,
26 });
28 const numbl = createNumblRunner(fs, workbench, mip);
29 workbench.registerRunner(numbl.runner);
31 return {
32 workbench,
33 dispose() {
34 numbl.dispose();
35 workbench.dispose();
36 mip.dispose();
37 },
38 };
41/** Opens the most useful starting file, if any. */
42export async function openStartingFile(fs: WorkspaceFileSystem, workbench: Workbench): Promise<void> {
43 for (const path of ['/waves.m', '/main.m', '/README.md']) {
44 const uri = fs.root.with({ path });
45 if (await fs.fileService.exists(uri)) {
46 await workbench.openFile(uri);
47 return;
48 }
49 }
52/** Opens the IDE for a project. Returns a disposable view. */
53export async function openIde(container: HTMLElement, project: ProjectInfo, theme: WorkbenchTheme): Promise<{ dispose(): void }> {
54 touchProject(project.id);
55 document.title = `${project.name} — numbl web IDE`;
57 const fs = await openProjectFileSystem(project.id);
58 const ide = await openNumblWorkbench(container, fs, project.name, theme);
60 // the project indicator: click to go back to the project list
61 ide.workbench.statusBar.setItem('project', 'left', project.name, {
62 icon: 'folder-opened',
63 title: 'Back to projects',
64 onClick: () => { location.hash = '#/'; },
65 });
66 // replace the default branding item with the project indicator
67 ide.workbench.statusBar.removeItem('branding');
69 // source control: publish this project to a new GitHub repo, or — once
70 // published — track changes and push
71 const sourceControl = await attachGitHubSourceControl(ide.workbench, fs, {
72 appName: 'numbl web IDE',
73 defaultRepoName: project.name,
74 // after publishing, the repo's own route is the canonical place to work
75 onPublished: ({ owner, repo }) => { location.hash = `#/github/${owner}/${repo}`; },
76 });
78 await openStartingFile(fs, ide.workbench);
80 return {
81 dispose() {
82 sourceControl.dispose();
83 ide.dispose();
84 fs.dispose();
85 },
86 };
moveopenescclose