Simple Perl-Skripts statten das profane Cut-and-Paste des Linux-Desktops mit zusätzlichen Puffern zum zeitsparenden Editieren aus.
Text auf dem Desktop mit der Maus abgreifen und mittels Cut-and-Paste wieder ablegen gehört zum Standardrepertoire selbst der engstirnigsten Kommandozeilenliebhaber. Genaugenommen unterstützt der Windows-Manager auf dem Linux-Desktop dabei sogar zwei verschiedene Puffermechanismen: Die sogenannte primäre Selektion und das Clipboard ([2]).
Wer mit der Maus eine
Textzeile selektiert, kann den Inhalt dieser primären Selektion durch Drücken
der mittleren Maustaste irgendwo anders wieder herauspurzeln lassen.
Das Clipboard
hingegen erfordert, dass der User nach dem Selektieren den Copy-Mechanismus
in Gang setzt (üblicherweise mit der Tastenkombination CTRL-C oder dem
Menüpunkt Edit->Copy
einer grafischen Applikation) und am Zielpunkt
die Paste-Funktion aufruft (CTRL-V oder Edit->Paste
).
Applikationen steht es frei, eines oder beide Verfahren zu implementieren
und deshalb kommt es in freier Wildbahn oft zu Verwirrung und frustrierten
Anwendern: Während zum Beispiel ein einfaches xterm
nur die primäre
Selektion kennt, bietet der Adobe-Flashplayer nur den
Clipboard-Mechanismus an.
Wer Text aus einem xterm
in ein in Flashplayer dargestelltes Formular
übertragen möchte, schaut mit dem Ofenrohr ins Gebirge.
Der Google-Chrome-Browser beherrscht sowohl die primäre als auch die
Clipboard-Selektion, läuft auf Chrome allerdings die Web-Applikation
von evernote.com, funktioniert die primäre Selektion nicht mehr. Die
User raufen sich die Haare.
Wer einen URL aus einem Textfenster kopiert und ihn zum Einholen und
Anzeigen einem Browser überreichen möchte, steht oft vor dem Problem,
dass der URL im Text umgebrochen wurde und der Browser dann nur den
ersten Teil aufschnappt. Ich bin ein bekennendes Unix-Urgestein und
lese meine Email in pine
in einem screen
-Fenster, und damit
die Übertragung derartiger URLs klappt, habe ich mir in Firefox unter
about:config
die Option editor.singleLine.pasteNewlines
auf den
Wert 3 gesetzt.
Chrome beherrscht dies allerdings nicht, und deswegen befindet sich in meinem Gnome-Panel am oberen Bildschirmrand ein Propellerhut, hinter dem das Skript in Listing 1 Dienst tut. Es schnappt sich den URL in der primären Selektion, entfernt etwaige Leerzeichen und Zeilenumbrüche und überreicht den gesäuberten URL dem Chrome-Browser.
Abbildung 1: Das hinter der Propellermütze steckende Perlskript schnappt sich den URL aus der primären Textselektion und startet Chrome. |
Abbildung 2: Der Chrome-Launcher, der den Chrome-Browser mit der in X-Windows selektierten URL startet. |
Zum Zugriff auf die primäre Desktop-Selektion nutzt
Listing 1 das CPAN-Modul Clipboard ([3]), das auf der auf Linux laufenden
Grafik-Unterlage X-Windows unter der Haube das Programm xclip
verwendet.
Letzteres lässt sich auf Ubuntu mit sudo apt-get install xclip
nachinstallieren.
Das CPAN-Modul hat gegenüber der direkten Verwendung von xclip
den Vorteil, dass es auch auf einem
Mac oder sogar einem Windows-Rechner funktioniert, da es auf diesen
Plattformen automatisch auf die nativen Clipboard-Mechanismen umschwenkt.
01 #!/usr/local/bin/perl -w 02 use strict; 03 use local::lib; 04 use Clipboard; 05 06 my $browser = "/usr/bin/google-chrome"; 07 my $url = Clipboard->paste; 08 09 $url =~ s/\s+//g; 10 11 system( $browser, $url );
Da das Clipboard-Modul zwar mittels der CPAN-Shell, doch
unter meiner User-ID in meinem Home-Verzeichnis
und nicht unter root
installiert wurde, weist local::lib den
Perl-Interpreter auf das lokale Verzeichnis hin. Die Methode
paste
der Klasse Clipboard
holt den Inhalt der aktuellen
primären Selektion ein, Zeile 9 entfernt mittels eines regulären
Ausdrucks unerwünschte Umbrüche und das Kommando system
ruft
den Chrome-Browser mit dem URL als Argument auf. Wird das
Skript in einem "Custom Applicaition Launcher" über den
Kontext-Menüpunkt Add to Panel
im Panel mit einem leicht
erkennbaren Icon eingetragen (Abbildung 2), braucht der User nach der Selektion
der URL (ohne Copy-Kommando) nur auf die Propellermütze zu klicken,
damit der Chrome-Browser mit der gesäuberten URL hochfährt und
der Email-lesende paranoide Dinosaurier zähneknirschend
einem Link folgen kann.
Um das eingangs erwähnte Kommunikationsproblem zwischen xterm
und
dem Flashplayer zu lösen, greift sich Listing 2 die primäre Selektion und
schiebt sie aufs Clipboard. Damit der User dieses Kommando auch aus einer
Applikation ausführen kann, die den Clipboard-Mechanismus nicht kennt,
definiert das Programm gconf-editor
in Abbildung 3 ein globales
Key-Mapping in Gnomes Window-Manager Metacity. Drückt der User nach
dem Selektieren des gewünschten Textabschnitts die Tastenkombination
CTRL-ALT-c
(definiert im Abschnitt global_keybindings
), löst
Metacity das konfigurierbare Kommando run_command_2
aus, das im
Abschnitt keybinding_commands
(Abbildung 4)
auf das Skript in Listing 2 gesetzt ist.
1 #!/usr/local/bin/perl 2 use local::lib; 3 use Clipboard::Xclip; 4 5 my $primary = Clipboard::Xclip-> 6 paste_from_selection( "primary" ); 7 8 Clipboard::Xclip->copy_to_selection( 9 "clipboard", $primary );
Dies ermöglicht es dem User, in einer Applikation, die kein Clipboard
kennt, einen Text zu selektieren, und diesen mit CTRL-ALT-c
aufs
Clipboard zu befördern. In der Zielapplikation, die die primäre Selektion
nicht unterstützt, ist dann nur noch CTRL-V
zu drücken, um den gewünschten
Text herunterzurasseln. Das Skript nutzt die undokumentierten Methoden
paste/copy_from_selection
der abgeleiteten Klasse Clipboard::Xclip,
da die Basisklasse Clipboard
keine Unterscheidung der verschiedenen
Puffer zulässt.
Abbildung 3: In Gnomes Window-Manager Metacity löst die Tastenkombination CTRL-ALT-c das Kommando 2 aus ... |
Abbildung 4: ... das wiederum das Skript primary-to-clipboard zum Kopieren der Selektion aufs Clipboard ausführt. |
Wer hat es sich nicht schon einmal gewünscht, mehrere Cut-und-Paste-Puffer zur Verfügung zu haben, um zunächst N Abschnitte zu selektieren und und sie anschließend alle zusammen in einem anderen Fenster abzulegen? Auf einem normalen Gnome-Desktop muss der User dazu N-mal zwischen Quelle und Ziel hin- und herspringen, jeweils einen Abschnitt an der Quelle aufnehmen, und ihn anschließend am Ziel ablegen.
Listing 3 implementiert darum einen persistenten Stack, auf den
der User den Inhalt der primären Selektion schieben kann, um
mit clipboard-stack push
Platz im Puffer für weitere Selektionen
freizuräumen. Um eine ausgediente Selektion wieder mit der kürzlich im Stack
abgelegten zu ersetzen, ruft der User clipboard-stack pop
auf.
Das Skript legt die im Stack befindlichen Werte im Array
@$stack
ab, dessen Inhalt es mittels des CPAN-Moduls YAML
persistent in die Datei .clipboard
im Home-Verzeichnis schreibt.
01 #!/usr/local/bin/perl -w 02 use strict; 03 use local::lib; 04 use Clipboard; 05 use YAML qw(DumpFile LoadFile); 06 07 my($home) = glob "~"; 08 my $clipboard = "$home/.clipboard"; 09 10 my $stack = []; 11 $stack = LoadFile( $clipboard ) if 12 -f $clipboard; 13 14 my( $command ) = @ARGV; 15 16 die "usage: $0 [push|pop]" if 17 !defined $command; 18 19 { 20 no strict 'refs'; 21 &$command( $stack ); 22 } 23 24 DumpFile( $clipboard, $stack ); 25 26 ########################################### 27 sub push { 28 ########################################### 29 my($stack) = @_; 30 31 push @$stack, Clipboard->paste; 32 } 33 34 ########################################### 35 sub pop { 36 ########################################### 37 my($stack) = @_; 38 39 Clipboard->copy( pop @$stack ); 40 }
Beim erneuten Aufruf des Skripts liest die Funktion LoadFile()
des
YAML-Moduls die abgelegten Daten wieder ein. Je nachdem, ob der User
das Skript mit dem Argument push
oder pop
aufgerufen hat, springt
der Aufruf &$command( $stack )
in Zeile 21 eine der weiter unten
definierten Funktionen an. Da das Skript im strict
-Modus keine
als Textstring vorgegebenen Funktionsaufrufe erlaubt, lockert das
Pragma no strict 'refs'
in Zeile 20 vorübergehend diese Einschränkung.
Die ab Zeile 27 definierte Funktion push()
holt mittels der Methode
paste()
der Klasse Clipboard
den
selektierten Text ein und schiebt ihn auf den Stack.
Die in Zeile 35 definierte Funktion pop()
kopiert den archivierten Inhalt
mit der Methode copy()
in die primäre Selektion.
Klickt der User anschließend auf die mittlere Maustaste, fließt der
archivierte Inhalt heraus.
Damit der User zum Jonglieren mit den Selektions-Inhalten nicht umständlich
ein Perlskript aufrufen muss, erhält das Gnome-Panel für den
Selektions-Stack zwei Einträge, die mit zwei formschönen Icons in
Pfeilform (gefunden unter /usr/share/icons/Human/48x48/actions
als
edit-redo.png
und edit-undo.png
) zum Klicken einladen.
Abbildung 5: Eintragen des Clipboard-Stacks auf dem Gnome-Panel. |
Abbildung 6: Der grüne Pfeil schiebt die aktuelle Selektion auf den Stack, der orange Pfeil holt sie wieder. |
Zu beachten ist, dass eine aufeinanderfolgende Kombination von
Push und Pop nichts bewirkt. Eine Selektion im Puffer kann der User
auch sofort wieder irgendwo ablegen, nur falls die Selektion ab ins Archiv
soll, weil eine weitere Selektion ansteht, bietet der Stack mit push
die erforderliche Funktionalität. Nachdem die aktuelle Selektion dann nicht
mehr gebraucht wird, holt der User mit pop
die archivierte Selektion
aus dem Archiv zurück auf den Desktop.
Statt nach jedem Paste im Clipboard-Archiv aufgereihte Daten per Knopfdruck ins Clipboard nachzufüllen, wäre es nun geradezu revolutionär, den User einfach N-mal klicken zu lassen und zwischendurch automatisch den nächsten Puffer nachzuschieben. Dies hilft zum Beispiel beim Ausfüllen von Web- oder PDF-Formularen, wenn man die Reihenfolge der Felder kennt und die Daten entsprechend im erweiterten Clipboard-Puffer vorab aufgereiht hat. Der User muss dann nur noch von Feld zu Feld springen und jeweils den Paste-Befehl absetzen.
Listing 4 implementiert das Verfahren, in dem es xclip
direkt aufruft.
Statt der primären Selektion nutzt es im Gegensatz zu den vorher vorgestellten
Skripts den Clipboard-Puffer, der mit CTRL-C
(Edit->Copy
)
aufgefüllt und mit CTRL-V
(Edit->Paste
) entleert wird. Der
Grund hierfür liegt schlichtweg in der Tatsache, dass ich das Skript
ursprünglich zur Befüllung der Formulardaten einer Flashplayer-Applikation
entwickelt habe. Lässt man -selection CLIPBOARD
weg, greift es stattdessen
auf die primäre Selektion zu und der User muss statt mehrmaligem
CTRL-V
nur auf die mittlere Maustaste hämmern.
Das Skript iteriert über eine Reihe von Wörtern ("yes", "no", "maybe", "so"),
schiebt sie eins nach dem anderen aufs Clipboard und wartet mit
-loops 2
, bis der User den aktuellen Inhalt mit dem Paste-Kommando
freigibt. Daraufhin kehrt das bis dahin blockierende xclip
zurück, die
Schleife des Perlskripts geht in die nächste Runde und der folgende
Aufruf von xclip
bekommt über die mit open
geöffnete Pipeline
das nächste Wort nachgeschoben.
01 #!/usr/local/bin/perl -w 02 use strict; 03 04 my @words = qw(yes no maybe so); 05 06 for my $word ( @words ) { 07 08 open my $pipe, "|-", 09 qw(xclip -verbose 10 -selection CLIPBOARD -loops 2); 11 12 print $pipe $word; 13 close $pipe or die; 14 }
In Abbildung 7 ist der User, nachdem er in einem anderen Fenster
multipaste
aufgerufen hat, mit der Maus- oder der Tab-Taste
in die verschiedenen Felder des Registrierungsformulars gesprungen
und hat jeweils mit CTRL-V
einen Paste-Vorgang ausgelöst.
Herausgepurzelt aus dem Puffer kam jeweils ein neues Wort aus dem
vorher eingetüteten Fundus.
Abbildung 7: Der User hat zunächst multipaste aufgerufen, und ist dann von Feld zu Feld gesprungen und hat jeweils CTRL-V gedrückt. |
Wer also oft die gleichen Webformulare ausfüllt, die sich nicht einfach
durch Verwendung von APIs oder Screenscraper automatisieren lassen,
kann sich auf diese
Weise mit einem Skript wie multipaste
die Werte in der richtigen
Reihenfolge vorab aufbereiten, um später dann immer noch von Hand,
aber blitzschnell von Feld zu Feld zu springen und ohne nachdenken zu müssen
die richtigen Werte tippfehler- und verdrussfrei einzufügen.
Listings zu diesem Artikel: ftp://www.linux-magazin.de/pub/listings/magazin/2012/03/Perl
"X Selections, Cut Buffers, and Kill Rings", Jamie Zawinski, http://www.jwz.org/doc/x-cut-and-paste.html
CPAN-Modul Clipboard, http://search.cpan.org/~king/Clipboard-0.13/
Michael Schilliarbeitet als Software-Engineer bei Yahoo! in Sunnyvale, Kalifornien. Er hat "Goto Perl 5" (deutsch) und "Perl Power" (englisch) für Addison-Wesley geschrieben und ist unter mschilli@perlmeister.com zu erreichen. Seine Homepage: http://perlmeister.com. |