1import { createWorkbench, type WorkbenchTheme } from 'minwebide';
2import { createCsvTableProvider } from './csvTable';
3import { openProjectFileSystem, touchProject, type ProjectInfo } from './projects';
4import { createStanRunner } from './stan/runner';
5import { createSampleEditorProvider } from './stan/sampleEditor';
6import { showServerDialog } from './stan/serverDialog';
7import { getServerUrl, onDidChangeServerUrl, probeServer } from './stan/settings';
9/** Opens the IDE for a project. Returns a disposable view. */
10export async function openIde(container: HTMLElement, project: ProjectInfo, theme: WorkbenchTheme): Promise<{ dispose(): void }> {
11 touchProject(project.id);
12 document.title = `${project.name} — stan web IDE`;
14 const fs = await openProjectFileSystem(project.id);
15 const stan = createStanRunner(fs);
17 const workbench = createWorkbench(container, {
18 fileSystem: fs,
19 theme,
20 workspaceName: project.name,
21 });
22 workbench.registerRunner(stan.runner);
23 workbench.registerCustomEditor(createSampleEditorProvider(fs, workbench, { stop: stan.stop }));
24 workbench.registerCustomEditor(createCsvTableProvider());
26 // the project indicator: click to go back to the project list
27 workbench.statusBar.setItem('project', 'left', project.name, {
28 icon: 'folder-opened',
29 title: 'Back to projects',
30 onClick: () => { location.hash = '#/'; },
31 });
32 // replace the default branding item with the project indicator
33 workbench.statusBar.removeItem('branding');
35 // compile-server status: shows connectivity, click to change the URL
36 let disposed = false;
37 const refreshServerItem = async () => {
38 const url = getServerUrl();
39 workbench.statusBar.setItem('stan-server', 'right', 'Stan server: checking...', {
40 icon: 'server',
41 title: `${url}\nClick to change the compilation server`,
42 onClick: () => showServerDialog(container),
43 });
44 const ok = await probeServer(url);
45 if (disposed || url !== getServerUrl()) {
46 return;
47 }
48 workbench.statusBar.setItem('stan-server', 'right', `Stan server: ${ok ? 'connected' : 'offline'}`, {
49 icon: ok ? 'server' : 'warning',
50 title: `${url} — ${ok ? 'connected' : 'not reachable'}\nClick to change the compilation server`,
51 onClick: () => showServerDialog(container),
52 });
53 };
54 void refreshServerItem();
55 const serverListener = onDidChangeServerUrl(() => void refreshServerItem());
57 // open the most useful starting file
58 for (const path of ['/fit.sample', '/main.stan', '/README.md']) {
59 const uri = fs.root.with({ path });
60 if (await fs.fileService.exists(uri)) {
61 await workbench.openFile(uri);
62 break;
63 }
64 }
66 return {
67 dispose() {
68 disposed = true;
69 serverListener.dispose();
70 stan.dispose();
71 workbench.dispose();
72 fs.dispose();
73 },
74 };
75}