github.com/vugu/vugu@v0.3.5/vgform/util.go (about) 1 package vgform 2 3 import ( 4 "sort" 5 "strings" 6 ) 7 8 // KeyLister provides a list keys as a string slice. 9 // Keys are used in the `value` attribute of HTML option tags (with a select). 10 type KeyLister interface { 11 KeyList() []string 12 } 13 14 // KeyListerFunc implements KeyLister as a function. 15 type KeyListerFunc func() []string 16 17 // KeyList implements the KeyLister interface. 18 func (f KeyListerFunc) KeyList() []string { return f() } 19 20 // TextMapper provides mapping from a key to the corresponding text. 21 // Text is used inside the contents of an HTML option tag (with a select). 22 // Text values are always HTML escaped. 23 type TextMapper interface { 24 TextMap(key string) string 25 } 26 27 // TextMapperFunc implements TextMapper as a function. 28 type TextMapperFunc func(key string) string 29 30 // TextMap implements the TextMapper interface. 31 func (f TextMapperFunc) TextMap(key string) string { return f(key) } 32 33 // SimpleTitle implements TextMapper by replacing '-' and '_' with a space and calling strings.Title. 34 var SimpleTitle = TextMapperFunc(func(key string) string { 35 return strings.Title(strings.NewReplacer("-", " ", "_", " ").Replace(key)) 36 }) 37 38 // Options is an interface with KeyList and TextMap. 39 // It is used to express the options for a select element. 40 // It intentionally does not support option groups or other 41 // advanced behavior as that can be accomplished using slots (TO BE IMPLEMENTED). 42 // Options is provided to make it easy for the common case of 43 // adapting a slice or map to be used as select options. 44 type Options interface { 45 KeyLister 46 TextMapper 47 } 48 49 // MapOptions implements the Options interface on a map[string]string. 50 // The keys will be returned in alphanumeric sequence (using sort.Strings), 51 // or you can call SortFunc to assign a custom sort function. 52 type MapOptions map[string]string 53 54 // KeyList implements KeyLister by returning the map keys sorted with sort.Strings(). 55 func (m MapOptions) KeyList() []string { 56 s := make([]string, 0, len(m)) 57 for k := range m { 58 s = append(s, k) 59 } 60 sort.Strings(s) 61 return s 62 } 63 64 // TextMap implements TextMapper by returning `m[key]`. 65 func (m MapOptions) TextMap(key string) string { return m[key] } 66 67 // SortFunc returns an Options instance that uses this map for 68 // keys and text and sorts according to the order specified by this 69 // function. 70 func (m MapOptions) SortFunc(sf func(i, j int) bool) Options { 71 return customOptions{ 72 KeyLister: KeyListerFunc(func() []string { 73 // build the key list directly, calling m.KeyList would call sort.Strings unnecessarily 74 s := make([]string, 0, len(m)) 75 for k := range m { 76 s = append(s, k) 77 } 78 sort.Slice(s, sf) 79 return s 80 }), 81 TextMapper: m, 82 } 83 } 84 85 // SliceOptions implements the Options interface on a []string. 86 // The slice specifies the sequence and these exact string keys are 87 // also used as the text. You can also call Title() to use the 88 // SimpleTitle mapper or use TextFunc to assign a custom text mapper. 89 type SliceOptions []string 90 91 // Title is shorthand for s.TextFunc(SimpleTitle). 92 func (s SliceOptions) Title() Options { 93 return s.TextFunc(SimpleTitle) 94 } 95 96 // KeyList implements KeyLister with a type conversion ([]string(s)). 97 func (s SliceOptions) KeyList() []string { return []string(s) } 98 99 // TextMap implements TextMapper by returning the key as the text. 100 func (s SliceOptions) TextMap(key string) string { return key } 101 102 // TextFunc returns an Options instance that uses this slice 103 // as the key list and the specified function for text mapping. 104 func (s SliceOptions) TextFunc(tmf TextMapperFunc) Options { 105 return customOptions{ 106 KeyLister: s, 107 TextMapper: tmf, 108 } 109 } 110 111 type customOptions struct { 112 KeyLister 113 TextMapper 114 }