Skip to content

Commit c2fdfae

Browse files
committed
huge improvements to tour editor
1 parent 1672f2e commit c2fdfae

4 files changed

Lines changed: 105 additions & 7 deletions

File tree

web/package-lock.json

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

web/src/lib/moduSyntax.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { StreamLanguage, StringStream } from "@codemirror/language";
2+
3+
export default StreamLanguage.define({
4+
startState() {
5+
return {
6+
inString: false,
7+
inComment: false,
8+
};
9+
},
10+
11+
token(stream: StringStream, state: any): string | null {
12+
if (stream.eatSpace()) return null;
13+
14+
if (stream.match("//")) {
15+
stream.skipToEnd();
16+
return "comment";
17+
}
18+
19+
if (stream.match('"')) {
20+
while (!stream.eol()) {
21+
const ch = stream.next();
22+
if (ch === "\\") {
23+
stream.next();r
24+
} else if (ch === '"') {
25+
break;
26+
}
27+
}
28+
29+
return "string";
30+
}
31+
32+
if (stream.match(/^[0-9]+\.[0-9]+/)) return "number";
33+
if (stream.match(/^[0-9]+/)) return "number";
34+
35+
if (stream.match("..=") || stream.match("..")) return "operator";
36+
if (stream.match("+=") || stream.match("-=") || stream.match("*=") || stream.match("/=") || stream.match("%=")) return "operator";
37+
if (stream.match("==") || stream.match("!=") || stream.match(">=") || stream.match("<=")) return "operator";
38+
if (stream.match(/^[+\-*/%=<>!]/)) return "operator";
39+
40+
if (stream.match(/^[{}\[\]()]/)) return "bracket";
41+
if (stream.match(/^[;,.]/)) return "punctuation";
42+
43+
if (stream.match(/^[a-zA-Z_][a-zA-Z0-9_]*/)) {
44+
const word = stream.current();
45+
46+
const keywords = [
47+
"let", "fn", "class", "import",
48+
"if", "else", "for", "while", "loop", "in",
49+
"return", "break", "continue", "self"
50+
];
51+
52+
if (keywords.includes(word)) return "keyword";
53+
if (word === "true" || word === "false") return "bool";
54+
if (word === "null") return "atom";
55+
if (word === "self") return "variableName.special";
56+
57+
return "variableName";
58+
}
59+
60+
stream.next();
61+
return null;
62+
}
63+
});
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
## Hello, World!
2-
hi
2+
Welcome to the modu language tour! This tour will teach you the basics of the modu programming language.
3+
The code examples are editable and can be ran by pressing the run button in the bottom right of the input,
4+
but normally code is ran with `modu run <file>.modu` or through the repl with `modu repl`.
35

46
[CODE]
7+
// This is a comment!
8+
// The code below prints "Hello, World!"
9+
// Try to change it!
510
print("Hello, World!");

web/src/routes/tour/[...slug]/+page.svelte

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,18 @@
22
import { Play } from "lucide-svelte";
33
import { basicSetup, EditorView } from "codemirror";
44
import { EditorState, Compartment } from "@codemirror/state"
5+
import { HighlightStyle, syntaxHighlighting, bracketMatching, indentUnit } from "@codemirror/language"
6+
import { tags } from "@lezer/highlight"
7+
import { keymap } from "@codemirror/view";
8+
import { indentWithTab } from "@codemirror/commands";
9+
import { closeBrackets, closeBracketsKeymap } from "@codemirror/autocomplete";
10+
511
import { onMount, onDestroy } from "svelte";
12+
import { AnsiUp } from "ansi_up";
613
714
import Navbar from '$lib/navbar.svelte';
815
import { getLesson, getNext, getPrevious } from '$lib/tour/data';
9-
import { AnsiUp } from "ansi_up";
16+
import moduSyntax from "$lib/moduSyntax.js";
1017
1118
let slug: string;
1219
@@ -21,7 +28,12 @@
2128
doc: "",
2229
extensions: [
2330
basicSetup,
24-
tabsize.of(EditorState.tabSize.of(4)),
31+
EditorState.tabSize.of(4),
32+
indentUnit.of(" "),
33+
language.of(moduSyntax),
34+
keymap.of([indentWithTab, ...closeBracketsKeymap]),
35+
closeBrackets(),
36+
bracketMatching(),
2537
EditorView.theme({
2638
"&": {
2739
color: "#fbf1c7",
@@ -53,7 +65,19 @@
5365
border: "none",
5466
},
5567
56-
}, { dark: true })
68+
}, { dark: true }),
69+
syntaxHighlighting(HighlightStyle.define([
70+
{ tag: tags.string, color: "#a6e3a1" },
71+
{ tag: tags.keyword, color: "#cba6f7" },
72+
{ tag: tags.atom, color: "#f38ba8" },
73+
{ tag: tags.escape, color: "#f5c2e7" },
74+
{ tag: tags.comment, color: "#a89984" },
75+
{ tag: tags.number, color: "#fab387" },
76+
{ tag: tags.float, color: "#fab387" },
77+
{ tag: tags.operator, color: "#89dceb" },
78+
{ tag: tags.brace, color: "#a89984" },
79+
{ tag: tags.bool, color: "#89b4fa" }
80+
])),
5781
]
5882
});
5983
@@ -94,8 +118,6 @@
94118
95119
run(); // run code on load
96120
}
97-
98-
console.log(lesson);
99121
})();
100122
}
101123
}
@@ -126,7 +148,7 @@
126148
<div class="prose max-w-none border border-bg2 py-2 px-4 rounded-lg flex-1">{@html html}</div>
127149
<div class="mt-6 text-center">
128150
<a href={getPrevious(slug)} class={`text-blue hover:underline ${!getPrevious(slug) && "opacity-50 cursor-not-allowed"}`}>&lt; previous</a>
129-
<span class="mx-2 text-fg2">—</span>
151+
<span class="mx-2 text-[#7c6d67]">—</span>
130152
<a href={getNext(slug)} class={`text-blue hover:underline ${!getNext(slug) && "opacity-50 cursor-not-allowed"}`}>next &gt;</a>
131153
</div>
132154
</div>

0 commit comments

Comments
 (0)