Delen via


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.

architectuur

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:

  1. Gebruik het opdrachtregelprogramma dotnet om een starter classlib-project te maken.

    dotnet new classlib --name SamplePredictor
    
  2. 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>
    
  3. Verwijder het standaardbestand Class1.cs dat is gemaakt door dotnet en kopieer de volgende code naar een SamplePredictorClass.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 (;).

  4. Voer dotnet build uit om de assemblage te produceren. U vindt de gecompileerde assembly op de bin/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.