Skip to content

Commit e45d916

Browse files
authored
support accepting default values while asking for inputs (#10)
* support accepting default values while asking for inputs * added basic validation in non-intercative UI
1 parent 73db60c commit e45d916

13 files changed

+134
-51
lines changed

ui/color_ui.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,12 @@ func (ui *ColorUI) PrintTable(table Table) {
6666
ui.parent.PrintTable(table)
6767
}
6868

69-
func (ui *ColorUI) AskForText(label string) (string, error) {
70-
return ui.parent.AskForText(label)
69+
func (ui *ColorUI) AskForText(opts TextOpts) (string, error) {
70+
return ui.parent.AskForText(opts)
7171
}
7272

73-
func (ui *ColorUI) AskForChoice(label string, options []string) (int, error) {
74-
return ui.parent.AskForChoice(label, options)
73+
func (ui *ColorUI) AskForChoice(opts ChoiceOpts) (int, error) {
74+
return ui.parent.AskForChoice(opts)
7575
}
7676

7777
func (ui *ColorUI) AskForPassword(label string) (string, error) {

ui/conf_ui.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,12 @@ func (ui *ConfUI) PrintTable(table Table) {
8989
ui.parent.PrintTable(table)
9090
}
9191

92-
func (ui *ConfUI) AskForText(label string) (string, error) {
93-
return ui.parent.AskForText(label)
92+
func (ui *ConfUI) AskForText(opts TextOpts) (string, error) {
93+
return ui.parent.AskForText(opts)
9494
}
9595

96-
func (ui *ConfUI) AskForChoice(label string, options []string) (int, error) {
97-
return ui.parent.AskForChoice(label, options)
96+
func (ui *ConfUI) AskForChoice(opts ChoiceOpts) (int, error) {
97+
return ui.parent.AskForChoice(opts)
9898
}
9999

100100
func (ui *ConfUI) AskForPassword(label string) (string, error) {

ui/fakes/fake_ui.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"sync"
66

7+
types "github.com/cppforlife/go-cli-ui/ui"
78
. "github.com/cppforlife/go-cli-ui/ui/table"
89
)
910

@@ -93,24 +94,24 @@ func (ui *FakeUI) PrintTable(table Table) {
9394
ui.Tables = append(ui.Tables, table)
9495
}
9596

96-
func (ui *FakeUI) AskForText(label string) (string, error) {
97+
func (ui *FakeUI) AskForText(opts types.TextOpts) (string, error) {
9798
ui.mutex.Lock()
9899
defer ui.mutex.Unlock()
99100

100-
ui.AskedTextLabels = append(ui.AskedTextLabels, label)
101+
ui.AskedTextLabels = append(ui.AskedTextLabels, opts.Label)
101102
answer := ui.AskedText[0]
102103
ui.AskedText = ui.AskedText[1:]
103104
return answer.Text, answer.Error
104105
}
105106

106-
func (ui *FakeUI) AskForChoice(label string, options []string) (int, error) {
107+
func (ui *FakeUI) AskForChoice(opts types.ChoiceOpts) (int, error) {
107108
ui.mutex.Lock()
108109
defer ui.mutex.Unlock()
109110

110111
ui.AskedChoiceCalled = true
111112

112-
ui.AskedChoiceLabel = label
113-
ui.AskedChoiceOptions = options
113+
ui.AskedChoiceLabel = opts.Label
114+
ui.AskedChoiceOptions = opts.Choices
114115

115116
chosen := ui.AskedChoiceChosens[0]
116117
ui.AskedChoiceChosens = ui.AskedChoiceChosens[1:]

ui/indenting_ui.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,12 @@ func (ui *IndentingUI) PrintTable(table Table) {
4242
ui.parent.PrintTable(table)
4343
}
4444

45-
func (ui *IndentingUI) AskForText(label string) (string, error) {
46-
return ui.parent.AskForText(label)
45+
func (ui *IndentingUI) AskForText(opts TextOpts) (string, error) {
46+
return ui.parent.AskForText(opts)
4747
}
4848

49-
func (ui *IndentingUI) AskForChoice(label string, options []string) (int, error) {
50-
return ui.parent.AskForChoice(label, options)
49+
func (ui *IndentingUI) AskForChoice(opts ChoiceOpts) (int, error) {
50+
return ui.parent.AskForChoice(opts)
5151
}
5252

5353
func (ui *IndentingUI) AskForPassword(label string) (string, error) {

ui/interfaces.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ type UI interface {
1616

1717
PrintTable(Table)
1818

19-
AskForText(label string) (string, error)
20-
AskForChoice(label string, options []string) (int, error)
19+
AskForText(opts TextOpts) (string, error)
20+
AskForChoice(opts ChoiceOpts) (int, error)
2121
AskForPassword(label string) (string, error)
2222

2323
// AskForConfirmation returns error if user doesnt want to continue

ui/json_ui.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,11 @@ func (ui *JSONUI) PrintTable(table Table) {
9898
ui.uiResp.Tables = append(ui.uiResp.Tables, resp)
9999
}
100100

101-
func (ui *JSONUI) AskForText(_ string) (string, error) {
101+
func (ui *JSONUI) AskForText(_ TextOpts) (string, error) {
102102
panic("Cannot ask for input in JSON UI")
103103
}
104104

105-
func (ui *JSONUI) AskForChoice(_ string, _ []string) (int, error) {
105+
func (ui *JSONUI) AskForChoice(_ ChoiceOpts) (int, error) {
106106
panic("Cannot ask for a choice in JSON UI")
107107
}
108108

ui/json_ui_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ func TestJSONUI(t *testing.T) {
310310
parentUI := &fakeui.FakeUI{}
311311
ui := NewJSONUI(parentUI, NewRecordingLogger())
312312

313-
assert.Panics(t, func() { ui.AskForText("") })
313+
assert.Panics(t, func() { ui.AskForText(TextOpts{}) })
314314
})
315315
})
316316

@@ -328,7 +328,7 @@ func TestJSONUI(t *testing.T) {
328328
parentUI := &fakeui.FakeUI{}
329329
ui := NewJSONUI(parentUI, NewRecordingLogger())
330330

331-
assert.Panics(t, func() { ui.AskForChoice("", nil) })
331+
assert.Panics(t, func() { ui.AskForChoice(ChoiceOpts{}) })
332332
})
333333
})
334334

ui/non_interactive.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package ui
22

33
import (
4+
"fmt"
5+
46
. "github.com/cppforlife/go-cli-ui/ui/table"
57
)
68

@@ -40,12 +42,21 @@ func (ui *NonInteractiveUI) PrintTable(table Table) {
4042
ui.parent.PrintTable(table)
4143
}
4244

43-
func (ui *NonInteractiveUI) AskForText(label string) (string, error) {
44-
panic("Cannot ask for input in non-interactive UI")
45+
func (ui *NonInteractiveUI) AskForText(opts TextOpts) (string, error) {
46+
if opts.ValidateFunc != nil {
47+
isValid, message, err := opts.ValidateFunc(opts.Default)
48+
if err != nil || !isValid {
49+
return "", fmt.Errorf("Validation error: %s", message)
50+
}
51+
}
52+
return opts.Default, nil
4553
}
4654

47-
func (ui *NonInteractiveUI) AskForChoice(label string, options []string) (int, error) {
48-
panic("Cannot ask for a choice in non-interactive UI")
55+
func (ui *NonInteractiveUI) AskForChoice(opts ChoiceOpts) (int, error) {
56+
if opts.Default >= len(opts.Choices) || opts.Default < 0 {
57+
return 0, fmt.Errorf("Default value should be index and must be in (0-%d)", len(opts.Choices)-1)
58+
}
59+
return opts.Default, nil
4960
}
5061

5162
func (ui *NonInteractiveUI) AskForPassword(label string) (string, error) {

ui/non_interactive_test.go

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package ui_test
22

33
import (
4+
"fmt"
45
"testing"
56

67
. "github.com/cppforlife/go-cli-ui/ui"
@@ -87,11 +88,41 @@ func TestNonInteractiveUI(t *testing.T) {
8788
})
8889

8990
t.Run("AskForText", func(t *testing.T) {
90-
t.Run("panics", func(t *testing.T) {
91+
t.Run("default non empty", func(t *testing.T) {
9192
parentUI := &fakeui.FakeUI{}
9293
ui := NewNonInteractiveUI(parentUI)
9394

94-
assert.Panics(t, func() { ui.AskForText("") })
95+
text, err := ui.AskForText(TextOpts{
96+
Label: "",
97+
Default: "foo",
98+
ValidateFunc: func(s string) (bool, string, error) {
99+
if s == "" {
100+
return false, "", fmt.Errorf("should not be empty")
101+
}
102+
return true, "", nil
103+
},
104+
})
105+
106+
assert.Equal(t, text, "foo")
107+
assert.Nil(t, err)
108+
})
109+
t.Run("default empty", func(t *testing.T) {
110+
parentUI := &fakeui.FakeUI{}
111+
ui := NewNonInteractiveUI(parentUI)
112+
113+
text, err := ui.AskForText(TextOpts{
114+
Label: "",
115+
Default: "",
116+
ValidateFunc: func(s string) (bool, string, error) {
117+
if s == "" {
118+
return false, "", fmt.Errorf("should not be empty")
119+
}
120+
return true, "", nil
121+
},
122+
})
123+
124+
assert.Equal(t, text, "")
125+
assert.NotNil(t, err)
95126
})
96127
})
97128

@@ -105,11 +136,18 @@ func TestNonInteractiveUI(t *testing.T) {
105136
})
106137

107138
t.Run("AskForChoice", func(t *testing.T) {
108-
t.Run("panics", func(t *testing.T) {
139+
t.Run("non negative default value", func(t *testing.T) {
109140
parentUI := &fakeui.FakeUI{}
110141
ui := NewNonInteractiveUI(parentUI)
111142

112-
assert.Panics(t, func() { ui.AskForChoice("", nil) })
143+
choice, err := ui.AskForChoice(ChoiceOpts{
144+
Label: "",
145+
Default: 1,
146+
Choices: []string{"a", "b", "c"},
147+
})
148+
149+
assert.Equal(t, choice, 1)
150+
assert.Nil(t, err)
113151
})
114152
})
115153

ui/non_tty_ui.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ func (ui *NonTTYUI) PrintTable(table Table) {
3939
ui.parent.PrintTable(table)
4040
}
4141

42-
func (ui *NonTTYUI) AskForText(label string) (string, error) {
43-
return ui.parent.AskForText(label)
42+
func (ui *NonTTYUI) AskForText(opts TextOpts) (string, error) {
43+
return ui.parent.AskForText(opts)
4444
}
4545

46-
func (ui *NonTTYUI) AskForChoice(label string, options []string) (int, error) {
47-
return ui.parent.AskForChoice(label, options)
46+
func (ui *NonTTYUI) AskForChoice(opts ChoiceOpts) (int, error) {
47+
return ui.parent.AskForChoice(opts)
4848
}
4949

5050
func (ui *NonTTYUI) AskForPassword(label string) (string, error) {

0 commit comments

Comments
 (0)