153 lines
3.9 KiB
TypeScript
153 lines
3.9 KiB
TypeScript
// import { useState } from 'react'
|
|
import { useEffect, useState } from 'react';
|
|
import './App.css'
|
|
import { Editor, initialEditorState, type EditorState } from './Editor'
|
|
import { trie, apply, Int } from "dope2";
|
|
|
|
const listPush = trie.get(initialEditorState.env.name2dyn)("list.push");
|
|
const listEmptyList = trie.get(initialEditorState.env.name2dyn)("list.emptyList");
|
|
const fourtyTwo = {i: 42n, t: Int};
|
|
|
|
const nonEmptyEditorState: EditorState = {
|
|
kind: "call",
|
|
env: initialEditorState.env,
|
|
fn: {
|
|
kind: "call",
|
|
env: initialEditorState.env,
|
|
fn: {
|
|
kind: "input",
|
|
env: initialEditorState.env,
|
|
text: "list.push",
|
|
resolved: listPush,
|
|
},
|
|
input: {
|
|
kind: "input",
|
|
env: initialEditorState.env,
|
|
text: "list.emptyList",
|
|
resolved: listEmptyList,
|
|
},
|
|
resolved: apply(listEmptyList)(listPush),
|
|
},
|
|
input: {
|
|
kind: "input",
|
|
env: initialEditorState.env,
|
|
text: "42",
|
|
resolved: fourtyTwo,
|
|
},
|
|
resolved: apply(fourtyTwo)(apply(listEmptyList)(listPush)),
|
|
};
|
|
|
|
const functionWith3Params = trie.get(initialEditorState.env.name2dyn)("functionWith3Params");
|
|
const fourtyThree = {i: 43n, t: Int};
|
|
const fourtyFour = {i: 44n, t: Int};
|
|
|
|
const tripleFunctionCallEditorState: EditorState = {
|
|
kind: "call",
|
|
env: initialEditorState.env,
|
|
fn: {
|
|
kind: "call",
|
|
env: initialEditorState.env,
|
|
fn: {
|
|
kind: "call",
|
|
env: initialEditorState.env,
|
|
fn: {
|
|
kind: "input",
|
|
env: initialEditorState.env,
|
|
text: "functionWith3Params",
|
|
resolved: functionWith3Params,
|
|
},
|
|
input: {
|
|
kind: "input",
|
|
env: initialEditorState.env,
|
|
text: "42",
|
|
resolved: fourtyTwo,
|
|
},
|
|
resolved: apply(fourtyTwo)(functionWith3Params),
|
|
},
|
|
input: {
|
|
kind: "input",
|
|
env: initialEditorState.env,
|
|
text: "43",
|
|
resolved: fourtyThree,
|
|
},
|
|
resolved: apply(fourtyThree)(apply(fourtyTwo)(functionWith3Params)),
|
|
},
|
|
input: {
|
|
kind: "input",
|
|
env: initialEditorState.env,
|
|
text: "44",
|
|
resolved: fourtyFour,
|
|
},
|
|
resolved: apply(fourtyFour)(apply(fourtyThree)(apply(fourtyTwo)(functionWith3Params))),
|
|
}
|
|
|
|
export function App() {
|
|
const [history, setHistory] = useState([initialEditorState]);
|
|
// const [history, setHistory] = useState([nonEmptyEditorState]);
|
|
// const [history, setHistory] = useState([tripleFunctionCallEditorState]);
|
|
|
|
const [future, setFuture] = useState<EditorState[]>([]);
|
|
|
|
const pushHistory = (s: EditorState) => {
|
|
console.log('pushHistory');
|
|
setHistory(history.concat([s]));
|
|
setFuture([]);
|
|
};
|
|
|
|
const onUndo = () => {
|
|
setFuture(future.concat(history.at(-1)!)); // add
|
|
setHistory(history.slice(0,-1)); // remove
|
|
};
|
|
const onRedo = () => {
|
|
setHistory(history.concat(future.at(-1)!)); // add
|
|
setFuture(future.slice(0,-1)); // remove
|
|
};
|
|
|
|
const onKeyDown = (e) => {
|
|
if (e.key === "Z" && e.ctrlKey) {
|
|
if (e.shiftKey) {
|
|
if (future.length > 0) {
|
|
onRedo();
|
|
}
|
|
}
|
|
else {
|
|
if (history.length > 1) {
|
|
onUndo();
|
|
}
|
|
}
|
|
e.preventDefault();
|
|
}
|
|
};
|
|
|
|
|
|
useEffect(() => {
|
|
window['APP_STATE'] = history;
|
|
// console.log("EDITOR STATE:", state);
|
|
}, [history]);
|
|
|
|
useEffect(() => {
|
|
window.onkeydown = onKeyDown;
|
|
}, []);
|
|
|
|
return (
|
|
<>
|
|
<header>
|
|
<button disabled={history.length===1} onClick={onUndo}>Undo ({history.length-1}) [Ctrl+Z]</button>
|
|
<button disabled={future.length===0} onClick={onRedo}>Redo ({future.length}) [Ctrl+Shift+Z]</button>
|
|
</header>
|
|
|
|
<main>
|
|
<Editor
|
|
state={history.at(-1)!}
|
|
setState={pushHistory}
|
|
onResolve={() => {console.log("toplevel resolved")}}
|
|
onCancel={() => {console.log("toplevel canceled")}}
|
|
/>
|
|
</main>
|
|
|
|
<footer>
|
|
<a href="https://deemz.org/git/joeri/dope2-webapp">Source code</a>
|
|
</footer>
|
|
</>
|
|
)
|
|
}
|