Tippen mit System
Das ReadLine-Modul der PowerShell beherrschen
Wie schnell und effizient man mit einem Programm umgeht, das per Tastatur bedient wird, hängt unter anderem davon ab, wie weit die zur Verfügung stehenden Tastenkürzel in Fleisch und Blut übergegangen sind. Bei der PowerShell geht das besonders schnell: Sie lässt sich an das vom Benutzer Gewohnte anpassen.
Wahrscheinlich gibt es kaum einen PowerShell-Anwender, der diesen Trick nicht benutzt: Nach der Eingabe von ein paar Zeichen kann man die Tab-Taste drücken, und die PowerShell versucht je nach Kontext, diese Buchstaben zu einem Befehl, einer Option oder dem Namen einer Datei oder eines Ordners zu vervollständigen.
Dieselbe Funktion dürften die meisten Benutzer von der Konsole her kennen, die sie vor der PowerShell benutzt haben: Windows-Anwender von der Eingabeaufforderung, Linux- und macOS-Nutzer von der Bash. Allerdings verhalten sich die beiden Shells unterschiedlich, wenn es beim Druck auf Tab mehrere mögliche Vervollständigungen gibt: Die Eingabeaufforderung fügt einfach die erste ein; jeder weitere Tab-Tastendruck ersetzt sie durch den nächsten Kandidaten. Die Bash ergänzt die Eingabe dagegen zunächst nur um die Zeichen, die in allen Vervollständigungen gleich sind; ein weiterer Druck auf die Tab-Taste zeigt eine Liste der möglichen Ergänzungen an.
Egal, ob Sie die Windows PowerShell benutzen oder die quelloffene PowerShell Core: Das Standard-Verhalten entspricht immer dem unter dem jeweiligen Betriebssystem Gewohnten. Nicht nur für die Tab-Ergänzung, sondern insgesamt für den Zeileneditor der PowerShell ist das Modul PSReadline zuständig, das nicht nur plattformspezifische Voreinstellungen liefert, sondern sich in weiten Bereichen eigenen Vorlieben anpassen lässt.
Editor-Modus
Sein wohl wichtigster Parameter ist die Einstellung EditMode; sie kennt die drei Zustände Windows, Emacs und Vi. Auswählen lässt sich eine der Voreinstellungen mit dem Befehl
Set-PSReadlineOption -EditMode <Modus>
Dabei entspricht der Modus Windows weitgehend dem Verhalten der Eingabeaufforderung. Emacs emuliert den gleichnamigen Texteditor und damit im Großen und Ganzen das Verhalten der Bash. Mit der Option Vi können Fans des bei Programmierern beliebten Editors vi ihre gewohnten Tastenkürzel und Modi benutzen.
Wenn Sie dauerhaft einen anderen als den für Ihr Betriebssystem voreingestellten Modus benutzen wollen, sollten Sie den dazugehörigen Aufruf in Ihr Profil-Skript einbauen [1]. Das gilt für alle im Folgenden vorgestellten Befehle.
Laut Dokumentation arbeitet das Modul PSReadline nicht mit der Terminal-Emulation im Integrated Scripting Environment (PowerShell ISE) zusammen. Obwohl wir hier bei unseren Tests keine Katastrophen erlebt haben, sollten Sie die Befehle dieses Artikels sicherheitshalber nur im normalen PowerShell-Textfenster benutzen und auch nur in das zu diesem Host gehörende Profil-Skript einfügen. Sein Dateiname steht in der Systemvariablen $profile, sofern Sie sie in der Textkonsole abrufen.
Außer dem reinen Zeileneditor für die Befehlseingabe übernimmt das Modul PSReadline auch die syntaktische Einfärbung der Eingabe sowie die Verwaltung und Speicherung der Befehls-Historie. Die verwendeten Farben lassen sich ebenso eigenen Wünschen anpassen wie der Speicherort der History-Datei. Details liefert
help Set-PSReadlineOption -Detailed
Tastenkürzel
Auch die Reaktion der PowerShell auf Tastendrücke lässt sich haarklein konfigurieren, angefangen bei Funktions- und Sondertasten über Tastenkombinationen mit der Umschalt-, Strg- oder Alt-Taste bis hin zu mehrteiligen Tastenfolgen. Das Modul PSReadline kennt dazu 150 Befehle, darunter simple Cursor-Bewegungen genauso wie die oben beschriebene Tab-Vervollständigung. Zudem kann man Tasten und Tastenkombinationen selbstgeschriebenen Code zuordnen.
Einen Überblick, welche Tastenkürzel aktuell definiert sind, liefert der Befehl
Get-PSReadlineKeyHandler -Bound
Welche Tastaturbefehle außerdem existieren, aber derzeit keinem Tastendruck zugeordnet sind, verrät
Get-PSReadlineKeyHandler -Unbound
Eine Funktion einer Tastenkombination zuzuordnen funktioniert nach diesem Muster:
-Chord 'Ctrl+End' `
-Function MoveToEndOfLine
Nach diesem Aufruf bewegt die Tastenkombination Strg+Ende den Cursor ans Zeilenende.
Als Chord kommen beliebige Tasten, Kombinationen und sogar Folgen in Frage. Tastenkombinationen bildet man mit den Präfixen Shift+, Ctrl+ und Alt+ für die Tasten Umschalt, Strg und Alt. Eine Folge von Tastendrücken wird durch Kommas getrennt: 'Ctrl+a,Ctrl+b' steht etwa für Strg+A gefolgt von Strg+B. Achtung: Das Komma steht hier innerhalb der Zeichenfolge. Im Unterschied dazu würde nach einem Set-PSReadlineKeyHandler-Aufruf mit mehreren Strings als Chord wie in
-Chord 'Ctrl+a', 'Ctrl+b'
die angegebene Funktion sowohl durch die Tastenkombination Strg+A als auch durch Strg+B ausgelöst.
Statt eine Tastenkombination oder -folge einem der vordefinierten Befehle zuzuordnen, kann man auch eigene Befehle implementieren. Erlaubt ist dabei alles, was sich in der Skriptsprache der PowerShell kodieren lässt. Das umfasst nicht nur Manipulationen der Eingabezeile, sondern beliebige Befehle. Sie wollen zum Beispiel aus der PowerShell heraus jederzeit mit Alt+E einen Explorer im aktuellen Ordner starten können? Kein Problem:
Set-PSReadLineKeyHandler `
-Chord 'Alt+e' `
-ScriptBlock {
explorer (Get-Location)
}
Statt des Parameters Function gibt man dem Aufruf von Set-PSReadLineKeyHandler einfach einen ScriptBlock mit. Der ist nicht wie im Beispiel auf eine Codezeile beschränkt, sondern darf beliebig kompliziert werden.
Um den Inhalt der Eingabezeile zu ändern, den Cursor zu bewegen oder auf die Befehls-Chronik zuzugreifen, kann man sich dabei der .NET-Klasse Microsoft.PowerShell.PSConsoleReadLine bedienen. Damit lässt sich dann beispielsweise so etwas wie die nebenstehende Funktion verwirklichen: Sie ergänzt die PowerShell um eine Schnelltaste, über die man in einem Rutsch ein Klammerpaar in die Eingabezeile einfügen kann. Je nachdem, ob gerade Text markiert ist oder nicht, umschließen die Klammern die Selektion oder den gesamten Text. Als Tastenkombination verwendet das Beispiel Alt+( – das ist Alt und Klammer auf, auf deutschen Tastaturen also Alt+Umschalt+8.
Set-PSReadLineKeyHandler -Chord 'Alt+(' ` -ScriptBlock { $line = $null $cursor = $null [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState( [ref]$line, [ref]$cursor) $selectionStart = $null $selectionLength = $null [Microsoft.PowerShell.PSConsoleReadLine]::GetSelectionState( [ref]$selectionStart, [ref]$selectionLength) if ($selectionStart -ne -1) { [Microsoft.PowerShell.PSConsoleReadLine]::Replace( $selectionStart, $selectionLength, '(' + $line.SubString($selectionStart, $selectionLength) + ')') [Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition( $selectionStart + $selectionLength + 2) } else { [Microsoft.PowerShell.PSConsoleReadLine]::Replace( 0, $line.Length, '(' + $line + ')') [Microsoft.PowerShell.PSConsoleReadLine]::EndOfLine() } }
Das Skript ruft als erstes die Methode GetBufferState() der Klasse PSConsoleReadLine auf. Die benötigt als Parameter Referenzen ([ref]) auf zwei Variablen: In der ersten verstaut sie den aktuellen Inhalt der Eingabezeile, in der zweiten die Position des Cursors. Nach demselben Muster findet [PSConsoleReadLine]::GetSelectionState() heraus, welcher Teil der Eingabezeile gerade markiert ist. Gibt es keine Selektion, enthält $selectionStart nach dem Aufruf den Wert –1.
Das prüft der folgende if-Ausdruck. In beiden Fällen benutzt der Code die Funktion [PSConsoleReadLine]::Replace(), um den Text auf der Eingabezeile um die Klammern zu ergänzen – entweder nur die Selektion ($line.SubString($selectionStart, $selectionLength)) oder den gesamten Inhalt. Die ersten beiden Argumente bestimmen dabei den Index des ersten zu ersetzenden Zeichens und die Anzahl der zu überschreibenden Zeichen. Die Funktionen [PSConsoleReadLine]::SetCursorPosition() und [PSConsoleReadLine]::EndOfLine() positionieren schließlich den Cursor neu – entweder hinter die schließende Klammer oder auf das Ende der Eingabe.
Die Klasse PSConsoleReadLine ist Bestandteil des PowerShell-SDK. Einen Link zu dessen Dokumentation inklusive einer Liste aller Methoden finden Sie unter ct.de/ye8t. Dort gibt es außerdem einen Link zu einer Datei namens SamplePSReadLineProfile.ps1 aus dem PowerShell-Quelltext-Repository auf GitHub. Diesem – lesenswerten (!) – Skript haben wir mit minimalen Änderungen das Klammerpaar-Beispiel entnommen. (hos@ct.de)
Referenz-Informationen, Quelltext:ct.de/ye8t