vscode-powershell icon indicating copy to clipboard operation
vscode-powershell copied to clipboard

Add option to filter out file/folder suggestions when completions are automatically triggered by a space

Open MartinGC94 opened this issue 1 year ago • 1 comments

Prerequisites

  • [X] I have written a descriptive issue title.
  • [X] I have searched all issues to ensure it has not already been reported.

Summary

I think the constant file/folder completion suggestions are distracting and I'd like to reduce those distractions. For example, if I type in a command like: Clear-Disk -Number 0 -RemoveData -RemoveOEM it will show unwanted file completions 4 times, once after the command and once for every space after each parameter/parameter value.
If you repeat this experiment in ISE you will note that it doesn't show any file completions. This is because ISE filters out file/folders from the automatic IntelliSense that is triggered by space.

Ideally something would be done about this in PowerShell itself to but unfortunately support for 5.1 has to be considered as well so adding an option in the extension would be nice.

Proposed Design

No response

MartinGC94 avatar Sep 30 '24 17:09 MartinGC94

As a workaround people can add this function to their $profile to filter out these file completion results:

function TabExpansion2
{
    <# Options include:
         RelativeFilePaths - [bool]
             Always resolve file paths using Resolve-Path -Relative.
             The default is to use some heuristics to guess if relative or absolute is better.

       To customize your own custom options, pass a hashtable to CompleteInput, e.g.
             return [System.Management.Automation.CommandCompletion]::CompleteInput($inputScript, $cursorColumn,
                 @{ RelativeFilePaths=$false }
    #>

    [CmdletBinding(DefaultParameterSetName = 'ScriptInputSet')]
    [OutputType([System.Management.Automation.CommandCompletion])]
    Param(
        [Parameter(ParameterSetName = 'ScriptInputSet', Mandatory = $true, Position = 0)]
        [AllowEmptyString()]
        [string] $inputScript,

        [Parameter(ParameterSetName = 'ScriptInputSet', Position = 1)]
        [int] $cursorColumn = $inputScript.Length,

        [Parameter(ParameterSetName = 'AstInputSet', Mandatory = $true, Position = 0)]
        [System.Management.Automation.Language.Ast] $ast,

        [Parameter(ParameterSetName = 'AstInputSet', Mandatory = $true, Position = 1)]
        [System.Management.Automation.Language.Token[]] $tokens,

        [Parameter(ParameterSetName = 'AstInputSet', Mandatory = $true, Position = 2)]
        [System.Management.Automation.Language.IScriptPosition] $positionOfCursor,

        [Parameter(ParameterSetName = 'ScriptInputSet', Position = 2)]
        [Parameter(ParameterSetName = 'AstInputSet', Position = 3)]
        [Hashtable] $options = $null
    )

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

            if ($Out.CompletionMatches.Count -gt 0 -and
                $ast.Extent.Text[$positionOfCursor.Offset - 1] -eq ' ' -and
                ($Out.CompletionMatches[0].ResultType -eq [System.Management.Automation.CompletionResultType]::ProviderContainer -or
                $Out.CompletionMatches[0].ResultType -eq [System.Management.Automation.CompletionResultType]::ProviderItem))
            {
                $Out.CompletionMatches = $Out.CompletionMatches | Where-Object -FilterScript {
                    $_.ResultType -ne [System.Management.Automation.CompletionResultType]::ProviderContainer -and
                    $_.ResultType -ne [System.Management.Automation.CompletionResultType]::ProviderItem
                }
            }

            $Out
        }
    }
}

The magic is in the else condition where I check if there was a space where the completion was triggered, and if so, filter out file/folder completions from the matches. This means you can still get the completions if you start typing out a path: ls -path C:\ you just won't get them without any partial input: ls -path <Tab>. And because it's only files/folders you still get relevant completions when it's an enum like: ls -ErrorAction <Tab>.

MartinGC94 avatar Jun 26 '25 09:06 MartinGC94