David K. Bainbridge | 528b318 | 2017-01-23 08:51:59 -0800 | [diff] [blame] | 1 | // Copyright 2016 Canonical Ltd. |
| 2 | // Licensed under the LGPLv3, see LICENCE file for details. |
| 3 | |
| 4 | package ansiterm |
| 5 | |
| 6 | import ( |
| 7 | "fmt" |
| 8 | "io" |
| 9 | ) |
| 10 | |
| 11 | // Context provides a way to specify both foreground and background colors |
| 12 | // along with other styles and write text to a Writer with those colors and |
| 13 | // styles. |
| 14 | type Context struct { |
| 15 | Foreground Color |
| 16 | Background Color |
| 17 | Styles []Style |
| 18 | } |
| 19 | |
| 20 | // Foreground is a convenience function that creates a Context with the |
| 21 | // specified color as the foreground color. |
| 22 | func Foreground(color Color) *Context { |
| 23 | return &Context{Foreground: color} |
| 24 | } |
| 25 | |
| 26 | // Background is a convenience function that creates a Context with the |
| 27 | // specified color as the background color. |
| 28 | func Background(color Color) *Context { |
| 29 | return &Context{Background: color} |
| 30 | } |
| 31 | |
| 32 | // Styles is a convenience function that creates a Context with the |
| 33 | // specified styles set. |
| 34 | func Styles(styles ...Style) *Context { |
| 35 | return &Context{Styles: styles} |
| 36 | } |
| 37 | |
| 38 | // SetForeground sets the foreground to the specified color. |
| 39 | func (c *Context) SetForeground(color Color) *Context { |
| 40 | c.Foreground = color |
| 41 | return c |
| 42 | } |
| 43 | |
| 44 | // SetBackground sets the background to the specified color. |
| 45 | func (c *Context) SetBackground(color Color) *Context { |
| 46 | c.Background = color |
| 47 | return c |
| 48 | } |
| 49 | |
| 50 | // SetStyle replaces the styles with the new values. |
| 51 | func (c *Context) SetStyle(styles ...Style) *Context { |
| 52 | c.Styles = styles |
| 53 | return c |
| 54 | } |
| 55 | |
| 56 | type sgrWriter interface { |
| 57 | io.Writer |
| 58 | writeSGR(value sgr) |
| 59 | } |
| 60 | |
| 61 | // Fprintf will set the sgr values of the writer to the specified |
| 62 | // foreground, background and styles, then write the formatted string, |
| 63 | // then reset the writer. |
| 64 | func (c *Context) Fprintf(w sgrWriter, format string, args ...interface{}) { |
| 65 | w.writeSGR(c) |
| 66 | fmt.Fprintf(w, format, args...) |
| 67 | w.writeSGR(reset) |
| 68 | } |
| 69 | |
| 70 | // Fprint will set the sgr values of the writer to the specified foreground, |
| 71 | // background and styles, then formats using the default formats for its |
| 72 | // operands and writes to w. Spaces are added between operands when neither is |
| 73 | // a string. It returns the number of bytes written and any write error |
| 74 | // encountered. |
| 75 | func (c *Context) Fprint(w sgrWriter, args ...interface{}) { |
| 76 | w.writeSGR(c) |
| 77 | fmt.Fprint(w, args...) |
| 78 | w.writeSGR(reset) |
| 79 | } |
| 80 | |
| 81 | func (c *Context) sgr() string { |
| 82 | var values attributes |
| 83 | if foreground := c.Foreground.foreground(); foreground != unknownAttribute { |
| 84 | values = append(values, foreground) |
| 85 | } |
| 86 | if background := c.Background.background(); background != unknownAttribute { |
| 87 | values = append(values, background) |
| 88 | } |
| 89 | for _, style := range c.Styles { |
| 90 | if value := style.enable(); value != unknownAttribute { |
| 91 | values = append(values, value) |
| 92 | } |
| 93 | } |
| 94 | return values.sgr() |
| 95 | } |