Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PsfArgumentCompleter behaviour not consistant with original ArgumentCompleter #638

Closed
azra1l opened this issue Aug 27, 2024 · 5 comments
Closed

Comments

@azra1l
Copy link

azra1l commented Aug 27, 2024

I so far used the original ArgumentCompleter to manage my tab completion, and am aiming to replace those with PsfArgumentCompleter, to make things more readable and easier to manage.

Unfortunately, i am facing wierd behaviour and i am hoping to get some insight here, as the documentation doesn't really explain much. Especially the PsfArgumentCompleter Parameter is not documented at all, i just adopted what i found in some builtin psf functions, so there might be something wrong with that. But i get the same behaviour if i use the Register-PSFTeppArgumentCompleter command, which is documented and supposed to achieve the same result if i am not mistaken?

Anyways, I've sketched up this test example, which does reproduce the issue on my end with PSFramework versions 1.9.310 and 1.11.343.

First, register a psf tepp scriptblock

Register-PSFTeppScriptblock -Name 'Test.PSFTepp' -ScriptBlock {
    @("XYZ","123","ABC") | Where-Object { $_ -like "*$($WordToComplete.trim("'"))*" } | ForEach-Object { "'$($_)'" }
}

Second, make a script to compare it to an original ArgumentCompleter with identical setup.

Param (
        [Parameter(Mandatory = $True, Position = 0)]
        [ArgumentCompleter(
            {
                Param($CommandName, $ParameterName, $WordToComplete, $CommandAst, $FakeBoundParameters)
                @("XYZ","123","ABC") | Where-Object { $_ -like "*$($WordToComplete.trim("'"))*" } | ForEach-Object { "'$($_)'" }
            }
        )]
        [String] $TestParam1,

        [Parameter(Mandatory = $True, Position = 1)]
        [PsfArgumentCompleter('Test.PSFTepp')]
        [String] $TestParam2
)

$TestParam1
$TestParam2

For me,
TestParam1 expands like expected, in the order provided. If i tab through, i get 'XYZ', '123' and 'ABC'. If i type ab and hit tab, it will expand to 'ABC'.
TestParam2 expands in alphabetic order, and it doesn't pick up typed values, unless i write * at the beginning. If i type *ab, it will expand to 'ABC'. Wierdly enough, not if i type ab*, which would actually make more sense.

My expectation here was, since the tepp scriptblock does support all the special variables from the original argumentcompleter, it would also behave the same given an identical scriptblock.

So my question here is, is this behaviour "working as intended?"
Or am i doing anything wrong?

@azra1l
Copy link
Author

azra1l commented Aug 27, 2024

~Update

i tried this,

Register-PSFTeppScriptblock -Name 'Test.PSFTepp' -ScriptBlock {
    @("XYZ","123","ABC")
}

And that appears to work. So PsfArgumentCompleter already does implement the $WordToComplete Filter mechanism and somehow doesn't like it if i bring my own.

@azra1l azra1l closed this as completed Aug 27, 2024
@azra1l azra1l reopened this Aug 27, 2024
@azra1l
Copy link
Author

azra1l commented Aug 27, 2024

~Another Update

Would it be possible to implement the $WordToComplete.trim("'") i showcased above?
This would allow to also consider typed values that already have quotes around them.

f.e. if it expanded some value, but i actually want a totally different value, so i can delete some chars and can tab again.

@FriedrichWeinmann
Copy link
Member

Heya @azra1l ,
as you noted, the system is designed to handle it all for you, so you don't have to bother (and sorry about the docs on the attribute - that came way later and I kind of forgot to add that to the docs at the time).

I could change the default behavior, yes. While I do have a "no breaking change" policy, as this only affects interactive execution in a non-intrusive way, I could add that to the next version.

In the meantime, you can work around this by disabling the assist system. This won't work with the attribute, but by assigning the completer it will work. At that point you are however back to pretty much the old ways and loose most of the benefits PSF actually brings to the completion table. Wouldn't recommend it and instead stick to the PSF way (but I'm somewhat biased):

Register-PSFTeppScriptblock -Name 'Test.PSFTepp' -ScriptBlock {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
    "XYZ","123","ABC" | Where-Object { $_ -like "*$($WordToComplete.trim("'"))*" } | ForEach-Object { "'$($_)'" }
} -Mode Full
Register-PSFTeppArgumentCompleter -Command Get-Test -Parameter TestParam2 -Name 'Test.PSFTepp'

function Get-Test {
[CmdletBinding()]
Param (
        [Parameter(Mandatory = $True, Position = 0)]
        [ArgumentCompleter(
            {
                Param($CommandName, $ParameterName, $WordToComplete, $CommandAst, $FakeBoundParameters)
                @("XYZ","123","ABC") | Where-Object { $_ -like "*$($WordToComplete.trim("'"))*" } | ForEach-Object { "'$($_)'" }
            }
        )]
        [String] $TestParam1,

        [Parameter(Mandatory = $True, Position = 1)]
        [String] $TestParam2
)
}

This will do the job, but ... yeah. not so great.

Will add the update to the pile for the next release :)

A quick extra ...

There are some fun features in PowerShell TabCompletion in general and the PSFramework version in particular, so let's make this a bit awesomer:

Register-PSFTeppScriptblock -Name 'Test.PSFTepp' -ScriptBlock {
    @{ Text = 'ABC'; ListItemText = 'DEF'; ToolTip = 'Take some awesome letters!' }
    @{ Text = '123'; ListItemText = '***'; ToolTip = 'Take some awesome numbers!' }
    @{ Text = 'XYZ'; ListItemText = 'XYZ'; ToolTip = 'The ListItemText is kind of pointless, right?' }
}
function Get-Test {
[CmdletBinding()]
Param (
        [Parameter(Mandatory = $True, Position = 0)]
        [ArgumentCompleter(
            {
                Param($CommandName, $ParameterName, $WordToComplete, $CommandAst, $FakeBoundParameters)
                @("XYZ","123","ABC") | Where-Object { $_ -like "*$($WordToComplete.trim("'"))*" } | ForEach-Object { "'$($_)'" }
            }
        )]
        [String] $TestParam1,

        [Parameter(Mandatory = $True, Position = 1)]
        [PsfArgumentCompleter('Test.PSFTepp')]
        [String] $TestParam2
)
}

Now tab completion will work as before, but CTRL+SpaceBar will be a bit more ... creative:

Get-Test -TestParam2 <CTRL+Space>

@FriedrichWeinmann
Copy link
Member

Alright, added a separate issue to track this, so I've got a clean tracking item:
#639
Feel free to follow that one in case you want to be notified when it's released (Not going to push for an immediate release, but it is going to be in the next one)

@azra1l
Copy link
Author

azra1l commented Aug 28, 2024

Holy cow, that was quick.

Yes, the tooltip stuff will definetly come in handy,
i have big plans for that, can't wait to see that in action.

Thanks for adding the feature request <3

@azra1l azra1l closed this as completed Aug 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants