Skip to content

Commit

Permalink
Autoinstall gem
Browse files Browse the repository at this point in the history
  • Loading branch information
skryukov committed Feb 5, 2024
1 parent 6524d0a commit d3212a7
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 16 deletions.
31 changes: 20 additions & 11 deletions src/components/Editor/Editor.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import cs from "../App/styles.module.css";
import MonacoEditor from "@monaco-editor/react";
import { decode, encode, workDir } from "../../engines/wasi/editorFS.ts";
import { decode, encode, gemFromURI, workDir } from "../../engines/wasi/editorFS.ts";
import { useEffect, useMemo, useRef, useState } from "react";
import { Directory, File, SyncOPFSFile } from "@bjorn3/browser_wasi_shim";
import { RbValue } from "@ruby/wasm-wasi";
Expand All @@ -23,7 +23,7 @@ function sortChildren(node: Directory): Entity[] {
const entries = Object.entries(node.contents).map((entry) => {
const id = idsMap.get(entry[1]) || nanoid();
idsMap.set(entry[1], id);
return { id, name: entry[0], object: entry[1] }
return { id, name: entry[0], object: entry[1] };
});
entries.sort((a, b) => {
if (a.object instanceof Directory && b.object instanceof File) return -1;
Expand All @@ -33,7 +33,7 @@ function sortChildren(node: Directory): Entity[] {
return entries;
}

const idsMap = new Map<File|Directory|SyncOPFSFile, string>
const idsMap = new Map<File | Directory | SyncOPFSFile, string>;

function getPath(node: NodeApi<Entity>) {
let path = node.data.name;
Expand All @@ -46,6 +46,7 @@ function getPath(node: NodeApi<Entity>) {
}

export const Editor = () => {
const [initializing, setInitializing] = useState(true);
const [loading, setLoading] = useState(true);
const [result, setResult] = useState("Press run...");
const [log, setLog] = useState<string[]>([]);
Expand Down Expand Up @@ -113,14 +114,14 @@ export const Editor = () => {
onError && onError(err);
})
.finally(() => {
setLoading(false)
setLoading(false);
setTreeData(sortChildren(workDir.dir));
})
, 20);
};

const runCode = () => {
if (!currentFilePath?.endsWith('.rb')) return;
if (!currentFilePath?.endsWith(".rb")) return;
if (currentFile === null) return;

runVM(`require "bundler/setup";${decode(currentFile.data)}`);
Expand Down Expand Up @@ -152,7 +153,7 @@ export const Editor = () => {
}
parent.contents[name] = node.data.object;
delete parent.contents[node.data.name];
node.data = {...node.data, name};
node.data = { ...node.data, name };
setTreeData(sortChildren(workDir.dir));
}
};
Expand Down Expand Up @@ -182,8 +183,12 @@ export const Editor = () => {
setTreeData(sortChildren(workDir.dir));
};

const canRunCode = useMemo(() => !loading && currentFilePath?.endsWith('.rb'), [currentFilePath, loading]);
const canRunBundleInstall = useMemo(() => !loading && treeData.find((entry) => entry.name === 'Gemfile'), [loading, treeData]);
const canRunCode = useMemo(() => !loading && currentFilePath?.endsWith(".rb"), [currentFilePath, loading]);
const canRunBundleInstall = useMemo(() => !loading && treeData.find((entry) => entry.name === "Gemfile"), [loading, treeData]);

useEffect(() => {
!initializing && gemFromURI() && bundleInstall();
}, [initializing]);

return (
<>
Expand All @@ -206,7 +211,7 @@ export const Editor = () => {
<Tree
openByDefault={false}
data={treeData}
childrenAccessor={({object}) => (object instanceof Directory) ? sortChildren(object) : null}
childrenAccessor={({ object }) => (object instanceof Directory) ? sortChildren(object) : null}
ref={treeRef}
disableDrag={true}
disableDrop={true}
Expand Down Expand Up @@ -238,7 +243,10 @@ export const Editor = () => {
path={currentFilePath}
defaultValue={decode(currentFile.data)}
onChange={handleEditorChange}
onMount={() => setLoading(false)}
onMount={() => {
setLoading(false);
setInitializing(false);
}}
options={{
wordWrap: "on",
minimap: { enabled: false },
Expand All @@ -258,7 +266,8 @@ export const Editor = () => {
<div className={cs.editorLoading}>
{loading && "loading..."}
</div>
<button className={`${cs.installButton} ${canRunBundleInstall ? "" : cs.buttonDisabled}`} disabled={!canRunBundleInstall}
<button className={`${cs.installButton} ${canRunBundleInstall ? "" : cs.buttonDisabled}`}
disabled={!canRunBundleInstall}
onClick={() => !loading && bundleInstall()}>
Bundle install
</button>
Expand Down
22 changes: 17 additions & 5 deletions src/engines/wasi/editorFS.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
import { File, PreopenDirectory } from "@bjorn3/browser_wasi_shim";

const gem = "uri-idna";

const gemCode = `
URI::IDNA.register(alabel: "xn--gdkl8fhk5egc.jp", ulabel: "ハロー・ワールド.jp")
`;

export const gemFromURI = () => {
const url = new URL(window.location.href);
const params = new URLSearchParams(url.search);
return params.get("gem");
}

const defaultGem = gemFromURI() || gem;

export const initialRubyCode = `# This is a Ruby WASI playground
# You can run any Ruby code here and see the result
# You can also install gems using Gemfile an the "Bundle install" button.
require "uri-idna"
URI::IDNA.register(alabel: "xn--gdkl8fhk5egc.jp", ulabel: "ハロー・ワールド.jp")
`;
require "${defaultGem}"
${defaultGem === gem ? gemCode : ''}`;

const initialGemfile = `source "https://rubygems.org"
gem "uri-idna"
gem "${defaultGem}"
`;

export const encode = (() => {
Expand Down

0 comments on commit d3212a7

Please sign in to comment.