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  }