Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Local FS UI #419

Merged
merged 112 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
112 commits
Select commit Hold shift + click to select a range
1620ca3
Change hardware simulator to use local file system API
netalondon Jul 7, 2024
f8bbf48
Handle chips with multiple test files
netalondon Jul 11, 2024
6ade4f5
Allow dash in comapre file names
netalondon Jul 11, 2024
07d4ed4
Use local storage file system as fallback
netalondon Jul 11, 2024
2684268
Always use file picker component
netalondon Jul 11, 2024
4ef20ae
Fix test script dropdown
netalondon Jul 11, 2024
bab4f22
Only load compare files using compare-to
netalondon Jul 11, 2024
ea1a7eb
Add warning when can't find matching test file
netalondon Jul 14, 2024
dd14927
Track fs upgrade in assembler
netalondon Jul 14, 2024
f01f147
Save seembler result on disk
netalondon Jul 14, 2024
131c3a0
Add compare-to inst to cpu and vm tests
netalondon Jul 14, 2024
97974a1
Implement loading custom chips
netalondon Jul 14, 2024
27bfc58
Fix ROM32K load inst in computer tests
netalondon Jul 21, 2024
aa18af3
Return chip selection dropdowns
netalondon Jul 21, 2024
65d288e
Fix change local fs
netalondon Jul 21, 2024
1c93ba8
Cleanup old code
netalondon Jul 21, 2024
dae6b32
Fix build errors
netalondon Jul 21, 2024
2497f12
Fix tests and test scripts
netalondon Jul 21, 2024
54643db
CR
netalondon Jul 29, 2024
cee6f41
CR
netalondon Jul 30, 2024
3a2da69
Implement test script load command
netalondon Jul 30, 2024
45c344e
Fix compilation error when loading single vm file
netalondon Jul 30, 2024
e41bfd7
Fix bug in vm file loading
netalondon Jul 30, 2024
05e2b3c
Add async behavior to test script load command
netalondon Jul 30, 2024
48e94e9
Add error message when loaded file is missing
netalondon Jul 30, 2024
b4781aa
Fix build and CI errors
netalondon Jul 30, 2024
0f74356
CR
netalondon Jul 31, 2024
3159cea
Remove console.logs
netalondon Jul 31, 2024
70ab4e7
Fix test
netalondon Jul 31, 2024
7220a12
Move Action<T> change to another PR
netalondon Jul 31, 2024
9c2f2d3
Revert test panel ui changes
netalondon Jul 31, 2024
61f57ce
Add newline in package.json
netalondon Jul 31, 2024
8fa6b68
Remove commented out code
netalondon Jul 31, 2024
1d2dd5c
Fix build errors
netalondon Jul 31, 2024
2eaa7eb
Register output-file as a keyword for styling puropses
netalondon Jul 30, 2024
2b39613
Add hardware simulator tooltips
netalondon Jul 30, 2024
b49c2f1
Sort file picker numbered entries by value
netalondon Jul 21, 2024
fd9f055
Remove beta tag
netalondon Jul 14, 2024
d33894f
Remove assembler download buttons if fs is upgraded
netalondon Jul 14, 2024
37a6de9
Add load compare button in assembler
netalondon Jul 14, 2024
5670b13
Hide file picker button 'Select local file' when fs is upgraded
netalondon Jul 14, 2024
169c569
Add flex wrap to file picker
netalondon Jul 11, 2024
85e2be9
Handle case where no chip is selected
netalondon Jul 11, 2024
04704a1
Hide download button if using local fs
netalondon Jul 11, 2024
354716d
Use file picker component in vm page
netalondon Jul 14, 2024
2f9dad6
Allow loading local folders to vm emulator
netalondon Jul 14, 2024
cdb1a0c
Automatically load matching vm test file
netalondon Jul 14, 2024
d7ef6b1
Load files to jack compiler in non-edit mode for browsers without Fil…
netalondon Jul 14, 2024
a9cf25e
Remove test panel edit mode
netalondon Jul 31, 2024
6b249eb
Change hardware simulator to use local file system API
netalondon Jul 7, 2024
ad830c1
Handle chips with multiple test files
netalondon Jul 11, 2024
19caa16
Allow dash in comapre file names
netalondon Jul 11, 2024
30c87ab
Use local storage file system as fallback
netalondon Jul 11, 2024
7dcad41
Always use file picker component
netalondon Jul 11, 2024
8144f84
Fix test script dropdown
netalondon Jul 11, 2024
48a03ce
Only load compare files using compare-to
netalondon Jul 11, 2024
4781296
Add warning when can't find matching test file
netalondon Jul 14, 2024
fd48b0c
Track fs upgrade in assembler
netalondon Jul 14, 2024
3a2c88d
Save seembler result on disk
netalondon Jul 14, 2024
1166a4a
Add compare-to inst to cpu and vm tests
netalondon Jul 14, 2024
72dddc9
Implement loading custom chips
netalondon Jul 14, 2024
087db53
Fix ROM32K load inst in computer tests
netalondon Jul 21, 2024
addc194
Return chip selection dropdowns
netalondon Jul 21, 2024
6d6893b
Fix change local fs
netalondon Jul 21, 2024
9389f52
Cleanup old code
netalondon Jul 21, 2024
d83e9aa
Fix build errors
netalondon Jul 21, 2024
3c6235c
Fix tests and test scripts
netalondon Jul 21, 2024
5cb1a3e
CR
netalondon Jul 29, 2024
507839b
CR
netalondon Jul 30, 2024
5845000
Implement test script load command
netalondon Jul 30, 2024
2e2b444
Fix compilation error when loading single vm file
netalondon Jul 30, 2024
d2e273f
Fix bug in vm file loading
netalondon Jul 30, 2024
9cf4b42
Add async behavior to test script load command
netalondon Jul 30, 2024
0c63bdf
Add error message when loaded file is missing
netalondon Jul 30, 2024
abda515
Fix build and CI errors
netalondon Jul 30, 2024
2342739
CR
netalondon Jul 31, 2024
aaf2130
Remove console.logs
netalondon Jul 31, 2024
dcbc08e
Fix test
netalondon Jul 31, 2024
0aa7faf
Move Action<T> change to another PR
netalondon Jul 31, 2024
5e7dae9
Revert test panel ui changes
netalondon Jul 31, 2024
ed465be
Add newline in package.json
netalondon Jul 31, 2024
29b7da4
Remove commented out code
netalondon Jul 31, 2024
fe7a17c
Fix build errors
netalondon Jul 31, 2024
7876a8b
Merge branch 'feat/local-fs' into feat/local-fs-ui
netalondon Jul 31, 2024
44fbe07
Reinstate reverted Action<string> cahnges
netalondon Aug 1, 2024
4e5963b
Add missing import
netalondon Aug 1, 2024
b346fed
Fix bug where switching chips while builtin will override new file co…
netalondon Aug 1, 2024
e54f525
Merge branch 'feat/local-fs' into feat/local-fs-ui
netalondon Aug 1, 2024
055ee3f
Fix build errors
netalondon Aug 1, 2024
2f0ea83
CR
netalondon Aug 1, 2024
eb98d99
Merge remote-tracking branch 'upstream/main' into feat/local-fs
netalondon Aug 4, 2024
d9cfd3a
Require a load command in test scripts
netalondon Jul 31, 2024
906c6b0
Add file not found error message for load command
netalondon Aug 4, 2024
dfdfbea
Force CPU emulator test to either have load inst or a file already lo…
netalondon Aug 4, 2024
2846859
Merge branch 'feat/local-fs' into feat/local-fs-ui
netalondon Aug 4, 2024
a0ba5cb
Update CPU emulator load tooltip
netalondon Aug 4, 2024
dc0f9ca
Doccuemnt FileSelectionRef type
netalondon Aug 4, 2024
647ac42
Merge remote-tracking branch 'upstream/main' into feat/local-fs
netalondon Aug 5, 2024
057697c
Fix tests
netalondon Aug 5, 2024
b706e62
Merge branch 'feat/local-fs' into feat/local-fs-ui
netalondon Aug 5, 2024
4683e18
Override pull in OutSubBus
netalondon Aug 5, 2024
bd27a50
Merge branch 'feat/local-fs' into feat/local-fs-ui
netalondon Aug 13, 2024
1552838
Add option to download project files from the IDE
netalondon Aug 27, 2024
06265db
Change hdl project menu text
netalondon Aug 27, 2024
a13ea16
Merge branch 'feat/local-fs' into feat/local-fs-ui
netalondon Aug 27, 2024
a156e83
CR
netalondon Sep 8, 2024
c9d5b1f
Specify return type
netalondon Sep 8, 2024
d7b5b6f
Merge remote-tracking branch 'upstream/main' into feat/local-fs
netalondon Sep 8, 2024
1abfe6f
Fix build error
netalondon Sep 8, 2024
d3cc013
Fix files not loaded on initial entrance in firefox
netalondon Sep 8, 2024
0d564a5
Merge branch 'feat/local-fs' into feat/local-fs-ui
netalondon Sep 8, 2024
68b979c
Merge branch 'release/fs-ui' into feat/local-fs-ui
DavidSouther Sep 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions components/src/chips/memory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ export const Memory = forwardRef(
showClear = true,
onChange = undefined,
onClear = undefined,
loadTooltip = undefined,
}: {
name?: string;
className?: string;
Expand All @@ -212,6 +213,7 @@ export const Memory = forwardRef(
showClear?: boolean;
onChange?: () => void;
onClear?: () => void;
loadTooltip?: { value: string; placement: string };
},
ref,
) => {
Expand Down Expand Up @@ -306,8 +308,8 @@ export const Memory = forwardRef(
<button
onClick={doLoad}
className="flex-0"
data-tooltip={"Load file"}
data-placement="bottom"
data-tooltip={loadTooltip?.value ?? "Load file"}
data-placement={loadTooltip?.placement ?? "bottom"}
>
{/* <Icon name="upload_file" /> */}
📂
Expand Down
5 changes: 0 additions & 5 deletions components/src/stores/vm.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ export interface VmSim {

export interface VMTestSim {
highlight: Span | undefined;
path: string;
}

export interface VmPageState {
Expand Down Expand Up @@ -163,9 +162,6 @@ export function makeVmStore(
}
state.controls.error = error;
},
setPath(state: VmPageState, path: string) {
state.test.path = path;
},
update(state: VmPageState) {
state.vm = reduceVMTest(test, dispatch, setStatus, showHighlight);
state.test.highlight = test.currentStep?.span;
Expand Down Expand Up @@ -203,7 +199,6 @@ export function makeVmStore(
},
test: {
highlight: undefined,
path: "/",
},
files: {
vm: "",
Expand Down
2 changes: 2 additions & 0 deletions web/src/languages/tst.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export const TstLanguage: monaco.languages.IMonarchLanguage = {

keywords: [
"output-list",
"compare-to",
"output-file",
"set",
"eval",
"output",
Expand Down
77 changes: 50 additions & 27 deletions web/src/pages/asm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { Panel } from "../shell/panel";
import { LOADING } from "@nand2tetris/components/messages.js";
import { ROM } from "@nand2tetris/simulator/cpu/memory";
import { Link } from "react-router-dom";
import { isPath } from "src/shell/file_select";
import { AppContext } from "../App.context";
import { PageContext } from "../Page.context";
import URLs from "../urls";
Expand All @@ -21,6 +22,7 @@ export const Asm = () => {
const { filePicker } = useContext(AppContext);
const { stores, setTool } = useContext(PageContext);
const { state, actions, dispatch } = stores.asm;
const { fs, localFsRoot } = useContext(BaseContext);

const sourceCursorPos = useRef(0);
const resultCursorPos = useRef(0);
Expand Down Expand Up @@ -62,15 +64,32 @@ export const Asm = () => {
const path = await filePicker.select({ suffix: ".asm" });
setStatus(LOADING);
requestAnimationFrame(async () => {
await actions.loadAsm(path);
await actions.loadAsm(path.path);
setStatus("");
dispatch.current({
action: "setTitle",
payload: path.split("/").pop() ?? "",
payload: path.path.split("/").pop() ?? "",
});
});
};

const loadCompare = async () => {
const filesRef = await filePicker.selectAllowLocal({ suffix: "hack" });
if (isPath(filesRef)) {
const cmp = await fs.readFile(filesRef.path);
dispatch.current({
action: "setCmp",
payload: { cmp, name: filesRef.path.split("/").pop() },
});
} else {
const file = Array.isArray(filesRef) ? filesRef[0] : filesRef;
dispatch.current({
action: "setCmp",
payload: { cmp: file.content, name: file.name },
});
}
};

const { setStatus } = useContext(BaseContext);

const downloadAsm = () =>
Expand Down Expand Up @@ -151,15 +170,17 @@ export const Asm = () => {
/>
)}
</div>
<fieldset role="group">
<button
data-tooltip="Download"
data-placement="left"
onClick={downloadAsm}
>
⬇️
</button>
</fieldset>
{!localFsRoot && (
<fieldset role="group">
<button
data-tooltip="Download"
data-placement="left"
onClick={downloadAsm}
>
⬇️
</button>
</fieldset>
)}
</>
}
>
Expand Down Expand Up @@ -217,13 +238,15 @@ export const Asm = () => {
>
↩️
</button>
<button
data-tooltip="Download"
data-placement="left"
onClick={downloadHack}
>
⬇️
</button>
{!localFsRoot && (
<button
data-tooltip="Download"
data-placement="left"
onClick={downloadHack}
>
⬇️
</button>
)}
</fieldset>
</div>
</>
Expand Down Expand Up @@ -278,11 +301,13 @@ export const Asm = () => {
<Trans>Compare Code</Trans>
{state.compareName && `: ${state.compareName}`}
</div>
<div>
<fieldset role="group">
<button onClick={compare}>Compare</button>
</fieldset>
</div>
<fieldset role="group">
<button onClick={loadCompare}>📂</button>
</fieldset>
<div className="flex-1" />
<fieldset role="group">
<button onClick={compare}>Compare</button>
</fieldset>
</>
}
>
Expand All @@ -292,11 +317,9 @@ export const Asm = () => {
highlightType={state.compareError ? "error" : "highlight"}
alwaysRecenter={false}
onChange={function (source: string): void {
dispatch.current({
action: "setCmp",
payload: { cmp: source },
});
return;
}}
disabled={true}
onCursorPositionChange={(index) => {
if (index == resultCursorPos.current) {
return;
Expand Down
53 changes: 32 additions & 21 deletions web/src/pages/chip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ export const Chip = () => {
const hdlToCompile = state.controls.usingBuiltin
? files.hdl
: files.hdl ?? hdl;

await actions.updateFiles({
hdl: hdlToCompile,
tst: files.tst ?? tst,
Expand Down Expand Up @@ -142,12 +141,16 @@ export const Chip = () => {

const loadFile = async () => {
const path = await filePicker.select({ suffix: "hdl" });
actions.loadChip(path);
actions.loadChip(path.path);
};

const selectors = (
<>
<fieldset role="group">
<fieldset
role="group"
data-tooltip="Open an HDL file using this menu"
data-placement="bottom"
>
<select
value={state.controls.project}
onChange={({ target: { value } }) => {
Expand All @@ -157,7 +160,7 @@ export const Chip = () => {
>
{state.controls.projects.map((project) => (
<option key={project} value={project}>
{project}
{`Project ${project}`}
</option>
))}
</select>
Expand Down Expand Up @@ -206,7 +209,13 @@ export const Chip = () => {
)}
{selectors}
<fieldset role="group">
<button onClick={loadFile}>📂</button>
<button
data-tooltip="Open an HDL file directly"
data-placement="left"
onClick={loadFile}
>
📂
</button>
</fieldset>
</>
}
Expand All @@ -224,7 +233,7 @@ export const Chip = () => {
}}
grammar={HDL.parser}
language={"hdl"}
disabled={state.controls.usingBuiltin}
disabled={state.controls.usingBuiltin || state.controls.chipName == ""}
/>
</Panel>
);
Expand Down Expand Up @@ -309,21 +318,23 @@ export const Chip = () => {
{state.sim.invalid ? (
<Trans>Syntax errors in the HDL code or test</Trans>
) : (
<>
<PinContext.Provider value={pinResetDispatcher}>
<FullPinout
sim={state.sim}
toggle={actions.toggle}
setInputValid={setInputValid}
hideInternal={state.controls.usingBuiltin}
/>
</PinContext.Provider>
{visualizations.length > 0 && (
<Accordian summary={<Trans>Visualization</Trans>} open={true}>
<main>{visualizations.map(([_, v]) => v)}</main>
</Accordian>
)}
</>
state.controls.chipName != "" && (
<>
<PinContext.Provider value={pinResetDispatcher}>
<FullPinout
sim={state.sim}
toggle={actions.toggle}
setInputValid={setInputValid}
hideInternal={state.controls.usingBuiltin}
/>
</PinContext.Provider>
{visualizations.length > 0 && (
<Accordian summary={<Trans>Visualization</Trans>} open={true}>
<main>{visualizations.map(([_, v]) => v)}</main>
</Accordian>
)}
</>
)
)}
</Panel>
);
Expand Down
65 changes: 46 additions & 19 deletions web/src/pages/compiler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ import URLs from "../urls";
import "./compiler.scss";

export const Compiler = () => {
const { setStatus } = useContext(BaseContext);
const { setStatus, canUpgradeFs } = useContext(BaseContext);
const { tracking } = useContext(AppContext);
const { stores, setTool } = useContext(PageContext);
const { state, dispatch, actions } = stores.compiler;

const [selected, setSelected] = useState(0);
const [suppressStatus, setSuppressStatus] = useState(false);
const [editable, setEditable] = useState(false);

const redirectRef = useRef<HTMLAnchorElement>(null);

Expand Down Expand Up @@ -57,28 +58,46 @@ export const Compiler = () => {
setSelected(Object.keys(state.files).indexOf(state.selected));
}, [state.selected]);

const uploadFiles = async () => {
const handle = await openNand2TetrisDirectory();
const fs = new FileSystem(new FileSystemAccessFileSystemAdapter(handle));

dispatch.current({
action: "setTitle",
payload: `${handle.name} / *.jack`,
});
const loadRef = useRef<HTMLInputElement>(null);

const empty =
(await fs.scandir("/")).filter(
(entry) => entry.isFile() && entry.name.endsWith(".jack"),
).length == 0;
const uploadFiles = async () => {
if (canUpgradeFs) {
const handle = await openNand2TetrisDirectory();
const fs = new FileSystem(new FileSystemAccessFileSystemAdapter(handle));
const empty =
(await fs.scandir("/")).filter(
(entry) => entry.isFile() && entry.name.endsWith(".jack"),
).length == 0;

if (empty) {
setStatus("No .jack files in the selected folder");
setSuppressStatus(true);
if (empty) {
setStatus("No .jack files in the selected folder");
setSuppressStatus(true);
} else {
setStatus("");
actions.loadProject(fs, `${handle.name} / *.jack`);
setEditable(true);
}
} else {
setStatus("");
setSuppressStatus(false);
loadRef.current?.click();
setEditable(false);
}
};

const onLoad = async () => {
if (
!loadRef.current ||
!loadRef.current?.files ||
loadRef.current.files?.length == 0
) {
return;
}
actions.loadProject(fs, `${handle.name} / *.jack`);
const files: Record<string, string> = {};
for (const file of loadRef.current.files) {
if (file.name.endsWith(".jack")) {
files[file.name.replace(".jack", "")] = await file.text();
}
}
actions.loadFiles(files);
};

const compileAll = (): VmFile[] => {
Expand Down Expand Up @@ -147,6 +166,13 @@ export const Compiler = () => {

return (
<div className="Page CompilerPage grid">
<input
type="file"
ref={loadRef}
webkitdirectory=""
onChange={onLoad}
style={{ display: "none" }}
></input>
<Link
ref={redirectRef}
to={URLs["vm"].href}
Expand Down Expand Up @@ -221,6 +247,7 @@ export const Compiler = () => {
}}
error={state.compiled[file].error}
language={"jack"}
disabled={!editable}
/>
</Tab>
))}
Expand Down
Loading
Loading