yay 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|