github.com/arunkumar7540/cli@v6.45.0+incompatible/util/ui/prompt.go (about)

     1  package ui
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"io"
     7  	"strconv"
     8  
     9  	"github.com/vito/go-interact/interact"
    10  	"github.com/vito/go-interact/interact/terminal"
    11  )
    12  
    13  const sigIntExitCode = 130
    14  
    15  var ErrInvalidIndex = errors.New("invalid list index")
    16  
    17  type InvalidChoiceError struct {
    18  	Choice string
    19  }
    20  
    21  func (InvalidChoiceError) Error() string {
    22  	return "Some error"
    23  }
    24  
    25  //go:generate counterfeiter . Resolver
    26  
    27  type Resolver interface {
    28  	Resolve(dst interface{}) error
    29  	SetIn(io.Reader)
    30  	SetOut(io.Writer)
    31  }
    32  
    33  // DisplayBoolPrompt outputs the prompt and waits for user input. It only
    34  // allows for a boolean response. A default boolean response can be set with
    35  // defaultResponse.
    36  func (ui *UI) DisplayBoolPrompt(defaultResponse bool, template string, templateValues ...map[string]interface{}) (bool, error) {
    37  	ui.terminalLock.Lock()
    38  	defer ui.terminalLock.Unlock()
    39  
    40  	response := defaultResponse
    41  	interactivePrompt := ui.Interactor.NewInteraction(ui.TranslateText(template, templateValues...))
    42  	interactivePrompt.SetIn(ui.In)
    43  	interactivePrompt.SetOut(ui.OutForInteration)
    44  	err := interactivePrompt.Resolve(&response)
    45  	if isInterrupt(err) {
    46  		ui.Exiter.Exit(sigIntExitCode)
    47  	}
    48  	return response, err
    49  }
    50  
    51  // DisplayOptionalTextPrompt outputs the prompt and waits for user input.
    52  func (ui *UI) DisplayOptionalTextPrompt(defaultValue string, template string, templateValues ...map[string]interface{}) (string, error) {
    53  	interactivePrompt := ui.Interactor.NewInteraction(ui.TranslateText(template, templateValues...))
    54  	var value = defaultValue
    55  	interactivePrompt.SetIn(ui.In)
    56  	interactivePrompt.SetOut(ui.OutForInteration)
    57  	err := interactivePrompt.Resolve(&value)
    58  	if isInterrupt(err) {
    59  		ui.Exiter.Exit(sigIntExitCode)
    60  	}
    61  	return value, err
    62  }
    63  
    64  // DisplayPasswordPrompt outputs the prompt and waits for user input. Hides
    65  // user's response from the screen.
    66  func (ui *UI) DisplayPasswordPrompt(template string, templateValues ...map[string]interface{}) (string, error) {
    67  	ui.terminalLock.Lock()
    68  	defer ui.terminalLock.Unlock()
    69  
    70  	var password interact.Password
    71  	interactivePrompt := ui.Interactor.NewInteraction(ui.TranslateText(template, templateValues...))
    72  	interactivePrompt.SetIn(ui.In)
    73  	interactivePrompt.SetOut(ui.OutForInteration)
    74  	err := interactivePrompt.Resolve(interact.Required(&password))
    75  	if isInterrupt(err) {
    76  		ui.Exiter.Exit(sigIntExitCode)
    77  	}
    78  	return string(password), err
    79  }
    80  
    81  // DisplayTextMenu lets the user choose from a list of options, either by name
    82  // or by number.
    83  func (ui *UI) DisplayTextMenu(choices []string, promptTemplate string, templateValues ...map[string]interface{}) (string, error) {
    84  	for i, c := range choices {
    85  		t := fmt.Sprintf("%d. %s", i+1, c)
    86  		ui.DisplayText(t)
    87  	}
    88  
    89  	translatedPrompt := ui.TranslateText(promptTemplate, templateValues...)
    90  
    91  	interactivePrompt := ui.Interactor.NewInteraction(translatedPrompt)
    92  
    93  	interactivePrompt.SetIn(ui.In)
    94  	interactivePrompt.SetOut(ui.OutForInteration)
    95  
    96  	var value string = "enter to skip"
    97  	err := interactivePrompt.Resolve(&value)
    98  
    99  	if isInterrupt(err) {
   100  		ui.Exiter.Exit(sigIntExitCode)
   101  	}
   102  
   103  	if err != nil {
   104  		return "", err
   105  	}
   106  
   107  	if value == "enter to skip" {
   108  		return "", nil
   109  	}
   110  
   111  	i, err := strconv.Atoi(value)
   112  	if err != nil {
   113  		if contains(choices, value) {
   114  			return value, nil
   115  		}
   116  		return "", InvalidChoiceError{Choice: value}
   117  	}
   118  
   119  	if i > len(choices) || i <= 0 {
   120  		return "", ErrInvalidIndex
   121  	}
   122  	return choices[i-1], nil
   123  }
   124  
   125  // DisplayTextPrompt outputs the prompt and waits for user input.
   126  func (ui *UI) DisplayTextPrompt(template string, templateValues ...map[string]interface{}) (string, error) {
   127  	interactivePrompt := ui.Interactor.NewInteraction(ui.TranslateText(template, templateValues...))
   128  	var value string
   129  	interactivePrompt.SetIn(ui.In)
   130  	interactivePrompt.SetOut(ui.OutForInteration)
   131  	err := interactivePrompt.Resolve(interact.Required(&value))
   132  	if isInterrupt(err) {
   133  		ui.Exiter.Exit(sigIntExitCode)
   134  	}
   135  	return value, err
   136  }
   137  
   138  func contains(s []string, v string) bool {
   139  	for _, x := range s {
   140  		if x == v {
   141  			return true
   142  		}
   143  	}
   144  	return false
   145  }
   146  
   147  func isInterrupt(err error) bool {
   148  	return err == interact.ErrKeyboardInterrupt || err == terminal.ErrKeyboardInterrupt
   149  }