Skip to content

Commit

Permalink
Merge pull request #262 from CircleCI-Public/prompt
Browse files Browse the repository at this point in the history
Refactor common prompt code to package
  • Loading branch information
Zachary Scott authored Jan 9, 2019
2 parents ba7477d + 98df35b commit 5896baa
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 92 deletions.
12 changes: 3 additions & 9 deletions cmd/namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (

"github.com/CircleCI-Public/circleci-cli/api"
"github.com/CircleCI-Public/circleci-cli/client"
"github.com/CircleCI-Public/circleci-cli/prompt"
"github.com/CircleCI-Public/circleci-cli/settings"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra"
)

Expand All @@ -30,14 +30,8 @@ type createNamespaceUserInterface interface {

type createNamespaceInteractiveUI struct{}

func (ui createNamespaceInteractiveUI) askUserToConfirm(message string) bool {
prompt := promptui.Prompt{
Label: message,
IsConfirm: true,
}

result, err := prompt.Run()
return err == nil && strings.ToLower(result) == "y"
func (createNamespaceInteractiveUI) askUserToConfirm(message string) bool {
return prompt.AskUserToConfirm(message)
}

type createNamespaceTestUI struct {
Expand Down
12 changes: 3 additions & 9 deletions cmd/orb.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (

"github.com/CircleCI-Public/circleci-cli/api"
"github.com/CircleCI-Public/circleci-cli/client"
"github.com/CircleCI-Public/circleci-cli/prompt"
"github.com/CircleCI-Public/circleci-cli/references"
"github.com/CircleCI-Public/circleci-cli/settings"
"github.com/manifoldco/promptui"
"github.com/pkg/errors"

"github.com/spf13/cobra"
Expand Down Expand Up @@ -46,14 +46,8 @@ type createOrbUserInterface interface {

type createOrbInteractiveUI struct{}

func (ui createOrbInteractiveUI) askUserToConfirm(message string) bool {
prompt := promptui.Prompt{
Label: message,
IsConfirm: true,
}

result, err := prompt.Run()
return err == nil && strings.ToLower(result) == "y"
func (createOrbInteractiveUI) askUserToConfirm(message string) bool {
return prompt.AskUserToConfirm(message)
}

type createOrbTestUI struct {
Expand Down
83 changes: 9 additions & 74 deletions cmd/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ package cmd

import (
"fmt"
"strings"

"github.com/CircleCI-Public/circleci-cli/api"
"github.com/CircleCI-Public/circleci-cli/client"
"github.com/CircleCI-Public/circleci-cli/prompt"
"github.com/CircleCI-Public/circleci-cli/settings"
"github.com/manifoldco/promptui"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
Expand All @@ -31,83 +30,32 @@ type setupOptions struct {
// This is because the first call to PromptUI reads from stdin correctly,
// but subsequent calls return EOF.
type setupUserInterface interface {
readSecretStringFromUser(message string) (string, error)
readTokenFromUser(message string) (string, error)

readStringFromUser(message string, defaultValue string) string
readHostFromUser(message string, defaultValue string) string

askUserToConfirm(message string) bool
askUserToConfirmEndpoint(message string) bool
askUserToConfirmToken(message string) bool
}

// setupUI implements the setupUserInterface used by the real program, not in tests.
type setupInteractiveUI struct{}

// readSecretStringFromUser can be used to read a value from the user by masking their input.
// It's useful for token input in our case.
func (setupInteractiveUI) readSecretStringFromUser(message string) (string, error) {
prompt := promptui.Prompt{
Label: message,
Mask: '*',
}

secret, err := prompt.Run()

if err != nil {
return "", err
}

return secret, nil
}

// readStringFromUser can be used to read any value from the user or the defaultValue when provided.
func (setupInteractiveUI) readStringFromUser(message string, defaultValue string) string {
prompt := promptui.Prompt{
Label: message,
}

if defaultValue != "" {
prompt.Default = defaultValue
}

token, err := prompt.Run()

if err != nil {
panic(err)
}

return token
}

// readHostFromUser implements the setupInteractiveUI interface for asking a user's input.
func (ui setupInteractiveUI) readHostFromUser(message string, defaultValue string) string {
return ui.readStringFromUser(message, defaultValue)
func (setupInteractiveUI) readHostFromUser(message string, defaultValue string) string {
return prompt.ReadStringFromUser(message, defaultValue)
}

// readTokenFromUser implements the setupInteractiveUI interface for asking a user's token.
func (ui setupInteractiveUI) readTokenFromUser(message string) (string, error) {
return ui.readSecretStringFromUser(message)
}

// askUserToConfirm will prompt the user to confirm with the provided message.
func (setupInteractiveUI) askUserToConfirm(message string) bool {
prompt := promptui.Prompt{
Label: message,
IsConfirm: true,
}

result, err := prompt.Run()
return err == nil && strings.ToLower(result) == "y"
func (setupInteractiveUI) readTokenFromUser(message string) (string, error) {
return prompt.ReadSecretStringFromUser(message)
}

func (ui setupInteractiveUI) askUserToConfirmEndpoint(message string) bool {
return ui.askUserToConfirm(message)
func (setupInteractiveUI) askUserToConfirmEndpoint(message string) bool {
return prompt.AskUserToConfirm(message)
}

func (ui setupInteractiveUI) askUserToConfirmToken(message string) bool {
return ui.askUserToConfirm(message)
func (setupInteractiveUI) askUserToConfirmToken(message string) bool {
return prompt.AskUserToConfirm(message)
}

// setupTestUI implements the setupUserInterface for our testing purposes.
Expand All @@ -118,14 +66,6 @@ type setupTestUI struct {
confirmToken bool
}

func (setupTestUI) readStringFromUser(message string, defaultValue string) string {
return ""
}

func (setupTestUI) readSecretStringFromUser(message string) (string, error) {
return "", nil
}

// readHostFromUser implements the setupTestUI interface for asking a user's input.
// It works by simply printing the message to standard output and passing the input through.
func (ui setupTestUI) readHostFromUser(message string, defaultValue string) string {
Expand All @@ -140,11 +80,6 @@ func (ui setupTestUI) readTokenFromUser(message string) (string, error) {
return ui.token, nil
}

// askUserToConfirm implements the setupTestUI interface for returning the confirm prompt.
func (ui setupTestUI) askUserToConfirm(message string) bool {
return true
}

// askUserToConfirmEndpoint works by printing the provided message to standard out and returning a Confirm dialogue up the chain.
func (ui setupTestUI) askUserToConfirmEndpoint(message string) bool {
fmt.Println(message)
Expand Down
54 changes: 54 additions & 0 deletions prompt/prompt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package prompt

import (
"strings"

"github.com/manifoldco/promptui"
)

// ReadSecretStringFromUser can be used to read a value from the user by masking their input.
// It's useful for token input in our case.
func ReadSecretStringFromUser(message string) (string, error) {
prompt := promptui.Prompt{
Label: message,
Mask: '*',
}

secret, err := prompt.Run()

if err != nil {
return "", err
}

return secret, nil
}

// ReadStringFromUser can be used to read any value from the user or the defaultValue when provided.
func ReadStringFromUser(message string, defaultValue string) string {
prompt := promptui.Prompt{
Label: message,
}

if defaultValue != "" {
prompt.Default = defaultValue
}

token, err := prompt.Run()

if err != nil {
panic(err)
}

return token
}

// AskUserToConfirm will prompt the user to confirm with the provided message.
func AskUserToConfirm(message string) bool {
prompt := promptui.Prompt{
Label: message,
IsConfirm: true,
}

result, err := prompt.Run()
return err == nil && strings.ToLower(result) == "y"
}

0 comments on commit 5896baa

Please sign in to comment.