File: vtclean.go

package info (click to toggle)
golang-github-lunixbochs-vtclean 0.0~git20170504.d14193d-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 84 kB
  • sloc: makefile: 3
file content (88 lines) | stat: -rw-r--r-- 1,843 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package vtclean

import (
	"bytes"
	"regexp"
	"strconv"
)

// see regex.txt for a slightly separated version of this regex
var vt100re = regexp.MustCompile(`^\033([\[\]]([\d\?]+)?(;[\d\?]+)*)?(.)`)
var vt100exc = regexp.MustCompile(`^\033(\[[^a-zA-Z0-9@\?]+|[\(\)]).`)

// this is to handle the RGB escape generated by `tput initc 1 500 500 500`
var vt100long = regexp.MustCompile(`^\033](\d+);([^\033]+)\033\\`)

func Clean(line string, color bool) string {
	var edit = newLineEdit(len(line))
	lineb := []byte(line)

	hadColor := false
	for i := 0; i < len(lineb); {
		c := lineb[i]
		switch c {
		case '\b':
			edit.Move(-1)
		case '\033':
			// set terminal title
			if bytes.HasPrefix(lineb[i:], []byte("\x1b]0;")) {
				pos := bytes.Index(lineb[i:], []byte("\a"))
				if pos != -1 {
					i += pos + 1
					continue
				}
			}
			if m := vt100long.Find(lineb[i:]); m != nil {
				i += len(m)
			} else if m := vt100exc.Find(lineb[i:]); m != nil {
				i += len(m)
			} else if m := vt100re.FindSubmatch(lineb[i:]); m != nil {
				i += len(m[0])
				num := string(m[2])
				n, err := strconv.Atoi(num)
				if err != nil || n > 10000 {
					n = 1
				}
				switch m[4][0] {
				case 'm':
					if color {
						hadColor = true
						edit.Vt100(m[0])
					}
				case '@':
					edit.Insert(bytes.Repeat([]byte{' '}, n))
				case 'G':
					edit.MoveAbs(n)
				case 'C':
					edit.Move(n)
				case 'D':
					edit.Move(-n)
				case 'P':
					edit.Delete(n)
				case 'K':
					switch num {
					case "", "0":
						edit.ClearRight()
					case "1":
						edit.ClearLeft()
					case "2":
						edit.Clear()
					}
				}
			} else {
				i += 1
			}
			continue
		default:
			if c == '\n' || c >= ' ' {
				edit.Write([]byte{c})
			}
		}
		i += 1
	}
	out := edit.Bytes()
	if hadColor {
		out = append(out, []byte("\033[0m")...)
	}
	return string(out)
}