Skip to content

Commit 5ff80d1

Browse files
author
minivera
committed
Improved documentation further and the SelectWithAdd example
1 parent 170b792 commit 5ff80d1

14 files changed

+296
-171
lines changed

_examples/select_add/main.go

+17-6
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,24 @@ import (
77
)
88

99
func main() {
10-
prompt := promptui.SelectWithAdd{
11-
Label: "What's your text editor",
12-
Items: []string{"Vim", "Emacs", "Sublime", "VSCode", "Atom"},
13-
AddLabel: "Other",
14-
}
10+
items := []string{"Vim", "Emacs", "Sublime", "VSCode", "Atom"}
11+
index := -1
12+
var result string
13+
var err error
14+
15+
for index < 0 {
16+
prompt := promptui.SelectWithAdd{
17+
Label: "What's your text editor",
18+
Items: items,
19+
AddLabel: "Other",
20+
}
1521

16-
_, result, err := prompt.Run()
22+
index, result, err = prompt.Run()
23+
24+
if index == -1 {
25+
items = append(items, result)
26+
}
27+
}
1728

1829
if err != nil {
1930
fmt.Printf("Prompt failed %v\n", err)

codes.go

+11-15
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,9 @@ const esc = "\033["
1111

1212
type attribute int
1313

14-
// Define the possible state of text inside the application, either Bold, faint, italic or underline.
14+
// The possible state of text inside the application, either Bold, faint, italic or underline.
1515
//
16-
// By using an identifier in templates similar to `"{{ . | underline }}"`, one of these state will be given to the
17-
// text through the use of the Styler function.
16+
// These constants are called through the use of the Styler function.
1817
const (
1918
reset attribute = iota
2019

@@ -24,10 +23,9 @@ const (
2423
FGUnderline
2524
)
2625

27-
// Define the possible colors of text inside the application.
26+
// The possible colors of text inside the application.
2827
//
29-
// By using an identifier in templates similar to `"{{ . | cyan }}"`, one of these colors will be given to the
30-
// text through the use of the Styler function.
28+
// These constants are called through the use of the Styler function.
3129
const (
3230
FGBlack attribute = iota + 30
3331
FGRed
@@ -39,10 +37,9 @@ const (
3937
FGWhite
4038
)
4139

42-
// Define the possible background colors of text inside the application.
40+
// The possible background colors of text inside the application.
4341
//
44-
// By using an identifier in templates similar to `"{{ . | red | cyan }}"`, where the second color is
45-
// the background color, one of these colors will be given to the text through the use of the Styler function.
42+
// These constants are called through the use of the Styler function.
4643
const (
4744
BGBlack attribute = iota + 40
4845
BGRed
@@ -63,11 +60,10 @@ const (
6360
clearLine = esc + "2K"
6461
)
6562

66-
// FuncMap defines template helpers for the output. It can be extended as a
67-
// regular map.
63+
// FuncMap defines template helpers for the output. It can be extended as a regular map.
6864
//
69-
// The function maps the state, color and background colors constants to string inside the promptui
70-
// templates. This allows the link between the string "black" in a template and the constant FGBlack.
65+
// The functions inside the map link the state, color and background colors strings detected in templates to a Styler
66+
// function that applies the given style using the corresponding constant.
7167
var FuncMap = template.FuncMap{
7268
"black": Styler(FGBlack),
7369
"red": Styler(FGRed),
@@ -99,12 +95,12 @@ func movementCode(n uint, code rune) string {
9995
return esc + strconv.FormatUint(uint64(n), 10) + string(code)
10096
}
10197

102-
// Styler is a closure that accepts multiple possible styling transforms from the state,
98+
// Styler is a function that accepts multiple possible styling transforms from the state,
10399
// color and background colors constants and transforms them into a templated string
104100
// to apply those styles in the CLI.
105101
//
106102
// The returned styling function accepts a string that will be extended with
107-
// the original function's styling attributes.
103+
// the wrapping function's styling attributes.
108104
func Styler(attrs ...attribute) func(interface{}) string {
109105
attrstrs := make([]string, len(attrs))
110106
for i, v := range attrs {

example_main_test.go

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package promptui
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"strconv"
7+
)
8+
9+
// This is an example for the Prompt mode of promptui. In this example, a prompt is created
10+
// with a validator function that validates the given value to make sure its a number.
11+
// If successful, it will output the chosen number in a formatted message.
12+
func Example() {
13+
validate := func(input string) error {
14+
_, err := strconv.ParseFloat(input, 64)
15+
if err != nil {
16+
return errors.New("Invalid number")
17+
}
18+
return nil
19+
}
20+
21+
prompt := Prompt{
22+
Label: "Number",
23+
Validate: validate,
24+
}
25+
26+
result, err := prompt.Run()
27+
28+
if err != nil {
29+
fmt.Printf("Prompt failed %v\n", err)
30+
return
31+
}
32+
33+
fmt.Printf("You choose %q\n", result)
34+
}
35+
36+
// This is an example for the Select mode of promptui. In this example, a select is created with
37+
// the days of the week as its items. When an item is selected, the selected day will be displayed
38+
// in a formatted message.
39+
func Example_aux() {
40+
prompt := Select{
41+
Label: "Select Day",
42+
Items: []string{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
43+
"Saturday", "Sunday"},
44+
}
45+
46+
_, result, err := prompt.Run()
47+
48+
if err != nil {
49+
fmt.Printf("Prompt failed %v\n", err)
50+
return
51+
}
52+
53+
fmt.Printf("You choose %q\n", result)
54+
}

example_prompt_test.go

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package promptui
2+
3+
import (
4+
"strconv"
5+
"fmt"
6+
)
7+
8+
// This example shows how to use the prompt validator and templates to create a stylized prompt.
9+
// The validator will make sure the value entered is a parseable float while the templates will
10+
// color the value to show validity.
11+
func ExamplePrompt() {
12+
// The validate function follows the required validator signature.
13+
validate := func(input string) error {
14+
_, err := strconv.ParseFloat(input, 64)
15+
return err
16+
}
17+
18+
// Each template displays the data received from the prompt with some formatting.
19+
templates := &PromptTemplates{
20+
Prompt: "{{ . }} ",
21+
Valid: "{{ . | green }} ",
22+
Invalid: "{{ . | red }} ",
23+
Success: "{{ . | bold }} ",
24+
}
25+
26+
prompt := Prompt{
27+
Label: "Spicy Level",
28+
Templates: templates,
29+
Validate: validate,
30+
}
31+
32+
result, err := prompt.Run()
33+
34+
if err != nil {
35+
fmt.Printf("Prompt failed %v\n", err)
36+
return
37+
}
38+
39+
// The result of the prompt, if valid, is displayed in a formatted message.
40+
fmt.Printf("You answered %s\n", result)
41+
}
42+

example_select_test.go

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package promptui
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
)
7+
8+
// Any type can be given to the select's item as long as the templates properly implement the dot notation
9+
// to display it.
10+
type pepper struct {
11+
Name string
12+
HeatUnit int
13+
Peppers int
14+
}
15+
16+
// This examples shows a complex and customized select.
17+
func ExampleSelect() {
18+
// The select will show a series of peppers stored inside a slice of structs. To display the content of the struct,
19+
// the usual dot notation is used inside the templates to select the fields and color them.
20+
peppers := []pepper{
21+
{Name: "Bell Pepper", HeatUnit: 0, Peppers: 0},
22+
{Name: "Banana Pepper", HeatUnit: 100, Peppers: 1},
23+
{Name: "Poblano", HeatUnit: 1000, Peppers: 2},
24+
{Name: "Jalapeño", HeatUnit: 3500, Peppers: 3},
25+
{Name: "Aleppo", HeatUnit: 10000, Peppers: 4},
26+
{Name: "Tabasco", HeatUnit: 30000, Peppers: 5},
27+
{Name: "Malagueta", HeatUnit: 50000, Peppers: 6},
28+
{Name: "Habanero", HeatUnit: 100000, Peppers: 7},
29+
{Name: "Red Savina Habanero", HeatUnit: 350000, Peppers: 8},
30+
{Name: "Dragon’s Breath", HeatUnit: 855000, Peppers: 9},
31+
}
32+
33+
// The Active and Selected templates set a small pepper icon next to the name colored and the heat unit for the
34+
// active template. The details template is show at the bottom of the select's list and displays the full info
35+
// for that pepper in a multi-line template.
36+
templates := &SelectTemplates{
37+
Label: "{{ . }}?",
38+
Active: "\U0001F336 {{ .Name | cyan }} ({{ .HeatUnit | red }})",
39+
Inactive: " {{ .Name | cyan }} ({{ .HeatUnit | red }})",
40+
Selected: "\U0001F336 {{ .Name | red | cyan }}",
41+
Details: `
42+
--------- Pepper ----------
43+
{{ "Name:" | faint }} {{ .Name }}
44+
{{ "Heat Unit:" | faint }} {{ .HeatUnit }}
45+
{{ "Peppers:" | faint }} {{ .Peppers }}`,
46+
}
47+
48+
// A searcher function is implemented which enabled the search mode for the select. The function follows
49+
// the required searcher signature and finds any pepper whose name contains the searched string.
50+
searcher := func(input string, index int) bool {
51+
pepper := peppers[index]
52+
name := strings.Replace(strings.ToLower(pepper.Name), " ", "", -1)
53+
input = strings.Replace(strings.ToLower(input), " ", "", -1)
54+
55+
return strings.Contains(name, input)
56+
}
57+
58+
prompt := Select{
59+
Label: "Spicy Level",
60+
Items: peppers,
61+
Templates: templates,
62+
Size: 4,
63+
Searcher: searcher,
64+
}
65+
66+
i, _, err := prompt.Run()
67+
68+
if err != nil {
69+
fmt.Printf("Prompt failed %v\n", err)
70+
return
71+
}
72+
73+
// The selected pepper will be displayed with its name and index in a formatted message.
74+
fmt.Printf("You choose number %d: %s\n", i+1, peppers[i].Name)
75+
}

example_selectwithadd_test.go

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package promptui
2+
3+
import "fmt"
4+
5+
// This example shows how to create a SelectWithAdd that will add each new item it is given to the
6+
// list of items until one is chosen.
7+
func ExampleSelectWithAdd() {
8+
items := []string{"Vim", "Emacs", "Sublime", "VSCode", "Atom"}
9+
index := -1
10+
var result string
11+
var err error
12+
13+
for index < 0 {
14+
prompt := SelectWithAdd{
15+
Label: "What's your text editor",
16+
Items: items,
17+
AddLabel: "Add your own",
18+
}
19+
20+
index, result, err = prompt.Run()
21+
22+
if index == -1 {
23+
items = append(items, result)
24+
}
25+
}
26+
27+
if err != nil {
28+
fmt.Printf("Prompt failed %v\n", err)
29+
return
30+
}
31+
32+
fmt.Printf("You choose %s\n", result)
33+
}

keycodes.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,23 @@ package promptui
55
import "github.com/chzyer/readline"
66

77
// These runes are used to identity the commands entered by the user in the command prompt. They map
8-
// to specific actions of prompt-ui and can be remapped if necessary.
8+
// to specific actions of promptui in prompt mode and can be remapped if necessary.
99
var (
10-
// KeyEnter is the default key for submission/selection inside a command line prompt.
10+
// KeyEnter is the default key for submission/selection.
1111
KeyEnter rune = readline.CharEnter
1212

13-
// KeyBackspace is the default key for deleting input text inside a command line prompt.
13+
// KeyBackspace is the default key for deleting input text.
1414
KeyBackspace rune = readline.CharBackspace
1515

16-
// KeyPrev is the default key to go up during selection inside a command line prompt.
16+
// KeyPrev is the default key to go up during selection.
1717
KeyPrev rune = readline.CharPrev
1818

19-
// KeyNext is the default key to go down during selection inside a command line prompt.
19+
// KeyNext is the default key to go down during selection.
2020
KeyNext rune = readline.CharNext
2121

22-
// KeyBackward is the default key to page up during selection inside a command line prompt.
22+
// KeyBackward is the default key to page up during selection.
2323
KeyBackward rune = readline.CharBackward
2424

25-
// KeyForward is the default key to page down during selection inside a command line prompt.
25+
// KeyForward is the default key to page down during selection.
2626
KeyForward rune = readline.CharForward
2727
)

list/list.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ type List struct {
2727
Searcher Searcher
2828
}
2929

30-
// New creates and initializes a list of searchable items. The items attribute must be a slice of items with a
30+
// New creates and initializes a list of searchable items. The items attribute must be a slice type with a
3131
// size greater than 0. Error will be returned if those two conditions are not met.
3232
func New(items interface{}, size int) (*List, error) {
3333
if size < 1 {
@@ -162,7 +162,7 @@ func (l *List) CanPageUp() bool {
162162
}
163163

164164
// Index returns the index of the item currently selected inside the searched list. If no item is selected,
165-
// the NotFound (-1) index will be returned instead.
165+
// the NotFound (-1) index is returned.
166166
func (l *List) Index() int {
167167
selected := l.scope[l.cursor]
168168

0 commit comments

Comments
 (0)