PowerShell 7.4の試験的な機能 Feedback Providers について

2023.07.14

しばたです。

少し前にPowerShell Team Blogで新しい試験的な機能として「Feedback Providers」を増やした旨のアナウンスがありました。

ちょっと面白い機能だったので本記事で解説したいと思います。  

Feedback Providers とは

Feedback ProvidersはユーザーがPowerShellプロンプト上で対話的にコマンドを実行した際の結果(成功、失敗、コマンドが見つからない、等)に応じて独自の応答メッセージ(フィードバック)を追加できる機能になります。

他シェルにあるpostexecに近い雰囲気ですが、PowerShellではあくまでもフィードバックを返すだけであり自由に処理をフックできない点が異なります。  

以前からPSCommandNotFoundSuggestionというコマンド名を間違えて入力した際に正しいと推測される名称をサジェストしてくれる試験的な機能があるのですが、これを実装した際に「より汎用的な仕組みを用意した方が良い」という判断になりFeedback Providerが生まれた様です。

Feedback Providersの仕様

具体的な仕様は以下のRFCで提案されています。

フィードバックの書式

本日時点でフィードバックの書式は以下の様に提案されています。

フィードバックの書式

[Providerの名前]
  ヘッダー (required):
    ➤ アクション1 (optional)
    ➤ アクション2 (optional)
    ➤ アクションn (optional)
  フッター (optional)

# 複数Providerがある場合は上記を繰り返す

Provider作成者が自由にレイアウトを決めるわけではなく、一定の書式に従う形になっています。
「ヘッダー」欄はシンプルに長文テキストを記述する自由欄として使われるケースも想定している様です。

フィードバックのトリガー

フィードバックを発生させるトリガーは5つ提案されています。

  • Comments
  • Success
  • CommandNotFound
  • Error
  • All

Comments トリガー

いきなり変わったトリガーが出てきましたが、これはプロンプトにコメント文(#で始まる文)を入力した際に発火するトリガーです。

PowerShellの利用において通常この様な行為しませんし、仮に実行しても何もせず終了するだけです。
RFCに記載されている意図としてはGitHub Copilotの様なコメントを読んで応答してくれるAI(を実装したProvider)での利用を想定しています。

Commentトリガーの実行例

PS># How do I list the files in my C drive?
[A.I Model]
  One way to list all your files in the C drive is the following:
    ➤ Get-ChildItem -Path C:

(RFCの例を転記 : コメントを書くとAIを実装したProviderがいい感じにフィードバックしてくれる)

Success トリガー

Successはコマンドが正常終了した時に発火するトリガーです。
RFCでは実行したコマンドに対し「より良い方法があればそれを提案する」といった使い方を想定しています。

CommandNotFound トリガー

CommandNotFoundは実行しようとしたコマンドが見つからなかった場合に発火するトリガーです。
そして現時点でデフォルトのトリガーでもあります。

前述の通り「適切なコマンドをサジェストする」使い方を想定しています。

Error トリガー

Errorはコマンドが異常終了した時に発火するトリガーです。
厳密にはCommandNotFoundもエラーの一種ですが、トリガーとしてはCommandNotFoundとそれ以外で区別されます。

PowerShell側では全てのエラーがトリガー対象となり、フィードバックを返すべきエラーを選択するのはProvider作成者の責務となっています。

All トリガー

Allは名前通り前述のすべてのタイミングでトリガーを発火させる設定です。

実行順など

複数のProviderを利用する際はImport-Moduleを明示的に実行して、インポートされた順にフィードバックを返す仕様になっています。

# インポート順でフィードバックを返す
Import-Module FeedbackProvider1
Import-Module FeedbackProvider2

PS>something to trigger feedback providers
[FeedbackProvider1]
  Header 1:
    ➤ Action
[FeedbackProvider2]
  Header2:
    ➤ Action

また、フィードバックから直接的に後続の処理を実行することは出来ないものの、予測変換のPredictorと間接的に連携させることは想定している様です。  

試してみた

ここからは実際に試していきます。

私の開発用PC(Windows 11)にインストールしたPowerShell 7.4-Preview.4を動作確認に使っていきます。
PowerShellのインストール方法は割愛します。

C:\> $PSVersionTable.PSVersion

Major  Minor  Patch  PreReleaseLabel BuildLabel
-----  -----  -----  --------------- ----------
7      4      0      preview.4

試験的な機能の有効化

Feedback ProvidersはPSFeedbackProviderと言う名前の試験的な機能で提供されています。

C:\> Get-ExperimentalFeature -Name PSFeedbackProvider | Format-List

Name        : PSFeedbackProvider
Enabled     : False
Source      : PSEngine
Description : Replace the hard-coded suggestion framework with the extensible feedback provider

Enable-ExperimentalFeatureコマンドでこの機能を有効にしてPowerShellコンソールを再起動します。
併せてPSCommandNotFoundSuggestion機能も有効にしてやります。

# Feedback Providersの機能を有効に
C:\> Enable-ExperimentalFeature -Name PSFeedbackProvider
WARNING: Enabling and disabling experimental features do not take effect until next start of PowerShell.

# PSCommandNotFoundSuggestion はFeedback Providerとして再実装されている
C:\> Enable-ExperimentalFeature -Name PSCommandNotFoundSuggestion
WARNING: Enabling and disabling experimental features do not take effect until next start of PowerShell.

再起動後これらの試験的な機能が有効になっていればOKです。

C:\> Get-ExperimentalFeature -Name PSFeedbackProvider, PSCommandNotFoundSuggestion | Select-Object Name, Enabled

Name                        Enabled
----                        -------
PSCommandNotFoundSuggestion    True
PSFeedbackProvider             True

動作確認

この状態で適当にコマンドを打ち間違えてみると、「コマンドが無い」エラーの後にFeedback Providerによるサジェストが表示される様になりました。

(dirrdirコマンドを打ち間違えてみる)

[general]
  The most similar commands are:
    > dir

PSCommandNotFoundSuggestionの試験的な機能自体は以前からあったため、既にお使いの方からするとわかりにくいかもしれませんが、サジェストの書式がRFCに沿ったものに変わっている点からFeedback Providerを使う様になったことが見て取れます。

補足 : JSON Adapter Feedback Provider を試してみる

PowerShell Team Blogでは別の例としてJSON Adapter Feedback ProviderというProviderを紹介しています。

補足としてこいつも動作確認しておきます。  

JSON Adapter Feedback Providerはネイティブコマンド向けのProviderで、あるコマンドを実行した際にPATH上に"コマンド名"-json.ps1というスクリプトファイルがある場合に「コマンド | コマンド名-jsonの形式でも実行可能だよ。」とお知らせしてくれるものになります。

"コマンド名"-json.ps1自体は自分で作り込む必要があり、ネイティブコマンドの結果をパースしてJSONにする処理を書いてやります。
要はPowerShell Crescendoと同様の目的を別のアプローチで試みている感じですね。
PowerShell Teamとしては有志で"コマンド名"-json.ps1を作り公開し共有する想定なんだと思いますが、現時点では全部自分で作り込む必要があるので正直しんどいです...

一応この他にjcコマンドとの連携機能もあり、jcがインストールされた環境でjcと連携可能なコマンドが実行された場合にもフィードバックを返してくれます。

こちらの機能は試しやすいので、本記事ではAWS CloudShell(Amazon Linux 2環境)にPowerShell 7.4-preview.4とjcをインストールした環境で動作確認していきます。

はじめにAWS CloudShellを起動し、以下のコマンドを実行して両者をインストールしておきます。

AWS CloudShellのBash

# AWS CloudShellにPowerShell 7.4-preview.4とjcをインストール
sudo yum install -y https://github.com/PowerShell/PowerShell/releases/download/v7.4.0-preview.4/powershell-preview-7.4.0_preview.4-1.rh.x86_64.rpm
sudo yum install -y https://github.com/kellyjonbrazil/jc/releases/download/v1.23.3/jc-1.23.3-1.x86_64.rpm

続けてpwsh-previewコマンドを実行してPowerShellを起動したうえでMicrosoft.PowerShell.JsonAdapterモジュールをインストールして明示的にインポートしておきます。

PowerShellコンソール上で実施

# モジュールのインストール
Install-Module -Name Microsoft.PowerShell.JsonAdapter -AllowPrerelease -Force

# 明示的にインポートしてProviderを使用する
Import-Module Microsoft.PowerShell.JsonAdapter

LinuxのPowerShell Preview版はデフォルトで全ての試験的な機能が有効になっているためこれで準備完了です。

jcで対応しているuname -aコマンドを実行してみると以下の様な感じでProviderがuname -a | jc --uname | ConvertFrom-Jsonの利用を薦めてくれます。
加えて入力補完にも表示される様になります。

[JsonAdapter]
  Json adapter found additional ways to run.
    ➤ uname -a | jc --uname | ConvertFrom-Json

フィードバックに従いuname -a | jc --uname | ConvertFrom-Jsonを実行するとこんな感じでよりPowerShellらしい操作になりました。
一応uname -a | jc --unameの結果も記載しておきます。

最後に

以上となります。

シンプルな仕組みですが面白いですね。
これから登場するProviderによっては非常に便利な体験を得ることができそうですし、できるだけ早く正式な機能になって欲しいと思った次第です。