Mutatoren |
Ein Mutator hat die Form <
Mutatoren sind eine besondere Eigenschaft von TeXmacs. Mit ihnen kann man interaktive Dokumente erzeugen. Beispielsweise wird innerhalb von Sitzungen mit anderen Anwendungen die Ausgabe der Anwendung aus einem Mutator entnommen, der automatisch am Ende der Ausgabe entfernt wird. In Zukunft könnten Mutatoren z.B. für Schnittstellen zu Rechtschreibprüfungen eingesetzt werden.
Die derzeitige Implementierung in TeXmacs überprüft in allen geladenen Dokumenten, wenn kurzzeitig keine Aktivität vorhanden ist, ob Mutatoren in ihnen enthalten sind. Dokument, die bekanntermaßen keine Mutatoren enthalten, werden ignoriert. Diese Implementierung ist zugleich effizient und inkompatibel mit dem Makrosystem. Da gibt es Spielraum für Verbesserungen.
Ein einfaches Beispiel mit zwei verschiedenen Arten von Mutatoren ist das mutator Plugin. Es erzeugt zwei Kurzbefehle C-F11 und C-F12, die die aktuelle Zeit bzw. einen blinkenden Text in das Dokument einfügen. Es besteht aus der Datei
mutator/progs/init-mutator.scm
Der Kurzbefehl C-F11 fügt die Zeichenkette <mutator|text|(mutate-date)> in den Haupt-Text:
(kbd-map ("C-F11" (insert '(mutator "" "(mutate-date)"))))
Der „sichere”
(tm-define (mutate-date)
(:secure #t)
(let* ((p (the-mutator-path))
(date (var-eval-system "date
+\"%H:%M:%S\"")))
(tm-assign-diff p date)))
Der Befehl tm-assign-diff ist besonders geeignet, da er nur dann Änderungen durchführt, wenn sich etwas geändert hat.
Die Einfügung von blinkendem Text ist etwas komplexer, denn es muss den aktuellen Inhalt des Mutator-Befehl berücksichtigen. Der C-F12 fügt <mutator|text|(mutate-blink)> in den Haupt-Text ein und versetzt den Cursor hinter den Text in den Rumpf des Mutators:
(kbd-map ("C-F12" (insert-go-to '(mutator "text" "(mutate-blink)") '(0 4))))
Dabei ist die „sichere”
(tm-define (mutate-blink)
(:secure #t)
(let* ((mod (lambda (x y) (* y (- (/ x y) (floor (/
x y))))))
(p (the-mutator-path))
(t (tm-subtree p))
(s (string->number (var-eval-system
"date +\"%S\"")))
(e (mod s 4)))
(if (and (<= e 1) (not (match? t '(strong
:%1))))
(tm-ins-unary p 'strong))
(if (and (>= e 2) (match? t '(strong :%1)))
(tm-rem-unary p))))