【问题标题】:Tab-complete a parameter value based on another parameter's already specified value基于另一个参数的已经指定的值来完成一个参数值
【发布时间】:2021-01-25 21:15:38
【问题描述】:

这个自我回答的问题解决了以下场景:

  • 给定命令的自定义 tab-completion 是否可以根据先前在同一命令行上传递给 another 参数的值动态确定完成,使用参数级[ArgumentCompleter()] 属性 还是Register-ArgumentCompleter cmdlet

  • 如果是这样,这种方法的局限性是什么?

示例场景:

假设的Get-Property 命令有一个-Object 参数,它接受任何类型的对象,还有一个-Property 参数,它接受要从对象中提取其值的属性的名称。

现在,在键入 Get-Property 调用的过程中,如果已经为 -Object 指定了值,则制表符完成 -Property 应该循环遍历指定对象的(公共)属性的名称。

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

Get-Property -Object $obj -Property # <- pressing <tab> here should cycle
                                    # through 'foo', 'bar', 'baz'

【问题讨论】:

    标签: powershell dynamic tab-completion


    【解决方案1】:

    以下解决方案使用特定于参数的[ArgumentCompleter()] 属性作为Get-Property 函数本身定义的一部分,但该解决方案类似地适用于通过Register-CommandCompleter cmdlet 单独定义自定义完成逻辑。

    限制

    • PowerShell 调用的自定义完成脚本块 ({ ... }) 基本上只能看到通过参数指定的值,而不是通过管道 .

      • 也就是说,如果您键入Get-Property -Object $obj -Property &lt;tab&gt;,脚本块可以确定$obj 的值将绑定到-Object 参数,但这不适用于
        $obj | Get-Property -Property &lt;tab&gt; (即使-Object 被声明为管道绑定)。
    • 即使在通过参数指定的那些值中,只有可以评估的值没有副作用实际上可以在脚本块中访问;具体来说,这意味着:

      • 文字值(例如,-Object ([pscustomobject] @{ foo = 1; bar = 2; baz = 3 })
      • 简单的变量引用(例如,-Object $obj)或 property-accessindex-access 表达式(例如,-Object $obj.Foo-Object $obj[0] )
      • 值得注意的是,不可访问以下值:
        • 方法-调用结果(例如,-Object $object.Foo()
        • 命令输出(通过(...)$(...)@(...),例如
          -Object (Invoke-RestMethod http://example.org)
        • 此限制的原因是,在实际提交命令之前评估此类值可能会产生不良副作用和/或可能需要很长时间才能完成。
    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
    
      )
    
      # ...
    
    }
    

    【讨论】:

      猜你喜欢
      • 2014-07-11
      • 2019-02-04
      • 1970-01-01
      • 2013-05-20
      • 1970-01-01
      • 2021-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多