elvish/styled/styled.go
fehnomenal e89fe48870 Add styled and styled-segment builtins (#674)
* Add compatibility test with old implementation

* Add color type

* Add basic style structs and utilities

* Add structs for styled segments and texts

* Add default style transformers to reimplement $edit:styled~

* Add builtins to manipulate styled segments and texts

* Rename style 'underline' -> 'underlined'

* Fix test case

* Add conversion from styled text to ansi sequences

* Return errors rather than throwing

* Validate the type of boolean options

* Delegate old to new styled function

* Rebase for new test framework api and expand test cases

* Remove old builtin function $edit:styled~

* Use strings to represent colors

* Convert bool pointers to simple bool values

* Validate color strings

* Do no longer expose builtin style transformers

* Fix confusion about pointers

* Make outputs more stable

* Expand tests

* Use pointers instead of passing setter functions

* Unexport and rename color check

* Use the empty string for default colors

* Expand tests

* Simplify styled transformers

Now there are three transformers for each boolean style attribute that
allow setting, unsetting and toggling the corresponding attribute.

* Rework and add doc comments
2018-05-28 21:24:09 +01:00

102 lines
1.9 KiB
Go

package styled
import (
"fmt"
)
// Style specifies how something (mostly a string) shall be displayed.
type Style struct {
Foreground string
Background string
Bold bool
Dim bool
Italic bool
Underlined bool
Blink bool
Inverse bool
}
// ImportFromOptions assigns all recognized values from a map to the current
// Style.
func (s *Style) ImportFromOptions(options map[string]interface{}) error {
assignColor := func(key string, colorField *string) error {
if c, ok := options[key]; ok {
if c, ok := c.(string); ok && isValidColorName(c) {
if c == "default" {
*colorField = ""
} else {
*colorField = c
}
} else {
return fmt.Errorf("value to option '%s' must be a valid color string", key)
}
}
return nil
}
assignBool := func(key string, attrField *bool) error {
if b, ok := options[key]; ok {
if b, ok := b.(bool); ok {
*attrField = b
} else {
return fmt.Errorf("value to option '%s' must be a bool value", key)
}
}
return nil
}
if err := assignColor("fg-color", &s.Foreground); err != nil {
return err
}
if err := assignColor("bg-color", &s.Background); err != nil {
return err
}
if err := assignBool("bold", &s.Bold); err != nil {
return err
}
if err := assignBool("dim", &s.Dim); err != nil {
return err
}
if err := assignBool("italic", &s.Italic); err != nil {
return err
}
if err := assignBool("underlined", &s.Underlined); err != nil {
return err
}
if err := assignBool("blink", &s.Blink); err != nil {
return err
}
if err := assignBool("inverse", &s.Inverse); err != nil {
return err
}
return nil
}
func isValidColorName(col string) bool {
switch col {
case
"default",
"black",
"red",
"green",
"yellow",
"blue",
"magenta",
"cyan",
"lightgray",
"gray",
"lightred",
"lightgreen",
"lightyellow",
"lightblue",
"lightmagenta",
"lightcyan",
"white":
return true
default:
return false
}
}