如何修改PowerShell制表符完成功能,使某些文件类型优先于其他文件类型?

guz6ccqo  于 2023-03-12  发布在  Shell
关注(0)|答案(1)|浏览(140)

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

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

当我将cd输入此目录并键入.\,然后按Tab键时,PowerShell将按以下顺序自动完成文件:

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

因为默认情况下,提示符会按字母顺序遍历目录中的所有文件。
我希望它在提示我可执行文件之前提示我任何其他文件,即:

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

我该怎么做呢?

0md85ypi

0md85ypi1#

您需要替换用于制表符完成的默认PowerShell函数mostly-undocumented TabExpansion2,您可以通过运行get-content function:global:tabexpansion2获得其内容。
由于此函数的内容在您的系统上可能有所不同,因此我不会完整地展示它,只会展示相关部分,即返回计算的制表符完成可能性(这来自运行在Windows 10 21 H2 x64上的PowerShell Core 7.3.2 x64):

... start 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修改为:

... start of 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, $nonExeMatches = $completion.CompletionMatches
        .Where({$_.CompletionText -Like "*.exe"}, "Split")
    $completion.CompletionMatches = @($exeMatches) + @($nonExeMatches)

    return $completion
}

其实很简单

  • 我们使用幻数Where方法来过滤CommandCompletion已经为我们填充的CompletionMatches集合,将其分成包含找到的可执行匹配项的一部分和包含剩余匹配项的另一部分
  • 我用排序后的匹配项覆盖默认的完成匹配项,将EXE匹配项放在第一位,以便它们首先显示,并确保我们使用数组构造函数来克服PowerShell的causing problems by silently returning a single item instead of an array倾向
  • 返回完成

将更新后的TabCompletion2安装到我们的配置文件中,然后通过键入.$profile并按Enter键重新加载所述配置文件,键入.\并按Tab键,现在会产生所需的结果:

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

相关问题