Skip to content

Instantly share code, notes, and snippets.

@wyozi
Created January 13, 2023 09:52
Show Gist options
  • Save wyozi/5ea367d55dc725c02676520e6f6c8804 to your computer and use it in GitHub Desktop.
Save wyozi/5ea367d55dc725c02676520e6f6c8804 to your computer and use it in GitHub Desktop.
JSONNet language for codemirror v6
// src https://github.com/google/codemirror-mode-jsonnet
const jsonnet: any = {
token: function (stream, state) {
// Handle special states:
// In a C-style comment
if (state.cComment) {
if (stream.match(/\*\//)) {
state.cComment = false;
return "comment";
}
stream.next();
return "comment";
}
// In a text block (|||)
if (state.textBlock) {
if (state.textBlockIndent == null) {
state.textBlockIndent = stream.indentation();
}
if (stream.indentation() >= state.textBlockIndent) {
stream.skipToEnd();
return "string";
}
if (stream.match(/\s*\|\|\|/)) {
state.textBlock = false;
return "string";
}
stream.next();
return "error";
}
// In a string (all 4 variants)
if (state.string || state.importString) {
let mode = state.string ? "string" : "meta";
if (state.stringRaw) {
if (stream.match(state.stringSingle ? /''/ : /""/)) {
return "string-2";
}
} else {
if (stream.match(/\\[\\"'bfnrt0]/)) {
return "string-2";
}
if (stream.match(/\\u[0-9a-fA-F]{4}/)) {
return "string-2";
}
if (stream.match(/\\/)) {
return "error";
}
}
if (stream.match(state.stringSingle ? /'/ : /"/)) {
state.string = false;
state.importString = false;
state.stringRaw = false;
state.stringDouble = false;
return mode;
}
stream.next();
return mode;
}
// Regular (whole token at a time) processing:
// Comments.
if (stream.match(/\/\//) || stream.match(/#/)) {
stream.skipToEnd();
return "comment";
}
if (stream.match(/\/\*/)) {
state.cComment = true;
return "comment";
}
// Imports (including the strings after them).
if (stream.match(/import(?:str)?\s*"/)) {
state.importString = true;
state.stringSingle = false;
state.stringRaw = false;
return "meta";
}
if (stream.match(/import(?:str)?\s*'/)) {
state.importString = true;
state.stringSingle = true;
state.stringRaw = false;
return "meta";
}
if (stream.match(/import(?:str)?\s*@"/)) {
state.importString = true;
state.stringSingle = false;
state.stringRaw = true;
return "meta";
}
if (stream.match(/import(?:str)?\s*@'/)) {
state.importString = true;
state.stringSingle = true;
state.stringRaw = true;
return "meta";
}
// Strings (without imports)
if (stream.match(/"/)) {
state.string = true;
state.stringSingle = false;
state.stringRaw = false;
return "string";
}
if (stream.match(/'/)) {
state.string = true;
state.stringSingle = true;
state.stringRaw = false;
return "string";
}
if (stream.match(/@"/)) {
state.string = true;
state.stringSingle = false;
state.stringRaw = true;
return "string";
}
if (stream.match(/@'/)) {
state.string = true;
state.stringSingle = true;
state.stringRaw = true;
return "string";
}
// Enter text block.
if (stream.match(/\|\|\|/)) {
state.textBlock = true;
state.textBlockCol = null;
return "string";
}
// Various keywords.
if (stream.match(/local\b/)) return "keyword";
if (stream.match(/\$\b/)) return "keyword";
if (stream.match(/(?:self|super)\b/)) return "keyword";
if (stream.match(/(?:assert|function|if|then|else|for|in)\b/))
return "keyword";
if (stream.match(/tailstrict\b/)) return "keyword";
if (stream.match(/error\b/)) return "keyword";
if (stream.match(/(?:true|false|null)\b/)) return "atom";
if (stream.match(/(?:\.\d+|\d+\.?\d*)(?:e[-+]?\d+)?/i)) return "number";
if (stream.match(/[-+\/*=<>!&~^|$%]+/)) return "operator";
stream.next();
return null;
},
startState: function () {
return {
cComment: false,
textBlock: false,
string: false,
importString: false,
stringSingle: false,
stringRaw: false,
};
},
};
const jsonnetLanguage = StreamLanguage.define(jsonnet);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment