Shortcuts for reset and run

This commit is contained in:
2026-09-05 14:08:43 -05:00
parent 015be8f49a
commit ca5915bf31
6 changed files with 57 additions and 11 deletions
View File
+1
View File
@@ -1,2 +1,3 @@
pub mod display;
mod keyboard;
+23 -6
View File
@@ -7,6 +7,7 @@
"dependencies": {
"@codemirror/commands": "^6.5.0",
"@codemirror/language": "^6.10.1",
"@codemirror/state": "^6.5.2",
"@codemirror/view": "^6.26.3",
"cm6-theme-gruvbox-dark": "^0.2.0",
"codemirror": "^6.0.1",
@@ -79,9 +80,12 @@
}
},
"node_modules/@codemirror/state": {
"version": "6.4.1",
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz",
"integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A=="
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.2.tgz",
"integrity": "sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==",
"dependencies": {
"@marijn/find-cluster-break": "^1.0.0"
}
},
"node_modules/@codemirror/view": {
"version": "6.26.3",
@@ -444,6 +448,11 @@
"@lezer/common": "^1.0.0"
}
},
"node_modules/@marijn/find-cluster-break": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz",
"integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g=="
},
"node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
@@ -686,9 +695,12 @@
}
},
"@codemirror/state": {
"version": "6.4.1",
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz",
"integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A=="
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.2.tgz",
"integrity": "sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==",
"requires": {
"@marijn/find-cluster-break": "^1.0.0"
}
},
"@codemirror/view": {
"version": "6.26.3",
@@ -853,6 +865,11 @@
"@lezer/common": "^1.0.0"
}
},
"@marijn/find-cluster-break": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz",
"integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g=="
},
"ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+1
View File
@@ -2,6 +2,7 @@
"dependencies": {
"@codemirror/commands": "^6.5.0",
"@codemirror/language": "^6.10.1",
"@codemirror/state": "^6.5.2",
"@codemirror/view": "^6.26.3",
"cm6-theme-gruvbox-dark": "^0.2.0",
"codemirror": "^6.0.1",
+7
View File
@@ -6,6 +6,7 @@ import {indentWithTab} from '@codemirror/commands'
import {StreamLanguage} from '@codemirror/language'
import {gruvboxDark} from 'cm6-theme-gruvbox-dark'
import ForgeHighlighter from './forge_highlighter'
import { Prec } from "@codemirror/state"
export default function ForgeEditor({ src, updateSrc, fileName }) {
const editor = useRef(null)
@@ -16,6 +17,12 @@ export default function ForgeEditor({ src, updateSrc, fileName }) {
doc: src,
extensions: [
basicSetup,
// Normally F3 opens the search dialog, but we want to just eat it so the document's handler will get it.
// We use F3 as a global shortcut for resetting the machine, even if the editor has focus.
// Since the editor doesn't do anything for F1, 2, or 4, we don't need to do anything to ignore those.
Prec.highest(
keymap.of([{ key: "F3", run: () => { return true } }])
),
keymap.of([indentWithTab]),
gruvboxDark,
EditorView.updateListener.of((update) => {
+25 -5
View File
@@ -12,6 +12,7 @@ export default function({ src: defaultSrc }) {
const [errors, setErrors] = useState(null) // What's displayed on the compile errors tab
const [status, setStatus] = useState('') // The contents of the status bar
const [stale, setStale] = useState(false) // Whether the editor has been changed since the last build
const [keyFocus, setKeyFocus] = useState('editor') // The lens for interpreting key events: 'editor', 'emulator', 'filelist'
// Whether the emulator should be running. Has to be a ref because the CPU setTimeout loop won't ever see changes in it otherwise
const running = useRef(false)
@@ -131,6 +132,24 @@ export default function({ src: defaultSrc }) {
content = <ForgeEditor build={build} run={run} updateSrc={updateSrc} src={src} fileName={currentFile}/>
}
useEffect(() => {
const listener = (event) => {
// F1-4 act the same in every mode:
if (event.key === 'F3') {
event.preventDefault()
reset()
}
if (event.key === 'F4') {
event.preventDefault()
setKeyFocus('emulator')
run()
}
}
document.addEventListener('keydown', listener)
return () => document.removeEventListener('keydown', listener)
}, [reset, run])
return (
<>
<Tabbar activeTab={activeTab} setActiveTab={setActiveTab} anyErrors={!!errors}/>
@@ -168,7 +187,7 @@ function Tabbar({ activeTab, setActiveTab, anyErrors }) {
const classNames = name => (name === activeTab ? 'button active' : 'button')
return (
<div className='tabbar'>
<a className={classNames('editor')} onClick={onChangeTab} data-tab='editor'>[Editor]</a>
<a className={classNames('editor')} onClick={onChangeTab} data-tab='editor'>[Editor (F2)]</a>
<a className={classNames('assembly')} onClick={onChangeTab} data-tab='assembly'>[Assembly]</a>
{anyErrors && <a className={classNames('errors')} onClick={onChangeTab} data-tab='errors'>[Errors]</a>}
</div>
@@ -176,25 +195,26 @@ function Tabbar({ activeTab, setActiveTab, anyErrors }) {
}
// Toolbar of the controls for the simulator
function Toolbar({activeTab, running, compile, build, run, stop, reset, addFile, removeFile }) {
function Toolbar({ running, build, run, stop, reset, addFile, removeFile }) {
let buildBtn, runBtn
// TODO: Make this assemble on assembly tab, make that editable
buildBtn = <a className='build' onClick={build}>[Build]</a>
if (running) {
runBtn = <a className='stop' onClick={stop}>[Stop]</a>
runBtn = <a className='stop' onClick={stop}>[Stop (F4)]</a>
} else {
runBtn = <a className='run' onClick={run}>[Run]</a>
runBtn = <a className='run' onClick={run}>[Run (F4)]</a>
}
return (
<>
<div className='file-buttons'>
(F1)
<a className='new' onClick={addFile}>[new]</a>
<a className='del' onClick={removeFile}>[del]</a>
</div>
<div className='buttons'>
<a className='reset' onClick={reset}>[Reset]</a>
<a className='reset' onClick={reset}>[Reset (F3)]</a>
{buildBtn}
{runBtn}
</div>