github.com/xyproto/u-root@v6.0.1-0.20200302025726-5528e0c77a3c+incompatible/cmds/core/elvish/edit/ui/styled.go (about)

     1  package ui
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/u-root/u-root/cmds/core/elvish/eval/vals"
     8  	"github.com/u-root/u-root/cmds/core/elvish/hash"
     9  	"github.com/u-root/u-root/cmds/core/elvish/parse"
    10  	"github.com/u-root/u-root/cmds/core/elvish/vector"
    11  )
    12  
    13  // Styled is a piece of text with style.
    14  type Styled struct {
    15  	Text   string
    16  	Styles Styles
    17  }
    18  
    19  var styleTranslationTable = map[string]string{
    20  	"bold":       "1",
    21  	"dim":        "2",
    22  	"italic":     "3",
    23  	"underlined": "4",
    24  	"blink":      "5",
    25  	"inverse":    "7",
    26  
    27  	"black":        "30",
    28  	"red":          "31",
    29  	"green":        "32",
    30  	"yellow":       "33",
    31  	"blue":         "34",
    32  	"magenta":      "35",
    33  	"cyan":         "36",
    34  	"lightgray":    "37",
    35  	"gray":         "90",
    36  	"lightred":     "91",
    37  	"lightgreen":   "92",
    38  	"lightyellow":  "93",
    39  	"lightblue":    "94",
    40  	"lightmagenta": "95",
    41  	"lightcyan":    "96",
    42  	"white":        "97",
    43  
    44  	"bg-default":      "49",
    45  	"bg-black":        "40",
    46  	"bg-red":          "41",
    47  	"bg-green":        "42",
    48  	"bg-yellow":       "43",
    49  	"bg-blue":         "44",
    50  	"bg-magenta":      "45",
    51  	"bg-cyan":         "46",
    52  	"bg-lightgray":    "47",
    53  	"bg-gray":         "100",
    54  	"bg-lightred":     "101",
    55  	"bg-lightgreen":   "102",
    56  	"bg-lightyellow":  "103",
    57  	"bg-lightblue":    "104",
    58  	"bg-lightmagenta": "105",
    59  	"bg-lightcyan":    "106",
    60  	"bg-white":        "107",
    61  }
    62  
    63  func Unstyled(s string) Styled {
    64  	return Styled{s, Styles{}}
    65  }
    66  
    67  func (s *Styled) Kind() string {
    68  	return "styled"
    69  }
    70  
    71  func (s *Styled) Equal(a interface{}) bool {
    72  	rhs, ok := a.(*Styled)
    73  	if !ok {
    74  		return false
    75  	}
    76  	return s.Text == rhs.Text && s.Styles.Eq(rhs.Styles)
    77  }
    78  
    79  func (s *Styled) Hash() uint32 {
    80  	h := hash.DJBInit
    81  	h = hash.DJBCombine(h, hash.Hash(s.Text))
    82  	h = hash.DJBCombine(h, s.Styles.Hash())
    83  	return h
    84  }
    85  
    86  func (s *Styled) String() string {
    87  	return "\033[" + s.Styles.String() + "m" + s.Text + "\033[m"
    88  }
    89  
    90  func (s *Styled) Repr(indent int) string {
    91  	quotedStyles := make([]string, len(s.Styles))
    92  	for i, st := range s.Styles {
    93  		quotedStyles[i] = parse.Quote(st)
    94  	}
    95  	return fmt.Sprintf("(edit:styled %s [%s]",
    96  		parse.Quote(s.Text), strings.Join(quotedStyles, " "))
    97  }
    98  
    99  func (s *Styled) Index(k interface{}) (interface{}, bool) {
   100  	switch k {
   101  	case "text":
   102  		return s.Text, true
   103  	case "styles":
   104  		li := vector.Empty
   105  		for _, st := range s.Styles {
   106  			li = li.Cons(st)
   107  		}
   108  		return li, true
   109  	default:
   110  		return nil, false
   111  	}
   112  }
   113  
   114  func (s *Styled) IterateKeys(f func(interface{}) bool) {
   115  	vals.Feed(f, "text", "styles")
   116  }
   117  
   118  type Styles []string
   119  
   120  func (ss Styles) Eq(rhs Styles) bool {
   121  	if len(ss) != len(rhs) {
   122  		return false
   123  	}
   124  	for i, s := range ss {
   125  		if s != rhs[i] {
   126  			return false
   127  		}
   128  	}
   129  	return true
   130  }
   131  
   132  func (ss Styles) Hash() uint32 {
   133  	h := hash.DJBInit
   134  	for _, s := range ss {
   135  		h = hash.DJBCombine(h, hash.Hash(s))
   136  	}
   137  	return h
   138  }
   139  
   140  func JoinStyles(so Styles, st ...Styles) Styles {
   141  	for _, v := range st {
   142  		so = append(so, v...)
   143  	}
   144  
   145  	return so
   146  }
   147  
   148  func TranslateStyle(s string) string {
   149  	v, ok := styleTranslationTable[s]
   150  	if ok {
   151  		return v
   152  	}
   153  	return s
   154  }
   155  
   156  func StylesFromString(s string) Styles {
   157  	var st Styles
   158  	for _, v := range strings.Split(s, ";") {
   159  		st = append(st, v)
   160  	}
   161  
   162  	return st
   163  }
   164  
   165  func (s Styles) String() string {
   166  	var o string
   167  	for i, v := range s {
   168  		if len(v) > 0 {
   169  			if i > 0 {
   170  				o += ";"
   171  			}
   172  			o += TranslateStyle(v)
   173  		}
   174  	}
   175  
   176  	return o
   177  }