ja-JP/about_Functions_Argument_Completion.help.txt

TOPIC
    about_Functions_Argument_Completion

簡単な説明
    引数の補完は、入力候補のヒントを表示し、値の発見を助け、引数値の
    入力を高速化する PowerShell の機能です。
    (PSHelpJaJP 日本語パッチ版)

詳細な説明
    この記事では、PowerShell の関数に対して引数補完を実装する
    さまざまな方法について説明します。引数補完は、パラメーターに
    指定できる値の候補を提供します。利用できる値は、ユーザーが
    パラメーター名の後ろで Tab キーを押したときに、実行時に計算
    されます。パラメーターに引数補完を定義する方法はいくつか
    あります。

    メモ: Windows では Tab キーが既定のキー割り当てです。この
    キー割り当ては、PSReadLine モジュールや PowerShell をホストして
    いるアプリケーションによって変更できます。Windows 以外の
    プラットフォームでは、キー割り当てが異なります。詳しくは、
    about_PSReadLine を参照してください。

ValidateSet 属性
    ValidateSet 属性は、パラメーターまたは変数に有効な値の集合を
    指定し、タブ補完を有効にします。

    パラメーターまたは変数の値が集合内のいずれの値とも一致しない
    場合、PowerShell はエラーを生成します。次の例では、Fruit
    パラメーターの値として指定できるのは Apple、Banana、Pear の
    いずれかだけです。

        param (
            [Parameter(Mandatory=$true)]
            [ValidateSet('Apple', 'Banana', 'Pear')]
            [string[]]$Fruit
        )

    次の例では、変数 $flavor の値は Chocolate、Strawberry、Vanilla
    のいずれかでなければなりません。ValidateSet 属性は、パラメーター
    だけでなく任意の変数に対して使用できます。

        [ValidateSet('Chocolate', 'Strawberry', 'Vanilla')]
        [string]$Flavor = 'Strawberry'

    検証は、スクリプト内も含め、その変数に値が代入されるたびに
    実行されます。

        param (
            [ValidateSet('hello', 'world')]
            [string]$Message
        )

        $Message = 'bye'

    この例は、実行時に次のエラーを返します。

        MetadataError: The attribute cannot be added because variable
        Message with value bye would no longer be valid.

    タブ展開について詳しくは、about_Tab_Expansion を参照して
    ください。

    クラスを使った動的な ValidateSet 値
        class を使うと、ValidateSet の値を実行時に動的に生成できます。
        次の例では、変数 $Sound の有効な値は、3 つのファイルシステム
        パスを調べて利用可能なサウンドファイルを探す SoundNames という
        class によって生成されます。

            class SoundNames : System.Management.Automation.IValidateSetValuesGenerator {
                [string[]] GetValidValues() {
                    $SoundPaths = '/System/Library/Sounds/',
                                  '/Library/Sounds',
                                  '~/Library/Sounds'
                    $SoundNames = foreach ($SoundPath in $SoundPaths) {
                        if (Test-Path $SoundPath) {
                            (Get-ChildItem $SoundPath).BaseName
                        }
                    }
                    return [string[]] $SoundNames
                }
            }

        この [SoundNames] クラスは、次のようにして動的な ValidateSet
        値として実装します。

            param (
                [ValidateSet([SoundNames])]
                [string]$Sound
            )

        メモ: IValidateSetValuesGenerator クラスは PowerShell 6.0 で
        導入されました。

ArgumentCompletions 属性
    ArgumentCompletions 属性を使うと、特定のパラメーターにタブ補完の
    値を追加できます。

    ArgumentCompletions 属性は、タブ補完が必要なパラメーターごとに
    定義する必要があります。ArgumentCompletions 属性は ValidateSet と
    似ています。どちらの属性も、ユーザーがパラメーター名の後ろで Tab
    を押したときに表示する値の一覧を受け取ります。ただし ValidateSet
    と異なり、これらの値は検証されず、あくまで候補に近いものです。
    そのため、ユーザーは一覧にない値も含めて任意の値を指定できます。

    ArgumentCompletions 属性は、選択肢の定義にスクリプトブロックを
    必要とする ArgumentCompleter 属性と混同しないようにしてください。

    構文は次のとおりです。

        function Test-ArgumentCompletions {
            [CmdletBinding()]
            param (
                [Parameter(Mandatory=$true)]
                [ArgumentCompletions('Fruits', 'Vegetables')]
                $Type,

                [Parameter()]
                [ArgumentCompletions('Apple', 'Banana', 'Orange')]
                $Fruit,

                [Parameter()]
                [ArgumentCompletions('Onion', 'Carrot', 'Lettuce')]
                $Vegetable
            )
        }

    各パラメーターには、タブ補完を有効にするため、選択肢の一覧が
    ArgumentCompletions 属性に渡されています。

    この属性は PowerShell 6.0 で導入されました。

ArgumentCompleter 属性
    ArgumentCompleter 属性を使うと、特定のパラメーターにタブ補完の
    値を追加できます。

    ArgumentCompleter 属性は、タブ補完が必要なパラメーターごとに
    定義する必要があります。

    ArgumentCompleter 属性を追加するには、値を決定する
    スクリプトブロックを定義する必要があります。スクリプトブロックは、
    以下に示す順序で次のパラメーターを受け取らなければなりません。
    値は位置で渡されるため、パラメーターの名前は問いません。

    構文は次のとおりです。

        function MyArgumentCompleter {
            param (
                [Parameter(Mandatory)]
                [ArgumentCompleter( {
                    param ( $commandName,
                            $parameterName,
                            $wordToComplete,
                            $commandAst,
                            $fakeBoundParameters )
                    # Perform calculation of tab completed values here.
                } )]
                $ParamName
            )
        }

    ArgumentCompleter スクリプトブロック
        スクリプトブロックのパラメーターには、次の値が設定されます。

        - $commandName (位置 0) - スクリプトブロックがタブ補完を
          提供している対象コマンドの名前が設定されます。

        - $parameterName (位置 1) - タブ補完による値が必要な
          パラメーターが設定されます。

        - $wordToComplete (位置 2) - ユーザーが Tab を押す前に入力した
          値が設定されます。スクリプトブロックでは、この値を使って
          タブ補完の候補を決定してください。

        - $commandAst (位置 3) - 現在の入力行に対する抽象構文木 (AST)
          が設定されます。

        - $fakeBoundParameters (位置 4) - ユーザーが Tab を押す前の
          時点における、コマンドレットの $PSBoundParameters を含む
          ハッシュテーブルが設定されます。

        ArgumentCompleter スクリプトブロックは、ForEach-Object、
        Where-Object などの適切な方法を使って、値をパイプライン経由で
        1 つずつ展開しなければなりません。

        値の配列をそのまま返すと、PowerShell は配列全体を「1 つ」の
        タブ補完値として扱います。

        次の例では、Value パラメーターにタブ補完を追加しています。
        Value パラメーターだけが指定された場合は、Value に指定できる
        すべての候補 (引数) が表示されます。Type パラメーターが
        指定された場合は、Value パラメーターはその型に対応する候補
        だけを表示します。

        さらに、-like 演算子により、ユーザーが次のコマンドを入力して
        Tab 補完を使ったとき、Apple だけが返されるようになります。

            Test-ArgumentCompleter -Type Fruits -Value A

            function MyArgumentCompleter{
                param ( $commandName,
                        $parameterName,
                        $wordToComplete,
                        $commandAst,
                        $fakeBoundParameters )

                $possibleValues = @{
                    Fruits = @('Apple', 'Orange', 'Banana')
                    Vegetables = @('Onion', 'Carrot', 'Lettuce')
                }

                if ($fakeBoundParameters.ContainsKey('Type')) {
                    $possibleValues[$fakeBoundParameters.Type] | Where-Object {
                        $_ -like "$wordToComplete*"
                    }
                } else {
                    $possibleValues.Values | ForEach-Object {$_}
                }
            }

            function Test-ArgumentCompleter {
            [CmdletBinding()]
             param (
                    [Parameter(Mandatory=$true)]
                    [ValidateSet('Fruits', 'Vegetables')]
                    $Type,

                    [Parameter(Mandatory=$true)]
                    [ArgumentCompleter({ MyArgumentCompleter @args })]
                    $Value
                  )
            }

クラスベースの引数補完
    PowerShell 7.2 以降では、パラメーター化された引数補完を、より
    汎用的に実装できる新機能が追加されました。

    ArgumentCompleterAttribute から派生させることで、再利用可能な
    汎用的な補完を作成できます。たとえば次のとおりです。

        [DirectoryCompleter(ContainingFile="pwsh.exe", Depth=2)]

        [DateCompleter(WeekDay='Monday', From="LastYear")]

        [GitCommits(Branch='release')]

    派生した属性は IArgumentCompleterFactory インターフェイスを実装し、
    プロパティ値を使って専用の補完を作成する必要があります。

        using namespace System.Collections
        using namespace System.Collections.Generic
        using namespace System.Management.Automation
        using namespace System.Management.Automation.Language

        class NumberCompleter : IArgumentCompleter {

            [int] $From
            [int] $To
            [int] $Step

            NumberCompleter([int] $from, [int] $to, [int] $step) {
                if ($from -gt $to) {
                    throw [ArgumentOutOfRangeException]::new("from")
                }
                $this.From = $from
                $this.To = $to
                $this.Step = $step -lt 1 ? 1 : $step
            }

            [IEnumerable[CompletionResult]] CompleteArgument(
                [string] $CommandName,
                [string] $parameterName,
                [string] $wordToComplete,
                [CommandAst] $commandAst,
                [IDictionary] $fakeBoundParameters) {

                $resultList = [List[CompletionResult]]::new()
                $Local:to = $this.To
                $Local:step = $this.Step
                for ($i = $this.From; $i -lt $to; $i += $step) {
                    $resultList.Add([CompletionResult]::new($i.ToString()))
                }

                return $resultList
            }
        }

        class NumberCompletionsAttribute : ArgumentCompleterAttribute, IArgumentCompleterFactory {
            [int] $From
            [int] $To
            [int] $Step

            NumberCompletionsAttribute([int] $from, [int] $to, [int] $step) {
                $this.From = $from
                $this.To = $to
                $this.Step = $step
            }

            [IArgumentCompleter] Create() { return [NumberCompleter]::new($this.From, $this.To, $this.Step) }
        }

    PowerShell からの使用例は次のとおりです。

        function Add{
            param(
               [NumberCompletions(0, 100, 5)]
               [int] $X,

               [NumberCompletions(0, 100, 5)]
               [int] $Y
            )
            $X + $Y
        }

Register-ArgumentCompleter
    Register-ArgumentCompleter コマンドレットは、カスタムの引数補完を
    登録します。引数補完を使うと、指定した任意のコマンドに対して、
    実行時に動的なタブ補完を提供できます。

    詳しくは、Register-ArgumentCompleter を参照してください。

関連項目
    about_Functions_Advanced_Parameters
    about_Tab_Expansion
    Register-ArgumentCompleter

----
原文: PowerShell-Docs (CC BY 4.0) の翻訳 / PSHelpJaJP