Open slang25 opened 3 years ago
Could someone please add the shell suggestion
label please 🙂
Hi,
I spent the last two evenings on writing a shim script for fish
that provides basic completion. I used the zsh
shim script as a basis.
Here it is:
# dotnet suggest shell complete script start
function _dotnet_fish_complete
# Get current content of the command line
set --local cmd_line (commandline --current-process --tokenize --cut-at-cursor)
# Get full path to script because dotnet-suggest needs it
# NOTE: this requires a command registered with dotnet-suggest be on the PATH
set --local full_path (which $cmd_line[1]) # fish arrays are 1-indexed
# Get the completion results, will be newline-delimited
# `string collect` is used to receive multiline input and leave it like this
set --local completions (dotnet-suggest get --executable "$full_path" -- "$cmd_line" | string collect)
# Return list of completions as content for `complete --arguments`
echo $completions
end
# Apply this function to each command the dotnet-suggest knows about
function _register_dotnet_completions
for cmd in (dotnet-suggest list)
# This is a workaround for the fact that Fish is missing something like compdef (zsh) or complete -F (bash)
# It calls _dotnet_fish_complete when tabbing the respective command,
# which then fills --arguments with a list of the current suggestions generated by `dotnet-suggest`
complete --no-files --command $cmd --arguments '(_dotnet_fish_complete)'
end
end
# Call register function
_register_dotnet_completions
set -x DOTNET_SUGGEST_SCRIPT_VERSION "1.0.0"
# dotnet suggest shell complete script end
However, since the fish
completion system is mightier than the ones of other shells, this is not adequate imho. It only delivers a very basic completion style. But it's better than nothing for now.
It also comes with the following caveats:
--no-files
in the "register" command. I turned this on, because if you don't have it, your completion suggestions are mixed with the files of the current directory which is confusing.complete
command per argument suggestion for this, which is currently blocked because we deliver the current arguments ourselves-?
and /?
still have the question marks escaped, I will check how I can get rid of thatNote: For better understanding how fish
completions usually work, here is an example for the dotnet-suggest --help
flag, which would then represent one suggestion item:
complete --short h --long help --description "Show help and usage information"
A more fish
-agnostic way would be to generate real fish
completion files for every command (Edit: examples); containing all the bells and whistles (--short
, --long
, Files yes/no, --description
, subcommand distinction ...) for each argument and subcommand and put them into the right folder. Of course this also comes with the caveat that one has to generate all these scripts again when anything in the CLI changes. But this is something you have to deal with when using fish
either way. So there should be a possibility for developers using System.CommandLine.Suggestions
to generate a completion file for their program.
This would probably also mean that one would need to touch System.CommandLine.Suggestions
to add a generator class (which would probably not be that big, the Rust clap CLI library one is not even 200 lines long), but that is a descision the maintainers have to make.
Another alternative would be to write a sophisticated fish
script for this that would be quite big (which wouldn't be a big deal, because one should but this script to ~/.config/fish/functions/
and just call the register function in ~/.config/fish/config.fish
-- what would be a big deal though, is the shell start time when generating all the scripts for the first time)
I'm also still wrapping my head around how one could achieve this dynamically by constructing the right complete
commands for every suggestion item, but I wasn't able to find a way that tells fish
to use a function for completions.
(I was also wondering where the correct fish
-agnostic completions for the dotnet
command come from on my system, but it seems that they are shipped with fish
itself)
Edit: grammar, typos
Thanks, @deg0nz! Would you be open to submitting a pull request?
However, since the fish completion system is mightier than the ones of other shells, this is not adequate imho. It only delivers a very basic completion style. But it's better than nothing for now.
Can you provide some additional details or screenshots here? Are there features that System.CommandLine appears to be missing to provide this experience? We've recently made its completion model richer, though dotnet-suggest
doesn't expose this yet.
We've also been discussing how best to support richer scripts for specific shells, including approaches like generating scripts that handle many completions without needing to call dotnet-suggest
.
Regarding file completions, we're planning to include better support for including them in the default System.CommandLine completions (#1697), but as you pointed out this is also an area where specific shells might have better approaches. It's just a bit more work to do something different for each shell and community involvement will be important.
Hey, @jonsequitur
Would you be open to submitting a pull request?
Sure, can do. I have no experience in dotnet
but I will just orientate on the zsh
shim PR, that looks pretty straightforward.
Can you provide some additional details or screenshots here? Are there features that System.CommandLine appears to be missing to provide this experience? We've recently made its completion model richer, though dotnet-suggest doesn't expose this yet.
I tried to explain that in the "additional thoughts" section above. What I meant by that was just the fact that fish
actually needs dedicated completion scripts to use the full potential of it's completion system.
Fish suggestions actually look like this:
And fish is also able to distinguish between subcommands and flags like so:
Those completions rely on more or less complex completion scripts as you can see here in the official Git completion file (This is a very complex example though...)
When you look at the complete
commands from line 839 onwards, you can see that every option has it's own entry including the description. So the shim script I wrote above is just a dirty workaround to provide suggestions offered by dotnet-suggest
to the user, since only 1 complete is used that is filled with the output of dotnet-suggest
.
We've also been discussing how best to support richer scripts for specific shells, including approaches like generating scripts that handle many completions without needing to call dotnet-suggest.
This is exactly what I meant :) So yeah, until completion-script-generators get implemented the shim script above will suffice as basic completion helper I think.
It would be great if Fish was added to the supported shells for
dotnet-suggest
as documented here.