yay 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
File without changes
data/bin/yay ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/ruby
2
+
3
+ $:.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
4
+ require 'yay/application'
5
+ Yay::Application.new(STDIN, STDOUT, STDERR, ARGV).run
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/yay
2
+ # Highlights a lot of different log messages
3
+
4
+ use syslog
5
+ use log4x
@@ -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,6 @@
1
+ #!/usr/bin/yay
2
+ # Will pipe some lines to stderr
3
+
4
+ warn is an error
5
+ error and fatal are errors
6
+
@@ -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
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/yay
2
+ # Shows off variables
3
+
4
+ debug is @boring
5
+ warn is @interesting
6
+ error is @serious
7
+ fatal is @serious
8
+
9
+ all @boring are hidden
10
+ all @interesting are yellow
11
+ all @serious are red lines
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
@@ -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