github.com/markusbkk/elvish@v0.0.0-20231204143114-91dc52438621/pkg/ui/style.go (about) 1 package ui 2 3 import ( 4 "fmt" 5 "strings" 6 ) 7 8 // Style specifies how something (mostly a string) shall be displayed. 9 type Style struct { 10 Foreground Color 11 Background Color 12 Bold bool 13 Dim bool 14 Italic bool 15 Underlined bool 16 Blink bool 17 Inverse bool 18 } 19 20 // SGR returns SGR sequence for the style. 21 func (s Style) SGR() string { 22 var sgr []string 23 24 addIf := func(b bool, code string) { 25 if b { 26 sgr = append(sgr, code) 27 } 28 } 29 addIf(s.Bold, "1") 30 addIf(s.Dim, "2") 31 addIf(s.Italic, "3") 32 addIf(s.Underlined, "4") 33 addIf(s.Blink, "5") 34 addIf(s.Inverse, "7") 35 if s.Foreground != nil { 36 sgr = append(sgr, s.Foreground.fgSGR()) 37 } 38 if s.Background != nil { 39 sgr = append(sgr, s.Background.bgSGR()) 40 } 41 42 return strings.Join(sgr, ";") 43 } 44 45 // MergeFromOptions merges all recognized values from a map to the current 46 // Style. 47 func (s *Style) MergeFromOptions(options map[string]interface{}) error { 48 assignColor := func(val interface{}, colorField *Color) string { 49 if val == "default" { 50 *colorField = nil 51 return "" 52 } else if s, ok := val.(string); ok { 53 color := parseColor(s) 54 if color != nil { 55 *colorField = color 56 return "" 57 } 58 } 59 return "valid color string" 60 } 61 assignBool := func(val interface{}, attrField *bool) string { 62 if b, ok := val.(bool); ok { 63 *attrField = b 64 } else { 65 return "bool value" 66 } 67 return "" 68 } 69 70 for k, v := range options { 71 var need string 72 73 switch k { 74 case "fg-color": 75 need = assignColor(v, &s.Foreground) 76 case "bg-color": 77 need = assignColor(v, &s.Background) 78 case "bold": 79 need = assignBool(v, &s.Bold) 80 case "dim": 81 need = assignBool(v, &s.Dim) 82 case "italic": 83 need = assignBool(v, &s.Italic) 84 case "underlined": 85 need = assignBool(v, &s.Underlined) 86 case "blink": 87 need = assignBool(v, &s.Blink) 88 case "inverse": 89 need = assignBool(v, &s.Inverse) 90 91 default: 92 return fmt.Errorf("unrecognized option '%s'", k) 93 } 94 95 if need != "" { 96 return fmt.Errorf("value for option '%s' must be a %s", k, need) 97 } 98 } 99 100 return nil 101 }