Das Konfigurationsformat CASC
CASC ist eine Konfigurationssprache mit echter Spezifikation: verschachtelte Blöcke, typisierte Werte von Zeitdauern bis zu IP-Bereichen, Variablen, Umgebungszugriffe, Verweise auf andere Schlüssel, Imports und Schleifen — in einer Syntax, die als Klartext lesbar bleibt.
Ein erster Blick
Eine CASC-Datei ist eine Folge von Anweisungen, die zusammen einen Baum benannter Werte ergeben. Diese hier liest eine Umgebungsdatei, einige Umgebungsvariablen und eine gemeinsame Variable und verweist von einem Schlüssel auf zwei andere:
#@version = 1.0
import "env/${APP_ENV:dev}.casc"
@region = ${REGION:"eu-west"}
server {
host = "0.0.0.0"
port = !int(${PORT:8080})
}
database {
host = "db.@{region}.internal"
*password = ${DB_PASSWORD:?"DB_PASSWORD is required"}
timeout = 500ms
cache = 512MiB
}
health.url = "http://%{server.host}:%{server.port}/health"#@version = 1.0— jede Datei beginnt mit ihrer Formatversion.importholt eine weitere Datei hinzu; ihr Pfad darf die Umgebung lesen.@regionist eine Variable,${…}liest die Umgebung,%{…}verweist auf einen anderen Schlüssel des fertigen Baums.500msund512MiBsind Werte eigenen Typs, keine Zeichenketten, die später noch geparst werden müssen.*passwordist als geheim markiert: der Wert bleibt überall geschwärzt, wo er landet.:?"…"macht eine fehlende Umgebungsvariable zu einem Ladefehler mit eigener Meldung.
Gestaltung
- Eine Art von Map. Block und Punkt-Pfad sind zwei Schreibweisen desselben Baums, und doppelt geschriebene Blöcke werden zusammengeführt.
- Typisierte Literale. Zeitdauern, Bytegrößen, Datum und Uhrzeit, IP-Adressen und Tupel sind Werte der Sprache selbst.
- Drei Verweisarten, eine Grammatik.
@{}für Variablen,${}für die Umgebung und%{}für Konfigurationspfade teilen sich Defaults, Wächter, Indizes und Filter. - Ausdrückliches Zusammenführen. Spätere Zuweisungen gewinnen, Blöcke werden tief gemischt; die Sigils
~,+und-ersetzen, hängen an und entfernen, wenn genau das gemeint ist. - Nichts Unbekanntes rutscht durch. Ein Tag, Resolver oder Import-Schema, das niemand registriert hat, ist ein Ladefehler, der es beim Namen nennt.
- Geheimnisse in der Syntax. Ein
*am Schlüssel markiert den Wert als geheim, und wer ihn interpoliert, erhält ein ebenfalls geschwärztes Ergebnis.
Der Name ist ein Wortspiel: Ein Cooper ist ein Böttcher, und ein „casc“ ist ein Fass. Das Format ist das, was im Fass steckt.
Eckdaten
| Eigenschaft | Wert |
|---|---|
| Endung | .casc |
| Kodierung | UTF-8 |
| Erste Zeile | #@version = 1.0 — Pflicht, in jeder Datei |
| Kommentare | # gefolgt von einem Leerzeichen, bis zum Zeilenende |
| Ergebnis | Ein Baum: Blöcke sind Maps, Blätter typisierte Werte |
| Grammatik | PEG, geschrieben in Aether — siehe Grammatik |
Implementierungen und Werkzeuge
Diese Seiten beschreiben das Format. Wie die folgenden Bibliotheken es laden oder bereitstellen, steht jeweils in deren eigener Dokumentation.
| Name | Sprache | Rolle |
|---|---|---|
| cooper | Elixir | Die Referenzimplementierung |
| cooper_config | Elixir | Nutzt eine CASC-Datei als Konfiguration eines Mix-Projekts oder Releases |
| CASC for VS Code | TypeScript | Syntaxhervorhebung, Snippets und ein Language Server |
| cooper | Praxis | Ein Port von Cooper, aus derselben Grammatik erzeugt |
| cooper_prx | Praxis | Liest die config.casc eines Praxis-Projekts |
| ichor | Elixir | Der Grammatik-Compiler, mit dem beide Parser erzeugt werden |
Auf diesen Seiten
- Aufbau — Kopfzeile, Kommentare, Schlüssel, Blöcke, Zusammenführen.
- Werte — alle Literal-Typen.
- Verweise — Variablen, Umgebung, Konfigurationspfade, Filter, Tags.
- Imports und Schleifen — Konfiguration aufteilen und erzeugen, mit einem vollständigen Beispiel.
- Grammatik — die formale Grammatik und wo die Referenzimplementierung noch davon abweicht.