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

148 lines
4.3 KiB
TypeScript

import { parse } from "./notcl";
describe("Parsing Notcl", () => {
describe("Commands", () => {
it("can parse an empty script", () =>
expect(parse("")).toEqual([true, []]));
it("can parse a one-word command", () =>
expect(parse("a")).toEqual([true, [[{ text: "a" }]]]));
it("can parse a multi-word command", () =>
expect(parse("a b c")).toEqual([
true,
[[{ text: "a" }, { text: "b" }, { text: "c" }]],
]));
it("accepts newlines as command separators", () =>
expect(parse("a\nb")).toEqual([
true,
[[{ text: "a" }], [{ text: "b" }]],
]));
it("does not split commands on folded newlines", () =>
expect(
parse(String.raw`a\
b`)
).toEqual([true, [[{ text: "a" }, { text: "b" }]]]));
it("does split words on folded newlines", () =>
expect(
parse(String.raw`a\
b`)
).toEqual([true, [[{ text: "a" }, { text: "b" }]]]));
it("does split commands on newlines with escaped backslashes", () =>
expect(
parse(String.raw`a\\
b`)
).toEqual([true, [[{ text: "a\\\\" }], [{ text: "b" }]]]));
it("does not split commands on folded newlines with escaped backslashes", () =>
expect(
parse(String.raw`a\\\
b`)
).toEqual([true, [[{ text: "a\\\\" }, { text: "b" }]]]));
it("accepts semicolons as command separators", () =>
expect(parse("a;b")).toEqual([true, [[{ text: "a" }], [{ text: "b" }]]]));
it("tolerates, and ignores, empty commands", () =>
expect(parse("a;;b\n\nc")).toEqual([
true,
[[{ text: "a" }], [{ text: "b" }], [{ text: "c" }]],
]));
test.each([[" a"], ["a "], ["a ;"], ["; a"]])(
"tolerates whitespace before and after commands {%s}",
(text) => expect(parse(text)).toEqual([true, [[{ text: "a" }]]])
);
});
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, [[{ text: "a" }, { text: "#1" }]]]));
it("can have commands before a comment", () =>
expect(parse("a ;#comment")).toEqual([true, [[{ text: "a" }]]]));
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, [[{ text: "b" }]]]));
it("continues the comment through a folded newline with escaped backslashes", () =>
expect(
parse(String.raw`#a\\\
b`)
).toEqual([true, []]));
});
// Enchanted Words
// Braces
// nesting
// escapes
// {, }, correct newline folding
// no trailing chars
// "Quotes"
// no trailing chars
// Interpolated words
// bare
// quotes
// variables- bare, brace
// command subst
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();
});
});
});