Login
Newsletter
Werbung

Do, 12. Januar 2017, 15:00

Skripten mit Emacs

Skript-Verbesserung

Diese Variante hat allerdings einige Schwächen. Zum einen lässt die Shebang nur ein Argument zu, sodass keine weiteren Optionen an Emacs übergeben werden können und damit die Nutzung von z.B.

#!/usr/bin/env emacs --script
(message "Hallo Emacs Skript!")

nicht möglich ist. Dies hätte den Vorteil, dass der Pfad zu Emacs nicht im Skript festgelegt ist und das Skript somit etwas portabler wäre.

Zum anderen ist es nicht möglich, eigene Optionen für das Skript zu definieren. Diese werden von der Shell einfach an Emacs weitergereicht. So gibt folgender Befehl z.B. den Hilfetext von Emacs aus:

$ ./script2.el --help

Um diese Probleme zu umgehen, muss man ein wenig tricksen.

Zur Erläuterung der etwas komplizierten Methode ist es sinnvoll, zunächst einmal zu erklären, wie Emacs im Allgemeinen zur Skriptausführung aufgerufen werden sollte:

$ emacs --quick --script SKRIPTNAME -f main -- [Skript Argumente]

Die --quick-Option dient dazu, den Initialisierungsvorgang, den Emacs zum Starten des Editors normalerweise durchläuft, zu umgehen. Für Skripte ist dessen Ausführung in der Regel unerwünscht. Mit -f wird Emacs mitgeteilt, nach dem Einlesen der Datei die Funktion main aufzurufen. Dies ist eine gängige Methode für Skripte aller Art, um diese übersichtlich zu gestalten. Mit -- wird signalisiert, dass alle folgenden Argumente nicht für den Emacs-Programmaufruf selbst vorgesehen sind.

Wenn man obigen Ansatz in ein Shell-Skript übersetzt, könnte dies wie folgt aussehen:

#!/bin/sh
exec emacs --quick --script $0 -f main -- $@
(message "Hallo Emacs Skript!")

Damit wird das Skript nach dem Aufruf durch die Shell erneut durch Emacs selbst aufgerufen. Die Shebang-Zeile wird von Emacs richtigerweise ignoriert, aber mit dem darauffolgenden Shell-Befehl kann der Emacs-Lisp-Interpreter nichts anfangen. Die Zeile muss also irgendwie vor Emacs »versteckt« werden, dabei aber für die Shell immer noch sichtbar sein. Mit einem Semikolon ließe sich der Befehl in Emacs Lisp als Kommentar kennzeichnen und könnte somit ignoriert werden. Für die Shell ist das Semikolon ein Befehlstrenner. Vor einem Semikolon erwartet die Shell aber einen gültigen Befehl, sonst verweigert sie ihren Dienst. Die Lösung ist, einen Befehl voranzustellen, der in der Shell und in Emacs Lisp folgenlos bleibt:

#!/bin/sh
":"; exec emacs --quick --script "$0" -f main -- "$@"

;; Hier kann nun Emacs Lisp Code folgen ...
(message "Hallo Emacs Skript!")

":" ist ein Shell-Befehl, der per Definition nichts macht, aber als Befehl bekannt ist und damit akzeptiert wird. Die Anführungszeichen sind folgenlos für die Interpretation durch die Shell und der Befehl wird ohne weitere Nebeneffekte ausgeführt. Danach wird durch exec der Shell-Prozess durch den neu gestarteten Emacs-Prozess ersetzt und der Interpreter fängt an, das Skript einzulesen. In Emacs Lisp ist ":" ein regulärer String, der folgenlos evaluiert wird. Der darauf folgende Kommentar wird vom Interpreter ignoriert. Auf diese Weise ist also das Ziel erreicht. Der Interpreter würde nun damit fortfahren, den Rest der Datei einzulesen, um im Anschluss schließlich die main-Funktion aufzurufen.

Kommentare (Insgesamt: 1 || Alle anzeigen )
Remacs (ShalokShalom, Fr, 13. Januar 2017)
Pro-Linux
Pro-Linux @Facebook
Neue Nachrichten
Werbung