Open banbh opened 4 years ago
A couple of things to check.
Does .\DragonFruit [suggest] --f
return results? If so, your app is able to return completions.
If you cat $profile
in the PowerShell instance where you're expecting completions, do the contents contain the completions shim script? (Different profiles in different contexts has bitten me a few times.)
Thanks. For the experiments below I started a (PowerShell) terminal from VS2019 (View -> Terminal) and then changed directory all the way down to the notcoreapp3.1
containing the exe.
When I execute .\DragonFruit [suggest] --f
I get --foo
(which seems correct). cat $profile
seems be correct.
This comment describes an approach to debugging this if you'd like to give it a try:
https://github.com/dotnet/command-line-api/issues/794#issuecomment-600601807
I followed the instructions in the comment to #749 that you referenced, and I think it gives some insight into what is happening. Since I'm not certain I know what I'm doing, below are the explicit steps I followed.
I cloned https://github.com/dotnet/command-line-api.git
and made a Debug build. Back in the DragonFruit terminal, I prepended the artifact directory (namely, C:\Users\MYUSERNAME\git\command-line-api\artifacts\bin\dotnet-suggest\Debug\netcoreapp3.1
) to my path. At this point dotnet-suggest --version
returns 1.1.0-dev
(as expected). Next I set $env:DOTNET_SUGGEST_LOGGING=1
. At this point dotnet-suggest --v<TAB>
autocompletes to dotnet-suggest --version
and the logfile (C:\Users\MYUSERNAME\AppData\Roaming\dotnet-suggest\debug.log
) has the following lines appended.
dotnet-suggest received: |get|-e|C:\Users\MYUSERNAME\git\command-line-api\artifacts\bin\dotnet-suggest\Debug\netcoreapp3.1\dotnet-suggest.exe|--position|18|--|dotnet-suggest --v
dotnet-suggest sending: [suggest:3] "--v"
dotnet-suggest received: |[suggest:3]|--v
dotnet-suggest returning: "--version"
As best as I can tell this is all as expected. Finally I did .\DragonFruit.exe --fo<TAB>
; this resulted in no autocompletion, and nothing appeared in the logfile.
From this is it seems like the "ArgumentCompleter" is simply not being called for my DragonFruit executable.
Below are some comments which probably won't directly help to resolve this issue, but might help me understand what is going on.
In trying to understand how this functionality is supposed to work a portion of the story I was confused by is what exactly is getting registered by the powershell shim. It seems to register (via Register-ArgumentCompleter
) a script block to figure out the completions for a set of commands, namely dotnet-suggest
and dotnet suggest
. However the command that needs a suggestion is actually (in my case) .\DragonFruit.exe
. Is what's happening that a <TAB>
gets translated into a dotnet suggest ...
which then is intercepted by the registered ArgumentCompleter?
Not quite. Register-ArgumentCompleter
called once for each executable registered by RegisterWithDotnetSuggest
. But my memory is that this also should work with the executable directly.
Also, which versions of System.CommandLine
and dotnet-suggest
are you using?
I'm actually seeing the same issue with the Sample Command Line app on macOS/bash.
My own application does have auto-complete working for somethings. But it crashes with arithmetic overflow in a call to MaximumArgumentCapacity(). (This is sorta obvious to see if you look at the method which adds up all the maximum values of all arguments. If at least one is OneOrMore and then you have other arguments, you'll overflow. I created #997 to document this.) While trying to get this down to a minimal reproducible example I tried the sample CommandLine app. I don't get any suggestions for any of the options.
I did try app [suggest] -f
and got back --file-option
. But if I type tab after -f I get nothing.
I'll take a look at the suggestions in this thread to see if I can learn anything else.
Regarding MaximumArgumentCapacity(): https://github.com/dotnet/command-line-api/blob/d4f3327d62d3faa8e35bc11d0df86bc92fd881e1/src/System.CommandLine/Parsing/SymbolResult.cs#L47-L49 you can see that if you have a ZeroOrMore or a OneOrMore and then at least one ExactlyOne you'll get overflow. But typically this wouldn't throw an exception (but likely it would be a defect). I'm trying to reproduce why I'm getting an exception and will open a new issue if/when I do.
My DragonFruit app uses System.CommandLine.DragonFruit
version 0.3.0-alpha.20371.2
(which, in turn, depends on System.CommandLine
version 2.0.0-beta1.20371.2
).
The version of dotnet-suggest
I was initially using was 1.1.137102+f2556cacb35c0b68201d73eaf1c0df8c5e57e43e
but then for the Debug build I cloned 1.1.0-dev
.
But it crashes with arithmetic overflow in a call to MaximumArgumentCapacity(). (This is sorta obvious to see if you look at the method which adds up all the maximum values of all arguments. If at least one is OneOrMore and then you have other arguments, you'll overflow. )
@michaelgwelch Yeah that's a pretty clear bug.
So I have a root command and one subcommand. The root command has no arguments or options (other than the "built-ins").
The name of my tool is enuf
and the one subcommand is lookup
So when I type
> enuf <tab>
I see
enuf
--help
--version
-?
-h
/?
/h
lookup
So it's working. And the log file agrees with this.
Now I have one argument for lookup
command. I never see any suggestions
> enuf lookup <tab>
But the log shows that there are suggestions:
dotnet-suggest received: |get|--executable|/Users/mgwelch/.dotnet/tools/enuf|--position|12|--|enuf lookup
dotnet-suggest sending: [suggest:7] "lookup "
dotnet-suggest returning: "--help\n-?\n-h\n/?\n/h\nattributeCategoryEnumSet\nattributeEnumSet"
(Sometimes it throws all the root level built-in switches into the list and some times it doesn't.)
If I explicitly ask for suggestions using directive
> enuf [suggest] lookup
Nothing is returned.
I wonder whether someone could explain how one aspect of the PowerShell completion architecture works. Concretely, suppose I clone the command-line-api
repo, build it, open a PowerShell in the directory with the DragonFruit
exe, and type (say) .\DragonFruit --f<TAB>
(which, incidentally still produces nothing). How is this supposed to result in suggestions being generated? I assume hitting <TAB>
is supposed to cause dotnet-suggest get ...
to be executed; but what is the mechanism for that to happen?
In contrast, if I type dotnet-suggest <TAB>
(which does work) then I understand the pathway (namely, the shim in my profile has already registered an ArgumentCompleter
for the command dotnet-suggest
; since I just typed that command it fires off a request to dotnet-suggest get ...
). But, returning to DragonFruit, how does PowerShell know it's supposed to call dotnet get
when presented with .\DragonFruit
? It's as if what is needed is a (hypothetical) call to Register-Argument-Completer -Native -Command "*" ...
(meaning try to complete anything with ...
).
[By the way, following the explanation of @jonsequitur, I have verified that RegisterWithDotnetSuggest
does get called successfully when (say) .\DragonFruit [suggest]
is called. In fact if you delete the sentinel file then I can see dotnet-suggest register ...
being called. In short, as far as I can tell, everything is working the way it's supposed to (IMO) except that nothing causes dotnet-suggest get ...
to fire for random executables like .\DragonFruit
.]
If I explicitly ask for suggestions using directive
enuf [suggest] lookup Nothing is returned.
Directives are only valid as the first token in the command line, so this wouldn't be expected to work. The following should:
> [suggest] enuf lookup
I created a simple DragonFruit console app, then followed the instructions in https://github.com/dotnet/command-line-api/wiki/dotnet-suggest (and resolved the execution policy issues in 64- and 32-bit) then I opened a "Developer Powershell" from Visual Studio, change directory to where the exe is and typed
.\DragonFruit --f<TAB>
(my Main method has anint foo
argument) however it did not autocomplete (instead nothing happens). Things like.\DragonFruit -h
work as expected. Also$availableToComplete
is given a value during startup, namely "dotnet-suggest\ndotnet suggest".How can I debug this?