aboutsummaryrefslogtreecommitdiffstats
path: root/cmd/utils/input.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/utils/input.go')
-rw-r--r--cmd/utils/input.go98
1 files changed, 98 insertions, 0 deletions
diff --git a/cmd/utils/input.go b/cmd/utils/input.go
new file mode 100644
index 000000000..523d5a587
--- /dev/null
+++ b/cmd/utils/input.go
@@ -0,0 +1,98 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
+
+package utils
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/peterh/liner"
+)
+
+// Holds the stdin line reader.
+// Only this reader may be used for input because it keeps
+// an internal buffer.
+var Stdin = newUserInputReader()
+
+type userInputReader struct {
+ *liner.State
+ warned bool
+ supported bool
+ normalMode liner.ModeApplier
+ rawMode liner.ModeApplier
+}
+
+func newUserInputReader() *userInputReader {
+ r := new(userInputReader)
+ // Get the original mode before calling NewLiner.
+ // This is usually regular "cooked" mode where characters echo.
+ normalMode, _ := liner.TerminalMode()
+ // Turn on liner. It switches to raw mode.
+ r.State = liner.NewLiner()
+ rawMode, err := liner.TerminalMode()
+ if err != nil || !liner.TerminalSupported() {
+ r.supported = false
+ } else {
+ r.supported = true
+ r.normalMode = normalMode
+ r.rawMode = rawMode
+ // Switch back to normal mode while we're not prompting.
+ normalMode.ApplyMode()
+ }
+ return r
+}
+
+func (r *userInputReader) Prompt(prompt string) (string, error) {
+ if r.supported {
+ r.rawMode.ApplyMode()
+ defer r.normalMode.ApplyMode()
+ } else {
+ // liner tries to be smart about printing the prompt
+ // and doesn't print anything if input is redirected.
+ // Un-smart it by printing the prompt always.
+ fmt.Print(prompt)
+ prompt = ""
+ defer fmt.Println()
+ }
+ return r.State.Prompt(prompt)
+}
+
+func (r *userInputReader) PasswordPrompt(prompt string) (passwd string, err error) {
+ if r.supported {
+ r.rawMode.ApplyMode()
+ defer r.normalMode.ApplyMode()
+ return r.State.PasswordPrompt(prompt)
+ }
+ if !r.warned {
+ fmt.Println("!! Unsupported terminal, password will be echoed.")
+ r.warned = true
+ }
+ // Just as in Prompt, handle printing the prompt here instead of relying on liner.
+ fmt.Print(prompt)
+ passwd, err = r.State.Prompt("")
+ fmt.Println()
+ return passwd, err
+}
+
+func (r *userInputReader) ConfirmPrompt(prompt string) (bool, error) {
+ prompt = prompt + " [y/N] "
+ input, err := r.Prompt(prompt)
+ if len(input) > 0 && strings.ToUpper(input[:1]) == "Y" {
+ return true, nil
+ }
+ return false, err
+}