diff --git a/app/Editor.jsx b/app/Editor.jsx
index de159f7..8710d28 100644
--- a/app/Editor.jsx
+++ b/app/Editor.jsx
@@ -9,10 +9,6 @@ const styles = {
iconButton: "w-4 h-4 hover:scale-110 transition-transform duration-100",
};
-function metaKey() {
- return navigator.userAgent.includes("Mac") ? "cmd" : "ctrl";
-}
-
export function Editor({
initialCode,
onUserInput = () => {},
@@ -75,6 +71,10 @@ export function Editor({
editorRef.current.run();
}
+ function metaKey() {
+ return typeof navigator !== "undefined" || navigator.userAgent.includes("Mac") ? "cmd" : "ctrl";
+ }
+
return (
This first donut code is ported from https://www.a1k0n.net/js/donut.js,
+ * > the original author is Alex Naka, please refer to the original post for
+ * > more math details: https://www.a1k0n.net/2011/07/20/donut-math.html
+ *
+ * In this example, we draw a donut by a "donut" code, and the code for
+ * formatting the "donut" code is also a "donut" code. So, there are three
+ * donuts in this example!!!
+ */
+
+// Click to change the rotation speed of the donut.
+const S = recho.number(10, {min: 5, max: 30, step: 1});
+
+const T = recho.interval(30);
+
+//➜
+//➜
+//➜
+//➜ $$$@@@@@@
+//➜ #####**###$$$$@@@@$
+//➜ ##**!!!==!!!**##$$$@@@$$
+//➜ ##*!=!===;;:;=!!*##$$$$$$$$#
+//➜ *#**!!=;::~~~~::==**##$$$$$$$#*
+//➜ ###*!=;:~-,...,-~;=!*###$$$$$$##*
+//➜ !####*!=:~,.......~;=!*###$$$$$$##*
+//➜ =#$$$##*=:-..... .~;!!*####$$$$###*!
+//➜ *$$$$$#*!;~.. ~=!**###########**=
+//➜ !#$$@@$$#*=~. :=!**###########**!=
+//➜ !#$@@@@$$#*; ;!!***##########***!!;
+//➜ !#$$@@@@$$#*!!!!****##########****!!=:
+//➜ =*#$$$$$$$#################*****!!!=:
+//➜ ;!*##$$$$##############*******!!!=;;
+//➜ :;!**############*********!*!!!==;:
+//➜ :=!!!***************!*!*!!!!==;:~
+//➜ :;!===!***!!!!!!!!!!!!!!===;:~-
+//➜ ~:;=====!!!!!!!!!====;;;::~,
+//➜ -~::;;;===;=;;;;;;:::~-.
+//➜
+{
+
+ var b=[];var z=[];
+ var A=1+(T*0.07*S)/10;var
+ B=1+(T*0.03*S)/10;var sin=/***/
+ Math.sin;var cos=Math.cos;var cA=
+ cos(A),sA=sin(A),cB=cos(B),sB=sin(B);
+ for(var k=0;k<1760;k++){b[k]=k%80==79?
+ "\n":" ";z[k]=0;}for (var j=0;j<6.28;j+=
+ 0.07){var ct=/**/ cos(j),st=sin(j);
+ for(var i=0;i< 6.28;i+=0.02){
+ var sp=sin(i), cp=cos(i),h=ct
+ +2,D=1/(sp*h* sA+st*cA+5),t
+ =sp*h*cA-st*sA; var x=0|(40+30
+ *D*(cp*h*cB-t* sB)),y=0|(12+15
+ *D*(cp*h*sB+t*/**/ cB)),o=x+80*y,N=
+ 0|(8*((st*sA-sp*ct* cA)*cB-sp*ct*sA-st*cA
+ -cp*ct*sB));if(y<22&&y>=0&&x>=0&&x<79&&
+ D>z[o]){z[o]=D;b[o]=".,-~:;=!*#$@"[N>
+ 0?N:0];}}}echo(b.join(""));/*****
+ *******************************
+ *************************
+ ******************/
+
+}
+
+
+/**
+ * We use a format function to format the code for drawing the
+ * donut. The readable code is as follows:
+ */
+
+echo(format(`
+var b = [];
+var z = [];
+var A = 1 + (T * 0.07 * S) / 10;
+var B = 1 + (T * 0.03 * S) / 10;
+var sin = Math.sin;
+var cos = Math.cos;
+var cA = cos(A),
+ sA = sin(A),
+ cB = cos(B),
+ sB = sin(B);
+for (var k = 0; k < 1760; k++) {
+ b[k] = k % 80 == 79 ? "\\n" : " ";
+ z[k] = 0;
+}
+for (var j = 0; j < 6.28; j += 0.07) {
+ var ct = cos(j),
+ st = sin(j);
+ for (var i = 0; i < 6.28; i += 0.02) {
+ var sp = sin(i),
+ cp = cos(i),
+ h = ct + 2,
+ D = 1 / (sp * h * sA + st * cA + 5),
+ t = sp * h * cA - st * sA;
+ var x = 0 | (40 + 30 * D * (cp * h * cB - t * sB)),
+ y = 0 | (12 + 15 * D * (cp * h * sB + t * cB)),
+ o = x + 80 * y,
+ N = 0 | (8 * ((st * sA - sp * ct * cA) * cB - sp * ct * sA - st * cA - cp * ct * sB));
+ if (y < 22 && y >= 0 && x >= 0 && x < 79 && D > z[o]) {
+ z[o] = D;
+ b[o] = ".,-~:;=!*#$@"[N > 0 ? N : 0];
+ }
+ }
+}
+echo(b.join(""));
+`));
+
+/**
+ * !!! The format function is also a "donut" code !!!
+ */
+
+ function /********/
+ format(code,{w=80,h=24,K=/**/
+ ["var"],R1=11,R2=4}={}){let n=w
+ *h,mi=-1,M=new Array(n).fill(null),
+ T=code.replace('" "',"__")/**********/
+ .replace(/\s+/g," ").split(" ").filter((d)=>
+ d!=="").map((d)=>d.replace("__",'" "')),tn=
+ T.length;for(let i=0;i R2;if(m)mi=i;/**/
+ M[i]=m?1:x===w-1 ?"\n":" ";}let ni=
+ -1;for(let i=0, wi=0;i/**/
+ s.includes(k)))s=s +" ";let si=0;while
+ (M[i+si]===1)si++;if(si d !== "")
+ .map((d) => d.replace("__", '" "')),
+ tn = T.length;
+ for (let i = 0; i < n; i++) {
+ let x = i % w,
+ y = Math.floor(i / w),
+ d = Math.hypot((x - w / 2) / 2, y - h / 2),
+ m = d < R1 && d > R2;
+ if (m) mi = i;
+ M[i] = m ? 1 : x === w - 1 ? "\n" : " ";
+ }
+ let ni = -1;
+ for (let i = 0, wi = 0; i < n; i++) {
+ if (M[i] !== 1) continue;
+ if (wi < tn) {
+ let s = T[wi];
+ if (K.some((k) => s.includes(k))) s = s + " ";
+ let si = 0;
+ while (M[i + si] === 1) si++;
+ if (si < s.length - 1) s = si - 1 <= 0 ? " " : "/*" + "*".repeat(Math.max(0, si - 4)) + "*/";
+ else wi++;
+ for (let k = 0; k < s.length; k++) M[(ni = i + k)] = s[k];
+ } else if (i - ni <= 2) M[i] = "/\*"[i - ni - 1];
+ else if (mi - i <= 1) M[i] = "/\*"[mi - i];
+ else M[i] = "*";
+ }
+ return M.join("");
+ }
+ `, {K:["let", "function", "new", "else", "return"], R1:12}));
diff --git a/app/examples/donut.snap.png b/app/examples/donut.snap.png
new file mode 100644
index 0000000..d4a63e1
Binary files /dev/null and b/app/examples/donut.snap.png differ
diff --git a/app/examples/matrix-rain.recho.js b/app/examples/matrix-rain.recho.js
index 1421953..146b9e5 100644
--- a/app/examples/matrix-rain.recho.js
+++ b/app/examples/matrix-rain.recho.js
@@ -16,7 +16,7 @@
* a way to render **shapes** in Recho.
*
* My implementation is basically a **particle system**. Each column of the
- * matrix is a particle. Each particle has a lifespan, a initial y position,
+ * matrix is a particle. Each particle has a lifespan, a initial y position,
* and a set of characters. The following rules are applied to each particle:
*
* - If a particle is dead (lifespan < 0), it will be reset,
@@ -93,7 +93,10 @@ const columns = d3.range(width).map(() => createColumn(height));
for (let j = 0; j < width; ++j) output += buffer[i * width + j];
output += i === height - 1 ? "" : "\n";
}
- output = output.split("\n").map((d) => " " + d).join("\n");
+ output = output
+ .split("\n")
+ .map((d) => " " + d)
+ .join("\n");
echo(output);
}