yay 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +0 -0
- data/bin/yay +5 -0
- data/data/defaults/log.yay +5 -0
- data/data/defaults/log4x.yay +18 -0
- data/data/defaults/syslog.yay +18 -0
- data/data/examples/errors.yay +6 -0
- data/data/examples/regex.yay +24 -0
- data/data/examples/variables.yay +11 -0
- data/data/grammar.y +56 -0
- data/data/lexer_tests.rb +171 -0
- data/data/parser_tests.rb +153 -0
- data/lib/yay/application.rb +44 -0
- data/lib/yay/colour_wheel.rb +58 -0
- data/lib/yay/colourizer.rb +58 -0
- data/lib/yay/errors.rb +109 -0
- data/lib/yay/installer.rb +12 -0
- data/lib/yay/lexer.rb +60 -0
- data/lib/yay/lexer_regex.rb +38 -0
- data/lib/yay/loader.rb +57 -0
- data/lib/yay/parser.rb +89 -0
- data/lib/yay/parser_gen.rb +319 -0
- data/lib/yay/rule_set.rb +92 -0
- data/lib/yay/version.rb +19 -0
- metadata +89 -0
data/LICENSE
ADDED
File without changes
|
data/bin/yay
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/yay
|
2
|
+
# Highlights log4j style messages
|
3
|
+
|
4
|
+
debug and trace are @boring
|
5
|
+
"normal" and info are @normal
|
6
|
+
warning is @interesting
|
7
|
+
error is @serious
|
8
|
+
fatal is @serious
|
9
|
+
|
10
|
+
# some words that aren't logger levels but are still important
|
11
|
+
exception is @serious
|
12
|
+
"unhandled exception" is @serious
|
13
|
+
important is @serious
|
14
|
+
|
15
|
+
@boring are dim lines
|
16
|
+
@normal is normal
|
17
|
+
@interesting is yellow
|
18
|
+
@serious is an inverted red line
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/yay
|
2
|
+
# Highlights syslog messages
|
3
|
+
|
4
|
+
insensitive
|
5
|
+
|
6
|
+
debug is normal
|
7
|
+
informational is gray
|
8
|
+
notice and warning are yellow
|
9
|
+
error and alert are red
|
10
|
+
critical and emergency are red lines
|
11
|
+
|
12
|
+
# some aliases
|
13
|
+
dbg is normal
|
14
|
+
info is gray
|
15
|
+
notice and warn are yellow
|
16
|
+
err and alert
|
17
|
+
crit and emerg are red lines
|
18
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/yay
|
2
|
+
# yay regexes are just like the ones in ruby/perl
|
3
|
+
|
4
|
+
# Lets write something really simple
|
5
|
+
/simple/ is blue
|
6
|
+
|
7
|
+
# Let's match something more complex (like _this _th1s __)
|
8
|
+
/_[_\w0-9]*/ is green
|
9
|
+
|
10
|
+
# Let's find a regex with a regex!
|
11
|
+
/\/\[\_\\w\]\[\_\\w0\-9\]\*\// is yellow
|
12
|
+
|
13
|
+
# So how can we make them case insensitive?
|
14
|
+
/HELLO/i is blue
|
15
|
+
|
16
|
+
# Yay's case commands only affect literals, not regexes
|
17
|
+
sensitive /Sensitive/ is blue
|
18
|
+
insensitive /Insensitive/ is green
|
19
|
+
|
20
|
+
# We can treat a regex like a normal string by using quotes
|
21
|
+
"/[match this string]/" is red
|
22
|
+
|
23
|
+
# Or we can escape the first character
|
24
|
+
\/[andthisonetoo]/ is red
|
data/data/grammar.y
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# the yay language grammar
|
2
|
+
|
3
|
+
class ParserGen
|
4
|
+
rule
|
5
|
+
|
6
|
+
body: command_list { }
|
7
|
+
| literal { load_file val[0] }
|
8
|
+
| install literal { install_file val[1] }
|
9
|
+
| installed { print_installed }
|
10
|
+
|
|
11
|
+
|
12
|
+
command_list: command and_opt command_list { }
|
13
|
+
| command { }
|
14
|
+
|
15
|
+
command: match
|
16
|
+
| assignment
|
17
|
+
| substitution
|
18
|
+
| equivalence
|
19
|
+
| include_file
|
20
|
+
|
21
|
+
match: string_list verbs_opt colour_list line_opt { @ruleset.add_match val[0], handle_colours(val[2]), val[3] }
|
22
|
+
|
23
|
+
assignment: string_list verbs_opt variable { @ruleset.add_assignment val[0], val[2] }
|
24
|
+
|
25
|
+
substitution: variable verbs_opt colour_list line_opt { @ruleset.add_substitution val[0], handle_colours(val[2]), val[3] }
|
26
|
+
|
27
|
+
equivalence: variable verbs_opt variable { @ruleset.add_equivalence val[0], val[2] }
|
28
|
+
|
29
|
+
include_file: include literal { load_file val[0] }
|
30
|
+
|
31
|
+
string_list: string and_opt string_list { val[2].unshift(val[0]); result = val[2] }
|
32
|
+
| string { result = [val[0]] }
|
33
|
+
|
34
|
+
string: literal { result = handle_string(val[0]) }
|
35
|
+
| regex { result = handle_regex(val[0]) }
|
36
|
+
|
37
|
+
colour_list: colour colour_list { val[1].unshift(val[0].to_sym); result = val[1] }
|
38
|
+
| colour { result = [val[0].to_sym] }
|
39
|
+
|
40
|
+
and_opt: and { result = nil }
|
41
|
+
| { }
|
42
|
+
|
43
|
+
line_opt: line { result = true }
|
44
|
+
| { result = false }
|
45
|
+
|
46
|
+
verbs_opt: verb verbs_opt { result = nil }
|
47
|
+
| { }
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
---- header
|
52
|
+
class Yay
|
53
|
+
---- inner
|
54
|
+
|
55
|
+
---- footer
|
56
|
+
end # class Yay
|
data/data/lexer_tests.rb
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
class Yay
|
2
|
+
LEXER_TESTS = {
|
3
|
+
|
4
|
+
# empty files
|
5
|
+
"" => [],
|
6
|
+
" " => [],
|
7
|
+
|
8
|
+
# isolated colour
|
9
|
+
"red" => [
|
10
|
+
[:colour, "red"]
|
11
|
+
],
|
12
|
+
|
13
|
+
# non-interference with literals
|
14
|
+
"splodge red" => [
|
15
|
+
[:literal, "splodge"],
|
16
|
+
[:colour, "red"]
|
17
|
+
],
|
18
|
+
|
19
|
+
# multiple colours
|
20
|
+
"green red" => [
|
21
|
+
[:colour, "green"],
|
22
|
+
[:colour, "red"]
|
23
|
+
],
|
24
|
+
|
25
|
+
# quoted
|
26
|
+
"\"red\" green" => [
|
27
|
+
[:literal, "red"],
|
28
|
+
[:colour, "green"]
|
29
|
+
],
|
30
|
+
|
31
|
+
# word boundaries
|
32
|
+
"hatred of greenspan red" => [
|
33
|
+
[:literal, "hatred"],
|
34
|
+
[:literal, "of"],
|
35
|
+
[:literal, "greenspan"],
|
36
|
+
[:colour, "red"]
|
37
|
+
],
|
38
|
+
|
39
|
+
# literal
|
40
|
+
"abc" => [
|
41
|
+
[:literal, "abc"]
|
42
|
+
],
|
43
|
+
|
44
|
+
# multiple literals
|
45
|
+
" abc d_e_f h1i2j " => [
|
46
|
+
[:literal, "abc"],
|
47
|
+
[:literal, "d_e_f"],
|
48
|
+
[:literal, "h1i2j"]
|
49
|
+
],
|
50
|
+
|
51
|
+
# double quoted literals
|
52
|
+
"\"abc\"" => [
|
53
|
+
[:literal, "abc"]
|
54
|
+
],
|
55
|
+
|
56
|
+
"\"a b c\"" => [
|
57
|
+
[:literal, "a b c"]
|
58
|
+
],
|
59
|
+
|
60
|
+
# double quoted - non-interference
|
61
|
+
"123 \"abc\" def" => [
|
62
|
+
[:literal, "123"],
|
63
|
+
[:literal, "abc"],
|
64
|
+
[:literal, "def"]
|
65
|
+
],
|
66
|
+
|
67
|
+
# double quoted and escaped
|
68
|
+
" \"abc\\\"def\\\"hij\"" => [
|
69
|
+
[:literal, "abc\"def\"hij"]
|
70
|
+
],
|
71
|
+
|
72
|
+
# multiple double quoted and escaped
|
73
|
+
" \"abc\\\"def\\\"hij\" \"123\\\"456\\\"789\"" => [
|
74
|
+
[:literal, "abc\"def\"hij"],
|
75
|
+
[:literal, "123\"456\"789"]
|
76
|
+
],
|
77
|
+
|
78
|
+
# regular expressions
|
79
|
+
"/abc/" => [
|
80
|
+
[:regex, "/abc/"]
|
81
|
+
],
|
82
|
+
|
83
|
+
# unclosed regex
|
84
|
+
"/abc" => [
|
85
|
+
[:junk, "/abc"]
|
86
|
+
],
|
87
|
+
|
88
|
+
# regex with modifier
|
89
|
+
"/abc/i" => [
|
90
|
+
[:regex, "/abc/i"]
|
91
|
+
],
|
92
|
+
|
93
|
+
# regex with whitespace
|
94
|
+
"/abc def/" => [
|
95
|
+
[:regex, "/abc def/"]
|
96
|
+
],
|
97
|
+
|
98
|
+
# FIXME
|
99
|
+
# regex with escaping
|
100
|
+
#"/abc\/def/" => [
|
101
|
+
# [:regex, "/abc\/def/"]
|
102
|
+
#],
|
103
|
+
|
104
|
+
# FIXME
|
105
|
+
# regex withescaping and modifier
|
106
|
+
#"/abc\/def/i" => [
|
107
|
+
# [:regex, "/abc\/def/i"]
|
108
|
+
#],
|
109
|
+
|
110
|
+
# regex noninterference
|
111
|
+
"/abc/ 123" => [
|
112
|
+
[:regex, "/abc/"],
|
113
|
+
[:literal, "123"],
|
114
|
+
],
|
115
|
+
|
116
|
+
# refex noninterference
|
117
|
+
"/abc/ 123 /def/" => [
|
118
|
+
[:regex, "/abc/"],
|
119
|
+
[:literal, "123"],
|
120
|
+
[:regex, "/def/"],
|
121
|
+
],
|
122
|
+
|
123
|
+
# regex with modifier noninterference
|
124
|
+
"/abc/i 123 /def/" => [
|
125
|
+
[:regex, "/abc/i"],
|
126
|
+
[:literal, "123"],
|
127
|
+
[:regex, "/def/"],
|
128
|
+
],
|
129
|
+
|
130
|
+
# FIXME
|
131
|
+
# regex with modifier, regex with escaping noninterference
|
132
|
+
#"/abc/i 123 /def/ /abc\/def/ efg" => [
|
133
|
+
# [:regex, "/abc/i"],
|
134
|
+
# [:literal, "123"],
|
135
|
+
# [:regex, "/def/"],
|
136
|
+
# [:regex, "/abc\/def/"],
|
137
|
+
# [:literal, "efg"],
|
138
|
+
#],
|
139
|
+
|
140
|
+
# quoted regex
|
141
|
+
"\"/abc/i\"" => [
|
142
|
+
[:literal, "/abc/i"]
|
143
|
+
],
|
144
|
+
|
145
|
+
# multiple quoted regexes with whitespace
|
146
|
+
"\"/abc/ /def\"" => [
|
147
|
+
[:literal, "/abc/ /def"]
|
148
|
+
],
|
149
|
+
|
150
|
+
# and
|
151
|
+
"and cheese and" => [
|
152
|
+
[:and, "and"],
|
153
|
+
[:literal, "cheese"],
|
154
|
+
[:and, "and"]
|
155
|
+
],
|
156
|
+
|
157
|
+
# quoted and
|
158
|
+
"\"and\"" => [
|
159
|
+
[:literal, "and"]
|
160
|
+
],
|
161
|
+
|
162
|
+
# commas
|
163
|
+
"mushroom, chicken and pasta" => [
|
164
|
+
[:literal, "mushroom"],
|
165
|
+
[:and, ","],
|
166
|
+
[:literal, "chicken"],
|
167
|
+
[:and, "and"],
|
168
|
+
[:literal, "pasta"]
|
169
|
+
],
|
170
|
+
}
|
171
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
require 'yay/colour_wheel'
|
2
|
+
class Yay
|
3
|
+
PARSER_TESTS = {
|
4
|
+
|
5
|
+
# empty files
|
6
|
+
"" => [],
|
7
|
+
" " => [],
|
8
|
+
|
9
|
+
# simple match
|
10
|
+
"apples are green" => [
|
11
|
+
[/apples/i, [ColourWheel::FG[:green]], false],
|
12
|
+
],
|
13
|
+
|
14
|
+
# simple match, lines
|
15
|
+
"apples are green lines" => [
|
16
|
+
[/apples/i, [ColourWheel::FG[:green]], true],
|
17
|
+
],
|
18
|
+
|
19
|
+
# multiple match without and or are
|
20
|
+
"apples grass green" => [
|
21
|
+
[/apples/i, [ColourWheel::FG[:green]], false],
|
22
|
+
[/grass/i, [ColourWheel::FG[:green]], false],
|
23
|
+
],
|
24
|
+
|
25
|
+
# multiple match with and
|
26
|
+
"apples and grass green" => [
|
27
|
+
[/apples/i, [ColourWheel::FG[:green]], false],
|
28
|
+
[/grass/i, [ColourWheel::FG[:green]], false],
|
29
|
+
],
|
30
|
+
|
31
|
+
# multiple match with and and are
|
32
|
+
"apples and grass are green" => [
|
33
|
+
[/apples/i, [ColourWheel::FG[:green]], false],
|
34
|
+
[/grass/i, [ColourWheel::FG[:green]], false],
|
35
|
+
],
|
36
|
+
|
37
|
+
# more matches
|
38
|
+
"apples olives and grass are green" => [
|
39
|
+
[/apples/i, [ColourWheel::FG[:green]], false],
|
40
|
+
[/olives/i, [ColourWheel::FG[:green]], false],
|
41
|
+
[/grass/i, [ColourWheel::FG[:green]], false],
|
42
|
+
],
|
43
|
+
|
44
|
+
# newlines allowed
|
45
|
+
"apples \nolives and \ngrass are\n green" => [
|
46
|
+
[/apples/i, [ColourWheel::FG[:green]], false],
|
47
|
+
[/olives/i, [ColourWheel::FG[:green]], false],
|
48
|
+
[/grass/i, [ColourWheel::FG[:green]], false],
|
49
|
+
],
|
50
|
+
|
51
|
+
# multiple matches
|
52
|
+
"apples and olives are green bananas are yellow" => [
|
53
|
+
[/apples/i, [ColourWheel::FG[:green]], false],
|
54
|
+
[/olives/i, [ColourWheel::FG[:green]], false],
|
55
|
+
[/bananas/i, [ColourWheel::FG[:yellow]], false],
|
56
|
+
],
|
57
|
+
|
58
|
+
# multiple matches without any conjugation
|
59
|
+
"apples olives green bananas yellow" => [
|
60
|
+
[/apples/i, [ColourWheel::FG[:green]], false],
|
61
|
+
[/olives/i, [ColourWheel::FG[:green]], false],
|
62
|
+
[/bananas/i, [ColourWheel::FG[:yellow]], false],
|
63
|
+
],
|
64
|
+
|
65
|
+
# multiple matches with conjugation
|
66
|
+
"apples and olives are green but bananas are yellow" => [
|
67
|
+
[/apples/i, [ColourWheel::FG[:green]], false],
|
68
|
+
[/olives/i, [ColourWheel::FG[:green]], false],
|
69
|
+
[/bananas/i, [ColourWheel::FG[:yellow]], false],
|
70
|
+
],
|
71
|
+
|
72
|
+
# multiple matches with multiple matches and conjugation
|
73
|
+
"apples and olives are green but bananas and cheese are yellow" => [
|
74
|
+
[/apples/i, [ColourWheel::FG[:green]], false],
|
75
|
+
[/olives/i, [ColourWheel::FG[:green]], false],
|
76
|
+
[/bananas/i, [ColourWheel::FG[:yellow]], false],
|
77
|
+
[/cheese/i, [ColourWheel::FG[:yellow]], false],
|
78
|
+
],
|
79
|
+
|
80
|
+
# multiple matches with multiple matches without any conjugation
|
81
|
+
"apples olives green bananas cheese yellow" => [
|
82
|
+
[/apples/i, [ColourWheel::FG[:green]], false],
|
83
|
+
[/olives/i, [ColourWheel::FG[:green]], false],
|
84
|
+
[/bananas/i, [ColourWheel::FG[:yellow]], false],
|
85
|
+
[/cheese/i, [ColourWheel::FG[:yellow]], false],
|
86
|
+
],
|
87
|
+
|
88
|
+
# multiple matches with multiple matches across lines
|
89
|
+
"apples and olives are green\n bananas and cheese are yellow" => [
|
90
|
+
[/apples/i, [ColourWheel::FG[:green]], false],
|
91
|
+
[/olives/i, [ColourWheel::FG[:green]], false],
|
92
|
+
[/bananas/i, [ColourWheel::FG[:yellow]], false],
|
93
|
+
[/cheese/i, [ColourWheel::FG[:yellow]], false],
|
94
|
+
],
|
95
|
+
|
96
|
+
# foreground and background colours
|
97
|
+
"apples are red green" => [
|
98
|
+
[/apples/i, [ColourWheel::FG[:red], ColourWheel::BG[:green]], false],
|
99
|
+
],
|
100
|
+
|
101
|
+
# foreground and background colours with lines
|
102
|
+
"apples are red green lines" => [
|
103
|
+
[/apples/i, [ColourWheel::FG[:red], ColourWheel::BG[:green]], true],
|
104
|
+
],
|
105
|
+
|
106
|
+
# colour precedence - command first, one colour
|
107
|
+
"apples are normal red lines" => [
|
108
|
+
[/apples/i, [ColourWheel::MISC[:normal], ColourWheel::FG[:red]], true],
|
109
|
+
],
|
110
|
+
|
111
|
+
# colour precedence - command first
|
112
|
+
"apples are normal red green lines" => [
|
113
|
+
[/apples/i, [ColourWheel::MISC[:normal], ColourWheel::FG[:red], ColourWheel::BG[:green]], true],
|
114
|
+
],
|
115
|
+
|
116
|
+
# two commands
|
117
|
+
"apples are normal inverted lines" => [
|
118
|
+
[/apples/i, [ColourWheel::MISC[:normal], ColourWheel::MISC[:invert]], true],
|
119
|
+
],
|
120
|
+
|
121
|
+
# a basic substitution
|
122
|
+
"apples are @nice and @nice are green lines" => [
|
123
|
+
[/apples/i, [ColourWheel::FG[:green]], true],
|
124
|
+
],
|
125
|
+
|
126
|
+
# a more complicated substitution
|
127
|
+
"apples and strawberries are @nice and @nice are green red lines" => [
|
128
|
+
[/apples/i, [ColourWheel::FG[:green], ColourWheel::BG[:red]], true],
|
129
|
+
[/strawberries/i, [ColourWheel::FG[:green], ColourWheel::BG[:red]], true],
|
130
|
+
],
|
131
|
+
|
132
|
+
# an indirect substitution
|
133
|
+
"apples and strawberries are @nice and @nice are @cool and @cool are green red lines" => [
|
134
|
+
[/apples/i, [ColourWheel::FG[:green], ColourWheel::BG[:red]], true],
|
135
|
+
[/strawberries/i, [ColourWheel::FG[:green], ColourWheel::BG[:red]], true],
|
136
|
+
],
|
137
|
+
|
138
|
+
# even more indirect
|
139
|
+
"apples and strawberries are @nice and @nice are @cool and @cool are @awesome and @awesome are green red lines" => [
|
140
|
+
[/apples/i, [ColourWheel::FG[:green], ColourWheel::BG[:red]], true],
|
141
|
+
[/strawberries/i, [ColourWheel::FG[:green], ColourWheel::BG[:red]], true],
|
142
|
+
],
|
143
|
+
|
144
|
+
# complex rules don't interfere with other rules
|
145
|
+
"cheese is yellow and apples and strawberries are @nice and @nice are @cool and @cool are @awesome and @awesome are green red lines and jon is @awesome" => [
|
146
|
+
[/cheese/i, [ColourWheel::FG[:yellow]], false],
|
147
|
+
[/apples/i, [ColourWheel::FG[:green], ColourWheel::BG[:red]], true],
|
148
|
+
[/strawberries/i, [ColourWheel::FG[:green], ColourWheel::BG[:red]], true],
|
149
|
+
[/jon/i, [ColourWheel::FG[:green], ColourWheel::BG[:red]], true]
|
150
|
+
],
|
151
|
+
}
|
152
|
+
|
153
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'yay/parser'
|
2
|
+
require 'yay/colourizer'
|
3
|
+
|
4
|
+
class Yay
|
5
|
+
class Application
|
6
|
+
|
7
|
+
# args that can be used if you don't want the application to do anything
|
8
|
+
DO_NOTHING_ARGS = ['--do-nothing']
|
9
|
+
|
10
|
+
def initialize(input, output, error, args)
|
11
|
+
raise ArgumentError, "input" unless input.kind_of? IO
|
12
|
+
raise ArgumentError, "output" unless output.kind_of? IO
|
13
|
+
raise ArgumentError, "error" unless error.kind_of? IO
|
14
|
+
raise ArgumentError, "args" unless args.kind_of? Array
|
15
|
+
|
16
|
+
@input = input
|
17
|
+
@output = output
|
18
|
+
@error = error
|
19
|
+
@args = args
|
20
|
+
@running = false
|
21
|
+
end
|
22
|
+
|
23
|
+
def run
|
24
|
+
raise "already running" if @running
|
25
|
+
@running = true
|
26
|
+
|
27
|
+
return if @args == DO_NOTHING_ARGS
|
28
|
+
|
29
|
+
begin
|
30
|
+
|
31
|
+
@parser = Yay::Parser.new
|
32
|
+
@parser.parse_array(@args)
|
33
|
+
@rules = @parser.get_rules
|
34
|
+
|
35
|
+
@colourizer = Yay::Colourizer.new @rules, @input, @output
|
36
|
+
@colourizer.colourize_pipe
|
37
|
+
rescue Yay::Error => error
|
38
|
+
@error.puts error.printable_message
|
39
|
+
rescue Interrupt
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# To change this template, choose Tools | Templates
|
2
|
+
# and open the template in the editor.
|
3
|
+
|
4
|
+
class Yay
|
5
|
+
class ColourWheel
|
6
|
+
|
7
|
+
# not colours as such. commandline support varies
|
8
|
+
MISC = {
|
9
|
+
:reset => 0,
|
10
|
+
:bright => 1,
|
11
|
+
:dim => 2,
|
12
|
+
:underscore => 4,
|
13
|
+
:blink => 5,
|
14
|
+
:reverse => 7,
|
15
|
+
:hidden => 8,
|
16
|
+
|
17
|
+
:normal => 0, #alias
|
18
|
+
:invert => 7, #alias
|
19
|
+
:inverted => 7, #alias
|
20
|
+
:underscored => 4, #alias
|
21
|
+
}
|
22
|
+
|
23
|
+
FG = {
|
24
|
+
:black => 30,
|
25
|
+
:red => 31,
|
26
|
+
:green => 32,
|
27
|
+
:yellow => 33,
|
28
|
+
:blue => 34,
|
29
|
+
:magenta => 35,
|
30
|
+
:cyan => 36,
|
31
|
+
:white => 37,
|
32
|
+
};
|
33
|
+
|
34
|
+
BG = {
|
35
|
+
:black => 40,
|
36
|
+
:red => 41,
|
37
|
+
:green => 42,
|
38
|
+
:yellow => 43,
|
39
|
+
:blue => 44,
|
40
|
+
:magenta => 45,
|
41
|
+
:cyan => 46,
|
42
|
+
:white => 47
|
43
|
+
};
|
44
|
+
|
45
|
+
def self.all_names
|
46
|
+
# assume BG and FG have the same keys
|
47
|
+
MISC.keys | FG.keys
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.begin_colours(colours)
|
51
|
+
"\033[#{colours.join(';')}m"
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.end_colour()
|
55
|
+
"\033[0m"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'yay/colour_wheel'
|
2
|
+
|
3
|
+
class Yay
|
4
|
+
class Colourizer
|
5
|
+
def initialize rules, input, output
|
6
|
+
colourize_rules rules
|
7
|
+
@input = input
|
8
|
+
@output = output
|
9
|
+
end
|
10
|
+
|
11
|
+
def colourize_rules rules
|
12
|
+
@line_rules = []
|
13
|
+
@part_rules = []
|
14
|
+
|
15
|
+
rules.each { |rule|
|
16
|
+
|
17
|
+
regex = rule[0]
|
18
|
+
colours = rule[1]
|
19
|
+
is_line = rule[2]
|
20
|
+
|
21
|
+
colour_string = ColourWheel::begin_colours(colours)
|
22
|
+
|
23
|
+
if is_line
|
24
|
+
@line_rules.unshift [regex, colour_string]
|
25
|
+
else
|
26
|
+
@part_rules.unshift [regex, colour_string]
|
27
|
+
end
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
def colourize_pipe
|
32
|
+
default_end_colour = ColourWheel::end_colour
|
33
|
+
|
34
|
+
@input.each_line { |line|
|
35
|
+
|
36
|
+
# track the line_rules end colour so we can return to this after each match
|
37
|
+
end_colour = default_end_colour
|
38
|
+
|
39
|
+
#
|
40
|
+
@line_rules.each { |rule|
|
41
|
+
if line.match(rule[0])
|
42
|
+
line = "#{rule[1]}#{line.rstrip}#{default_end_colour}"
|
43
|
+
end_colour = rule[1]
|
44
|
+
# only allow one line
|
45
|
+
break
|
46
|
+
end
|
47
|
+
}
|
48
|
+
|
49
|
+
#
|
50
|
+
@part_rules.each { |rule|
|
51
|
+
line.gsub!(rule[0], "#{rule[1]}\\0#{end_colour}")
|
52
|
+
}
|
53
|
+
|
54
|
+
@output.puts line
|
55
|
+
}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|