From bd89e46a203f012c36d90d0a999ef213a178f0ee Mon Sep 17 00:00:00 2001 From: Juto Yu Date: Sun, 19 Feb 2017 12:27:35 +0000 Subject: [PATCH] Allow the cli to accpect single lined interactivity - This makes the prompts easier to test, e.g., if we ask for both username and password, we can now simply do printf "myName\nmyPassword\n" | myCli. - We don't create a new bufio.Reader each tiem we ask, hopefully it doesn't break someone's program. - All the tests pass! --- ui.go | 8 ++++++-- ui_test.go | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/ui.go b/ui.go index a2d6f94..22dcc65 100644 --- a/ui.go +++ b/ui.go @@ -49,6 +49,7 @@ type BasicUi struct { Reader io.Reader Writer io.Writer ErrorWriter io.Writer + RichReader *bufio.Reader } func (u *BasicUi) Ask(query string) (string, error) { @@ -60,6 +61,10 @@ func (u *BasicUi) AskSecret(query string) (string, error) { } func (u *BasicUi) ask(query string, secret bool) (string, error) { + if u.RichReader == nil { + u.RichReader = bufio.NewReader(u.Reader) + } + if _, err := fmt.Fprint(u.Writer, query+" "); err != nil { return "", err } @@ -79,8 +84,7 @@ func (u *BasicUi) ask(query string, secret bool) (string, error) { if secret && isatty.IsTerminal(os.Stdin.Fd()) { line, err = speakeasy.Ask("") } else { - r := bufio.NewReader(u.Reader) - line, err = r.ReadString('\n') + line, err = u.RichReader.ReadString('\n') } if err != nil { errCh <- err diff --git a/ui_test.go b/ui_test.go index ac795ba..24b4680 100644 --- a/ui_test.go +++ b/ui_test.go @@ -64,6 +64,42 @@ func TestBasicUi_AskSecret(t *testing.T) { } } +func TestBasicUi_Ask_And_AskSecret(t *testing.T) { + in_r, in_w := io.Pipe() + defer in_r.Close() + defer in_w.Close() + + writer := new(bytes.Buffer) + ui := &BasicUi{ + Reader: in_r, + Writer: writer, + } + + go in_w.Write([]byte("foo bar\nbaz\n")) + + name, err := ui.Ask("Name?") + if err != nil { + t.Fatalf("err: %s", err) + } + + password, err := ui.AskSecret("Password?") + if err != nil { + t.Fatalf("err: %s", err) + } + + if writer.String() != "Name? Password? " { + t.Fatalf("bad: %#v", writer.String()) + } + + if name != "foo bar" { + t.Fatalf("bad: %#v", name) + } + + if password != "baz" { + t.Fatalf("bad: %#v", password) + } +} + func TestBasicUi_Error(t *testing.T) { writer := new(bytes.Buffer) ui := &BasicUi{Writer: writer}