【问题标题】:How can I modify PowerShell tab-completion to proritise certain file types over others?如何修改 PowerShell 制表符补全功能,使某些文件类型优先于其他文件类型?
【发布时间】:2023-02-20 21:20:00
【问题描述】:

我有一个包含大量文件的目录:

a.json
b.dll
c.config
d.exe
...
z.exe

当我cd进入这个目录并输入.\然后按标签, PowerShell 按以下顺序自动完成文件:

> .\a.json
> .\b.dll
> .\c.config
> .\d.exe
> .\z.exe

因为默认情况下,提示符会按字母顺序遍历目录中的所有文件。

我希望它能在其他任何文件之前提示我可执行文件,即:

> .\d.exe
> .\z.exe
> .\a.json
> .\b.dll
> .\c.config

我怎样才能做到这一点?

【问题讨论】:

    标签: powershell tab-completion


    【解决方案1】:

    您需要替换用于 Tab 完成的默认 PowerShell 函数,即大部分未记录的 TabExpansion2,您可以通过运行 get-content function:global:tabexpansion2 获取其内容。

    因为此函数的内容在您的系统上可能有所不同,所以我不会完整地展示它,只展示相关部分,即返回计算出的选项卡完成可能性(这是来自运行在 PowerShell Core 7.3.2 x64 上的Windows 10 21H2 x64):

    ... rest of TabCompletion2...
    
    End
    {       
        if ($psCmdlet.ParameterSetName -eq 'ScriptInputSet')
        {
            return [System.Management.Automation.CommandCompletion]::CompleteInput(
                <#inputScript#>  $inputScript,
                <#cursorColumn#> $cursorColumn,
                <#options#>      $options)
        }
        else
        {
            return [System.Management.Automation.CommandCompletion]::CompleteInput(
                <#ast#>              $ast,
                <#tokens#>           $tokens,
                <#positionOfCursor#> $positionOfCursor,
                <#options#>          $options)
        }
    }
    

    两个代码路径都调用静态 System.Management.Automation.CommandCompletion.CompleteInput 方法,根据传递给 TabExpansion2 的参数使用该方法的不同版本。

    在这一点上,您可能认为我们需要深入研究这些方法的内部结构并调整它们以适应口味,但值得庆幸的是,情况并非如此。我们实际上不需要更改CommandCompletion.CompleteInput 的工作方式——我们只是想更改其建议的顺序。由于它已经完成了困难的工作,我们只需要重新排序!

    因此,将 TabCompletion2 修改为以下内容:

    End
    {
        if ($psCmdlet.ParameterSetName -eq 'ScriptInputSet')
        {
            $completion = [System.Management.Automation.CommandCompletion]::CompleteInput(
                <#inputScript#>  $inputScript,
                <#cursorColumn#> $cursorColumn,
                <#options#>      $options)
        }
        else
        {
            $completion = [System.Management.Automation.CommandCompletion]::CompleteInput(
                <#ast#>              $ast,
                <#tokens#>           $tokens,
                <#positionOfCursor#> $positionOfCursor,
                <#options#>          $options)
        }
    
        $exeMatches = $completion.CompletionMatches
            |Where-Object { $_.CompletionText -Like "*.exe" }
        $nonExeMatches = $completion.CompletionMatches
            |Where-Object { $_.CompletionText -NotLike "*.exe" }
        $allMatches = @($exeMatches) + @($nonExeMatches)
    
        $completion.CompletionMatches = $allMatches
    
        return $completion
    }
    

    它实际上非常简单:我们使用旧的 Where-Object cmdlet 来过滤 CommandCompletion 已经为我们填充的 CompletionMatches 集合,用我们排序的集合的结果覆盖这些默认匹配,然后返回它。

    将这个更新的TabCompletion2安装到我们的profile中,并在通过输入.$profile并按下重新加载所述配置文件后进入, 输入 . 并按下标签现在产生了期望的结果:

    > .d.exe
    > .z.exe
    > ..json
    > ..dll
    > .c.config
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-07
      • 1970-01-01
      • 2013-03-14
      • 2010-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多