github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/utilities/console/prompter.go (about)

     1  package console
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/peterh/liner"
     8  )
     9  
    10  var Stdin = newTerminalPrompter()
    11  
    12  type UserPrompter interface {
    13  	PromptInput(prompt string) (string, error)
    14  
    15  	PromptPassword(prompt string) (string, error)
    16  
    17  	PromptConfirm(prompt string) (bool, error)
    18  
    19  	SetHistory(history []string)
    20  
    21  	AppendHistory(command string)
    22  
    23  	ClearHistory()
    24  
    25  	SetWordCompleter(completer WordCompleter)
    26  }
    27  
    28  type WordCompleter func(line string, pos int) (string, []string, string)
    29  
    30  type terminalPrompter struct {
    31  	*liner.State
    32  	warned     bool
    33  	supported  bool
    34  	normalMode liner.ModeApplier
    35  	rawMode    liner.ModeApplier
    36  }
    37  
    38  func newTerminalPrompter() *terminalPrompter {
    39  	p := new(terminalPrompter)
    40  
    41  	normalMode, _ := liner.TerminalMode()
    42  
    43  	p.State = liner.NewLiner()
    44  	rawMode, err := liner.TerminalMode()
    45  	if err != nil || !liner.TerminalSupported() {
    46  		p.supported = false
    47  	} else {
    48  		p.supported = true
    49  		p.normalMode = normalMode
    50  		p.rawMode = rawMode
    51  
    52  		normalMode.ApplyMode()
    53  	}
    54  	p.SetCtrlCAborts(true)
    55  	p.SetTabCompletionStyle(liner.TabPrints)
    56  	p.SetMultiLineMode(true)
    57  	return p
    58  }
    59  
    60  func (p *terminalPrompter) PromptInput(prompt string) (string, error) {
    61  	if p.supported {
    62  		p.rawMode.ApplyMode()
    63  		defer p.normalMode.ApplyMode()
    64  	} else {
    65  
    66  		fmt.Print(prompt)
    67  		prompt = ""
    68  		defer fmt.Println()
    69  	}
    70  	return p.State.Prompt(prompt)
    71  }
    72  
    73  func (p *terminalPrompter) PromptPassword(prompt string) (passwd string, err error) {
    74  	if p.supported {
    75  		p.rawMode.ApplyMode()
    76  		defer p.normalMode.ApplyMode()
    77  		return p.State.PasswordPrompt(prompt)
    78  	}
    79  	if !p.warned {
    80  		fmt.Println("!! Unsupported terminal, password will be echoed.")
    81  		p.warned = true
    82  	}
    83  
    84  	fmt.Print(prompt)
    85  	passwd, err = p.State.Prompt("")
    86  	fmt.Println()
    87  	return passwd, err
    88  }
    89  
    90  func (p *terminalPrompter) PromptConfirm(prompt string) (bool, error) {
    91  	input, err := p.Prompt(prompt + " [y/N] ")
    92  	if len(input) > 0 && strings.ToUpper(input[:1]) == "Y" {
    93  		return true, nil
    94  	}
    95  	return false, err
    96  }
    97  
    98  func (p *terminalPrompter) SetHistory(history []string) {
    99  	p.State.ReadHistory(strings.NewReader(strings.Join(history, "\n")))
   100  }
   101  
   102  func (p *terminalPrompter) AppendHistory(command string) {
   103  	p.State.AppendHistory(command)
   104  }
   105  
   106  func (p *terminalPrompter) ClearHistory() {
   107  	p.State.ClearHistory()
   108  }
   109  
   110  func (p *terminalPrompter) SetWordCompleter(completer WordCompleter) {
   111  	p.State.SetWordCompleter(liner.WordCompleter(completer))
   112  }