From 92269635162a8bb48e33027cd6ed7e7ea957f936 Mon Sep 17 00:00:00 2001 From: mwiegand Date: Sun, 17 May 2026 01:55:59 +0200 Subject: [PATCH] feat(editor-v2): srccfg StreamLanguage mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ~30 LOC StreamLanguage definition for Source-engine .cfg syntax. Tokens: line comment (//…), string, number, keyword (exec/alias/bind/ unbindall/wait), identifier. Linewise, no nesting — matches the shape we authored as a Prism regex grammar in the v1 attempt. Co-Authored-By: Claude Opus 4.7 (1M context) --- l4d2web/scripts/editor-src/srccfg-mode.js | 26 +++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 l4d2web/scripts/editor-src/srccfg-mode.js diff --git a/l4d2web/scripts/editor-src/srccfg-mode.js b/l4d2web/scripts/editor-src/srccfg-mode.js new file mode 100644 index 0000000..9c1944c --- /dev/null +++ b/l4d2web/scripts/editor-src/srccfg-mode.js @@ -0,0 +1,26 @@ +import { StreamLanguage } from "@codemirror/language"; + +// Source-engine .cfg syntax (server.cfg style). +// Linewise. No nesting. Tokens: comment, string, number, keyword, identifier. +const KEYWORDS = new Set(["exec", "alias", "bind", "unbindall", "wait"]); + +export const srccfgLanguage = StreamLanguage.define({ + name: "srccfg", + startState: () => ({}), + token(stream) { + if (stream.eatSpace()) return null; + if (stream.match("//")) { + stream.skipToEnd(); + return "comment"; + } + if (stream.match(/^"(?:[^"\\]|\\.)*"?/)) return "string"; + if (stream.match(/^-?\d+(?:\.\d+)?/)) return "number"; + if (stream.match(/^[A-Za-z_][A-Za-z0-9_]*/)) { + const word = stream.current(); + return KEYWORDS.has(word) ? "keyword" : "variableName"; + } + stream.next(); + return null; + }, + languageData: { commentTokens: { line: "//" } }, +});