Dokumentation für Sprachentwickler - lakrme/atom-levels GitHub Wiki
Garantierte Kompatibilität dieser Seite:
<=0.1.0
Dieser Teil der Dokumentation richtet sich hauptsächlich an Entwickler von LPS-Sprachen. Er beschreibt, welche Schritte notwendig sind, um mit dem LPS-Plug-in für Eclipse erstellte gestufte Programmiersprachen für die fehlerfreie Installation und Verwendung mit dem Levels-Paket vorzubereiten. Zudem werden weitere (optionale) Konfigurationen beschrieben, die vorgenommen werden können, um dem Benutzer zusätzliche Features (wie z.B. Syntax-Highlighting) verfügbar zu machen.
Inhaltsverzeichnis:
- Voraussetzungen
- Notwendige Konfigurationen
- Optionale Konfigurationen
- Level-Beschreibungen
- Syntax-Highlighting
- Dateiendungen
- Language Information File Header
- Vollständiges Beispiel
Grundsätzlich wird vorausgesetzt, dass die Entwicklung der LPS-Sprache schon so weit fortgeschritten ist, dass die Executable erzeugt werden kann (und funktioniert). Die Executable wird von Levels zwingend benötigt, um die Sprache installieren zu können.
Abgesehen von der Executable verwendet Levels die im Stammverzeichnis des LPS-Projektordners enthaltene Konfigurationsdatei config.json
. Aus dieser werden alle für die Installation und Verwendung notwendingen Informationen über die Sprache entnommen. Im oben beschriebenen Stadium der Sprachentwicklung hat die Konfigurationsdatei typischerweise mindestens in etwa folgenden Inhalt (hier am Beispiel einer Level-Programmiersprache, die auf Ruby basiert):
{
"name": "Ruby",
"levels": [
{
"name": "Level 1"
},
{
"name": "Level 2"
},
{
"name": "Level 3"
}
],
"objectCodeFileType": "rb",
"interpreterCmdPattern": "ruby <filePath>"
}
Weiterhin können statt dem interpreterCmdPattern
(oder zusätzlich) auch die Schlüssel compilerCmdPattern
und executionCmdPattern
definiert sein (abhängig vom Ausführungsmodus der Basissprache).
Die Konfigurationsdatei sollte also in etwa obigen Inhalt haben, was grundsätzlich der Fall sein sollte, wenn sie bereits für die Executable vorbereitet wurde (siehe hier).
Momentan muss nur ein weiterer Schlüssel per Hand hinzugefügt werden, um die Sprache zu Levels kompatibel zu machen, und zwar der Schlüssel executable
. Dieser enthält den Pfad der Executable, relativ zu dem Verzeichnis, in dem sich die Konfigurationsdatei befindet. Liegt die Konfigurationsdatei also bspw. wie üblich im Stammverzeichnis des Projektordners und die Executable run
(run.exe
unter Windows) im Unterordner bin
, so muss der Konfigurationsdatei das Schlüssel-Wert-Paar "executable": "bin/run"
hinzugefügt werden. Liegt run
im selben Verzeichnis wie config.json
muss das Schlüssel-Wert-Paar "executable": "run"
hinzugefügt werden.
Nach dem Hinzufügen des Executable-Pfades kann die Sprache in Levels (wie hier beschrieben) über die Konfigurationsdatei installiert werden.
Im Folgenden werden einige zustätzliche Konfigurationen beschrieben, die vorgenommen werden können, um die Arbeit mit der Level-Sprache in Atom so angenehm wie möglich zu gestalten.
Möchte man dem Nutzer zusätzliche Informationen über die Level einer Sprache zur Verfügung stellen, so kann dies über den description
-Schlüssel für die Level-Objekte im levels
-Array erreicht werden:
...
"levels": [
{
"name": "Level 1",
"description": "Description for level 1"
},
...
]
...
Level-Beschreibungen werden bei der Levelauswahl unterhalb des Level-Namens angezeigt:
Bezüglich des Syntax-Highlightings ist zunächst anzumerken, dass Atom wie TextMate sogenannte Language Grammars für das Syntax-Highlighting verwendet. Dies sind .json
- oder .cson
-Dateien, die Regeln bezüglich des Mappings von Quelltext-Token auf bestimmte Identifikatoren definieren, welche dann durch ein Syntax Theme eingefärbt werden. Momentan müssen Sprachentwickler solche Language Grammars noch selbst verfassen, wenn sie die Vorteile von Syntax-Highlighting in Atom nutzen wollen. Eine Anleitung zur Erstellung von Language Grammars gibt es z.B. hier.
(TODO: Beschreiben, welche Schlüssel in der Language Grammar nicht gesetzt werden müssen)
Levels erlaubt es, unterschiedliche Language Grammars für die einzelnen Level einer Sprache zu verwenden (z.B. um in bestimmten Leveln bestimmte Schlüsselwörter nicht einzufärben, o.ä.). Möchte man einem Level aus dem levels
-Array eine Grammatik zuweisen kann man dies analog zum description
-Schlüssel mit dem grammar
-Schlüssel bewerkstelligen:
...
"levels": [
{
"name": "Level 1",
"description": "Description for level 1",
"grammar": "grammars/level-1.cson"
},
...
]
...
Der Schlüssel grammar
enthält den Pfad zur Language-Grammar-Datei, relativ zu dem Verzeichnis, in dem sich die Konfigurationsdatei befindet. Im obigen Beispiel befindet sich in dem Verzeichnis, in dem die config.json
liegt also auch ein Ordner grammars
, der die Grammatik level-1.cson
enthält. Der grammar
-Schlüssel für Level-Objekte ist optional und muss nicht für alle Level definiert werden.
Möchte man ein einheitliches Syntax-Highlighting für alle Level oder eine Teilmenge der Level festlegen, so kann man hierfür den Schlüssel defaultGrammar
im Wurzelobjekt verwenden. Analog zu grammar
enthält defaultGrammar
den Pfad zu einer Grammatik-Datei, relativ zu dem Verzeichnis, in dem sich die Konfigurationsdatei befindet. Die defaultGrammar
wird dann für alle Level benutzt, für die keine eigene Grammatik über den grammar
-Schlüssel festgelegt wurde.
Zusammengefasst wird die Auswahl einer Grammatik für ein Level von Levels also wie folgt getroffen:
- Wurde für das entsprechende Level eine Grammatik über den Schlüssel
grammar
festgelegt, so wird diese Grammatik für das Syntax-Highlighting gewählt. - Falls nicht: Wurde über den Schlüssel
defaultGrammar
eine Standard-Grammatik für die Level-Sprache festgelegt, so wird diese für das Syntax-Highlighting gewählt. - Falls nicht: In diesem Fall wählt Levels eine "leere Grammatik" für das Level aus, welche keine Regeln definiert, d.h. in diesem Fall gibt es kein Syntax-Highlighting.
Der Language Information File Header ist ein Kommentar der Form Language: <languageName>, Level: <levelName>
in der ersten Zeile eines Level-Code-Programms, der von Levels verwendet wird, um Dateien, die Level-Code-Programme enthalten (sitzungsübergreifend) der richtigen Level-Sprache und vor allem dem richtigen Sprachlevel zuordnen zu können:
Wird eine Datei geöffnet, so kann Levels bspw. über den Language Information File Header erkennen, welche Sprache und welches Level eingestellt werden müssen.
Da der File Header im Quelltext enthalten ist, muss er in Form eines Kommentars notiert werden, damit der Level-Code-Parser ihn überliest. Die Entscheidung wie ein solcher Kommentar aussieht kann Levels allerdings nicht selbst treffen. Zu diesem Zweck kann über den Schlüssel lineCommentPattern
ein Muster für Zeilenkommentare mit der Variable <commentText>
definiert werden, welche beim Setzen des File Headers durch den eigentlichen Kommentar ersetzt wird. Wird ein Zeilenkommentar bspw. mit #
gekennzeichnet, so muss der Konfigurationsdatei das Schlüssel-Wert-Paar "lineCommentPattern": "# <commentText>"
hinzugefügt werden, um das korrekte Setzen des Language Information File Headers wie im obigen Beispiel zu ermöglichen.
Wie viele andere Texteditoren auch kann Atom die Grammatik einer Datei an der Endung erkennen. Bspw. werden Dateien mit der Endung java
stets der Grammatik Java
zugeordnet. Durch den Language Information File Header unterstützt Levels bereits einen Mechanismus, der das gleiche Ziel verfolgt. Allerdings ist der File Header nicht in allen Fällen vorhanden oder lesbar (z.B. wenn er vom Nutzer versehentlich verändert wurde). In diesen Fällen versucht Levels stattdessen zumindest die Level-Sprache über die Dateiendung herzuleiten.
Zu diesem Zweck kann man über den Schlüssel levelCodeFileTypes
ein Array von Dateiendungen definieren, welche mit der Level-Sprache verknüpft werden sollen. Sollen bspw. Dateien mit den Endungen lrb
oder rbl
mit der Sprache assoziiert werden, so muss der Konfigurationsdatei das Schlüssel-Wert-Paar "levelCodeFileTypes": ["lrb","rbl"]
hinzugefügt werden.
Der Schlüssel levelCodeFileTypes
entspricht dem Schlüssel fileTypes
für Language Grammars. Tatsächlich wird intern für alle Grammatiken einer Sprache (Level-Grammatiken, Standard-Grammatik) einfach automatisch der Wert von fileTypes
auf den Wert von levelCodeFileTypes
gesetzt. D.h. das Setzen des Schlüssels levelCodeFileTypes
ersetzt das Setzen des Schlüssels fileTypes
in jeder Grammatik.
Vollständiges Beispiel einer Konfigurationsdatei mit Level-Beschreibungen und einer eigenen Grammatik für das erste Level, einer Standard-Grammatik, verschiedenen Dateiendungen für Level-Code-Dateien und dem Line Comment Pattern:
{
"name": "Ruby",
"levels": [
{
"name": "Level 1",
"description": "Description for level 1",
"grammar": "grammars/level-1.cson"
},
{
"name": "Level 2",
"description": "Description for level 2"
},
{
"name": "Level 3",
"description": "Description for level 3"
}
],
"defaultGrammar": "grammars/default.cson",
"levelCodeFileTypes": [
"lrb",
"rbl",
"level-rb"
],
"objectCodeFileType": "rb",
"lineCommentPattern": "# <commentText>",
"executable": "bin/run",
"interpreterCmdPattern": "ruby <filePath>"
}