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

Support Fish Shell Suggestions #1173

Open
slang25 opened this issue Jan 26, 2021 · 4 comments
Open

Support Fish Shell Suggestions #1173

slang25 opened this issue Jan 26, 2021 · 4 comments
Labels
Area-Completions Related to support for tab completion enhancement New feature or request

Comments

@slang25
Copy link

slang25 commented Jan 26, 2021

It would be great if Fish was added to the supported shells for dotnet-suggest as documented here.

@slang25
Copy link
Author

slang25 commented Jan 26, 2021

Could someone please add the shell suggestion label please 🙂

@jonsequitur jonsequitur added Area-Completions Related to support for tab completion enhancement New feature or request labels Jan 26, 2021
@deg0nz
Copy link

deg0nz commented Apr 13, 2022

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 file autocompletion because of --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.
  • No possibility for adding descriptions later, because we would need one complete command per argument suggestion for this, which is currently blocked because we deliver the current arguments ourselves
  • Edit: I also found out, that -? and /? still have the question marks escaped, I will check how I can get rid of that

Additional thoughs about this

Note: 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

@jonsequitur
Copy link
Contributor

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.

@deg0nz
Copy link

deg0nz commented Apr 26, 2022

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:

Screenshot 2022-04-26 at 12 40 50

And fish is also able to distinguish between subcommands and flags like so:

Screenshot 2022-04-26 at 12 42 32

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Completions Related to support for tab completion enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants