1 // The code in this file is adapted from github.com/mattn/go-colorable.
17 type colorWriter struct {
24 // NewColorWriter returns an io.Writer that writes to w and provides cross
25 // platform support for ANSI color codes. If w is not a terminal it is
26 // returned unmodified.
27 func NewColorWriter(w io.Writer) io.Writer {
32 var csbi consoleScreenBufferInfo
33 handle := syscall.Handle(w.(fder).Fd())
34 procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
39 oldattr: csbi.attributes,
43 func (w *colorWriter) Write(data []byte) (n int, err error) {
44 var csbi consoleScreenBufferInfo
45 procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
47 er := bytes.NewBuffer(data)
50 r1, _, err := procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
55 c1, _, err := er.ReadRune()
60 fmt.Fprint(w.out, string(c1))
63 c2, _, err := er.ReadRune()
65 w.lastbuf.WriteRune(c1)
69 w.lastbuf.WriteRune(c1)
70 w.lastbuf.WriteRune(c2)
77 c, _, err := er.ReadRune()
79 w.lastbuf.WriteRune(c1)
80 w.lastbuf.WriteRune(c2)
81 w.lastbuf.Write(buf.Bytes())
84 if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' {
88 buf.Write([]byte(string(c)))
93 attr := csbi.attributes
96 procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(w.oldattr))
99 token := strings.Split(cs, ";")
100 intensityMode := word(0)
101 for _, ns := range token {
102 if n, err = strconv.Atoi(ns); err == nil {
107 attr |= intensityMode
108 case 30 <= n && n <= 37:
109 attr = (attr & backgroundMask)
111 attr |= foregroundRed
114 attr |= foregroundGreen
117 attr |= foregroundBlue
119 intensityMode = foregroundIntensity
120 case n == 39: // reset foreground color
121 attr &= backgroundMask
122 attr |= w.oldattr & foregroundMask
123 case 40 <= n && n <= 47:
124 attr = (attr & foregroundMask)
126 attr |= backgroundRed
129 attr |= backgroundGreen
132 attr |= backgroundBlue
134 intensityMode = backgroundIntensity
135 case n == 49: // reset background color
136 attr &= foregroundMask
137 attr |= w.oldattr & backgroundMask
139 procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(attr))
144 return len(data) - w.lastbuf.Len(), nil
148 procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
149 procSetConsoleTextAttribute = kernel32.NewProc("SetConsoleTextAttribute")
154 foregroundGreen = 0x2
156 foregroundIntensity = 0x8
157 foregroundMask = (foregroundRed | foregroundBlue | foregroundGreen | foregroundIntensity)
158 backgroundBlue = 0x10
159 backgroundGreen = 0x20
161 backgroundIntensity = 0x80
162 backgroundMask = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity)
177 type smallRect struct {
184 type consoleScreenBufferInfo struct {
189 maximumWindowSize coord