Skip to content

Commit

Permalink
Current file fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
skryukov committed Feb 6, 2024
1 parent d3212a7 commit ad47dc7
Show file tree
Hide file tree
Showing 9 changed files with 55 additions and 212 deletions.
4 changes: 2 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
<meta charset="UTF-8" />
<!-- <link rel="icon" type="image/svg+xml" href="/src/favicon.svg" /> -->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Ruby WASI Playground</title>
<title>RunRuby.dev</title>
</head>
<body>
<body style="background-color: #1a1a1a">
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
Expand Down
4 changes: 2 additions & 2 deletions src/components/App/App.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import cs from "./styles.module.css";
import { Editor } from "../Editor/Editor.tsx";

import cs from "./styles.module.css";

export default function App() {
return (
<div className={cs.container}>
<div className={cs.header}>
<h1 className={cs.title}>Ruby WASI Playground</h1>
<h1 className={cs.title}>RunRuby.dev</h1>
</div>
<Editor />
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/App/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@

.editorPlaceholder {
font-size: 16px;
padding: 8px 16px;
padding: 32px 32px;
}

.editorText {
Expand Down
68 changes: 46 additions & 22 deletions src/components/Editor/Editor.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
import cs from "../App/styles.module.css";
import MonacoEditor from "@monaco-editor/react";
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";
import { CreateHandler, DeleteHandler, RenameHandler, Tree, TreeApi, NodeApi } from "react-arborist";
import { VscNewFile, VscNewFolder } from "react-icons/vsc";
import { nanoid } from "nanoid";

import { runWASI } from "../../engines/wasi";
import { decode, encode, gemFromURI, workDir } from "../../engines/wasi/editorFS.ts";

import Node from "../FileTree/Node";
import Node from "../Node/Node";
import cs from "../App/styles.module.css";

export type Entity = {
id: string;
name: string;
object: Directory | File | SyncOPFSFile;
}

import { CreateHandler, DeleteHandler, RenameHandler, Tree, TreeApi } from "react-arborist";
import { NodeApi } from "react-arborist/dist/module/interfaces/node-api";
import { VscNewFile, VscNewFolder } from "react-icons/vsc";
import { nanoid } from "nanoid";

function sortChildren(node: Directory): Entity[] {
const entries = Object.entries(node.contents).map((entry) => {
const id = idsMap.get(entry[1]) || nanoid();
Expand Down Expand Up @@ -52,7 +51,14 @@ export const Editor = () => {
const [log, setLog] = useState<string[]>([]);
const [editorValueSource, setEditorValueSource] = useState<"result" | "logs">("result");

const [currentFilePath, setCurrentFilePath] = useState<string | null>("main.rb");
const [currentNodeId, setCurrentNodeId] = useState<string | null>(null);
const treeRef = useRef<TreeApi<Entity>>(null);
const [treeData, setTreeData] = useState(sortChildren(workDir.dir));

const currentFilePath = useMemo(() => {
const currentNode = treeRef.current?.get(currentNodeId);
return currentNode ? getPath(currentNode) : null;
}, [currentNodeId]);

const currentFile = useMemo(
() => {
Expand Down Expand Up @@ -124,10 +130,17 @@ export const Editor = () => {
if (!currentFilePath?.endsWith(".rb")) return;
if (currentFile === null) return;

runVM(`require "bundler/setup";${decode(currentFile.data)}`);
runVM(`eval <<~CODE, binding, '${currentFilePath}', 0
${canRunBundleInstall ? "require \"bundler/setup\";" : ""}${decode(currentFile.data)}
CODE`);
};
const bundleInstall = () => {
runVM(`require "bundler/cli";require "bundler/cli/install";Bundler::CLI::Install.new({path: './gems'}).run`,
runVM(`require "rubygems_stub"
require "thread_stub"
require "bundler_stub"
require "bundler/cli"
require "bundler/cli/install"
Bundler::CLI::Install.new({path: './gems'}).run`,
() => {
setResult("Bundle install successful (see logs for details)");
},
Expand All @@ -140,9 +153,6 @@ export const Editor = () => {
const handleEditorChange = (value: string | undefined) => {
setCode(value || "");
};
const treeRef = useRef<TreeApi<Entity>>(null);

const [treeData, setTreeData] = useState(sortChildren(workDir.dir));

const onRename: RenameHandler<Entity> = ({ name, node }) => {
const parent = (node.parent == null || node.parent.isRoot) ? workDir.dir : node.parent.data.object as Directory;
Expand All @@ -153,8 +163,12 @@ export const Editor = () => {
}
parent.contents[name] = node.data.object;
delete parent.contents[node.data.name];
node.data = { ...node.data, name };

setTreeData(sortChildren(workDir.dir));

setTimeout(() => {
setCurrentNodeId(currentNodeId);
}, 20);
}
};

Expand All @@ -176,7 +190,7 @@ export const Editor = () => {
const parent = (node.parent == null || node.parent.isRoot) ? workDir.dir : node.parent.data.object as Directory;
delete parent.contents[node.data.name];
if (currentFilePath === getPath(node)) {
setCurrentFilePath(null);
setCurrentNodeId(null);
}
}
});
Expand All @@ -187,8 +201,16 @@ export const Editor = () => {
const canRunBundleInstall = useMemo(() => !loading && treeData.find((entry) => entry.name === "Gemfile"), [loading, treeData]);

useEffect(() => {
!initializing && gemFromURI() && bundleInstall();
}, [initializing]);
if (initializing) {
const tree = treeRef.current;
if (tree) {
const node = tree.visibleNodes.find((n) => n.data.name?.endsWith(".rb"));
node ? node.activate() : tree?.firstNode?.activate();
}
} else {
gemFromURI() && bundleInstall();
}
}, [initializing, treeRef]);

return (
<>
Expand Down Expand Up @@ -220,7 +242,7 @@ export const Editor = () => {
onDelete={onDelete}
onActivate={(node: NodeApi) => {
if (node.isLeaf) {
setCurrentFilePath(getPath(node));
setCurrentNodeId(node.id);
}
}}
>
Expand Down Expand Up @@ -256,9 +278,11 @@ export const Editor = () => {
/>

) : (
<div className={cs.editorPlaceholder}>
Select a file to edit
</div>
!initializing && (
<div className={cs.editorPlaceholder}>
Select a file to edit
</div>
)
)
}
</div>
Expand Down
78 changes: 0 additions & 78 deletions src/components/FileTree/FileTree.tsx

This file was deleted.

103 changes: 0 additions & 103 deletions src/components/FileTree/styles.module.css

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import cs from "./Node.module.css";
import { NodeRendererProps } from "react-arborist";
import { NodeRendererProps, NodeApi } from "react-arborist";
import { VscEdit, VscFile, VscFolder, VscFolderOpened, VscTrash } from "react-icons/vsc";
import { NodeApi } from "react-arborist/dist/module/interfaces/node-api";

import { Entity } from "../Editor/Editor.tsx";
import cs from "./styles.module.css";

function isValidFileName(fileName: string) {
if (fileName.trim() === "") {
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion src/engines/wasi/wasi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ async function createRuby(setStdout: TSetString, setStderr: TSetString) {
await ruby.setInstance(instance);

wasi.initialize(instance as any);
ruby.initialize(["ruby.wasm", "-e_=0", `-I${rubyStubsPath}`, "-rrubygems_stub", "-rthread_stub", "-rbundler_stub"]);
ruby.initialize(["ruby.wasm", "-e_=0", `-I${rubyStubsPath}`]);

return ruby;
}
Expand Down

0 comments on commit ad47dc7

Please sign in to comment.