prototype-3x5/src/notcl.test.ts

224 lines
7.5 KiB
TypeScript
Raw Normal View History

2023-08-06 06:38:52 +00:00
import { parse } from "./notcl";
describe("Parsing Notcl", () => {
describe("Commands", () => {
2023-08-06 23:52:00 +00:00
it("can parse an empty script", () =>
2023-08-06 06:38:52 +00:00
expect(parse("")).toEqual([true, []]));
2023-08-06 23:52:00 +00:00
it("can parse a one-word command", () =>
expect(parse("a")).toEqual([true, [[{ enchanted: "a" }]]]));
2023-08-06 23:52:00 +00:00
it("can parse a multi-word command", () =>
expect(parse("a b c")).toEqual([
true,
[[{ enchanted: "a" }, { enchanted: "b" }, { enchanted: "c" }]],
2023-08-06 23:52:00 +00:00
]));
it("accepts newlines as command separators", () =>
expect(parse("a\nb")).toEqual([
true,
[[{ enchanted: "a" }], [{ enchanted: "b" }]],
2023-08-06 23:52:00 +00:00
]));
it("does not split commands on folded newlines", () =>
expect(
parse(String.raw`a\
b`)
).toEqual([true, [[{ enchanted: "a" }, { enchanted: "b" }]]]));
it("does split words on folded newlines", () =>
expect(
parse(String.raw`a\
b`)
).toEqual([true, [[{ enchanted: "a" }, { enchanted: "b" }]]]));
it("does split commands on newlines with escaped backslashes", () =>
2023-08-06 23:52:00 +00:00
expect(
parse(String.raw`a\\
b`)
2023-08-23 05:09:56 +00:00
).toEqual([true, [[{ text: "a\\" }], [{ enchanted: "b" }]]]));
2023-08-06 23:52:00 +00:00
it("does not split commands on folded newlines with escaped backslashes", () =>
expect(
parse(String.raw`a\\\
b`)
2023-08-23 05:09:56 +00:00
).toEqual([true, [[{ text: "a\\" }, { enchanted: "b" }]]]));
2023-08-06 23:52:00 +00:00
it("accepts semicolons as command separators", () =>
expect(parse("a;b")).toEqual([
true,
[[{ enchanted: "a" }], [{ enchanted: "b" }]],
]));
2023-08-06 23:52:00 +00:00
it("tolerates, and ignores, empty commands", () =>
expect(parse("a;;b\n\nc")).toEqual([
true,
[[{ enchanted: "a" }], [{ enchanted: "b" }], [{ enchanted: "c" }]],
2023-08-06 23:52:00 +00:00
]));
test.each([[" a"], ["a "], ["a ;"], ["; a"]])(
"tolerates whitespace before and after commands {%s}",
(text) => expect(parse(text)).toEqual([true, [[{ enchanted: "a" }]]])
2023-08-06 23:52:00 +00:00
);
});
describe("Comments", () => {
it("ignores comments", () => expect(parse("#comment")).toEqual([true, []]));
it("does not treat # in argument position as a comment", () =>
expect(parse("a #1")).toEqual([
true,
[[{ enchanted: "a" }, { enchanted: "#1" }]],
]));
2023-08-06 23:52:00 +00:00
it("can have commands before a comment", () =>
expect(parse("a ;#comment")).toEqual([true, [[{ enchanted: "a" }]]]));
2023-08-06 23:52:00 +00:00
it("ignores the whole line after a comment", () =>
expect(parse("# comment ; not a command")).toEqual([true, []]));
it("continues the comment through a folded newline", () =>
expect(
parse(String.raw`#a\
b`)
).toEqual([true, []]));
it("does not continue the comment through a newline with escaped backslashes", () =>
expect(
parse(String.raw`#a\\
b`)
).toEqual([true, [[{ enchanted: "b" }]]]));
2023-08-06 23:52:00 +00:00
it("continues the comment through a folded newline with escaped backslashes", () =>
expect(
parse(String.raw`#a\\\
b`)
).toEqual([true, []]));
2023-08-06 06:38:52 +00:00
});
2023-08-06 23:52:00 +00:00
2023-08-11 01:51:23 +00:00
describe("enchanted words", () => {
// Enchanted Words
// simple words
// not braces
// not quotes
// not variables
// not commands
// not backslashes
// yes before folded newline
// no before folded newline that gives us backslashes
});
2023-08-23 05:09:56 +00:00
describe("interpolated words", () => {
it("accepts empty quotes", () =>
expect(parse('""')).toEqual([true, [[{ text: "" }]]]));
it("accepts quoted words", () =>
expect(parse('"a"')).toEqual([true, [[{ text: "a" }]]]));
it("accepts quoted words with spaces", () =>
expect(parse('"a b"')).toEqual([true, [[{ text: "a b" }]]]));
it("allows escaped quotes inside a quote", () =>
expect(parse('"a\\"b"')).toEqual([true, [[{ text: 'a"b' }]]]));
it("does not allow trailing characters after a closing quote", () =>
expect(parse('""a')).toMatchObject([false, {}]));
it("accepts escaped spaces", () =>
expect(parse("a\\ b")).toEqual([true, [[{ text: "a b" }]]]));
it("treats a non-leading quote as a plain character", () =>
expect(parse('a"')).toEqual([true, [[{ text: 'a"' }]]]));
it("treats a non-leading brace as a plain character", () =>
expect(parse("a{")).toEqual([true, [[{ text: "a{" }]]]));
it("treats an escaped quote as a plain character", () =>
expect(parse('\\"')).toEqual([true, [[{ text: '"' }]]]));
it("treats an escaped brace as a plain character", () =>
expect(parse("\\{")).toEqual([true, [[{ text: "{" }]]]));
it("treats a quoted brace as a plain character", () =>
expect(parse('"{"')).toEqual([true, [[{ text: "{" }]]]));
// Interpolated words
// variables- bare, brace
// command subst
});
2023-08-11 01:51:23 +00:00
describe("brace words", () => {
it("can parse empty braces", () =>
expect(parse("{}")).toEqual([true, [[{ text: "" }]]]));
it("can parse braces with text", () =>
expect(parse("{a b c}")).toEqual([true, [[{ text: "a b c" }]]]));
it("can parse nested braces", () =>
expect(parse("{{}}")).toEqual([true, [[{ text: "{}" }]]]));
it("can parse nested braces with text", () =>
expect(parse("{a{b}c}")).toEqual([true, [[{ text: "a{b}c" }]]]));
2023-08-22 03:57:27 +00:00
it("does not allow trailing characters after a closing brace", () =>
expect(parse("{}a")).toMatchObject([false, {}]));
it("doesn't count suppressed braces for nesting", () =>
expect(parse(String.raw`{a\{b}`)).toEqual([true, [[{ text: "a\\{b" }]]]));
it("doesn't count suppressed braces for unnesting", () =>
expect(parse(String.raw`{a\}b}`)).toEqual([true, [[{ text: "a\\}b" }]]]));
2023-08-11 01:51:23 +00:00
it("nests braces after suppressed backslashes", () =>
expect(parse(String.raw`{a\\{b}}`)).toEqual([
true,
[[{ text: "a\\\\{b}" }]],
]));
it("permits newlines in braces", () =>
expect(parse("{\n}")).toEqual([true, [[{ text: "\n" }]]]));
it("folds newlines in braces", () =>
expect(
parse(String.raw`{\
}`)
).toEqual([true, [[{ text: " " }]]]));
it("doesn't fold newlines in braces with escaped backslashes", () =>
expect(
parse(String.raw`{\\
}`)
).toEqual([true, [[{ text: "\\\\\n" }]]]));
it("folds newlines in braces with escaped backslashes", () =>
expect(
parse(String.raw`{\\\
}`)
).toEqual([true, [[{ text: "\\\\ " }]]]));
});
2023-08-06 23:52:00 +00:00
describe("Misc", () => {
test("Big mess of markup", () => {
expect(
parse(String.raw`
h1 "Hello, World!"
para [2 + 2]
block {
This is a paragraph of text, with one [b bold] word. Yes, this means there has to be some magic in text processing... <b>this</b> won't work.
}
block -red "Beware!"
para "All text should be quoted, it's clearer that way. & blockquotes already should contain paragraphs. (maybe normalize nested paragraphs)"
block {
First block
} {
Second block
Is this markdown-parsed?
[button "No we want to render UI" \\{noop}]
} {
Since we want escapes to work, these blocks [i will] be subject to substitutions.
}
# A comment
para {
line endings escaped\
one slash
not escaped if \\
two slashes
escaped with a slash if \\\
three slashes
not escaped with two slashes if \\\\
four slashes
escaped with two slashes if \\\\\
five slashes
not escaped with three slashes if \\\\\\
six slashes
}
`)
).toMatchSnapshot();
});
});
2023-08-06 06:38:52 +00:00
});