此问题解决以下情况:
- 给定命令的自定义制表符完成功能是否可以使用参数级
[ArgumentCompleter()]
* 属性 * 或Register-ArgumentCompleter
* cmdlet *,根据先前传递给同一命令行上的 * another * 参数的值动态确定完成? - 如果是,这种方法的局限性是什么?
场景示例:
假设的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'
2条答案
按热度按时间eyh26e7m1#
@mklement0,关于your answer中规定的第一个限制
PowerShell调用的自定义完成脚本块(
{ ... }
)基本上只能看到通过 * 参数 * 指定的值,而不能看到通过管道指定的值。我为此而挣扎,经过一番固执之后,我找到了一个可行的解决方案。
至少对我的工具来说已经足够好了,我希望它能让其他许多人的生活更轻松。
此解决方案经验证可与PowerShell版本
5.1
和7.1.2
配合使用。这里我使用了
$cmdAst
(在文档中称为$commandAst
),其中包含有关管道的信息。有了它,我们可以了解前面的管道 * 元素 *,甚至可以区分它只包含变量还是命令。是的,COMMAND,它在Get-Command
和命令的OutputType()
成员方法的帮助下,我们可以得到(建议的)属性名称等!用法示例
功能代码
请注意,除了现在使用
$cmdAst
之外,我还添加了[Parameter(ValueFromPipeline=$true)]
,以便我们实际选取对象,以及PROCESS {$Object.$Property}
,以便可以测试并查看代码实际工作。i7uq4tfw2#
更新:请参见betoz's helpful answer,了解更完整的解决方案,该解决方案还支持 * 管道输入 *。
下面的回答部分阐明了输入对象数据类型的执行前检测的限制,这一部分仍然适用。
以下解决方案使用特定于参数的
[ArgumentCompleter()]
属性作为Get-Property
函数本身定义的一部分,但该解决方案类似地适用于通过Register-CommandCompleter
cmdlet单独定义自定义完成逻辑。限制:
{ ... }
)基本上只能看到通过 * 参数 * 指定的值,而不能 * 通过管道指定的值。Get-Property -Object $obj -Property <tab>
,脚本块可以确定$obj
的值将绑定到-Object
参数,但这不适用于$obj | Get-Property -Property <tab>
(即使-Object
声明为管道绑定)。-Object ([pscustomobject] @{ foo = 1; bar = 2; baz = 3 })
-Object $obj
)或 * 属性访问 * 或 * 索引访问 * 表达式(例如-Object $obj.Foo
或-Object $obj[0]
)-Object $object.Foo()
)(...)
、$(...)
或@(...)
,例如1米17分1秒)