hljs.registerLanguage("relux", function (hljs) {
const INTERPOLATION = {
className: "subst",
begin: /\$\{/,
end: /\}/,
contains: [
{ className: "variable", begin: /[a-zA-Z_][a-zA-Z0-9_]*/ },
{ begin: /\./ }
]
};
const CAPTURE_VAR = { className: "variable", begin: /\$[0-9]+/ };
const STRING = {
className: "string",
begin: '"',
end: '"',
contains: [hljs.BACKSLASH_ESCAPE, INTERPOLATION, CAPTURE_VAR]
};
const DOCSTRING = { className: "string", begin: '"""', end: '"""' };
const COMMENT = hljs.COMMENT("//", "$");
const PAYLOAD_CONTAINS = [INTERPOLATION, CAPTURE_VAR];
const DURATION = { scope: "keyword.duration", begin: /[~@][0-9][0-9a-zA-Z]*\b/ };
const MARKER = {
className: "comment",
begin: /^\s*#\s+(?=(?:skip|run|flaky)\b)/,
end: /$/,
contains: [
{ className: "keyword", begin: /\b(?:skip|run|flaky|if|unless)\b/ },
{ className: "keyword", begin: /\s(?:\?=|=)(?=\s)/ },
{ className: "title", begin: /\b[a-z_][a-zA-Z0-9_]*(?=\()/ },
INTERPOLATION,
CAPTURE_VAR,
STRING,
{ className: "variable", begin: /\b[a-zA-Z_][a-zA-Z0-9_]*\b/ }
]
};
const OP_TIMED_MATCH_REGEX = {
begin: [/</, /[~@][0-9][0-9a-zA-Z]*/, /\?/],
beginScope: { 1: "keyword", 2: "keyword.duration", 3: "keyword" },
end: /$/,
contains: PAYLOAD_CONTAINS,
className: "string"
};
const OP_TIMED_MATCH_LITERAL = {
begin: [/</, /[~@][0-9][0-9a-zA-Z]*/, /=/],
beginScope: { 1: "keyword", 2: "keyword.duration", 3: "keyword" },
end: /$/,
contains: PAYLOAD_CONTAINS,
className: "string"
};
const OP_MATCH_REGEX = {
begin: /<\?/,
beginScope: "keyword",
end: /$/,
contains: PAYLOAD_CONTAINS,
className: "string"
};
const OP_MATCH_LITERAL = {
begin: /<=/,
beginScope: "keyword",
end: /$/,
contains: PAYLOAD_CONTAINS,
className: "string"
};
const OP_FAIL_REGEX = {
begin: /!\?/,
beginScope: "keyword",
end: /$/,
contains: PAYLOAD_CONTAINS,
className: "string"
};
const OP_FAIL_LITERAL = {
begin: /!=/,
beginScope: "keyword",
end: /$/,
contains: PAYLOAD_CONTAINS,
className: "string"
};
const OP_SEND_RAW = {
begin: /=>/,
beginScope: "keyword",
end: /$/,
contains: PAYLOAD_CONTAINS,
className: "string"
};
const OP_SEND = {
begin: /(?<![-=<!)>])>/,
beginScope: "keyword",
end: /$/,
contains: PAYLOAD_CONTAINS,
className: "string"
};
const DECL_FN = {
match: [/\bfn/, /\s+/, /[a-z_][a-zA-Z0-9_]*/],
scope: { 1: "keyword", 3: "title.function" }
};
const DECL_EFFECT = {
match: [/\beffect/, /\s+/, /[A-Z][a-z][a-zA-Z0-9_]*/],
scope: { 1: "keyword", 3: "type" }
};
const DECL_LET_VAR = {
match: [/\b(?:let|var)/, /\s+/, /[a-z_][a-zA-Z0-9_]*/],
scope: { 1: "keyword", 3: "variable" }
};
const DECL_EXPOSE = {
match: [/\bexpose/, /\s+/, /shell/, /\s+/, /[a-z_][a-zA-Z0-9_]*/],
scope: { 1: "keyword", 3: "keyword", 5: "variable" }
};
const DECL_EXPECT = {
match: [/\bexpect/, /\s+/, /[a-zA-Z_][a-zA-Z0-9_]*/],
scope: { 1: "keyword", 3: "variable" }
};
const DECL_SHELL = {
match: [/\bshell/, /\s+/, /[a-z_][a-zA-Z0-9_]*/],
scope: { 1: "keyword", 3: "variable" }
};
const DECL_START_AS = {
match: [
/\bstart/,
/\s+/,
/[A-Z][a-z][a-zA-Z0-9_]*/,
/\s+/,
/as/,
/\s+/,
/[A-Z][a-z][a-zA-Z0-9_]*/
],
scope: { 1: "keyword", 3: "type", 5: "keyword", 7: "type" }
};
const DECL_START = {
match: [/\bstart/, /\s+/, /[A-Z][a-z][a-zA-Z0-9_]*/],
scope: { 1: "keyword", 3: "type" }
};
const DECL_IMPORT = {
match: [/\bimport/, /\s+/, /[a-zA-Z_][a-zA-Z0-9_/]*/],
scope: { 1: "keyword", 3: "variable" }
};
const IMPORT_BRACE = {
begin: /(?<=import\s+[a-zA-Z_][a-zA-Z0-9_/]*\s*)\{/,
end: /\}/,
contains: [
{ className: "type", begin: /\b[A-Z][a-zA-Z0-9_]*\b/ },
{
match: [/\bas/, /\s+/, /[A-Z][a-zA-Z0-9_]*/],
scope: { 1: "keyword", 3: "type" }
},
{
match: [/\bas/, /\s+/, /[a-z_][a-zA-Z0-9_]*/],
scope: { 1: "keyword", 3: "title" }
},
{ className: "title", begin: /\b[a-z_][a-zA-Z0-9_]*\b/ }
]
};
const DECL_AS_TYPE = {
match: [/\bas/, /\s+/, /[A-Z][a-z][a-zA-Z0-9_]*/],
scope: { 1: "keyword", 3: "type" }
};
const DECL_AS_VAR = {
match: [/\bas/, /\s+/, /[a-z_][a-zA-Z0-9_]*/],
scope: { 1: "keyword", 3: "variable" }
};
const ASSIGN_LHS = {
match: [/\b[a-zA-Z_][a-zA-Z0-9_]*/, /\s*/, /=(?!>)/],
scope: { 1: "variable" }
};
const FN_CALL_ARGS = {
begin: /\(/,
end: /\)/,
contains: [
INTERPOLATION,
CAPTURE_VAR,
STRING,
{ className: "title", begin: /\b[a-z_][a-zA-Z0-9_]*(?=\()/ },
{ className: "type", begin: /\b[A-Z][a-z][a-zA-Z0-9_]*\b/ },
{ className: "variable", begin: /\b[A-Z_][A-Z0-9_]*\b/ },
{ className: "variable", begin: /\b[a-z_][a-zA-Z0-9_]*\b/ },
{ className: "number", begin: /\b[0-9]+\b/ }
]
};
const USE_DOTTED_TYPE = {
match: [/\b[A-Z][a-z][a-zA-Z0-9_]*/, /\./, /[a-z_][a-zA-Z0-9_]*/],
scope: { 1: "type", 3: "variable" }
};
const USE_DOTTED_VAR = {
match: [/\b[a-z_][a-zA-Z0-9_]*/, /\./, /[a-z_][a-zA-Z0-9_]*/],
scope: { 1: "variable", 3: "variable" }
};
const USE_TYPE = { scope: "type", begin: /\b[A-Z][a-z][a-zA-Z0-9_]*\b/ };
const USE_ENV = { scope: "variable", begin: /\b[A-Z_][A-Z0-9_]*\b/ };
const USE_FN_CALL = { scope: "title.function", begin: /\b[a-z_][a-zA-Z0-9_]*(?=\()/ };
const USE_VAR = {
scope: "variable",
begin: /\b(?!(?:test|effect|fn|pure|import|shell|let|start|expect|expose|var|as|cleanup|needs|if|unless)\b)[a-z_][a-zA-Z0-9_]*\b(?!\s*[(.={])/
};
return {
name: "Relux",
aliases: ["relux"],
case_insensitive: false,
keywords: {
keyword:
"test effect fn pure import shell let start expect expose var as cleanup needs if unless",
built_in:
"trim upper lower replace split len uuid rand available_port which default " +
"sleep annotate log match_prompt match_exit_code match_ok match_not_ok " +
"ctrl_c ctrl_d ctrl_z ctrl_l ctrl_backslash"
},
contains: [
COMMENT,
DOCSTRING,
MARKER,
DECL_START_AS,
DECL_START,
DECL_FN,
DECL_EFFECT,
DECL_LET_VAR,
DECL_EXPOSE,
DECL_EXPECT,
DECL_SHELL,
DECL_IMPORT,
IMPORT_BRACE,
DECL_AS_TYPE,
DECL_AS_VAR,
ASSIGN_LHS,
FN_CALL_ARGS,
OP_TIMED_MATCH_REGEX,
OP_TIMED_MATCH_LITERAL,
OP_MATCH_REGEX,
OP_MATCH_LITERAL,
OP_FAIL_REGEX,
OP_FAIL_LITERAL,
OP_SEND_RAW,
OP_SEND,
DURATION,
USE_DOTTED_TYPE,
USE_DOTTED_VAR,
USE_TYPE,
USE_ENV,
USE_FN_CALL,
USE_VAR,
STRING,
CAPTURE_VAR,
{ className: "number", begin: /\b[0-9]+\b/ }
]
};
});
(function rehighlightRelux() {
function run() {
document.querySelectorAll("code.language-relux").forEach(function (block) {
block.classList.remove("hljs");
delete block.dataset.highlighted;
hljs.highlightBlock(block);
});
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", run);
} else {
run();
}
})();