-
Notifications
You must be signed in to change notification settings - Fork 0
/
logh.go
115 lines (96 loc) · 2.29 KB
/
logh.go
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package logh
import (
"bufio"
"fmt"
"io"
"regexp"
"github.com/fatih/color"
)
var Colors = []color.Attribute{
color.FgRed,
color.FgGreen,
color.FgBlue,
color.FgYellow,
color.FgCyan,
color.FgHiRed,
color.FgHiGreen,
color.FgHiBlue,
color.FgHiYellow,
color.FgHiCyan,
}
type HighlightConfig struct {
IgnoreCase bool
}
func Highlight(in io.Reader, out io.Writer, config HighlightConfig, expressions ...string) error {
// Instantiates all the colors
colors := make([]*color.Color, len(expressions))
// Create a regexp for each expression
regexes := make([]*regexp.Regexp, len(expressions))
for i, expr := range expressions {
if expr == "" { // if expr is empty, we shouldn't really match with anything
expr = "^$"
}
if config.IgnoreCase {
expr = "(?i)" + expr
}
rg, err := regexp.Compile(expr)
if err != nil {
return fmt.Errorf("error compiling regular expression %s: %s", expr, err)
}
regexes[i] = rg
c := Colors[i%len(Colors)]
colors[i] = color.New(c)
}
// Read each line from in
scanner := bufio.NewScanner(in)
for scanner.Scan() {
line := scanner.Text()
// Maps a color for each char in line.
// -1 is the default color
// each matching regex will "paint" this slice with the color index
lineColors := make([]int, len(line))
for i := range lineColors {
lineColors[i] = -1
}
// See if matches with any regexes
matched := false
for i, rg := range regexes {
indexes := rg.FindAllStringIndex(line, -1)
for _, match := range indexes {
start, end := match[0], match[1]
for j := start; j < end; j++ {
lineColors[j] = i
}
matched = true
}
}
if matched {
buff := ""
lastColorIdx := -1
for i, ch := range line {
if lineColors[i] == lastColorIdx {
buff += string(ch)
continue
}
if lastColorIdx == -1 {
fmt.Fprintf(out, "%s", buff)
} else {
lastColor := colors[lastColorIdx]
fmt.Fprintf(out, "%s", lastColor.Sprint(buff))
}
lastColorIdx = lineColors[i]
buff = string(ch)
}
if lastColorIdx == -1 {
fmt.Fprintf(out, "%s\n", buff)
} else {
lastColor := colors[lastColorIdx]
fmt.Fprintf(out, "%s\n", lastColor.Sprint(buff))
}
} else {
// No matches, print with default color
fmt.Fprintf(out, "%s\n", scanner.Text())
}
}
return nil
}