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 }