cobra: shell completions do not expand ~ or environment variables
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 the ValidArgsFunction.
For example, if the user types the following to trigger shell completion:
$ command arg ~/.z<tab>
ValidArgsFunction is called with the toComplete argument equal to ~/.z. The tilde expansion should be done before this, i.e. the toComplete 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 the toComplete 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 to ValidArgsFunction.
The expansion of ~ and environment variables must be done in the fish shell itself. It cannot be done by the ValidArgsFunction because:
- The value of environment variables might not be known. For example, if
toCompletecontains an unexported environment variable then its value is not available to the process executingValidArgsFunction. - The exact interpretation of
~depends on the shell. Example common interpretations include~for the user’s home directory,~/filefor a file in the user’s home directory,~usernamefor a different user’s home directory, and~username/filefor a file in a different user’s home directory. It is unreasonable for theValidArgsFunctionto emulate fish’s behavior exactly. - As the fish completions behave differently to other shell completions, implementing fish’s logic in
ValidArgsFunctionwould break other shell completions.
Refs https://github.com/twpayne/chezmoi/issues/1796#issuecomment-1008247269.
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 16 (9 by maintainers)
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: https://github.com/spf13/cobra/blob/e04ec725508c760e70263b031e5697c232d5c3fa/fish_completions.go#L36
We made this choice willingly but I didn’t realize the impact it would have. See this comment https://github.com/spf13/cobra/pull/1249#discussion_r563348012
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
~are not expanded, file completion still works from the user’s perspective. I’m assuming the problem is for the program receiving this unexpanded argument.I don’t think this issue is stale. On the contrary, it communicates a genuine problem that still exists and should not be forgotten.
This issue is being marked as stale due to a long period of inactivity
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
completioncommand to generate the fish completion file. Ensure thatprogis in your$PATH.I see the following in
$BASH_COMP_DEBUG_FILE:Note that
toCompleteis$HOME/, i.e. the$HOMEenvironment variable has not been expanded.Modified Go code: