more settings

This commit is contained in:
nora 2021-06-25 13:05:12 +02:00
parent e13d82ff46
commit dc79c96f63
10 changed files with 246 additions and 116 deletions

View file

@ -1,7 +1,10 @@
import React, {useState} from 'react';
import presets from "../presets.json";
export interface CodeOptions {
minify?: boolean
minify?: boolean,
directStart?: boolean,
enableBreakpoints?: boolean
}
interface CodeInputProps {
@ -15,10 +18,8 @@ const CodeInput = ({code, setInput}: CodeInputProps) => {
const [codeOptions, setCodeOptions] = useState<CodeOptions>({});
const setStart = () => {
setInput(
"++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.",
codeOptions);
const setPreset = (name: keyof typeof presets) => () => {
setInput(presets[name], codeOptions);
}
const changeMinify = (e: React.ChangeEvent<HTMLInputElement>) => {
@ -26,6 +27,16 @@ const CodeInput = ({code, setInput}: CodeInputProps) => {
setInput(code, codeOptions);
}
const changeStart = (e: React.ChangeEvent<HTMLInputElement>) => {
setCodeOptions(old => ({...old, directStart: e.target.checked}))
setInput(code, codeOptions);
}
const changeBreakpoint = (e: React.ChangeEvent<HTMLInputElement>) => {
setCodeOptions(old => ({...old, enableBreakpoints: e.target.checked}))
setInput(code, codeOptions);
}
return (
<div>
<div className="bf-input">
@ -34,14 +45,35 @@ const CodeInput = ({code, setInput}: CodeInputProps) => {
<label htmlFor="bf-input-fontsize-range">Font Size</label>
<input type="range" id="bf-input-fontsize-range" onChange={v => setFontSize(+v.target.value)}/>
</span>
<input type="checkbox" checked={codeOptions.minify} id="input-options-minify" onChange={changeMinify}/>
<span>
<input type="checkbox" checked={codeOptions.minify} id="input-options-minify"
onChange={changeMinify}/>
<label htmlFor="input-options-minify">Minify Code</label>
</span>
<span>
<input type="checkbox" checked={codeOptions.directStart} id="input-options-directstart"
onChange={changeStart}/>
<label htmlFor="input-options-directstart">Start Directly</label>
</span>
<span>
<input type="checkbox" checked={codeOptions.enableBreakpoints} id="input-options-enableBreakpoints"
onChange={changeBreakpoint}/>
<label htmlFor="input-options-enableBreakpoints">Breakpoints ()</label>
</span>
</div>
<textarea value={code} onChange={e => setInput(e.target.value, codeOptions)} style={{fontSize}}
className="code-input"
placeholder="Input your code here..."/>
<div>
<button onClick={setStart}>Set Hello World</button>
<div>Presets</div>
<div>
<button onClick={setPreset("helloworld")}>Hello World</button>
<button onClick={setPreset("hanoi")}>Towers of Hanoi</button>
<button onClick={setPreset("quine")}>Quine</button>
<button onClick={setPreset("gameoflife")}>Game Of Life</button>
<button onClick={setPreset("benchmark")}>Benchmark</button>
<button onClick={setPreset("fizzbuzz")}>Fizzbuzz</button>
</div>
</div>
</div>
</div>

View file

@ -1,4 +1,4 @@
import React from 'react';
import React, {useRef, useState} from 'react';
import Interpreter from "../brainfuck/Interpreter";
const MAX_TABLE_COLUMNS = 20;
@ -35,7 +35,7 @@ const RunDisplay = ({interpreter}: RunDisplayProps) => {
<tbody>
<tr>
{
arrayWithIndex.map((n) => <td className="cell" key={n}>{interpreter.array[n]}</td>)
arrayWithIndex.map((n) => <MemoryCell key={n} index={n} interpreter={interpreter}/>)
}
</tr>
<tr>
@ -50,4 +50,48 @@ const RunDisplay = ({interpreter}: RunDisplayProps) => {
);
};
const MemoryCell = ({index, interpreter}: { index: number, interpreter: Interpreter }) => {
const [isEditing, setIsEditing] = useState(false);
const [input, setInput] = useState(interpreter.array[index] + "");
const inputField = useRef<HTMLInputElement>(null);
const saveAndQuit = () => {
interpreter.array[index] = +(input);
setIsEditing(false);
}
const click = () => {
setIsEditing(true);
inputField.current?.select();
}
const keyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
console.log("key", e.key);
if (e.key === "Escape") {
setIsEditing(false);
} else if (e.key === "Enter") {
saveAndQuit();
}
}
return (
<td onClick={click} className="cell">
{
isEditing ?
<input onKeyDown={keyDown}
className="array-set-value-field"
ref={inputField}
onChange={e => setInput(e.target.value)}
value={input}
onBlur={saveAndQuit}
autoFocus
/>
:
interpreter.array[index]
}
</td>
);
}
export default RunDisplay;

View file

@ -14,7 +14,9 @@ interface RunInfoProps {
const Runner = ({setRunning, running, outHandler, input}: RunInfoProps) => {
const [speed, setSpeed] = useState(0);
const [interpreter, setInterpreter] = useState<Interpreter | null>(null);
const [error, setError] = useState<string | null>(null);
const [info, setInfo] = useState<string | null>(null);
const [startTime, setStartTime] = useState(0);
const [, setRerenderNumber] = useState(0);
@ -34,34 +36,48 @@ const Runner = ({setRunning, running, outHandler, input}: RunInfoProps) => {
return char;
}
const errorHandler = (msg: string) => setError(msg);
const startHandler = useCallback(() => {
setSpeed(0);
setInterpreter(new Interpreter(input, outHandler, inputHandler, errorHandler));
if (input[1].directStart) {
setSpeed(100);
} else {
setSpeed(0);
}
setStartTime(Date.now);
setInterpreter(new Interpreter(input, outHandler, inputHandler));
setRunning(false);
setRunning(true);
}, [input, outHandler, setRunning]);
const stopHandler = () => setRunning(false);
const stopHandler = () => {
setRunning(false);
setInfo(null);
}
const nextHandler = useCallback(() => {
setError(null);
interpreter?.next();
if (interpreter?.reachedEnd) {
setInfo(null);
try {
interpreter?.next();
} catch (e) {
setInfo(e.message);
setSpeed(0);
}
if (interpreter?.reachedEnd) {
setSpeed(0);
setInfo(`Finished Execution. Took ${(Date.now() - startTime) / 1000}s`)
}
setRerenderNumber(n => n + 1);
}, [interpreter]);
}, [interpreter, startTime]);
useEffect(() => {
if (running) {
if (speed === 0) {
return;
}
const interval = setInterval(() => {
nextHandler();
}, 1000 / (speed));
}, 1000 / (speed * 10));
return () => clearInterval(interval);
}
@ -77,23 +93,28 @@ const Runner = ({setRunning, running, outHandler, input}: RunInfoProps) => {
</>
}
<div>
<button onClick={stopHandler}>Back</button>
<button onClick={startHandler}>Start</button>
<button onClick={nextHandler}>Next</button>
{running && <button onClick={stopHandler}>Back</button>}
<button onClick={startHandler}>{running ? "Restart" : "Start"}</button>
{running && <button onClick={nextHandler}>Next</button>}
</div>
{
running && <>
<div>
<label htmlFor="run-info-speed-range">Speed</label>
<input type="range" id="run-info-speed-range" value={speed}
onChange={e => setSpeed(+e.target.value)}/>
<span> {speed}</span>
</div>
</>
}
{
error && <div className="error">{error}</div>
running &&
<div>
<label htmlFor="run-info-speed-range">Speed</label>
<input type="range" id="run-info-speed-range" value={speed}
onChange={e => setSpeed(+e.target.value)}/>
<span> {speed}</span>
<span>
<button onClick={() => setSpeed(s => s === 0 ? 0 : s - 1)}
className="small-speed-button">-</button>
<button onClick={() => setSpeed(0)}
className="small-speed-button">0</button>
<button onClick={() => setSpeed(s => s === 100 ? 100 : s + 1)}
className="small-speed-button">+</button>
</span>
</div>
}
{info && <div className="info">{info}</div>}
{
running && <div>
<div>Input:</div>