Dela via


Så här skapar du en kommandoradsförse förutsägare

PSReadLine 2.1.0 introducerade konceptet med en smart kommandoradsförseningar genom att implementera funktionen Predictive IntelliSense. PSReadLine 2.2.2 expanderade funktionen genom att lägga till en plugin-modell som gör att du kan skapa egna kommandoradsförutsägare.

Predictive IntelliSense förbättrar flikens slutförande genom att ge förslag på kommandoraden när du skriver. Förutsägelseförslaget visas som färgad text efter markören. På så sätt kan du identifiera, redigera och köra fullständiga kommandon baserat på matchande förutsägelser från din kommandohistorik eller ytterligare domänspecifika plugin-program.

Systemkrav

Om du vill skapa och använda en plugin-prediktor måste du använda följande versioner av programvara:

  • PowerShell 7.2 (eller senare) – tillhandahåller de API:er som krävs för att skapa en kommandoförsägare
  • PSReadLine 2.2.2 (eller senare) – låter dig konfigurera PSReadLine att använda plugin-programmet

Översikt över en prediktor

En prediktor är en Binär PowerShell-modul. Modulen måste implementera System.Management.Automation.Subsystem.Prediction.ICommandPredictor gränssnittet. Det här gränssnittet deklarerar de metoder som används för att fråga efter förutsägelseresultat och ge feedback.

En förutsägelsemodul måste registrera ett CommandPredictor undersystem med PowerShell SubsystemManager när det läses in och avregistreras när det tas bort.

Följande diagram visar arkitekturen för en förutsägelse i PowerShell.

Arkitektur

Skapa koden

Om du vill skapa en förutsägelse måste du ha .NET 6 SDK installerat för din plattform. Mer information om SDK finns i Ladda ned .NET 6.0.

Skapa ett nytt PowerShell-modulprojekt genom att följa dessa steg:

  1. Använd kommandoradsverktyget dotnet för att skapa ett starter classlib-projekt.

    dotnet new classlib --name SamplePredictor
    
  2. Redigera för SamplePredictor.csproj att innehålla följande information:

    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <TargetFramework>net6.0</TargetFramework>
      </PropertyGroup>
    
      <ItemGroup>
        <PackageReference Include="Microsoft.PowerShell.SDK" Version="7.2.0" />
      </ItemGroup>
    
    </Project>
    
  3. Ta bort standardfilen Class1.cs som skapats av dotnet och kopiera följande kod till en SamplePredictorClass.cs fil i projektmappen.

    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));
            }
        }
    }
    

    Följande exempelkod returnerar strängen "HELLO WORLD" för förutsägelseresultatet för alla användarindata. Eftersom exempel förutsägaren inte bearbetar någon feedback implementerar koden inte feedbackmetoderna från gränssnittet. Ändra förutsägelse- och feedbackkoden så att den uppfyller dina prediktorbehov.

    Kommentar

    Listvyn för PSReadLine stöder inte flerradsförslag. Varje förslag ska vara en enda rad. Om koden har ett flerradsförslag bör du dela upp raderna i separata förslag eller koppla samman raderna med ett semikolon (;).

  4. Kör dotnet build för att skapa sammansättningen. Du hittar den kompilerade sammansättningen på platsen för projektmappen bin/Debug/net6.0 .

    Kommentar

    För att säkerställa en dynamisk användarupplevelse har ICommandPredictor-gränssnittet en tidsgräns på 20 ms för svar från Predictors. Din förutsägelsekod måste returnera resultat på mindre än 20 ms för att visas.

Använda ditt plugin-program för förutsägelse

Om du vill testa din nya prediktor öppnar du en ny PowerShell 7.2-session och kör följande kommandon:

Set-PSReadLineOption -PredictionSource HistoryAndPlugin
Import-Module .\bin\Debug\net6.0\SamplePredictor.dll

När sammansättningen läses in i sessionen visas texten "HELLO WORLD" när du skriver i terminalen. Du kan trycka på F2 för att växla mellan Inline vyn och List vyn.

Mer information om PSReadLine-alternativ finns i Set-PSReadLineOption.

Du kan hämta en lista över installerade prediktorer med hjälp av följande kommando:

Get-PSSubsystem -Kind CommandPredictor
Kind              SubsystemType      IsRegistered Implementations
----              -------------      ------------ ---------------
CommandPredictor  ICommandPredictor          True {SamplePredictor}

Kommentar

Get-PSSubsystem är en experimentell cmdlet som introducerades i PowerShell 7.1 Du måste aktivera den PSSubsystemPluginModel experimentella funktionen för att använda den här cmdleten. Mer information finns i Använda experimentella funktioner.