package cli import ( "fmt" "golang.org/x/xerrors" "github.com/coder/coder/v2/cli/cliui" "github.com/coder/serpent" "github.com/coder/serpent/completion" ) func (*RootCmd) completion() *serpent.Command { var shellName string var printOutput bool shellOptions := completion.ShellOptions(&shellName) return &serpent.Command{ Use: "completion", Short: "Install or update shell completion scripts for the detected or chosen shell.", Options: []serpent.Option{ { Flag: "shell", FlagShorthand: "s", Description: "The shell to install completion for.", Value: shellOptions, }, { Flag: "print", Description: "Print the completion script instead of installing it.", FlagShorthand: "p", Value: serpent.BoolOf(&printOutput), }, }, Handler: func(inv *serpent.Invocation) error { if shellName != "" { shell, err := completion.ShellByName(shellName, inv.Command.Parent.Name()) if err != nil { return err } if printOutput { return shell.WriteCompletion(inv.Stdout) } return installCompletion(inv, shell) } shell, err := completion.DetectUserShell(inv.Command.Parent.Name()) if err == nil { return installCompletion(inv, shell) } if !isTTYOut(inv) { return xerrors.New("could not detect the current shell, please specify one with --shell or run interactively") } // Silently continue to the shell selection if detecting failed in interactive mode choice, err := cliui.Select(inv, cliui.SelectOptions{ Message: "Select a shell to install completion for:", Options: shellOptions.Choices, }) if err != nil { return err } shellChoice, err := completion.ShellByName(choice, inv.Command.Parent.Name()) if err != nil { return err } if printOutput { return shellChoice.WriteCompletion(inv.Stdout) } return installCompletion(inv, shellChoice) }, } } func installCompletion(inv *serpent.Invocation, shell completion.Shell) error { path, err := shell.InstallPath() if err != nil { cliui.Error(inv.Stderr, fmt.Sprintf("Failed to determine completion path %v", err)) return shell.WriteCompletion(inv.Stdout) } if !isTTYOut(inv) { return shell.WriteCompletion(inv.Stdout) } choice, err := cliui.Select(inv, cliui.SelectOptions{ Options: []string{ "Confirm", "Print to terminal", }, Message: fmt.Sprintf("Install completion for %s at %s?", shell.Name(), path), HideSearch: true, }) if err != nil { return err } if choice == "Print to terminal" { return shell.WriteCompletion(inv.Stdout) } return completion.InstallShellCompletion(shell) }