Skip to content

Commit e70b8f7

Browse files
committed
feat(web-host): add badge on wand button to track the examples you don't have tested yet
1 parent a8ee0d0 commit e70b8f7

File tree

4 files changed

+146
-121
lines changed

4 files changed

+146
-121
lines changed

packages/web-host/src/components/Repl.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { Play, WandSparkles } from "lucide-react";
22
import { useEffect, useRef, useState } from "react";
3+
import { useGetExampleCommand } from "../hooks/exampleCommands";
34
import { useReplHistory } from "../hooks/replHistory";
45
import { useReplLogic } from "../hooks/replLogic";
56
import { cn } from "../utils/css";
6-
import { getExampleCommand } from "../utils/exampleCommands";
77
import type { WasmEngine } from "../wasm/engine";
88
import { ReplHistory } from "./ReplHistory";
99

@@ -23,6 +23,8 @@ export function Repl({
2323
const [inputFocus, setInputFocus] = useState(false);
2424
const { history } = useReplHistory();
2525
const [wandButtonUsed, setWandButtonUsed] = useState(false);
26+
const { getExampleCommand, remainingExampleCommands, doneExampleCommands } =
27+
useGetExampleCommand();
2628

2729
function handleSubmit(
2830
event: Pick<
@@ -123,12 +125,22 @@ export function Repl({
123125
}}
124126
type="button"
125127
className={cn(
126-
"cursor-pointer bg-primary text-white px-4 py-2 rounded-md",
128+
"cursor-pointer bg-primary text-white px-4 py-2 rounded-md relative",
127129
!wandButtonUsed && "animate-bounce",
128130
)}
129131
title="Run example command"
130132
>
131133
<WandSparkles />
134+
{(() => {
135+
if (!doneExampleCommands) {
136+
return (
137+
<span className="absolute -top-2 -right-2 bg-red-500 text-white text-xs rounded-full w-5 h-5 flex items-center justify-center font-bold">
138+
{remainingExampleCommands}
139+
</span>
140+
);
141+
}
142+
return null;
143+
})()}
132144
</button>
133145
</div>
134146
</form>
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import { useState } from "react";
2+
3+
function echo_foo() {
4+
return "echo foo";
5+
}
6+
7+
function echo_bar() {
8+
return "echo bar";
9+
}
10+
11+
function echo_baz() {
12+
return "echo baz";
13+
}
14+
15+
function echo_$0() {
16+
return "echo $0";
17+
}
18+
19+
function echo_$ROOT_$USER() {
20+
return "echo $ROOT/$USER";
21+
}
22+
23+
function export_USER_WebAssembly() {
24+
return "export USER=WebAssembly";
25+
}
26+
27+
function export_USER_Tophe() {
28+
return "export USER=Tophe";
29+
}
30+
31+
function greet_USER() {
32+
return "greet $USER";
33+
}
34+
35+
function azertyuiop() {
36+
return "azertyuiop";
37+
}
38+
39+
function echo_$question_mark() {
40+
return "echo $?";
41+
}
42+
43+
function help() {
44+
return "help";
45+
}
46+
47+
function man_weather() {
48+
return "man weather";
49+
}
50+
51+
function ls(path?: string) {
52+
if (path) {
53+
return `ls ${path}`;
54+
}
55+
return "ls";
56+
}
57+
58+
function cat(path?: string) {
59+
if (path) {
60+
return `cat ${path}`;
61+
}
62+
return "cat";
63+
}
64+
65+
function weather_Paris() {
66+
return "weather Paris";
67+
}
68+
69+
function export_DATE() {
70+
return `export DATE=${new Date().toISOString()}`;
71+
}
72+
73+
function echo_DATE() {
74+
return `echo $DATE`;
75+
}
76+
77+
const commands = [
78+
echo_foo,
79+
echo_bar,
80+
echo_baz,
81+
echo_$0,
82+
echo_$ROOT_$USER,
83+
greet_USER,
84+
echo_$0,
85+
export_USER_WebAssembly,
86+
echo_$ROOT_$USER,
87+
echo_$0,
88+
echo_$question_mark,
89+
azertyuiop,
90+
echo_$question_mark,
91+
echo_$question_mark,
92+
export_DATE,
93+
echo_DATE,
94+
export_USER_Tophe,
95+
echo_$ROOT_$USER,
96+
ls,
97+
() => cat("README.md"),
98+
ls,
99+
() => ls("data"),
100+
() => ls("data/processed"),
101+
() => ls("data/processed/2024"),
102+
() => ls("documents"),
103+
() => cat("documents/config.json"),
104+
weather_Paris,
105+
man_weather,
106+
help,
107+
];
108+
109+
export function useGetExampleCommand() {
110+
const [index, setIndex] = useState<number>(0);
111+
const [command, setCommand] = useState<string>("");
112+
const [remaining, setRemaining] = useState<number>(commands.length);
113+
const [done, setDone] = useState<boolean>(false);
114+
115+
return {
116+
getExampleCommand: function getExampleCommand() {
117+
if (commands.length - index - 1 === 0) {
118+
setDone(true);
119+
setIndex(0);
120+
}
121+
const output = commands[index]();
122+
setCommand(output);
123+
setRemaining((left) => left - 1);
124+
setIndex((index) => index + 1);
125+
return output;
126+
},
127+
currentExampleCommand: command,
128+
remainingExampleCommands: remaining,
129+
doneExampleCommands: done,
130+
};
131+
}

packages/web-host/src/utils/exampleCommands.ts

Lines changed: 0 additions & 116 deletions
This file was deleted.

packages/web-host/tests/utils.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,7 @@ export async function clickWandButton(
5959
expectStderr?: string;
6060
} = {},
6161
) {
62-
await page
63-
.getByRole("button", { name: "Run example command" })
64-
.click({ force: true });
62+
await page.getByTitle("Run example command").click({ force: true });
6563
const input = await page.getByPlaceholder("Type a command...");
6664
await expect(input).toHaveValue(expectStdin);
6765
const stdin = await getLastStd(page, "stdin");

0 commit comments

Comments
 (0)