Textersetzung mit Espanso

Oft ver­wen­det man beim Schreiben immer wie­der­keh­ren­de Textbausteine, sei es der eige­ne Name, Höflichkeitsfloskeln in der E‑Mail-Korrespondenz oder Code-Snippets. Damit man die­se Textbausteine nicht immer wie­der ein­tip­pen muss, gibt es so genann­te Textexpander, die z.B. das Kürzel “mfg” mit dem Text „Mit freund­li­chen Grüßen” erset­zen. Apple hat dafür ein Tool in das MacOS inte­griert, dass sich in den Systemeinstellungen → Tastatur → Textersetzungen ver­steckt. Allerdings hat die­se inte­grier­te Funktion ihre Grenzen: Ersetzungen sind auf nur eine Zeile begrenzt und funk­tio­nie­ren nicht in jedem Programm – zum Beispiel ver­wei­gert Google im URL/Suchfeld sol­che Ersetzungen.

Es gibt diver­se Alternativtools, die zusätz­li­che Funktionen bie­ten. Für den Mac gibt es bei­spiels­wei­se Keyboard Maestro und die Alfred App. Beide gehen in ihren Möglichkeiten weit über die Textersetzung hin­aus, kos­ten daher auch etwas. Ich nut­ze zwar Alfred, fin­de aber die Textersetzungen dar­in etwas kom­pli­ziert. Daher such­te ich ein Tool, das etwas ein­fa­cher in der Handhabung ist, aber auch nicht unbe­dingt so mäch­tig wie die Alfred.

Bei mei­nen Recherchen bin ich dann auf Espanso gesto­ßen, das nicht nur kos­ten­los, son­dern auch für Windows und Linux ver­füg­bar ist. Sogar der OpenSource-Code ist auf GitHub ver­füg­bar. Espanso bie­tet zwar kei­ne gra­fi­sche Oberfläche für die Konfiguration und im lau­fen­den Betrieb nur vier Funktionen in einem Menüleisteneintrag, aber mit ein wenig Einarbeitung ist die Konfiguration zu meis­tern und dann steht einer kom­for­ta­blen Textersetzung nichts mehr im Wege.

Installation

Espanso kann auf dem Mac auf ver­schie­de­ne Weisen instal­liert wer­den. Eine Möglichkeit ist über Homebrew, was beson­ders prak­tisch ist, wenn die­ser Package-Manager schon für Linux/Unix-Kommandos im Einsatz ist. Alternativ kann das Zip-Archiv, für den Intel Prozessor oder für Apple Silicon, direkt von der Espanso-Webseite her­un­ter­ge­la­den wer­den. Nach dem Entpacken bewegt man die Programmdatei ein­fach in den Programmordner. Für Windows-Nutzer steht sowohl eine regu­lä­re als auch por­ta­ble Version zur Auswahl, und für Linux sind diver­se Pakete je nach Distribution ver­füg­bar. Persönlich hat­te ich beim Versuch, Espanso unter Ubuntu zu instal­lie­ren, kei­nen Erfolg.

Ist Espanso im Programmordner plat­ziert, kann es gestar­tet wer­den. Ein Dialog infor­miert dar­über, dass die App aus dem Internet stammt. Durch einen Klick auf „Öffnen” wird dies bestä­tigt und Espanso star­tet den Installationsprozess. Aufgrund sei­ner Funktionsweise, spe­zi­ell bei den Textersetzungen, müs­sen eini­ge Einstellungen im System bestä­tigt wer­den.

Welcome Dialogfenster

Möchte man, dass Espanso nach einem Neustart des Systems auto­ma­tisch star­tet, soll­te die ent­spre­chen­de Option akti­viert blei­ben. Andernfalls muss man Espanso manu­ell aus dem Programmordner her­aus star­ten.

Systemstart Option

Diese Meldung ist die Bestätigung dafür, dass Espanso ab sofort beim Systemstart mit gestar­tet wird und dann im Hintergrund läuft.

Eine wei­te­re Einstellung sorgt dafür, dass Espanso ein­fach über das Terminal gesteu­ert wer­den kann.

Bevor das Programm voll­stän­dig funk­tio­niert, muss noch ein Script geneh­migt und aus­ge­führt wer­den, um Espanso in den Datenschutz- und Sicherheitseinstellungen unter „Bedienungshilfen” die Steuerung des Computers zu ermög­li­chen, wodurch Espanso dann die Texte erst ersetz­ten kann.

Espanso Hilfe Screen zum Setzten der Berechtigung

Sobald die­se Einstellungen vor­ge­nom­men sind, ist Espanso betriebs­be­reit. Ein Symbol in der Menüleiste ermög­licht den direk­ten Zugriff auf eini­ge der Funktionen von Espanso.


Grundlegende Anwendung

Nachdem Espanso instal­liert wur­de, muss es erst kon­fi­gu­riert wer­den. In der Grundkonfiguration bie­tet eine Bespiele für Ersetzungsregeln. Wenn man in einem Texteditor :espanso ein­gibt, wird es durch “Hi the­re!” ersetzt, und :date zeigt das aktu­el­le Datum in dem Format 10/30/2023.

Um es nach den eige­nen Bedürfnissen zu per­so­na­li­sie­ren, müs­sen eige­ne Ersetzungen erstellt wer­den. Dazu defi­niert man einen „Trigger”, wie in dem Beispiel :espanso, und die zuge­hö­ri­ge Ersetzung, das „Replace”, in die­sem Fall Hi there!. Diese Definitionen wer­den in einer YAML-Textdatei hin­ter­legt. Das sieht zwar etwas alt­mo­disch aus, hat aber den Vorteil, dass die erstell­ten Regeln sehr ein­fach auf ande­re Computer mit ande­ren Betriebssystemen oder mit Familie, Freunden und Kollegen aus­ge­tauscht wer­den kön­nen. Die Konfiguration für die Beispiele sieht wie folgt aus:

# espanso match file

# For a complete introduction, visit the official docs at: https://espanso.org/docs/

# You can use this file to define the base matches (aka snippets)
# that will be available in every application when using espanso.

# Matches are substitution rules: when you type the "trigger" string
# it gets replaced by the "replace" string.
matches:
  # Simple text replacement
  - trigger: ":espanso"
    replace: "Hi there!"

  # NOTE: espanso uses YAML to define matches, so pay attention to the indentation!

  # But matches can also be dynamic:

  # Print the current date
  - trigger: ":date"
    replace: "{{mydate}}"
    vars:
      - name: mydate
        type: date
        params:
          format: "%m/%d/%Y"

Auf dem Mac befin­det sich die Konfigurationsdatei unter ~/Library/Application Support/espanso/match/base.yml. Diese soll­te mit einem rei­nen Texteditor bear­bei­tet wer­den, so ist von der Nutzung von TextEdit abzu­ra­ten ist, da es nicht stan­dard­mä­ßig rei­ne Textdateien erstellt. Empfehlenswerte Texteditoren sind Sublime (Testmodus ohne Limit), Textmate (kos­ten­los), Visual Code (kos­ten­los), BBedit (kos­ten­lo­ser Modus) oder Terminal-basier­te Editoren wie pico, nano oder vim.

Ich per­sön­lich emp­feh­le Textmate. Es ist nicht so kom­plex wie Visual Code und im Gegensatz zu BBedit und Sublime kos­ten­los. Wichtig ist, dass man nach der Installation in den Einstellungen den Shell-Support akti­viert. Beim ers­ten Öffnen einer YAML-Datei wird man außer­dem gefragt, ob man den YAML-Support instal­lie­ren möch­te, was man bestä­ti­gen soll­te. Außerdem soll­te der Einzug bei der Verwendung von der Tab-Taste auf 2 Leerzeichen gesetzt wer­den. Diese Einstellung kann am unte­ren Fensterrand des Editors vor­ge­nom­men wer­den.

Einstellungen für den Shell-Support von Textmate
Indent-Einstellung für YAML in Textmate

Nach der Aktivierung kann das Terminal geöff­net wer­den, wel­ches sich im „Programme”-Ordner unter „Dienstprogramme” befin­det. Um die Konfigurationsdatei zu bear­bei­ten, gibt man espanso edit im Terminal ein, was stan­dard­mä­ßig (zumin­dest in mei­ner MacOS Installation) den pico Editor auf­ruft.

Beim Bearbeiten die­ser Datei muss die Struktur bei­be­hal­ten wer­den. Es ist wich­tig, dar­auf zu ach­ten, dass die Einrückungen genau denen ent­spre­chen, wie sie auf dem Bild und im Code-Block oben ange­ge­ben sind. Das Wort matches nach dem ers­ten Kommentarblock soll­te ganz am Anfang der Zeile posi­tio­niert sein. Die Einrückungen in den fol­gen­den Zeilen wer­den durch zwei Leerzeichen erzeugt, für den Textmate Editor könn­te man, wie oben gezeigt, die Tab-Taste ent­spre­chend umkon­fi­gu­rie­ren. Wenn etwas ver­rückt wur­de, gibt Espanso in der Regel eine Meldung aus, wenn die feh­ler­haf­te Datei gela­den wird.

Sollte ein ande­rer Editor gewünscht wer­den, so befin­det sich die Datei unter fol­gen­dem Pfad:

'/User/name_des_user/Library/Application Support/espanso/match/base.yml'

Wie bereits erwähnt, ist die Struktur grund­sätz­lich recht ein­fach. Zunächst wird der - trigger: defi­niert, gefolgt von der Ersetzung in der nächs­ten Zeile, also dem replace:. Die ein­fachs­te Form der Ersetzung, näm­lich der „Simple text repla­ce­ment”, lässt sich am Beispiel des Triggers espanso ver­an­schau­li­chen:

# Das folgende 'matches:' steht nur einmal am Anfang und veranschaulicht die Einrückungen
matches:
  - trigger: ":espanso"
    replace: "Hi there!"

Eine etwas kom­ple­xe­re Regel stellt die zwei­te Regel in die­ser Standardkonfiguration dar:

# Gibt das aktuelle Datum aus
  - trigger: ":date"
    replace: "{{mydate}}"
    vars:
      - name: mydate
        type: date
        params:
          format: "%m/%d/%Y"

In die­sem Beispiel wird die Regel für den Trigger :date defi­niert. Der Trigger wird durch den Inhalt der Variable mydate ersetzt. Dieser Inhalt wird unter dem Schlüsselwort vars defi­niert. Die Variable mydate ist vom type: date und ent­hält zusätz­lich einen Parameter, wel­cher das Format des Datums bestimmt. Damit wird der Variablen dann das aktu­el­le Datum zuge­wie­sen. Zum drit­ten Beispiel wer­de ich im Folgenden näher ein­ge­hen.

Zwei Schritte soll­te man zu Beginn durch­füh­ren. Erstens, eine Regel erstel­len, die das Konfigurationsfile in Textmate öff­net, falls man mit dem Editor im Terminal nicht zurecht kommt. Und zwei­tens, die vor­han­de­ne Regel für :date so anpas­sen, dass sie nicht :date durch 10/30/2023, son­dern durch 30.10.2023 ersetzt. Für die Änderung um mit Textmate die Konfigurationsdatei zu öff­nen, habe ich die Regel für :espan­so geän­dert und den replace:-Teil ange­passt. Dazu öff­net man, falls noch nicht gesche­hen, die Konfigurationsdatei im Terminal mit dem Befehl espan­so edit und navi­giert mit den Pfeiltasten zum „H” von „Hi the­re! Dort ersetzt man den Text durch den ent­spre­chen­den Kommandozeilenbefehl. Für Textmate sieht die Regel dann so aus, wobei der Text hin­ter dem replace eine Zeile ist:

  # Simple text replacement
  - trigger: ":espanso"
    replace: "mate ~/Library/Application\\ Support/espanso/match/base.yml"

Für sub­li­me ersetzt man mate durch subl und für Visual Code durch code. Der dop­pel­te Backslash \\ ist erfor­der­lich, um auf der Kommandozeile einen ein­fa­chen Backslash dar­zu­stel­len; ohne die­sen zusätz­li­chen Backslash wür­de der ers­te gar nicht ange­zeigt.

Die zwei­te Anpassung ist eben­falls rasch erle­digt: Man ersetzt das Format "%m/%d/%Y" durch "%d.%m.%Y".

Anschließend spei­chert man die Datei mit der Tastenkombination Ctrl‑X gefolgt von Ctrl‑Y. Sollte beim Editieren der Datei ein Fehler unter­lau­fen sein (bei­spiels­wei­se durch ein über­flüs­si­ges Leerzeichen), gibt Espanso in der Regel eine Meldung aus.

Wenn alles geklappt hat und man nun :espan­so in ein Terminalfenster ein­gibt, wird der Befehl zum Öffnen ein­ge­fügt und durch Drücken der Return-Taste die Konfigurationsdatei im Textmate Editor ange­zeigt. Das funk­tio­niert natür­lich auch in jeder ande­ren Textbox, wobei dann der Befehl mate ~/Library/Application\ Support/espanso/match/base.yml erscheint, aber natür­lich nicht gestar­tet wer­den kann. Auch :date zeigt nun das rich­ti­ge Datumsformat 03.11.202 an, egal in wel­chen Texteingabefeld :date ein­ge­ge­ben wird, auch in der Google URL/Such-Eingabe.

Der Doppelpunkt vor dem Trigger-Wort gehört nicht zur Syntax bei der Definition einer Regel. Man kann ihn sogar weg­las­sen, wenn eine Zeichenfolge gewählt wird, die sonst nie in Texten vor­kommt. Es ist aber bes­ser ein ande­res Zeichen in den Trigger zu inte­grie­ren, um sicher­zu­stel­len, dass nicht doch an irgend­ei­ner Stelle eine Ersetzungsregel zuschlägt. Wenn bei­spiels­wei­se hml der Trigger für Hans Müller Ludenscheid ist, könn­te unter ;hml der Link zu sei­ner Webseite auf­ge­ru­fen wer­den, oder &hml die Adresse usw..

Mit die­ser kur­zen Einführung kann man bereits begin­nen, ein­fa­che Textersetzungen zu defi­nie­ren. Zum Beispiel Regeln für Namen, die Email-Adressen oder URLs von Webseiten, die man häu­fig tip­pen muss.

Komplexere Konfigurationen

In die­sem Abschnitt gehe ich tie­fer auf kom­ple­xe­re Regeldefinitionen ein. Die Entwickler von Espanso defi­nie­ren ver­schie­de­ne Typen von Ersetzungsregeln und Syntaxen, um prä­zi­se­re Ersetzungen zu ermög­li­chen:

  1. Statische Regeln
  2. Dynamische Regeln
  3. Globale Variablen
  4. Wortergänzungen
  5. Übernahme von Großbuchstaben
  6. Cursor-Platzierung
  7. Regel-Auswahl (Match Disambiguation)
  8. Bezeichnerdefinition für den Suchdialog
  9. Regeln mit meh­re­ren Triggern
  10. Regel für Bildersetzung
  11. Verschachtelte Regeln
  12. Formulare

Statische Regeln

Ein Beispiel für eine ein­fa­che sta­ti­sche Regel wur­de bereits an Hand der Auslieferungsdatei demons­triert, hier ein wei­te­res Beispiel:

  - trigger: "hml"
    replace: "Herr Müller Lüdenscheidt"

Wie erwähnt könn­te man bei­spiels­wei­se mit ;hml die Adresse von dem Herren in ein Dokument ein­fü­gen:

  - trigger: ";hml"
    replace: "Herr Müller Lüdenscheidt, Beispielsstraße 7, 80331 München"

Damit wird ;hml durch Herr Müller Lüdenscheidt, Beispielsstraße 7, 80331 München in einer Zeile ersetzt. Aber eigent­lich wünscht man sich oft die Adresse in meh­re­ren Zeilen:

Herr Müller Lüdenscheidt
Beispielsstraße 7
80331 München

Für die­se mehr­zei­li­ge Ausgabe bie­tet Espanso zwei Methoden an. Die ers­te ver­wen­det das Steuerzeichen \n für einen Zeilenumbruch:

  - trigger: ";hml"
    replace: "Herr Müller Lüdenscheidt\nBeispielsstraße 7\n80331 München"

oder, etwas über­sicht­li­cher, mit der fol­gen­den Struktur:

  - trigger: ";hml"
    replace: |
             Herr Müller Lüdenscheidt
             Beispielsstraße 7
             80331 München

Wenn man die Lesbarkeit in der Definition schätzt, doch die Ausgabe in einer Zeile schätzt, kann man die fol­gen­de Regel ver­wen­den:

  - trigger: ";hml"
    replace: >
             Herr Müller Lüdenscheidt,
             Beispielsstraße 7,
             80331 München

Daraufhin wird ;hml wie­der durch Herr Müller Lüdenscheidt, Beispielsstraße 7, 80331 München ersetzt.

Hinweis: Wie schon mehr­fach erwähnt, Espanso ist sehr genau, wenn es um die Syntax von YAML geht. Es dür­fen kei­ne Tabs oder ande­re Zeichen an uner­wünsch­ten Stellen vor­kom­men. Obwohl Espanso bei fal­schem YAML Fehlermeldungen aus­gibt, sind die­se nicht immer prä­zi­se. Hier kön­nen YAML-Syntax-Checker wie z.B. YAMLlint — The YAML Validator nütz­lich sein, da sie Fehler genau­er loka­li­sie­ren.

Dynamische Regeln

Dynamische Regeln unter­schei­den sich von sta­ti­schen Regeln dadurch, dass sie nicht ein Kürzel durch einen vor­ge­ge­be­nen Text, son­dern durch einen zum Zeitpunkt der Eingabe erstell­ten Text erset­zen. Diese Texte kön­nen das aktu­el­le Datum sein oder das Ergebnis eines Shell-Befehles. Der Trigger :date, das durch 31.10.2023 ersetzt wird, ist hier­für ein gutes Beispiel. Solche dyna­mi­schen Regeln sind beson­ders hilf­reich, wenn aktu­el­le Informationen wie Datum, Zeit oder Systemdaten in die Eingabe inte­griert wer­den sol­len. Solche Informationen kön­nen durch die Einbindung von Shell-Befehlen erstellt wer­den. Im nächs­ten Beispiel zeigt wie durch den Trigger :wetter die aktu­el­le Wetterinformation aus dem Internet bezo­gen wer­den:

  - trigger: ":wetter"
    replace: "{{output}}"
    vars:
      - name: output
        type: shell
        params:
          cmd: "curl 'wttr.in/?format=4'"

Nun wird :wetter durch die aktu­el­le Wettervorhersage, mit Bruchsal Germany: ☁️ 🌡️+11°C 🌬️↗17km/h, ersetzt.

Globale Variablen

Globale Variablen sind Variablen, die in ver­schie­de­nen Regeln wie­der­ver­wen­det wer­den kön­nen. Sie wer­den außer­halb der Regeldefinitionen dekla­riert. Ein Vorteil dabei ist, dass man nicht bei jeder Regel die­sel­be Variable erneut defi­nie­ren muss, son­dern sie zen­tral an einem Ort fest­legt und dann bei Bedarf in meh­re­ren Regeln auf­ruft.

Ein Beispiel für solch eine glo­ba­le Variable könn­te sein:

global_vars:
  - name: "terminal"
    type: "shell"
    params:
      cmd: "echo Hey"
  - name: "greet"
    type: "echo"
    params:
      echo: "Hey"

# Regeln, die globale Variablen verwenden 
matches:
  - trigger: ":hello"
    replace: "{{greet}} Jon"
  - trigger: ":terminal"
    replace: "{{terminal}} Jon"

In die­sem Beispiel haben bei­de Regeln Zugriff auf die glo­ba­len Variablen und kön­nen die­se in ihren Ersetzungen ver­wen­den.

Ein wei­te­res Beispiel zeigt die Verwendung einer glo­ba­len Variable, um Wetterdaten dyna­misch zu inte­grie­ren:

global_vars:
  - name: "wetter"
    type: "shell"
    params:
      cmd: "curl 'wttr.in/?format=4'"

matches:
  - trigger: ":moin"
    replace: "Hallo Jon, das Wetter ist {{wetter}}"

Durch die Eingabe von :moin wird eine Begrüßung aus­ge­ge­ben, die das aktu­el­le Wetter ent­hält: Hallo Jon, das Wetter ist in Bruchsal Germany: ☁️ 🌡️+11°C 🌬️↗17km/h.

Wort Ergänzungen

Wort Ergänzungen ist eine Möglichkeit, dass typi­sche Tippfehler kor­ri­giert wer­den. Da mir für die­ses Feature kein bes­se­res deut­sches Beispiel ein­fällt, neh­me ich das aus der Dokumentation.
Also falls man im eng­li­schen oft ther statt the­re schreibt, also das “e” ver­gisst, kann natür­lich eine Regel defi­niert wer­den, die ‘ther’ mit there ersetzt.

  - trigger: "ther"
    replace: "there"

Allerdings wür­de sie auch ande­re Vorkommnisse von ‘ther’ reagie­ren und so wür­de other beim Tippen othere wer­den. Im dies zu ver­mei­den, kann die Regel um das Attribut word:mit true ergänzt wer­den, dadurch wird die Regel immer auf ein gan­zes Wort ange­wandt.

  - trigger: "ther"
    replace: "there"
    word: true

Großbuchstaben Übernahme

Die Definition von einer Ersetzungsregel nimmt ohne eine spe­zi­el­le Massnahme, kei­ne Rücksicht auf die Groß/Kleinschreibung. Die fol­gen­den Definition von :ht wird das Wort heute immer klein schrei­ben, auch am Anfang eines Satzes.

  - trigger: ":ht" 
  - replace: "heute"


Durch das Setzten des Attribut propagate_case auf true kann man die Groß/Kleinschreibung aber steu­ern.

  - trigger: ":ht"
    replace: "heute"
    propagate_case: true

Nun wird aus :ht heute, aber :Ht wird durch Heute ersetzt und, falls gewünscht wird sogar aus :HT sogar HEUTE.

Wenn meh­re­ren Worten im replace ange­ge­ben sind, wie in die­ser Definition,

  - trigger: ":hies"
    replace: "heute ist es sonnig"
    propagate_case: true

wird :hies ersetzt durch heute ist es sonnig und aus :Hies wird Heute ist es sonnig, aber aus :HIES wird dann HEUTE IST ES SONNIG.

Wenn sicher­ge­stellt wer­den soll, dass alle Wörter mit Großbuchstaben ersetzt wer­den sol­len muss ein wei­te­res Attribut gesetz­te wer­den:

    replace: "heute ist es sonnig"
    uppercase_style: "capitalize_words"
    propagate_case: true 

So wird dann aus :Hies dann Heute Ist Es Sonnig

Cursor Platzierung

Oft ist es ganz prak­tisch, wenn nach einer Ersetzung der Cursor nicht am Ende des Textes steht, son­dern an einer bestimm­ten Stelle in der Ersetzung. Ein Beispiel aus dem Bereich des Editieren von Obsidian Dateien. Ich benut­ze beim Schreiben die­ses Textes oft einen Codeblock, der mit drei back­ticks ein­ge­führt wird und eben­so endet. Ich habe mir eine Regel erstellt, die die genau so einen Codeblock erstellt.

  - trigger: ":3b"
    replace: |
             ```

             ```

Allerdings ist der Cursor nach der Ersetzung hin­ter dem Block und ich muss ihn erst wie­der in den Block posi­tio­nie­ren. Aber auch die­ses Problem ist ein­fach zu lösen, in dem in die lee­re Zeile zwi­schen den Backticks $|$ ein­ge­fügt wird. Diese Zeichenkette defi­niert, wo der Cursor steht, wenn der Text ein­ge­fügt wur­de.

 - trigger: ":3b"
    replace: |
             ```
             $|$
             ```

Regel-Auswahl

Die Möglichkeit, den­sel­ben Trigger mit unter­schied­li­chen Ersetzungen zu ver­wen­den, bie­tet erheb­li­che Flexibilität. Wenn man zum Beispiel unter­schied­li­che Zitate oder Signaturen schnell zur Hand haben möch­te, muss man sich nicht an unter­schied­li­che Trigger erin­nern. Stattdessen kann man einen ein­zi­gen Trigger ver­wen­den und dann aus den vor­ge­schla­ge­nen Ersetzungen wäh­len. Dies ist beson­ders prak­tisch, wenn man vie­le Ersetzungen zu einem bestimm­ten Thema hat, aber nicht für jede eine eige­ne Tastenkombination oder ein eige­nes Schlüsselwort mer­ken möch­te.

- trigger: ":zitat"  
  replace: "Diejenigen, die verrückt genug sind zu denken, sie könnten die Welt verändern, sind diejenigen, die es tun."  
- trigger: ":zitat"  
  replace: "Kreativität bedeutet einfach, Dinge zu verbinden.“"  
- trigger: ":zitat"  
  replace: "Gute Designer kopieren, große Designer stehlen."
Dialogfenster aus dem ein Zitat aus­ge­wählt wer­den kann. Abbrechen mit esc

Bezeichnerdefinition für den Suchdialog

Der Suchdialog ist eine nütz­li­che Funktion, wenn man vie­le Ersetzungen in Espanso defi­niert hat und nicht mehr alle Trigger im Kopf behal­ten kann. Mit Hilfe der Label-Funktion kann man zusätz­li­che Beschreibungen zu jeder Ersetzung hin­zu­fü­gen, sodass man nicht nur nach dem Trigger, son­dern auch nach einer Beschreibung suchen kann. Dies macht es ein­fa­cher, die gewünsch­te Ersetzung zu fin­den, ins­be­son­de­re wenn man meh­re­re ähn­li­che Trigger hat.

  - trigger: ":wetter"
    replace: "{{output}}"
    label: "Fügt da aktuelle Wetter vom Standort ein"
    vars:
      - name: output
        type: shell
        params:
          cmd: "curl 'wttr.in/?format=4'"
Label wird im Such-Dialogfenster ange­zeigt. Abbrechen mit esc

Regeln mit mehreren Triggern

Manchmal kann es auch ganz prak­tisch sein, einer Ersetzungsregel über meh­re­re Trigger auf­zu­ru­fen. Statt meh­re­re Regeln zu defi­nie­ren, geht das auch in einer. Damit kann das aktu­el­le Wetter mit :wetter aber auch mit :weather ein­ge­setzt wer­den.

  - trigger: [":wetter", ":weather"]
    replace: "{{output}}"
    label: "Fügt da aktuelle Wetter vom Standort ein"
    vars:
      - name: output
        type: shell
        params:
          cmd: "curl 'wttr.in/?format=4'"

Entschuldigung für das Missverständnis. Ich wer­de nun ver­su­chen, näher am Originaltext zu blei­ben und den bereit­ge­stell­ten Code bei­zu­be­hal­ten.


Verschachtelte Regeln

Espanso bie­tet die Möglichkeit, ver­schach­tel­te Regeln zu defi­nie­ren. Persönlich bin ich mir noch unsi­cher über den prak­ti­schen Nutzen die­ser Art der Definition, aber hier ist das Beispiel direkt aus der Dokumentation:

  - trigger: ":one"
    replace: "nested"

  - trigger: ":nested"
    replace: "This is a {{output}} match"
    vars:
      - name: output
        type: match
        params:
          trigger: ":one"

Wenn man :nested ein­tippt, wird dies durch den Text „This is a nes­ted match” ersetzt. Das Wort „nes­ted” stammt aus der Regeldefinition des Triggers :one. Es wirkt fast so, als wür­de man eine Variable defi­nie­ren. Wenn jemand einen span­nen­den Anwendungsfall für die­ses Feature kennt, bit­te in den Kommentaren tei­len.

Formulare

Mit Espanso kön­nen auch Formulare defi­niert wer­den. Das bie­tet eine kom­ple­xe­re Möglichkeit, Ersetzungen mit vie­len Argumenten zu gestal­ten. Hier ein ein­fa­ches Beispiel:

  - trigger: ":birth"
    form: |
      Hallo [[name]],
      Herzlichen Glückwunsch!

Wenn man :birth ein­tippt, erscheint ein Dialog mit einem Eingabefeld für den Namen:

Gibt man z.B. „Heinz” ein und bestä­tigt, wird fol­gen­der Text gene­riert:

Hallo Heinz,
Herzlichen Glückwunsch!

Es gibt noch vie­le wei­te­re Optionen bei der Verwendung von Formularen, z. B. Listenboxen oder Dropdown-Menüs. Bei Interesse emp­feh­le ich einen Blick in die Online-Dokumentation.

Erweiterungen

Erweiterungen bie­ten in Espanso zusätz­li­che Möglichkeiten, vor allem für dyna­mi­sche Regeln. Dazu gehö­ren Datum, Auswahl, Zufall, Form, Echo und Shell Erweiterungen, die schon teil­wei­se in den Beispielen vor­ka­men. Ich will hier nur kurz auf die Clipboard- und Script-Erweiterung ein­ge­hen.

Clipboard Erweiterung

Die Clipboard-Erweiterung ermög­licht die Integration des aktu­el­len Inhalts der Zwischenablage in die Ersetzungsregel. Ein prak­ti­sches Anwendungsbeispiel wäre das Einfügen einer URL einer Webseite, die in die Zwischenablage kopiert wur­de in ein HTML-Dokument:

  - trigger: ":a"
    replace: "<a href='{{clipboard}}' />$|$</a>"
    vars:
      - name: "clipboard"
        type: "clipboard"

Script Erweiterung

Die Script-Erweiterung eröff­net eine Vielzahl kom­ple­xe­rer Möglichkeiten der Textersetzung. Mit einem ein­fa­chen Schlüsselwort kann ein kom­ple­xes Script gestar­tet wer­den, des­sen Ausgabe in den Text ein­ge­fügt wird.

Laut Dokumentation kann nahe­zu jede Skriptsprache ver­wen­det wer­den. Einzige Voraussetzung soll­te sein, dass das Skript auf der Kommandozeile aus­führ­bar ist und das Ergebnis auch dort als Text aus­gibt. Hier ein Beispiel, in dem ein Python Script.py aus­ge­führt und das Ergebnis anstel­le des Triggers ange­zeigt wird:

  - trigger: ":pyscript"
    replace: "{{output}}"
    vars:
      - name: output
        type: script
        params:
          args:
            - python3
            - /path/to/your/script.py

Packages

Packages sind Regeldefinitionen, die von der Community zur Verfügung gestellt wer­den und im Espanso Hub zu fin­den sind. Als Beispiel hier ein Package, das eine Reihe von nütz­li­chen Ersetzungsregeln für die Eingabe spe­zi­el­ler Apple-Symbole bie­tet.

Durch den Befehl:

espanso install apple-symbols

wird das Paket instal­liert und steht sofort zur Verfügung. Für Mac-Benutzer ist es sehr prak­tisch, nur noch :cmd zu tip­pen, um das Command-Zeichen zu erhal­ten. Vorsicht ist jedoch bei der Installation gebo­ten, denn Regeldefinitionen kön­nen Shell-Befehle oder Skripte aus­lö­sen, die nicht immer harm­los sein müs­sen. Außerdem kann es auch pas­sie­ren, dass bereits defi­nier­te Trigger Namen in einem Package erneut ver­wen­det wer­den. Im genann­ten Beispiel lös­te die Regel :alt > ⌥ mei­ne zuvor defi­nier­te Regel :a > <a href=':alt > ⌥' > </a> aus.

Auch wenn man mit den Regeln nicht ganz ein­ver­stan­den ist, kön­nen die­se Packages zumin­dest als Ideengeber und Steinbruch die­nen. Ein Blick in den Hub lohnt sich.

Konfigurationsdateien

Espanso arbei­tet mit Konfigurationsdateien, die sich im Espanso-Ordner befin­den. Mit dem Befehl espanso path lässt sich der genaue Pfad die­ses Ordners ermit­teln.

~% espanso path
Config: /Users/leifjp/Library/Application Support/espanso
Packages: /Users/leifjp/Library/Application Support/espanso/match/packages
Runtime: /Users/leifjp/Library/Caches/espanso

Der Ordneraufbau sieht fol­gen­der­ma­ßen aus:

~/Library/Application Support/espanso% tree
.
├── config
│  └── default.yml
└── match
   ├── base.yml
   └── packages 
         └── apple-symbols
             ├── _manifest.yml
             ├── _pkgsource.yml
             ├── LICENSE
             ├── package.yml
             └── README.md 

Im match-Ordner fin­den sich die Ersetzungsregeln und Community Packages. Für eine über­sicht­li­che Organisation kön­nen ver­schie­de­ne YAML-Dateien für unter­schied­li­che Regelgruppen erstellt wer­den, z. B. email.yml für E‑Mail-bezo­ge­ne Regeln oder markdown.yml für Regeln, die in Markdown-Editoren hilf­reich sind.

Im config-Ordner wird die Funktionsweise von Espanso selbst kon­fi­gu­riert. Hier fin­den sich ver­schie­de­ne Einstellungsparameter, die nach Bedarf akti­viert wer­den kön­nen. Beispielsweise kann die Tastenkombination für die Suche geän­dert wer­den:

#--- Search Shortcut
search_shortcut: ALT+CTRL+SPACE

Eine der leis­tungs­star­ken Funktionen von Espanso ist die Möglichkeit, spe­zi­fi­sche Konfigurationsdateien für indi­vi­du­el­le Anwendungen zu erstel­len. Zum Herausfinden der benö­tig­ten Filter-Parameter für eine Anwendung genügt die Eingabe von #detect# in einem Textfeld die­ser Anwendung. Hier für Obsidian:

title: 'Espanso Artikel - ObsidianNotes - Obsidian v1.4.16'
exec: '/Applications/Obsidian.app'
class: 'md.obsidian'

Mit den erhal­te­nen Informationen kann dann eine ange­pass­te Konfigurationsdatei erstellt wer­den, die nur in der spe­zi­fi­schen Anwendung aktiv ist. In die­ser Datei kön­nen match-Dateien für die­se Anwendungen aus­schließ­lich akti­viert oder aus­ge­schlos­sen wer­den. Oder Espanso kann für die Anwendung auch kom­plett aus­ge­schal­ten wer­den. So könn­te eine obsidian.yml im config-Ordner, die Espanso in Obsidian ganz aus­schal­tet, aus­se­hen:

filter_class: obsidian
enable: false 

Dateien mit einem vor­an­ge­stell­ten Unterstrich (z. B. _email.yml) wer­den stan­dard­mä­ßig nicht gela­den und kön­nen dann gezielt für spe­zi­fi­sche Anwendungen akti­viert wer­den.

So kön­nen bei­spiels­wei­se Regeln für Markdown und HTML in ver­schie­de­nen Dateien erstellt wer­den, die zwar die glei­chen Trigger ver­wen­den, die­se jedoch je nach Anwendung unter­schied­lich erset­zen. Das bie­tet den Vorteil, dass mit den­sel­ben Triggern bei­spiels­wei­se für das Einfügen eines Links, je nach Anwendung, ent­we­der die HTML- oder die Markdown-Syntax ein­ge­fügt wer­den kann.

filter_class: obsidian
enable: true

extra_includes:
  - "../match/`_markdown.yml"

Darüber hin­aus ist es auch mög­lich, das Laden von Packages in bestimm­ten Programmen zu ver­hin­dern. Es könn­te bei­spiels­wei­se ein emo­ji-Package in der Signal deak­ti­viert wer­den, wenn die­ses mit den pro­gramm­ei­ge­nen Definitionen in Konflikt gerät.

filter_exec: Signal

extra_excludes:
  - "../match/packages/all-emojis/*"

Die Dokumentation bie­tet wei­te­re Details und Anleitungen für spe­zi­fi­sche Konfigurationsoptionen.

Ein paar Links

Obwohl die­ser Artikel recht lang gewor­den ist, berüh­re ich nur einen klei­nen Teil der Möglichkeiten. Daher möch­te ich hier ein paar Links tei­len, die eben­falls gute Einführungen bie­ten:

The End

Durch Espanso ver­bes­sert sich mein Schreibfluss. Nicht nur für oft wie­der­keh­ren­de Textbausteine sind die Textergänzungen hilfl­reich. Gerade auch für so man­che Markdown Syntax, die ich nicht so häu­fig nut­ze, habe brau­che ich mir nur den Trigger zu mer­ken und brau­che dafür nicht das Schreiben abbre­chen um in der Doku zu suchen. Ich bin im Moment sel­ber erst am Anfang, den­ke aber, dass mein match Ordner sich in der nächs­ten Zeit mit Regeldefinitionen fül­len wird.

Danke für die Aufmerksamkeit und wie immer Anregungen, Kritik, Fehler, Lob bit­te in die Kommentare.

Ergänzung: Ich erwäh­ne, dass ich die Bedienung der Tastenersetzungen in der Alfred App als etwas kom­pli­ziert emp­fand und des­halb nach einer ande­ren Möglichkeit gesucht habe. Da ich eine Checkbox über­se­hen hat­te, dach­te ich bis heu­te, dass eine auto­ma­ti­sche Ergänzung beim Tippen nicht mög­lich wäre. Tatsächlich habe ich ein­fach eine Checkbox über­se­hen; es wäre mit der Alfred App auch mög­lich gewe­sen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert