Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
269 views
in Technique[技术] by (71.8m points)

powershell - Tab-complete a parameter value based on another parameter's already specified value

This self-answered question addresses the following scenario:

  • Can custom tab-completion for a given command dynamically determine completions based on the value previously passed to another parameter on the same command line, using either a parameter-level [ArgumentCompleter()] attribute or the Register-ArgumentCompleter cmdlet?

  • If so, what are the limitations of this approach?

Example scenario:

A hypothetical Get-Property command has an -Object parameter that accepts an object of any type, and a -Property parameter that accepts the name of a property whose value to extract from the object.

Now, in the course of typing a Get-Property call, if a value is already specified for -Object, tab-completing -Property should cycle through the names of the specified object's (public) properties.

$obj = [pscustomobject] @{ foo = 1; bar = 2; baz = 3 }

Get-Property -Object $obj -Property # <- pressing <tab> here should cycle
                                    # through 'foo', 'bar', 'baz'
question from:https://stackoverflow.com/questions/65892518/tab-complete-a-parameter-value-based-on-another-parameters-already-specified-va

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The following solution uses a parameter-specific [ArgumentCompleter()] attribute as part of the definition of the Get-Property function itself, but the solution analogously applies to separately defining custom-completion logic via the Register-CommandCompleter cmdlet.

Limitations:

  • The custom-completion script block ({ ... }) invoked by PowerShell fundamentally only sees values specified via parameters, not via the pipeline.

    • That is, if you type Get-Property -Object $obj -Property <tab>, the script block can determine that the value of $obj is to be bound to the -Object parameter, but that wouldn't work with
      $obj | Get-Property -Property <tab> (even if -Object is declared as pipeline-binding).
  • Even among those values specified via parameters, only values that can be evaluated without side effects are actually accessible in the script block; in concrete this terms, this means:

    • Literal values (e.g., -Object ([pscustomobject] @{ foo = 1; bar = 2; baz = 3 })
    • Simple variable references (e.g., -Object $obj) or property-access or index-access expressions (e.g., -Object $obj.Foo or -Object $obj[0])
    • Notably, the following values are not accessible:
      • Method-call results (e.g., -Object $object.Foo())
      • Command output (via (...), $(...), or @(...), e.g.
        -Object (Invoke-RestMethod http://example.org))
      • The reason for this limitation is that evaluating such values before actually submitting the command could have undesirable side effects and / or could take a long time to complete.
function Get-Property {

  param(

    [object] $Object,

    [ArgumentCompleter({

      # A fixed list of parameters is passed to an argument-completer script block.
      # Here, only two are of interest:
      #  * $wordToComplete: 
      #      The part of the value that the user has typed so far, if any.
      #  * $preBoundParameters (called $fakeBoundParameters 
      #    in the docs):
      #      A hashtable of those (future) parameter values specified so 
      #      far that are side effect-free (see above).
      param($cmdName, $paramName, $wordToComplete, $cmdAst, $preBoundParameters)

        # Was a side effect-free value specified for -Object?
        if ($obj = $preBoundParameters['Object']) {

          # Get all property names of the objects and filter them
          # by the partial value already typed, if any, 
          # interpreted as a name prefix.
          @($obj.psobject.Properties.Name) -like "$wordToComplete*"

        }
      })]
    [string] $Property

  )

  # ...

}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...