Aus Linux-Magazin 03/2015

Perl-Skript verwaltet Tastenkürzel

© rioblanco, 123RF

Das Utility Autokey automatisiert Abläufe, indem es bestimmte Aktionen auslöst, wenn der Anwender zugehörige Textabkürzungen eingibt oder Hotkey-Kombinationen drückt. Perl verwaltet die Helfer.

Online PLUS

In einem Screencast demonstriert Michael Schilli das Beispiel: https://www.linux-magazin.de/Videos

Vor über fünf Jahren war die Welt noch in Ordnung, da konnte ich den Gnome-Windowmanager Metacity noch dazu überreden, einfach auf eine Tastenkombination hin eine Applikation zu starten, indem ich sie mit dem Utility »gconf-editor« eintrug [2]. Da ich im Laufe eines Tages bestimmt hundert Terminalfenster öffne, verbandelte ich, um Zeit zu sparen, die Kombination [Ctrl]+[Alt]+[n] kurzerhand mit einem Shellskript, das ein neues Terminal mit Spezialfont und Hintergrundfarbe öffnete, egal in welcher Applikation sich der Tastaturfokus gerade befand.

Mit dem Windowmanager Compiz des Unity-Desktops scheint das aber inzwischen ein Ding der Unmöglichkeit zu sein, außerdem erscheint es mir mittlerweile zu doof, meine Skripte andauernd den wechselnden Moden anzupassen, denen die Desktop-Hersteller folgen.

Keine Gnome-Sperenzchen

Stattdessen soll sich künftig ein Mittelsmann um die Schnittstelle zwischen der Tastatur, dem sich gerade in Mode befindlichen Windowmanager der Gnome-Welt und den einzuleitenden Aktionen kümmern.

Da kommt das etwa zwei Jahre alte Projekt Autokey [3] gerade recht. Als zusätzlichen Bonus unterstützt es neben dem GTK-3-Toolkit sogar Qt 4, das heißt, ich könnte – wenn ich wollte – damit sogar eines fernen Tages theoretisch auf einen KDE-Desktop umziehen! Man soll bekanntlich niemals nie sagen.

Unter Ubuntu installiert das Kommando

sudo apt-get install autokey-gtk

das Autokey-Utility, und wer es automatisch beim Systemstart hochfahren möchte, trägt es in der Ubuntu-Konfiguration unter »Startup Applications« ein (Abbildung 1).

Abbildung 1: Damit Autokey automatisch startet, trägt der User das Utility auf Ubuntu unter »Startup Applications« ein.

Abbildung 1: Damit Autokey automatisch startet, trägt der User das Utility auf Ubuntu unter »Startup Applications« ein.

Autokey unterscheidet zwischen reiner Textersetzung (Phrases) und Skripten, die Aktionen einleiten. Beides wirft es entweder an, wenn ich einen bestimmten Text getippt habe, oder beim Drücken vordefinierter Hotkey-Kombinationen. So könnte jemand unter »Phrases« zum Beispiel eintragen, dass Autokey die vollständige Postadresse rauslässt, sobald der User »myaddr« tippt, etwa in einem Textdokument in »gedit« oder im Inhaltsfeld einer E-Mail.

“Wir hoffen, es hilft”

Abbildung 2 zeigt die Definition des Kürzels »hth« , das per Autokey zu der Floskel “Hope that helps, let me know …” mutiert. Um die Aktion auszulösen, tippt der User in einer Applikation, die ihre Tastatureingaben über den Gnome-Desktop erhält, den Text »hth« und drückt anschließend auf die Return-Taste.

Abbildung 2: Einfache Textersetzung mit Autokey: Die Abkürzung »hth« expandiert zu einer länglichen Floskel. Das spart eine Menge Tipperei bei wiederkehrenden Sätzen.

Abbildung 2: Einfache Textersetzung mit Autokey: Die Abkürzung »hth« expandiert zu einer länglichen Floskel. Das spart eine Menge Tipperei bei wiederkehrenden Sätzen.

Achtung: Das funktioniert zum Beispiel nicht in einem Xterm-Terminal, es muss schon das Gnome-Terminal sein. Und noch mal aufgepasst: Kürzel, die als Wörter häufig in normalem Text vorkommen, eignen sich naturgemäß weniger als offensichtliche Kunstgebilde wie »hth« oder »afaik« . Unter »Set Abbreviations« trägt der User das Kürzel in eine Liste ein und kann in Zukunft viel Tipparbeit sparen (Abbildungen 3 und 4).

Abbildung 3: In einer E-Mail-Applikation eines Webmail-Providers expandiert das Kürzel »hth« …

Abbildung 3: In einer E-Mail-Applikation eines Webmail-Providers expandiert das Kürzel »hth« …

Abbildung 4: … zu einer höflichen Floskel am Ende einer Sendung.

Abbildung 4: … zu einer höflichen Floskel am Ende einer Sendung.

Heiße Tasten

Wer auch unabhängig von Applikationen mit offenen Texteingabefeldern Aktionen auslösen möchte, zum Beispiel direkt auf dem Desktop, definiert im Konfigurationsdialog statt einer Textabkürzung einfach einen Hotkey, also eine Kombination gleichzeitig zu drückender Tasten.

Ein Mausklick im Autokey-Dialog auf den »Set« -Button unter »Hotkeys« bringt das Formular in Abbildung 5 zum Vorschein. Eine sicherlich nicht anderweitig genutzte Kombination wie [Ctrl]+[Alt]+[n] wählt der User am einfachsten durch einen Klick auf den Button »Press to Set« aus, um anschließend die Tastenkombination selbst zu drücken, während Autokey die Ohren spitzt.

Abbildung 5: Mit diesem Dialog lassen sich die Hotkeys einstellen.

Abbildung 5: Mit diesem Dialog lassen sich die Hotkeys einstellen.

Mit Hotkeys leitet der Desktop-Automatisierer nicht nur Textersetzungen ein, sondern kann in Autokey mittels selbst gekochter Python-Skripte auch beliebige Aktionen einleiten. Hierzu erzeugt das Autokey-UI mit »New Script« ein neues Skript und legt es nicht wie vorher im Ordner »My Phrases« , sondern unter »Sample Scripts« ab.

Die Unterscheidung zwischen Ersetzungen und dynamischen Skripten ist wichtig, denn ist ein Skript nicht als solches gekennzeichnet, gäbe Autokey im Aktionsfall einfach den Python-Code aus, statt ihn auszuführen. Abbildung 5 zeigt eine Aktion, die dem Hotkey [Ctrl]+[Alt]+[n] zugewiesen ist und die erwähnten maßgeschneiderten Terminalfenster aufmacht, von denen ich täglich Dutzende brauche.

Verteilung automatisieren

Natürlich geht es nicht an, die Kürzel und Hotkey-Aktionen auf jeder neuen Linux-Kiste von Hand ins GUI von »autokey-gtk« einzutragen. Auch neu hinzukommende Produktivitätshelfer sollen nicht von Hand auf dem Desktop, sondern programmierbar gleich in die Autokey-Konfiguration einfließen.

Hierzu hilft es, Autokey über die Schulter zu schauen: Nachdem der User die entsprechenden Knöpfe zur Autokey-Konfiguration gedrückt, die Textfelder gefüllt und die Dialoge geschlossen hat (nicht vergessen den »Save« -Knopf in der Kopfzeile zu klicken), legt Autokey die Daten im Homeverzeichnis unter »~/config/autokey/…« ab.

Die Metadaten der definierten Tastenkombinationen liegen im Json-Format unter dem jeweiligen Ordner, »My Phrases« für Textsnippets und »Sample Scripts« für Skripte. Eine frische Autokey-Installation erzeugt beim ersten Aufruf von »autokey-gtk« eine Reihe von Beispiel-Phrasen und -Skripten, die einen Eindruck davon vermitteln, was mit dem Tool alles möglich ist (Abbildung 6).

Abbildung 6: Beim ersten Aufruf erzeugt »autokey-gtk« einige Beispiel-Phrasen und -Skripte.

Abbildung 6: Beim ersten Aufruf erzeugt »autokey-gtk« einige Beispiel-Phrasen und -Skripte.

Um den Vorgang zu automatisieren, kopiert im Folgenden ein Perl-Skript das von Autokey genutzte Metadatenformat aus den bereits vorhandenen Beispielen und fügt neue Einstellungen hinzu, gemäß einer relativ kompakten Yaml-Datei, die jeder nach seinem Gusto ohne viel Aufwand anpassen kann (Listing 1).

Listing 1

autokey.yaml

01 -
02   name:   terminal
03   type:   script
04   exec:   /home/mschilli/bin/xt &
05   hotkey: ctrl-alt-n
06 -
07   name:   hth
08   type:   phrase
09   abbrv:  hth
10   text:   Hope that helps!

Geschwätziges Json

Die von Autokey genutzten Json-Dateien zum Speichern von Meta-Informationen sind relativ geschwätzig, wie in Abbildung 7 zu sehen. In der Datei ».name.json« stehen die mit dem Eintrag »name« verknüpften Informationen, während das zugehörige Python-Skript zum Auslösen der gewünschten Aktion in »name.py« im selben Ordner residiert.

Abbildung 7: In der Datei ».terminal.json« speichert Autokey die Zuordnung des Hotkey zum Python-Skript unter »terminal.py«.

Abbildung 7: In der Datei ».terminal.json« speichert Autokey die Zuordnung des Hotkey zum Python-Skript unter »terminal.py«.

Das Skript in Listing 2 schnappt sich beim Aufruf

Listing 2

autokeygen

01 #!/usr/local/bin/perl -w
02 use strict;
03 use Sysadm::Install qw(:all);
04 use Yaml qw( LoadFile );
05 use JSON qw( from_json to_json );
06
07 my $yaml_file   = "autokey.yaml";
08 my( $base_dir ) =
09   glob "~/.config/autokey/data";
10 my $script_dir  =
11   "$base_dir/Sample Scripts";
12 my $phrase_dir  = "$base_dir/My Phrases";
13
14 for my $entry (
15     @{ LoadFile $yaml_file } ) {
16   my $func = "process_$entry->{type}";
17   no strict 'refs';
18   $func->( $entry );
19 }
20
21 ###########################################
22 sub process_script {
23 ###########################################
24   my( $entry ) = @_;
25
26     # get template script
27   my $data =
28     json_rw( "Insert Date", $script_dir );
29
30   $data->{ hotkey } = hotkey( $entry );
31   $data->{ description } = $entry->{ name };
32   $data->{ modes } = [ 3 ];
33
34   json_rw( $entry->{ name }, $script_dir,
35            $data );
36
37   blurt( "system.exec_command(" .
38       "'$entry->{exec}')\n",
39       "$script_dir/$entry->{ name }.pi" );
40
41 }
42
43 ###########################################
44 sub hotkey {
45 ###########################################
46   my( $entry ) = @_;
47
48   my @mods = split /-/, $entry->{ hotkey };
49   my $key = pop @mods;
50
51   return {
52     hotKey    => $key,
53     modifiers => [ map { "<$_>" } @mods ],
54   };
55 }
56
57 ###########################################
58 sub process_phrase {
59 ###########################################
60   my( $entry ) = @_;
61
62     # get template phrase
63   my $data =
64     json_rw( "Second phrase", $phrase_dir );
65
66   $data->{ abbreviation }->
67     { abbreviations }->[ 0 ] =
68       $entry->{ abbrv };
69
70   $data->{ description }
71     = $entry->{ name };
72
73   $data->{ modes } = [ 1 ];
74
75   json_rw( $entry->{ name }, $phrase_dir,
76            $data );
77
78   blurt( "$entry->{ text }\n",
79     "$phrase_dir/$entry->{ name }.txt" );
80 }
81
82 ###########################################
83 sub json_rw {
84 ###########################################
85   my( $name, $dir, $data ) = @_;
86
87   my $path = "$dir/.$name.json";
88
89   if( defined $data ) {
90     return blurt to_json(
91           $data, { pretty => 1 } ), $path;
92   }
93
94   return from_json( slurp $path );
95 }
autokeygen autokey.yaml

die Yaml-Datei aus Listing 1 und formt aus den beiden dort stehenden Einträgen – einem zum Textersatz des Kürzels »hth« sowie einer Terminal-Aktion zur Tastenkombination [Ctrl]+[Alt]+[n] – insgesamt vier zusätzliche Einträge im Konfigurationsbaum von Autokey, wie aus Abbildung 8 ersichtlich.

"Abbildung

Jeder Eintrag erzeugt eine Json-Datei und eine Text- beziehungsweise Python-Datei. Zu beachten ist, dass Autokey zu diesem Zeitpunkt nicht laufen darf, sonst bekäme es die Änderung seiner Konfiguration nicht mit und würde die neuen Daten später rücksichtslos wieder mit alten Einträgen überkleistern.

Zum Lesen von Yaml- und Json-Dateien zieht Listing 2 zunächst die Module »JSON« und »YAML« vom CPAN herein. Die Zeilen 7 bis 12 definieren, wo Autokey die Konfigurationsdateien ablegt, die For-Schleife ab Zeile 14 iteriert über die Einträge der Yaml-Datei in Listing 1, deren Daten als Array von Hash-Elementen vorliegen.

Je nach Typ des Eintrags springt der symbolische Funktionsaufruf in Zeile 18 entweder »process_script()« oder »process_phrase()« an. Damit Perl solche gewagten Konstrukte im Strict-Modus erlaubt, muss Zeile 17 die Strenge bei der Interpretation von symbolischen Referenzen temporär auf ein geringeres Maß zurückdrehen.

Beispielhaft

Damit das Skript nicht den ganzen Json-Wust nachimplementiert, orientiert es sich an den bereits von Autokey erstellten Beispieldateien und für jeden Eintrag der Yaml-Datei nur explizit benötigten Feldern. Die Funktion »json_rw()« greift dabei sowohl lesend als auch schreibend auf Json-Dateien der Autokey-Konfiguration zu. Zeile 28 etwa liest die Testkonfiguration zu »Insert Date« ein, einem Beispielskript zum dynamischen Einfügen des aktuellen Datums. Danach modifiziert es in den Zeilen 30 bis 32 nur die Einträge »hotkey« , »description« und »modes« , um sie den Anforderungen gemäß dem Yaml-Eintrag zum Öffnen des Terminalfensters mit der Tastenkombination [Ctrl]+[Alt]+[n] anzupassen.

Mit einer Referenz auf den Datenhash als zusätzlichem Argument erzeugt der Aufruf von »json_rw()« in Zeile 34 dann die Datei ».terminal.json« in der Autokey-Konfiguration. Das Python-Skript, das mit der Funktion »system.exec_command()« über die Shell ein Kommando aufruft, landet per »blurt()« in Zeile 37 in der Python-Datei »terminal.py« .

Da die Hotkey-Definition in der Yaml-Datei kompakt als »ctrl-alt-n« vorliegt, Autokey aber eine kompliziertere Datenstruktur bevorzugt, bereitet »hotkey()« in Zeile 44 die Rohdaten auf.

Die Funktion »process_phrase()« ab Zeile 58 formt das Kürzel »hth« in das von Autokey geforderte Format um. »slurp()« und »blurt()« aus dem CPAN-Modul Sysadm::Install leisten ganze Arbeit. Wer Probleme mit den Skripten hat, der sei auf die Datei »~/.config/autokey/autokey.log« verwiesen. Dort treten alle Systemfehler zutage und die Meldungen helfen meist weiter.

Infos

  1. Listings zu diesem Artikel ftp://www.linux-magazin.de/pub/listings/magazin/2015/03/Perl
  2. Michael Schilli “At your fingertips”:Linux-Magazin 06/2008, https://www.linux-magazin.de/Ausgaben/2008/06/Schnellstart
  3. Autokey-Projekt https://code.google.com/p/autokey

Der Autor

Michael Schilli arbeitet als Software-Engineer bei Yahoo in Sunnyvale, Kalifornien. In seiner seit 1997 erscheinenden Kolumne forscht er jeden Monat nach praktischen Anwendungen der Skriptsprache Perl. Unter mailto:mschilli@perlmeister.com beantwortet er gerne Fragen.

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 4 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben