From ca5915bf31dcd8965739e85f0eff93a38b21f6bf Mon Sep 17 00:00:00 2001 From: Ross Andrews Date: Thu, 17 Apr 2025 21:14:21 -0500 Subject: [PATCH] Shortcuts for reset and run --- vgfx/src/keyboard.rs | 0 vgfx/src/lib.rs | 1 + vweb/package-lock.json | 29 +++++++++++++++++++++++------ vweb/package.json | 1 + vweb/src/forge_editor.jsx | 7 +++++++ vweb/src/forge_simulator.jsx | 30 +++++++++++++++++++++++++----- 6 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 vgfx/src/keyboard.rs diff --git a/vgfx/src/keyboard.rs b/vgfx/src/keyboard.rs new file mode 100644 index 0000000..e69de29 diff --git a/vgfx/src/lib.rs b/vgfx/src/lib.rs index 96f6858..e46f27d 100644 --- a/vgfx/src/lib.rs +++ b/vgfx/src/lib.rs @@ -1,2 +1,3 @@ pub mod display; +mod keyboard; diff --git a/vweb/package-lock.json b/vweb/package-lock.json index 0ef0750..da1b05a 100644 --- a/vweb/package-lock.json +++ b/vweb/package-lock.json @@ -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", diff --git a/vweb/package.json b/vweb/package.json index f5b5c20..c611419 100644 --- a/vweb/package.json +++ b/vweb/package.json @@ -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", diff --git a/vweb/src/forge_editor.jsx b/vweb/src/forge_editor.jsx index 6d38915..c675b92 100644 --- a/vweb/src/forge_editor.jsx +++ b/vweb/src/forge_editor.jsx @@ -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) => { diff --git a/vweb/src/forge_simulator.jsx b/vweb/src/forge_simulator.jsx index 7408bdd..d1dc394 100644 --- a/vweb/src/forge_simulator.jsx +++ b/vweb/src/forge_simulator.jsx @@ -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 = } + 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 ( <> @@ -168,7 +187,7 @@ function Tabbar({ activeTab, setActiveTab, anyErrors }) { const classNames = name => (name === activeTab ? 'button active' : 'button') return (
- [Editor] + [Editor (F2)] [Assembly] {anyErrors && [Errors]}
@@ -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 = [Build] if (running) { - runBtn = [Stop] + runBtn = [Stop (F4)] } else { - runBtn = [Run] + runBtn = [Run (F4)] } return ( <>
+ (F1) [new] [del]
- [Reset] + [Reset (F3)] {buildBtn} {runBtn}