Hoe maak je een opdrachtregelvoorspeller?
PSReadLine 2.1.0 heeft het concept van een slimme opdrachtregelvoorspelling geïntroduceerd door de functie Predictive IntelliSense te implementeren. PSReadLine 2.2.2 heeft die functie uitgebreid door een plug-inmodel toe te voegen waarmee u uw eigen opdrachtregelvoorspellers kunt maken.
Predictive IntelliSense verbetert de voltooiing van tab door suggesties te geven op de opdrachtregel terwijl u aan het typen bent. De voorspellingssuggestie wordt weergegeven als gekleurde tekst na de cursor. Hiermee kunt u volledige opdrachten detecteren, bewerken en uitvoeren op basis van overeenkomende voorspellingen uit uw opdrachtgeschiedenis of aanvullende domeinspecifieke invoegtoepassingen.
Systeemvereisten
Als u een voorspellingsfunctie voor invoegtoepassingen wilt maken en gebruiken, moet u de volgende versies van software gebruiken:
- PowerShell 7.2 (of hoger): biedt de API's die nodig zijn om een opdrachtvoorspeller te maken.
- PSReadLine 2.2.2 (of hoger): hiermee kunt u PSReadLine configureren voor gebruik van de invoegtoepassing
Overzicht van een voorspeller
Een predictor is een binaire PowerShell-module. De module moet de System.Management.Automation.Subsystem.Prediction.ICommandPredictor
-interface implementeren. Deze interface declareert de methoden die worden gebruikt om query's uit te voeren op voorspellingsresultaten en feedback te geven.
Een predictormodule moet een CommandPredictor
subsysteem registreren bij de SubsystemManager
van PowerShell wanneer deze wordt geladen en de registratie ervan ongedaan wordt gesteld wanneer deze wordt verwijderd.
In het volgende diagram ziet u de architectuur van een predictor in PowerShell.
De code maken
Als u een predictor wilt maken, moet de .NET 6 SDK voor uw platform zijn geïnstalleerd. Zie .NET 6.0 downloadenvoor meer informatie over de SDK.
Maak een nieuw PowerShell-moduleproject door de volgende stappen uit te voeren:
Gebruik het opdrachtregelprogramma
dotnet
om een starter classlib-project te maken.dotnet new classlib --name SamplePredictor
Bewerk de
SamplePredictor.csproj
met de volgende informatie:<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net6.0</TargetFramework> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.PowerShell.SDK" Version="7.2.0" /> </ItemGroup> </Project>
Verwijder het standaardbestand
Class1.cs
dat is gemaakt doordotnet
en kopieer de volgende code naar eenSamplePredictorClass.cs
bestand in de projectmap.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)); } } }
De volgende voorbeeldcode retourneert de tekenreeks 'HALLO WERELD' voor het voorspellingsresultaat voor alle gebruikersinvoer. Omdat de voorbeeld predictor geen feedback verwerkt, worden de feedbackmethoden van de interface niet door de code geïmplementeerd. Wijzig de voorspellings- en feedbackcode om te voldoen aan de behoeften van uw predictor.
Notitie
De lijstweergave van PSReadLine- biedt geen ondersteuning voor suggesties voor meerdere regels. Elke suggestie moet één regel zijn. Als uw code een suggestie met meerdere regels bevat, moet u de regels opsplitsen in afzonderlijke suggesties of de regels samenvoegen met een puntkomma (
;
).Voer
dotnet build
uit om de assemblage te produceren. U vindt de gecompileerde assembly op debin/Debug/net6.0
locatie van uw projectmap.Notitie
Om een responsieve gebruikerservaring te garanderen, heeft de interface ICommandPredictor een time-out van 20 ms voor reacties van de Predictors. Uw voorspellingscode moet resultaten retourneren in minder dan 20 ms.
Het gebruik van uw predictor-invoegtoepassing
Als u de nieuwe predictor wilt uitproberen, opent u een nieuwe PowerShell 7.2-sessie en voert u de volgende opdrachten uit:
Set-PSReadLineOption -PredictionSource HistoryAndPlugin
Import-Module .\bin\Debug\net6.0\SamplePredictor.dll
Wanneer de assembly in de sessie is geladen, ziet u dat de tekst 'HALLO WERELD' wordt weergegeven terwijl u in de terminal typt. U kunt op F2 drukken om te schakelen tussen de Inline
weergave en de List
weergave.
Zie Set-PSReadLineOptionvoor meer informatie over PSReadLineOption-opties.
U kunt een lijst met geïnstalleerde predictors ophalen met behulp van de volgende opdracht:
Get-PSSubsystem -Kind CommandPredictor
Kind SubsystemType IsRegistered Implementations
---- ------------- ------------ ---------------
CommandPredictor ICommandPredictor True {SamplePredictor}
Notitie
Get-PSSubsystem
is een experimentele cmdlet die is geïntroduceerd in PowerShell 7.1 U moet de PSSubsystemPluginModel
experimentele functie inschakelen om deze cmdlet te gebruiken. Zie Experimentele functies gebruikenvoor meer informatie.