-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
shell completions do not expand ~ or environment variables #1577
Comments
Thanks for the report @twpayne. I am not able to reproduce the problem. Which version of fish are you using and on which platform? I'm using fish 3.3.1 on MacOS. Here is a program to try to reproduce. I built it and then ran the following, which seems to expand properly:
|
I'm also using fish 3.3.1 on macOS installed with Homebrew.
This does not reproduce the problem because it does not invoke the tab completion logic in fish. To reproduce the problem, run the following with the modified Go code below. The modified Go code just adds a $ fish
$ prog completion > prog.fish # generate fish completion for prog
$ . prog.fish # source fish completion for prog
$ set -x BASH_COMP_DEBUG_FILE /tmp/bash-completion.log # enable fish completion debugging
$ prog $HOME/<tab><Ctrl-C> # invoke tab completion logic
$ cat $BASH_COMP_DEBUG_FILE # print debug file I see the following in
Note that Modified Go code: package main
import (
"fmt"
"os"
"github.com/spf13/cobra"
)
var rootCmd = &cobra.Command{
Use: "prog",
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
cobra.CompDebugln(fmt.Sprintf("args: %v, toComplete: %v", args, toComplete), true)
return nil, cobra.ShellCompDirectiveDefault
},
Run: func(cmd *cobra.Command, args []string) {},
}
var completionCmd = &cobra.Command{
Use: "completion",
RunE: func(cmd *cobra.Command, args []string) error {
return rootCmd.GenFishCompletion(os.Stdout, false)
},
}
func main() {
rootCmd.AddCommand(completionCmd)
rootCmd.Execute()
} |
For info, I've asked for help on fish's gitter. |
Sorry for getting back late. The problem is in the fact that cobra's fish script purposefully escapes the arguments, preventing them from being expanded by the shell. See here: Line 36 in e04ec72
We made this choice willingly but I didn't realize the impact it would have. See this comment #1249 (comment) I'll have to look into alternatives. @twpayne could you point me to the chezmoi code that has problems with this? I'm asking because although variables and |
The relevant code is here: https://github.com/twpayne/chezmoi/blob/v2.9.5/internal/cmd/config.go#L1954-L2001, but before you click on the link, please read the following. There's a bunch of project-specific code in here, but the short version is that chezmoi operates on a subset of files in the user's home directory and this code tries to only suggest autocompletion for files that chezmoi operates on, and not every possible file. Specific code blocks:
|
fish doesn't expand variables because the final completions should still have the variables.
the usual hack to support that in fish is to invoke
not sure how to integrate this into Cobra. The same hack can be used to implement other missing features: fish ships a helper |
Thank you for this insight @marckhouzam and @krobelus - it all makes sense now. Re:
I think that unexpand can be done precisely, without needing a heuristic. The rough plan would be something like:
Thoughts? |
From what I can see, this is fine. Remember that the Cobra completion script does not provide the completions itself but calls the program to get them. Therefore, when calling the program from the script, the variables could be expanded, while keeping them unexpanded for the script. The issue is that we escape the variables.
In the debug logs I now see what we want:
But to remove the @krobelus does this make sense, or am I confused? |
I don't think I had fully understood the situation. And I now better understand @krobelus explanation. Before continuing with the fish shell discussion, let's figure out if we may not have a larger "problem" which affects all shells. Let's take chezmoi as a concrete example, where I couldn't get things to work in any shell.
@twpayne I am missing something? |
I wouldn't use chezmoi as an example here. chezmoi is a medium-sized CLI with a few custom completion rules, written by someone who is not particularly familiar with shell completions. Instead, I would recommend using a minimal Go example, like the one that you wrote here. This will ensure that any problems are clearly attributable to cobra/shell completion code, instead of being attributable to the author of chezmoi :) I'd be happy to extend the minimal Go example to cover a few other cases (e.g. relative paths, absolute paths, custom argument completions, etc.) if that would be helpful. |
Ok, here is a minimal test program (see below). It has a
The problem is that the shell has The same thing happens in bash. So first question @twpayne is that I don't understand why you see a problem only with Program:
|
Thanks for the further investigation :)
The user reporting the problem was using fish, I didn't investigate other shells. Interesting that this seems to be a more general problem. I'll update the issue title. |
Makes sense 😀 This issue will require some thought. |
This issue is being marked as stale due to a long period of inactivity |
I don't think this issue is stale. On the contrary, it communicates a genuine problem that still exists and should not be forgotten. |
Closing due to inactivity. |
There's a proposed change to fish that will fix this issue. |
When using fish completions with a
cobra.Command.ValidArgsFunction
to specify custom completions, leading~
s and environment variables are not expanded before the argument to complete is passed to theValidArgsFunction
.For example, if the user types the following to trigger shell completion:
$ command arg ~/.z<tab>
ValidArgsFunction
is called with thetoComplete
argument equal to~/.z
. The tilde expansion should be done before this, i.e. thetoComplete
argument should be/home/user/.z
where/home/user
is the user's home directory.Similarly, if the user types:
$ command arg $SOME_VAR/.z
then
ValidArgsFunction
is called with thetoComplete
argument equal to$SOME_VAR/.z
. Instead,toComplete
should have the value with$SOME_VAR
expanded.This is different to other shell completions (e.g. zsh), where
~
and environment variables are expanded by the shell before being passed toValidArgsFunction
.The expansion of
~
and environment variables must be done in the fish shell itself. It cannot be done by theValidArgsFunction
because:toComplete
contains an unexported environment variable then its value is not available to the process executingValidArgsFunction
.~
depends on the shell. Example common interpretations include~
for the user's home directory,~/file
for a file in the user's home directory,~username
for a different user's home directory, and~username/file
for a file in a different user's home directory. It is unreasonable for theValidArgsFunction
to emulate fish's behavior exactly.ValidArgsFunction
would break other shell completions.Refs twpayne/chezmoi#1796 (comment).
The text was updated successfully, but these errors were encountered: