So erstellen Sie ein Prognosetool für die Befehlszeile
PSReadLine 2.1.0 hat das Konzept eines intelligenten Befehlszeilenvorhersagers eingeführt, indem das Predictive IntelliSense-Feature implementiert wird. PSReadLine 2.2.2 wurde auf dieses Feature erweitert, indem Sie ein Plug-In-Modell hinzufügen, mit dem Sie eigene Befehlszeilenvorhersagen erstellen können.
Predictive IntelliSense verbessert die Tab-Vervollständigung, indem während der Eingabe in der Befehlszeile Vorschläge bereitgestellt werden. Der Vorhersagevorschlag wird nach dem Cursor als farbiger Text angezeigt. Auf diese Weise können Sie vollständige Befehle basierend auf übereinstimmenden Vorhersagen aus Dem Befehlsverlauf oder zusätzlichen domänenspezifischen Plug-Ins ermitteln, bearbeiten und ausführen.
Systemanforderungen
Zum Erstellen und Verwenden eines Plug-In-Vorhersagemoduls müssen Sie die folgenden Softwareversionen verwenden:
- PowerShell 7.2 (oder höher) – stellt die APIs bereit, die zum Erstellen eines Befehlsvorhersagers erforderlich sind.
- PSReadLine 2.2.2 (oder höher) – ermöglicht Ihnen die Konfiguration von PSReadLine für die Verwendung des Plug-Ins.
Übersicht über einen Vorhersagegeber
Ein Vorhersagemodul ist ein PowerShell-Binärmodul. Das Modul muss die System.Management.Automation.Subsystem.Prediction.ICommandPredictor
Schnittstelle implementieren. Diese Schnittstelle deklariert die Methoden, die zum Abfragen von Vorhersageergebnissen und zum Bereitstellen von Feedback verwendet werden.
Ein Vorhersagemodul muss beim Laden ein CommandPredictor
-Subsystem beim SubsystemManager
von PowerShell registrieren und die Registrierung beim Entladen selbst aufheben.
Das folgende Diagramm zeigt die Architektur eines Prädiktors in PowerShell.
Erstellen des Codes
Um einen Vorhersagegeber zu erstellen, müssen Sie das .NET 6 SDK für Ihre Plattform installiert haben. Weitere Informationen zum SDK finden Sie unter Herunterladen von .NET 6.0.
Erstellen Sie ein neues PowerShell-Modulprojekt, indem Sie die folgenden Schritte ausführen:
Verwenden Sie das Befehlszeilentool
dotnet
, um ein Startklassenlib-Projekt zu erstellen.dotnet new classlib --name SamplePredictor
Bearbeiten Sie die
SamplePredictor.csproj
so, dass sie die folgenden Informationen enthält:<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net6.0</TargetFramework> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.PowerShell.SDK" Version="7.2.0" /> </ItemGroup> </Project>
Löschen Sie die von
dotnet
erstellte StandarddateiClass1.cs
, und kopieren Sie den folgenden Code in eineSamplePredictorClass.cs
Datei in Ihrem Projektordner.using System; using System.Collections.Generic; using System.Threading; using System.Management.Automation; using System.Management.Automation.Subsystem; using System.Management.Automation.Subsystem.Prediction; namespace PowerShell.Sample { public class SamplePredictor : ICommandPredictor { private readonly Guid _guid; internal SamplePredictor(string guid) { _guid = new Guid(guid); } /// <summary> /// Gets the unique identifier for a subsystem implementation. /// </summary> public Guid Id => _guid; /// <summary> /// Gets the name of a subsystem implementation. /// </summary> public string Name => "SamplePredictor"; /// <summary> /// Gets the description of a subsystem implementation. /// </summary> public string Description => "A sample predictor"; /// <summary> /// Get the predictive suggestions. It indicates the start of a suggestion rendering session. /// </summary> /// <param name="client">Represents the client that initiates the call.</param> /// <param name="context">The <see cref="PredictionContext"/> object to be used for prediction.</param> /// <param name="cancellationToken">The cancellation token to cancel the prediction.</param> /// <returns>An instance of <see cref="SuggestionPackage"/>.</returns> public SuggestionPackage GetSuggestion(PredictionClient client, PredictionContext context, CancellationToken cancellationToken) { string input = context.InputAst.Extent.Text; if (string.IsNullOrWhiteSpace(input)) { return default; } return new SuggestionPackage(new List<PredictiveSuggestion>{ new PredictiveSuggestion(string.Concat(input, " HELLO WORLD")) }); } #region "interface methods for processing feedback" /// <summary> /// Gets a value indicating whether the predictor accepts a specific kind of feedback. /// </summary> /// <param name="client">Represents the client that initiates the call.</param> /// <param name="feedback">A specific type of feedback.</param> /// <returns>True or false, to indicate whether the specific feedback is accepted.</returns> public bool CanAcceptFeedback(PredictionClient client, PredictorFeedbackKind feedback) => false; /// <summary> /// One or more suggestions provided by the predictor were displayed to the user. /// </summary> /// <param name="client">Represents the client that initiates the call.</param> /// <param name="session">The mini-session where the displayed suggestions came from.</param> /// <param name="countOrIndex"> /// When the value is greater than 0, it's the number of displayed suggestions from the list /// returned in <paramref name="session"/>, starting from the index 0. When the value is /// less than or equal to 0, it means a single suggestion from the list got displayed, and /// the index is the absolute value. /// </param> public void OnSuggestionDisplayed(PredictionClient client, uint session, int countOrIndex) { } /// <summary> /// The suggestion provided by the predictor was accepted. /// </summary> /// <param name="client">Represents the client that initiates the call.</param> /// <param name="session">Represents the mini-session where the accepted suggestion came from.</param> /// <param name="acceptedSuggestion">The accepted suggestion text.</param> public void OnSuggestionAccepted(PredictionClient client, uint session, string acceptedSuggestion) { } /// <summary> /// A command line was accepted to execute. /// The predictor can start processing early as needed with the latest history. /// </summary> /// <param name="client">Represents the client that initiates the call.</param> /// <param name="history">History command lines provided as references for prediction.</param> public void OnCommandLineAccepted(PredictionClient client, IReadOnlyList<string> history) { } /// <summary> /// A command line was done execution. /// </summary> /// <param name="client">Represents the client that initiates the call.</param> /// <param name="commandLine">The last accepted command line.</param> /// <param name="success">Shows whether the execution was successful.</param> public void OnCommandLineExecuted(PredictionClient client, string commandLine, bool success) { } #endregion; } /// <summary> /// Register the predictor on module loading and unregister it on module un-loading. /// </summary> public class Init : IModuleAssemblyInitializer, IModuleAssemblyCleanup { private const string Identifier = "843b51d0-55c8-4c1a-8116-f0728d419306"; /// <summary> /// Gets called when assembly is loaded. /// </summary> public void OnImport() { var predictor = new SamplePredictor(Identifier); SubsystemManager.RegisterSubsystem(SubsystemKind.CommandPredictor, predictor); } /// <summary> /// Gets called when the binary module is unloaded. /// </summary> public void OnRemove(PSModuleInfo psModuleInfo) { SubsystemManager.UnregisterSubsystem(SubsystemKind.CommandPredictor, new Guid(Identifier)); } } }
Der folgende Beispielcode gibt die Zeichenfolge "HELLO WORLD" für das Vorhersageergebnis für alle Benutzereingaben zurück. Da die Beispielvorhersage kein Feedback verarbeitet, implementiert der Code die Feedbackmethoden nicht aus der Schnittstelle. Ändern Sie den Vorhersage- und Feedbackcode so, dass er den Anforderungen Ihres Vorhersagegebers entspricht.
Anmerkung
Die Listenansicht PSReadLine unterstützt keine mehrzeiligen Vorschläge. Jeder Vorschlag sollte eine einzelne Zeile sein. Wenn Ihr Code über einen mehrteiligen Vorschlag verfügt, sollten Sie die Zeilen in separate Vorschläge aufteilen oder die Zeilen mit einem Semikolon (
;
) verbinden.Führen Sie
dotnet build
aus, um die Assembly zu erstellen. Sie finden die kompilierte Assembly imbin/Debug/net6.0
-Speicherort des Projektordners.Anmerkung
Um eine reaktionsfähige Benutzeroberfläche zu gewährleisten, verfügt die ICommandPredictor-Schnittstelle über ein Timeout von 20 ms für Antworten der Predictors. Ihr Vorhersagecode muss Ergebnisse in weniger als 20 ms zurückgeben, um angezeigt zu werden.
Verwenden Ihres Vorhersage-Plugins
Um Ihren neuen Vorhersager auszuprobieren, öffnen Sie eine neue PowerShell 7.2-Sitzung, und führen Sie die folgenden Befehle aus:
Set-PSReadLineOption -PredictionSource HistoryAndPlugin
Import-Module .\bin\Debug\net6.0\SamplePredictor.dll
Wenn die Assembly in der Sitzung geladen wurde, wird während der Eingabe im Terminal der Text „HELLO WORLD“ angezeigt. Sie können F2- drücken, um zwischen der ansicht Inline
und der List
Ansicht zu wechseln.
Weitere Informationen zu PSReadLine-Optionen finden Sie unter Set-PSReadLineOption.
Mit dem folgenden Befehl können Sie eine Liste der installierten Vorhersager abrufen:
Get-PSSubsystem -Kind CommandPredictor
Kind SubsystemType IsRegistered Implementations
---- ------------- ------------ ---------------
CommandPredictor ICommandPredictor True {SamplePredictor}
Anmerkung
Get-PSSubsystem
ist ein experimentelles Cmdlet, das in PowerShell 7.1 eingeführt wurde. Sie müssen das experimentelle Feature PSSubsystemPluginModel
aktivieren, um dieses Cmdlet zu verwenden. Weitere Informationen finden Sie unter Verwendung experimenteller Funktionen.