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 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