123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- package door
- import (
- "log"
- "regexp"
- "strconv"
- "strings"
- )
- var FindANSIColor *regexp.Regexp
- func init() {
- FindANSIColor = regexp.MustCompile("\x1b\\[([0-9;]*)m")
- }
- func find_ansicolor(text string) [][]int {
- var color_codes [][]int
- // word, _ := regexp.Compile("\x1b\\[([0-9;]+)m")
- colors := FindANSIColor.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)
- }
- }
- /*
- reading from a closed channel is easy to detect.
- res, ok := <-channel
- ok == false
- writing to a closed channel is a panic.
- */
- var writerChannel chan string
- // Write string to client.
- func (d *Door) Write(output string) {
- if d.Disconnected {
- return
- }
- defer func() {
- if r := recover(); r != nil {
- 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)
- }
- */
- }
|