cobra icon indicating copy to clipboard operation
cobra copied to clipboard

Shell completions with whitespace seem to work differently on bash vs. other supported shells

Open kangasta opened this issue 2 years ago • 7 comments

Other shell completions escape whitespace in completions, but bash completions seems to add completions with whitespace as multiple suggestions or multiple arguments depending on bash version. I would expect also bash completions to escape whitespace in completions from ValidArgsFunction.

bash v3:

$ ./sh-completion-demo whitespace [TAB][TAB]
no-whitespace    with whitespace
$ ./sh-completion-demo whitespace w[TAB]
$ ./sh-completion-demo whitespace with whitespace

bash v4 & v5

$ ./sh-completion-demo whitespace [TAB][TAB]
no-whitespace  whitespace     with 

fish:

> ./sh-completion-demo whitespace [TAB]
no-whitespace  with whitespace
> ./sh-completion-demo whitespace w[TAB]
> ./sh-completion-demo whitespace with\ whitespace

zsh:

% ./sh-completion-demo whitespace [TAB]
no-whitespace    with whitespace
% ./sh-completion-demo whitespace w[TAB]
% ./sh-completion-demo whitespace with\ whitespace

powershell

> .\sh-completion-demo.exe whitespace [TAB]
> .\sh-completion-demo.exe whitespace with` whitespace

Minimal code to reproduce above usage with github.com/spf13/cobra v1.5.0 (Gist):

package main

import (
	"fmt"
	"os"

	"github.com/spf13/cobra"
)

var RootCmd = &cobra.Command{
	Use:  "sh-completion-demo",
	Long: "Demo shell completion with whitespace",
}

var WhitespaceCmd = &cobra.Command{
	Use:   "whitespace",
	Short: "Noun with completion that includes whitespace",
	RunE: func(cmd *cobra.Command, args []string) error {
		if args[0] != "with whitespace" && args[0] != "no-whitespace" {
			return fmt.Errorf(`argument must be "with whitespace" or "no-whitespace"`)
		}
		return nil
	},
	SilenceUsage: true,
	ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
		return []string{"with whitespace", "no-whitespace"}, cobra.ShellCompDirectiveNoFileComp
	},
}

func init() {
	RootCmd.AddCommand(WhitespaceCmd)
}

func main() {
	if err := RootCmd.Execute(); err != nil {
		os.Exit(1)
	}
}

kangasta avatar Jun 21 '22 18:06 kangasta

@scop, you may have some expertise on this. Do you have special handling if a completion has a space in it for bash?

marckhouzam avatar Aug 15 '22 02:08 marckhouzam

Hi @kangasta ;)

It's annoyingly difficult in bash.

A cheap generic way is to fake the completions to be filenames. That does take care of the escaping, but it's obviously semantically incorrect for completions that really aren't filenames. And it may have side effects.

Another one is to run the strings through printf %q ... here and there in the completion code. Some related discussion e.g. at https://stackoverflow.com/questions/26509260/bash-tab-completion-with-spaces

Anyway I believe neither of these options is currently available for cobra users. I'll have a quick peek at PR #1743.

scop avatar Aug 20 '22 09:08 scop

The Cobra project currently lacks enough contributors to adequately respond to all issues. This bot triages issues and PRs according to the following rules:

  • After 60d of inactivity, lifecycle/stale is applied. - After 30d of inactivity since lifecycle/stale was applied, lifecycle/rotten is applied and the issue is closed. You can:
  • Make a comment to remove the stale label and show your support. The 60 days reset. - If an issue has lifecycle/rotten and is closed, comment and ask maintainers if they'd be interseted in reopening

github-actions[bot] avatar Oct 20 '22 00:10 github-actions[bot]

Rebased related PR and added comment there as well: #1743

kangasta avatar Oct 27 '22 11:10 kangasta

The Cobra project currently lacks enough contributors to adequately respond to all issues. This bot triages issues and PRs according to the following rules:

  • After 60d of inactivity, lifecycle/stale is applied. - After 30d of inactivity since lifecycle/stale was applied, lifecycle/rotten is applied and the issue is closed. You can:
  • Make a comment to remove the stale label and show your support. The 60 days reset. - If an issue has lifecycle/rotten and is closed, comment and ask maintainers if they'd be interested in reopening

github-actions[bot] avatar Dec 28 '22 00:12 github-actions[bot]

Adding a comment to keep this from being closed.

kangasta avatar Dec 29 '22 11:12 kangasta

I ran across this the other day. This isn't just limited to whitespace, but all characters that need escaping in bash. My completions were using >, which is kinda unfortunate because cobra started redirecting output to random places during completion

JeffFaer avatar Feb 28 '24 15:02 JeffFaer