github.com/ungtb10d/cli/v2@v2.0.0-20221110210412-98537dd9d6a1/internal/prompter/prompter.go (about)

     1  package prompter
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"strings"
     7  
     8  	"github.com/AlecAivazis/survey/v2"
     9  	"github.com/ungtb10d/cli/v2/internal/ghinstance"
    10  	"github.com/ungtb10d/cli/v2/pkg/surveyext"
    11  )
    12  
    13  //go:generate moq -rm -out prompter_mock.go . Prompter
    14  type Prompter interface {
    15  	Select(string, string, []string) (int, error)
    16  	MultiSelect(string, string, []string) (int, error)
    17  	Input(string, string) (string, error)
    18  	InputHostname() (string, error)
    19  	Password(string) (string, error)
    20  	AuthToken() (string, error)
    21  	Confirm(string, bool) (bool, error)
    22  	ConfirmDeletion(string) error
    23  	MarkdownEditor(string, string, bool) (string, error)
    24  }
    25  
    26  type fileWriter interface {
    27  	io.Writer
    28  	Fd() uintptr
    29  }
    30  
    31  type fileReader interface {
    32  	io.Reader
    33  	Fd() uintptr
    34  }
    35  
    36  func New(editorCmd string, stdin fileReader, stdout fileWriter, stderr io.Writer) Prompter {
    37  	return &surveyPrompter{
    38  		editorCmd: editorCmd,
    39  		stdin:     stdin,
    40  		stdout:    stdout,
    41  		stderr:    stderr,
    42  	}
    43  }
    44  
    45  type surveyPrompter struct {
    46  	editorCmd string
    47  	stdin     fileReader
    48  	stdout    fileWriter
    49  	stderr    io.Writer
    50  }
    51  
    52  func (p *surveyPrompter) Select(message, defaultValue string, options []string) (result int, err error) {
    53  	q := &survey.Select{
    54  		Message:  message,
    55  		Options:  options,
    56  		PageSize: 20,
    57  	}
    58  
    59  	if defaultValue != "" {
    60  		q.Default = defaultValue
    61  	}
    62  
    63  	err = p.ask(q, &result)
    64  
    65  	return
    66  }
    67  
    68  func (p *surveyPrompter) MultiSelect(message, defaultValue string, options []string) (result int, err error) {
    69  	q := &survey.MultiSelect{
    70  		Message:  message,
    71  		Options:  options,
    72  		PageSize: 20,
    73  	}
    74  
    75  	if defaultValue != "" {
    76  		q.Default = defaultValue
    77  	}
    78  
    79  	err = p.ask(q, &result)
    80  
    81  	return
    82  }
    83  
    84  func (p *surveyPrompter) ask(q survey.Prompt, response interface{}, opts ...survey.AskOpt) error {
    85  	opts = append(opts, survey.WithStdio(p.stdin, p.stdout, p.stderr))
    86  	err := survey.AskOne(q, response, opts...)
    87  	if err == nil {
    88  		return nil
    89  	}
    90  	return fmt.Errorf("could not prompt: %w", err)
    91  }
    92  
    93  func (p *surveyPrompter) Input(prompt, defaultValue string) (result string, err error) {
    94  	err = p.ask(&survey.Input{
    95  		Message: prompt,
    96  		Default: defaultValue,
    97  	}, &result)
    98  
    99  	return
   100  }
   101  
   102  func (p *surveyPrompter) ConfirmDeletion(requiredValue string) error {
   103  	var result string
   104  	return p.ask(
   105  		&survey.Input{
   106  			Message: fmt.Sprintf("Type %s to confirm deletion:", requiredValue),
   107  		},
   108  		&result,
   109  		survey.WithValidator(
   110  			func(val interface{}) error {
   111  				if str := val.(string); !strings.EqualFold(str, requiredValue) {
   112  					return fmt.Errorf("You entered %s", str)
   113  				}
   114  				return nil
   115  			}))
   116  }
   117  
   118  func (p *surveyPrompter) InputHostname() (result string, err error) {
   119  	err = p.ask(
   120  		&survey.Input{
   121  			Message: "GHE hostname:",
   122  		}, &result, survey.WithValidator(func(v interface{}) error {
   123  			return ghinstance.HostnameValidator(v.(string))
   124  		}))
   125  
   126  	return
   127  }
   128  
   129  func (p *surveyPrompter) Password(prompt string) (result string, err error) {
   130  	err = p.ask(&survey.Password{
   131  		Message: prompt,
   132  	}, &result)
   133  
   134  	return
   135  }
   136  
   137  func (p *surveyPrompter) Confirm(prompt string, defaultValue bool) (result bool, err error) {
   138  	err = p.ask(&survey.Confirm{
   139  		Message: prompt,
   140  		Default: defaultValue,
   141  	}, &result)
   142  
   143  	return
   144  }
   145  func (p *surveyPrompter) MarkdownEditor(message, defaultValue string, blankAllowed bool) (result string, err error) {
   146  
   147  	err = p.ask(&surveyext.GhEditor{
   148  		BlankAllowed:  blankAllowed,
   149  		EditorCommand: p.editorCmd,
   150  		Editor: &survey.Editor{
   151  			Message:       message,
   152  			Default:       defaultValue,
   153  			FileName:      "*.md",
   154  			HideDefault:   true,
   155  			AppendDefault: true,
   156  		},
   157  	}, &result)
   158  
   159  	return
   160  }
   161  
   162  func (p *surveyPrompter) AuthToken() (result string, err error) {
   163  	err = p.ask(&survey.Password{
   164  		Message: "Paste your authentication token:",
   165  	}, &result, survey.WithValidator(survey.Required))
   166  
   167  	return
   168  }