github.com/igggame/nebulas-go@v2.1.0+incompatible/cmd/console/prompter.go (about) 1 // Copyright (C) 2017 go-nebulas authors 2 // 3 // This file is part of the go-nebulas library. 4 // 5 // the go-nebulas library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // the go-nebulas library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with the go-nebulas library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 19 package console 20 21 import ( 22 "fmt" 23 24 "strings" 25 26 "github.com/peterh/liner" 27 ) 28 29 // Stdin holds the stdin line reader (also using stdout for printing prompts). 30 var Stdin = NewTerminalPrompter() 31 32 // UserPrompter handle console user input interactive 33 type UserPrompter interface { 34 Prompt(prompt string) (string, error) 35 PromptPassphrase(prompt string) (passwd string, err error) 36 PromptConfirm(prompt string) (bool, error) 37 SetHistory(history []string) 38 AppendHistory(command string) 39 SetWordCompleter(completer liner.WordCompleter) 40 } 41 42 // TerminalPrompter terminal prompter 43 type TerminalPrompter struct { 44 liner *liner.State 45 supported bool 46 origMode liner.ModeApplier 47 rawMode liner.ModeApplier 48 } 49 50 // NewTerminalPrompter create a terminal prompter 51 func NewTerminalPrompter() *TerminalPrompter { 52 p := new(TerminalPrompter) 53 // Get the original mode before calling NewLiner. 54 origMode, _ := liner.TerminalMode() 55 // Turn on liner. 56 p.liner = liner.NewLiner() 57 rawMode, err := liner.TerminalMode() 58 if err != nil || !liner.TerminalSupported() { 59 p.supported = false 60 } else { 61 p.supported = true 62 p.origMode = origMode 63 p.rawMode = rawMode 64 // Switch back to normal mode while we're not prompting. 65 origMode.ApplyMode() 66 } 67 p.liner.SetCtrlCAborts(true) 68 p.liner.SetTabCompletionStyle(liner.TabPrints) 69 p.liner.SetMultiLineMode(true) 70 return p 71 } 72 73 // Prompt shows the prompt and requests text input 74 // returning the input. 75 func (p *TerminalPrompter) Prompt(prompt string) (string, error) { 76 if p.supported { 77 p.rawMode.ApplyMode() 78 defer p.origMode.ApplyMode() 79 } else { 80 fmt.Print(prompt) 81 defer fmt.Println() 82 } 83 return p.liner.Prompt(prompt) 84 } 85 86 // PromptPassphrase shows the prompt and request passphrase text input, the passphrase 87 // not show, returns the passphrase 88 func (p *TerminalPrompter) PromptPassphrase(prompt string) (passwd string, err error) { 89 if p.supported { 90 p.rawMode.ApplyMode() 91 defer p.origMode.ApplyMode() 92 return p.liner.PasswordPrompt(prompt) 93 } 94 95 fmt.Print(prompt) 96 passwd, err = p.liner.Prompt("") 97 fmt.Println() 98 return passwd, err 99 } 100 101 // PromptConfirm shows the prompt to the user and requests a boolean 102 // choice to be made, returning that choice. 103 func (p *TerminalPrompter) PromptConfirm(prompt string) (bool, error) { 104 input, err := p.Prompt(prompt + " [y/N] ") 105 if len(input) > 0 && strings.ToUpper(input[:1]) == "Y" { 106 return true, nil 107 } 108 return false, err 109 } 110 111 // SetHistory sets the history that the prompter will allow 112 // the user to scroll back to. 113 func (p *TerminalPrompter) SetHistory(history []string) { 114 p.liner.ReadHistory(strings.NewReader(strings.Join(history, "\n"))) 115 } 116 117 // AppendHistory appends an entry to the scrollback history. 118 func (p *TerminalPrompter) AppendHistory(command string) { 119 p.liner.AppendHistory(command) 120 } 121 122 // SetWordCompleter sets the completion function that the prompter will call to 123 // fetch completion candidates when the user presses tab. 124 func (p *TerminalPrompter) SetWordCompleter(completer liner.WordCompleter) { 125 p.liner.SetWordCompleter(completer) 126 }