|
@@ -1,7 +1,10 @@
|
|
|
package door
|
|
|
|
|
|
import (
|
|
|
- "fmt"
|
|
|
+ "log"
|
|
|
+ "regexp"
|
|
|
+ "strconv"
|
|
|
+ "strings"
|
|
|
"syscall"
|
|
|
)
|
|
|
|
|
@@ -27,6 +30,105 @@ ok == false
|
|
|
writing to a closed channel is a panic.
|
|
|
|
|
|
*/
|
|
|
+func find_ansicolor(text string) [][]int {
|
|
|
+ var color_codes [][]int
|
|
|
+
|
|
|
+ word, _ := regexp.Compile("\x1b\\[([0-9;]+)m")
|
|
|
+ colors := word.FindAllStringIndex(text, -1)
|
|
|
+ // regexp seems to be ignoring the capture groups.
|
|
|
+ // colors := word.FindAllSubmatchIndex([]byte(text), len(text))
|
|
|
+ for _, pos := range colors {
|
|
|
+ txt := text[pos[0]+2 : pos[1]-1]
|
|
|
+ if txt == "" {
|
|
|
+ txt = "0"
|
|
|
+ }
|
|
|
+ log.Printf("Text: [%s]\n", txt)
|
|
|
+ codes := strings.Split(txt, ";")
|
|
|
+ log.Printf("Codes: [%#v]\n", codes)
|
|
|
+ code := make([]int, len(codes))
|
|
|
+ for idx, c := range codes {
|
|
|
+ var err error
|
|
|
+ code[idx], err = strconv.Atoi(c)
|
|
|
+ if err != nil {
|
|
|
+ log.Printf("Atoi: %#v [%s]\n", err, c)
|
|
|
+ }
|
|
|
+ color_codes = append(color_codes, code)
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ return color_codes
|
|
|
+}
|
|
|
+
|
|
|
+type ANSIColorParts struct {
|
|
|
+ Bold bool
|
|
|
+ Blink bool
|
|
|
+ FG int
|
|
|
+ BG int
|
|
|
+}
|
|
|
+
|
|
|
+func ParseColorArray(colorarray []int) ANSIColorParts {
|
|
|
+ var acp ANSIColorParts
|
|
|
+ acp.FG = -1
|
|
|
+ acp.BG = -1
|
|
|
+
|
|
|
+ for _, c := range colorarray {
|
|
|
+ switch c {
|
|
|
+ case 0:
|
|
|
+ acp.FG = 7
|
|
|
+ acp.BG = 0
|
|
|
+ case 1:
|
|
|
+ acp.Bold = true
|
|
|
+ case 5:
|
|
|
+ acp.Blink = true
|
|
|
+ case 30, 31, 32, 33, 34, 35, 36, 37:
|
|
|
+ acp.FG = c - 30
|
|
|
+ case 40, 41, 42, 43, 44, 45, 46, 47:
|
|
|
+ acp.BG = c - 40
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return acp
|
|
|
+}
|
|
|
+
|
|
|
+func (d *Door) ParseLastColor(output string) {
|
|
|
+ // use the last color information + whatever is in the string to
|
|
|
+ // track the last color set
|
|
|
+ updated := ParseColorArray(d.LastColor)
|
|
|
+ colors := find_ansicolor(output)
|
|
|
+ for _, codes := range colors {
|
|
|
+ if codes[0] == 0 {
|
|
|
+ updated = ParseColorArray(codes)
|
|
|
+ } else {
|
|
|
+ newCode := ParseColorArray(codes)
|
|
|
+ if newCode.Bold {
|
|
|
+ updated.Bold = true
|
|
|
+ }
|
|
|
+ if newCode.Blink {
|
|
|
+ updated.Blink = true
|
|
|
+ }
|
|
|
+ if (newCode.FG != -1) && (newCode.FG != updated.FG) {
|
|
|
+ updated.FG = newCode.FG
|
|
|
+ }
|
|
|
+ if (newCode.BG != -1) && (newCode.BG != updated.BG) {
|
|
|
+ updated.BG = newCode.BG
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ d.LastColor = make([]int, 1)
|
|
|
+ d.LastColor[0] = 0
|
|
|
+ if updated.Blink {
|
|
|
+ d.LastColor = append(d.LastColor, 5)
|
|
|
+ }
|
|
|
+ if updated.Bold {
|
|
|
+ d.LastColor = append(d.LastColor, 1)
|
|
|
+ }
|
|
|
+ if updated.FG != -1 {
|
|
|
+ d.LastColor = append(d.LastColor, updated.FG+30)
|
|
|
+ }
|
|
|
+ if updated.BG != -1 {
|
|
|
+ d.LastColor = append(d.LastColor, updated.BG+40)
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
// Write string to client.
|
|
|
func (d *Door) Write(output string) {
|
|
@@ -36,23 +138,35 @@ func (d *Door) Write(output string) {
|
|
|
|
|
|
defer func() {
|
|
|
if r := recover(); r != nil {
|
|
|
- fmt.println("Write error/HANGUP.")
|
|
|
+ log.Println("Write error/HANGUP.")
|
|
|
d.Disconnected = true
|
|
|
+ }
|
|
|
}()
|
|
|
|
|
|
+ if strings.HasSuffix(output, RestorePos) {
|
|
|
+ output += Color(d.LastColor...)
|
|
|
+ } else {
|
|
|
+ d.ParseLastColor(output)
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ temp := strings.Replace(output, "\x1b", "^[", -1)
|
|
|
+ log.Printf("Parse: [%s]\n", temp)
|
|
|
+ */
|
|
|
+
|
|
|
writerChannel <- output
|
|
|
|
|
|
/*
|
|
|
- buffer := []byte(output)
|
|
|
- n, err := syscall.Write(d.WRITEFD, buffer)
|
|
|
- if err != nil {
|
|
|
- fmt.Println("Write error/HANGUP?", n)
|
|
|
- d.Disconnected = true
|
|
|
- }
|
|
|
- // No, this isn't it. The # of bytes in buffer == bytes written.
|
|
|
- if n != len(buffer) {
|
|
|
- fmt.Printf("Write fail: %d != %d\n", len(buffer), n)
|
|
|
- }
|
|
|
+ buffer := []byte(output)
|
|
|
+ n, err := syscall.Write(d.WRITEFD, buffer)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("Write error/HANGUP?", n)
|
|
|
+ d.Disconnected = true
|
|
|
+ }
|
|
|
+ // No, this isn't it. The # of bytes in buffer == bytes written.
|
|
|
+ if n != len(buffer) {
|
|
|
+ fmt.Printf("Write fail: %d != %d\n", len(buffer), n)
|
|
|
+ }
|
|
|
*/
|
|
|
-
|
|
|
+
|
|
|
}
|