Bagikan melalui


Cara membuat prediktor baris perintah

PSReadLine 2.1.0 memperkenalkan konsep prediktor baris perintah pintar dengan menerapkan fitur Predictive IntelliSense. PSReadLine 2.2.2 diperluas pada fitur tersebut dengan menambahkan model plugin yang memungkinkan Anda membuat prediktor baris perintah Anda sendiri.

Predictive IntelliSense meningkatkan penyelesaian tab dengan memberikan saran, pada baris perintah, saat Anda mengetik. Saran prediksi muncul sebagai teks berwarna setelah kursor Anda. Ini memungkinkan Anda menemukan, mengedit, dan menjalankan perintah penuh berdasarkan prediksi yang cocok dari riwayat perintah Anda atau plugin khusus domain tambahan.

Persyaratan sistem

Untuk membuat dan menggunakan prediktor plugin, Anda harus menggunakan versi perangkat lunak berikut:

  • PowerShell 7.2 (atau lebih tinggi) - menyediakan API yang diperlukan untuk membuat prediktor perintah
  • PSReadLine 2.2.2 (atau lebih tinggi) - memungkinkan Anda mengonfigurasi PSReadLine untuk menggunakan plugin

Gambaran umum prediktor

Prediktor adalah modul biner PowerShell. Modul harus mengimplementasikan System.Management.Automation.Subsystem.Prediction.ICommandPredictor antarmuka. Antarmuka ini mendeklarasikan metode yang digunakan untuk mengkueri hasil prediksi dan memberikan umpan balik.

Modul prediktor harus mendaftarkan CommandPredictor subsistem dengan PowerShell SubsystemManager saat dimuat dan membatalkan pendaftaran dirinya sendiri saat dibongkar.

Diagram berikut menunjukkan arsitektur prediktor di PowerShell.

Sistem

Membuat kode

Untuk membuat prediktor, Anda harus menginstal .NET 6 SDK untuk platform Anda. Untuk informasi selengkapnya tentang SDK, lihat Mengunduh .NET 6.0.

Buat proyek modul PowerShell baru dengan mengikuti langkah-langkah berikut:

  1. dotnet Gunakan alat baris perintah untuk membuat proyek classlib starter.

    dotnet new classlib --name SamplePredictor
    
  2. SamplePredictor.csproj Edit untuk berisi informasi berikut:

    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <TargetFramework>net6.0</TargetFramework>
      </PropertyGroup>
    
      <ItemGroup>
        <PackageReference Include="Microsoft.PowerShell.SDK" Version="7.2.0" />
      </ItemGroup>
    
    </Project>
    
  3. Hapus file default Class1.cs yang dibuat oleh dotnet dan salin kode berikut ke SamplePredictorClass.cs file di folder proyek Anda.

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

    Contoh kode berikut mengembalikan string "HELLO WORLD" untuk hasil prediksi untuk semua input pengguna. Karena prediktor sampel tidak memproses umpan balik apa pun, kode tidak menerapkan metode umpan balik dari antarmuka. Ubah kode prediksi dan umpan balik untuk memenuhi kebutuhan prediktor Anda.

    Catatan

    Tampilan daftar PSReadLine tidak mendukung saran multibaris. Setiap saran harus berupa satu baris. Jika kode Anda memiliki saran multibaris, Anda harus membagi baris menjadi saran terpisah atau menggabungkan baris dengan titik koma (;).

  4. Jalankan dotnet build untuk menghasilkan assembly. Anda dapat menemukan rakitan yang dikompilasi di bin/Debug/net6.0 lokasi folder proyek Anda.

    Catatan

    Untuk memastikan pengalaman pengguna yang responsif, antarmuka ICommandPredictor memiliki waktu habis 20ms untuk respons dari Prediktor. Kode prediktor Anda harus mengembalikan hasil kurang dari 20ms untuk ditampilkan.

Menggunakan plugin prediktor Anda

Untuk mencoba prediktor baru Anda, buka sesi PowerShell 7.2 baru dan jalankan perintah berikut:

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

Dengan assembly dimuat dalam sesi, Anda akan melihat teks "HELLO WORLD" muncul saat Anda mengetik di terminal. Anda dapat menekan F2 untuk beralih antara Inline tampilan dan List tampilan.

Untuk informasi selengkapnya tentang opsi PSReadLine, lihat Set-PSReadLineOption.

Anda bisa mendapatkan daftar prediktor yang diinstal, menggunakan perintah berikut:

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

Catatan

Get-PSSubsystem adalah cmdlet eksperimental yang diperkenalkan di PowerShell 7.1 Anda harus mengaktifkan PSSubsystemPluginModel fitur eksperimental untuk menggunakan cmdlet ini. Untuk informasi selengkapnya, lihat Menggunakan Fitur Eksperimental.