grepper 0.9.0

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.
@@ -0,0 +1,6 @@
1
+ === 0.9.0 / 2008-12-21
2
+
3
+ * 1 major enhancement
4
+
5
+ * First release
6
+
@@ -0,0 +1,11 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ lib/grepper.rb
6
+ test/input.1
7
+ test/input.2
8
+ test/input.3
9
+ test/input.4
10
+ test/input.6
11
+ test/test_grepper.rb
@@ -0,0 +1,97 @@
1
+ Grepper -- simple way to grep through files and save results
2
+
3
+ == Version
4
+
5
+ 0.9.0, December 21, 2008
6
+
7
+ == Author
8
+
9
+ David A. Black (dblack@rubypal.com)
10
+
11
+ == Copyright and license
12
+
13
+ Copyright (c) 2008, Ruby Power and Light, LLC
14
+
15
+ Released under the Ruby license. No warranty of any kind. Use
16
+ entirely at your own risk.
17
+
18
+ == Description
19
+
20
+ The Grepper class greps through files, and returns a result
21
+ set of Grepper::Result objects. Each Result object represents the matches
22
+ found in a single file. The Result contains a set of
23
+ Grepper::Match objects. Each Match object represents a line (the
24
+ line that matched) and before- and after-context arrays. If no before
25
+ or after lines were requested, those context values will be nil.
26
+
27
+ To use, you prepare a Grepper object; call <tt>run</tt> on it; and
28
+ walk through the result set.
29
+
30
+ == Preparing a Grepper object
31
+
32
+ You instantiate Grepper, and provide it with:
33
+
34
+ * a pattern, in the form of a regular expression
35
+ * zero or more options, as an array
36
+ * an array of filenames
37
+
38
+ === Setting the grepper's pattern
39
+
40
+ To specify a pattern for the Grepper object:
41
+
42
+ grepper.pattern = /abc/
43
+
44
+ === Setting the grepper's file list
45
+
46
+ grepper.files = ["file1.txt", "file2.txt"]
47
+ grepper.files = Dir["grep_me/*.txt"]
48
+
49
+ === Options
50
+
51
+ To set options, you provide an array of strings. For example, for a
52
+ reverse grep with two lines of after-context you would do:
53
+
54
+ grepper.options = %w{ v A2 }
55
+
56
+ Available options are:
57
+
58
+ * <tt>v</tt> -- negate the sense of the match
59
+ * <tt>An</tt> -- provide n lines of after-context
60
+ * <tt>Bn</tt> -- provide b lines of before-context
61
+
62
+ == Generating the result set
63
+
64
+ To generate the result set, you call <tt>run</tt>.
65
+
66
+ grepper.run
67
+
68
+ Now you can access grepper.results, and walk through all the
69
+ matches.
70
+
71
+ == Walking through the result set and match set
72
+
73
+ Given a <tt>Grepper</tt> object <tt>grepper</tt>, the result set
74
+ will be at <tt>grepper.results</tt>.
75
+ It will iterate per entry, yielding
76
+ the filename and the corresponding set of matches.
77
+
78
+ grepper.results.each do |filename, matches|
79
+ ...
80
+ end
81
+
82
+ For each match set, you can iterate like this:
83
+
84
+ matches.each do |lineno, before, line, after|
85
+ ...
86
+ end
87
+
88
+ If you want to walk through either set and just get the
89
+ objects, not broken out into their properties, you can do:
90
+
91
+ grepper.results.each_result do |result|
92
+
93
+ and
94
+
95
+ matches.each_match do |match|
96
+
97
+
@@ -0,0 +1,12 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/grepper.rb'
6
+
7
+ Hoe.new('grepper', Grepper::VERSION) do |p|
8
+ # p.rubyforge_name = 'grepperx' # if different than lowercase project name
9
+ p.developer('David A. Black', 'dblack@rubypal.com')
10
+ end
11
+
12
+ # vim: syntax=Ruby
@@ -0,0 +1,229 @@
1
+ # Grepper -- simple way to grep through files and save results
2
+ #
3
+ # == Version
4
+ #
5
+ # 0.9.0, December 21, 2008
6
+ #
7
+ # == Author
8
+ #
9
+ # David A. Black (dblack@rubypal.com)
10
+ #
11
+ # == Copyright and license
12
+ #
13
+ # Copyright (c) 2008, Ruby Power and Light, LLC
14
+ #
15
+ # Released under the Ruby license. No warranty of any kind. Use
16
+ # entirely at your own risk.
17
+ #
18
+ # == Description
19
+ #
20
+ # The Grepper class greps through files, and returns a result
21
+ # set of Grepper::Result objects. Each Result object represents the matches
22
+ # found in a single file. The Result contains a set of
23
+ # Grepper::Match objects. Each Match object represents a line (the
24
+ # line that matched) and before- and after-context arrays. If no before
25
+ # or after lines were requested, those context values will be nil.
26
+ #
27
+ # To use, you prepare a Grepper object; call <tt>run</tt> on it; and
28
+ # walk through the result set.
29
+ #
30
+ # == Preparing a Grepper object
31
+ #
32
+ # You instantiate Grepper, and provide it with:
33
+ #
34
+ # * a pattern, in the form of a regular expression
35
+ # * zero or more options, as an array
36
+ # * an array of filenames
37
+ #
38
+ # === Setting the grepper's pattern
39
+ #
40
+ # To specify a pattern for the Grepper object:
41
+ #
42
+ # grepper.pattern = /abc/
43
+ #
44
+ # === Setting the grepper's file list
45
+ #
46
+ # grepper.files = ["file1.txt", "file2.txt"]
47
+ # grepper.files = Dir["grep_me/*.txt"]
48
+ #
49
+ # === Options
50
+ #
51
+ # To set options, you provide an array of strings. For example, for a
52
+ # reverse grep with two lines of after-context you would do:
53
+ #
54
+ # grepper.options = %w{ v A2 }
55
+ #
56
+ # Available options are:
57
+ #
58
+ # * <tt>v</tt> -- negate the sense of the match
59
+ # * <tt>An</tt> -- provide n lines of after-context
60
+ # * <tt>Bn</tt> -- provide b lines of before-context
61
+ #
62
+ # == Generating the result set
63
+ #
64
+ # To generate the result set, you call <tt>run</tt>.
65
+ #
66
+ # grepper.run
67
+ #
68
+ # Now you can access grepper.results, and walk through all the
69
+ # matches.
70
+ #
71
+ # == Walking through the result set and match set
72
+ #
73
+ # Given a <tt>Grepper</tt> object <tt>grepper</tt>, the result set
74
+ # will be at <tt>grepper.results</tt>.
75
+ # It will iterate per entry, yielding
76
+ # the filename and the corresponding set of matches.
77
+ #
78
+ # grepper.results.each do |filename, matches|
79
+ # ...
80
+ # end
81
+ #
82
+ # For each match set, you can iterate like this:
83
+ #
84
+ # matches.each do |lineno, before, line, after|
85
+ # ...
86
+ # end
87
+ #
88
+ # If you want to walk through either set and just get the
89
+ # objects, not broken out into their properties, you can do:
90
+ #
91
+ # grepper.results.each_result do |result|
92
+ #
93
+ # and
94
+ #
95
+ # matches.each_match do |match|
96
+ #
97
+
98
+ class Grepper
99
+ VERSION = '0.9.0'
100
+
101
+ attr_accessor :files, :pattern, :options
102
+ attr_reader :results
103
+
104
+ def initialize
105
+ @files = []
106
+ @options = []
107
+ @results = [].extend(ResultsExtension)
108
+ @negate = false
109
+ end
110
+
111
+ private
112
+
113
+ def get_after_context(fh, after_count)
114
+ res = []
115
+ after_count.times do |i|
116
+ line = fh.gets
117
+ break unless line
118
+ if match?(line)
119
+ fh.pos -= line.size
120
+ break
121
+ else
122
+ res << line
123
+ end
124
+ end
125
+ res.empty? ? nil : res
126
+ end
127
+
128
+ def match?(line)
129
+ m = line =~ @pattern
130
+ @negate ? !m : m
131
+ end
132
+
133
+ public
134
+
135
+ # Generate the result set.
136
+ def run
137
+ @negate = true if options.include?('v')
138
+
139
+ after_count = $1.to_i if options.find {|o| /A(\d)/.match(o) }
140
+ before_count = $1.to_i if options.find {|o| /B(\d)/.match(o) }
141
+
142
+ files.each do |file|
143
+ result = Result.new(file)
144
+ results << result
145
+ buffer = []
146
+ File.open(file) do |fh|
147
+ fh.each_with_index do |line,i|
148
+ if match?(line)
149
+ match = Match.new(line)
150
+ match.lineno = i + 1
151
+ if after_count
152
+ match.after = get_after_context(fh, after_count)
153
+ end
154
+
155
+ if before_count
156
+ match.before = buffer.empty? ? nil : buffer
157
+ buffer = []
158
+ end
159
+
160
+ result.matches << match
161
+
162
+ else
163
+ if before_count
164
+ buffer << line
165
+ buffer.shift if buffer.size > before_count
166
+ end
167
+ end
168
+ end
169
+ end
170
+ end
171
+ end
172
+
173
+ # Grepper::Match represents a match on a single line, possibly
174
+ # with before- and/or after-context.
175
+ #
176
+ # Match instances are created automatically by the Grepper
177
+ # object when you run it.
178
+ class Match
179
+ attr_accessor :before, :line, :after, :lineno
180
+ def initialize(line)
181
+ @before = @after = nil
182
+ @line = line
183
+ end
184
+ end
185
+
186
+ # Grepper::Result represents the matches from a single file. It
187
+ # connects the filename (the <tt>file</tt> attribute) with a
188
+ # set of Match objects (the <tt>matches</tt> attribute).
189
+ #
190
+ # Result objects are created automatically by the Grepper object
191
+ # when you run it.
192
+ class Result
193
+ attr_reader :file, :matches
194
+ def initialize(file)
195
+ @file = file
196
+ @matches = [].extend(MatchesExtension)
197
+ end
198
+ end
199
+
200
+ # Provides the iteration intelligence for result sets.
201
+ module ResultsExtension
202
+ def each(&block)
203
+ (0...size).each do |i|
204
+ yield(self[i].file, self[i].matches)
205
+ end
206
+ end
207
+ def each_result(&block)
208
+ (0...size).each do |i|
209
+ yield self[i]
210
+ end
211
+ end
212
+ end
213
+
214
+ # Provides the iteration intelligence for match sets.
215
+ module MatchesExtension
216
+ def each
217
+ (0...size).each do |i|
218
+ m = self[i]
219
+ yield(m.lineno,m.before,m.line,m.after)
220
+ end
221
+ end
222
+
223
+ def each_match
224
+ (0...size).each do |i|
225
+ yield(self[i])
226
+ end
227
+ end
228
+ end
229
+ end
@@ -0,0 +1,3 @@
1
+ This is a file
2
+ This matches abc.
3
+ This doesn't.
@@ -0,0 +1,4 @@
1
+ This doesn't match.
2
+ However, this:
3
+ So does this abc.
4
+ does.
@@ -0,0 +1,3 @@
1
+ This file
2
+ has no
3
+ matching lines.
@@ -0,0 +1,8 @@
1
+ this abc
2
+ blah one
3
+ blah two
4
+ blah three
5
+ that abc
6
+ one
7
+ two
8
+ three
@@ -0,0 +1,9 @@
1
+ one
2
+ two
3
+ abc
4
+ three
5
+ four
6
+ abc
7
+ five
8
+ six
9
+ abc
@@ -0,0 +1,139 @@
1
+ require 'test/unit'
2
+ require 'English'
3
+ require "lib/grepper.rb"
4
+
5
+ class GrepTest < Test::Unit::TestCase
6
+ def setup
7
+ @g = Grepper.new
8
+ @g.files = %w{ test/input.1 test/input.2 test/input.3 test/input.4 }
9
+ @g.pattern = /abc/
10
+ end
11
+
12
+ def test_basic_lines_from_one_file
13
+ @g.files = ["test/input.1"]
14
+ exp = ["This matches abc.\n"]
15
+ @g.run
16
+ @g.results.each do |file,matches|
17
+ assert_equal("test/input.1", file)
18
+ matches.each do |no,before,line,after|
19
+ assert_equal(nil, before)
20
+ assert_equal(nil, after)
21
+ assert_equal(exp.shift, line)
22
+ end
23
+ end
24
+ end
25
+
26
+ def test_basic_negation_from_one_file
27
+ @g.files =["test/input.4"]
28
+ @g.pattern = /a/
29
+ @g.options = ['v']
30
+ @g.run
31
+ assert_equal(["one\n","two\n","three\n"],
32
+ @g.results[0].matches.map {|m| m.line })
33
+ end
34
+
35
+ def test_case_insensitive_pattern
36
+ @g.files = ["test/input.1"]
37
+ @g.pattern = /ABC/i
38
+ exp = "This matches abc.\n"
39
+ @g.options = ['i']
40
+ @g.run
41
+ assert_equal(exp, @g.results[0].matches[0].line)
42
+ end
43
+
44
+ def test_basic_lines_from_multiple_files
45
+ @g.run
46
+ files = @g.files.dup
47
+ exp = <<EOM.scan(/.*\n/)
48
+ This matches abc.
49
+ So does this abc.
50
+ this abc
51
+ that abc
52
+ EOM
53
+ @g.results.each do |file,matches|
54
+ assert_equal(files.shift, file)
55
+ matches.each_match do |match|
56
+ assert_equal(nil, match.before)
57
+ assert_equal(nil, match.after)
58
+ assert_equal(exp.shift, match.line)
59
+ end
60
+ end
61
+ end
62
+
63
+ def test_after_context_from_one_file
64
+ @g.options = %w{ A2 }
65
+ @g.files = ["test/input.4"]
66
+ exp = <<EOM.scan(/.*\n/)
67
+ this abc
68
+ blah one
69
+ blah two
70
+ that abc
71
+ one
72
+ two
73
+ EOM
74
+ @g.run
75
+ @g.results.each do |file,matches|
76
+ assert_equal("test/input.4", file)
77
+ matches.each do |no,before,line,after|
78
+ assert_equal(nil, before)
79
+ assert_equal(exp.shift, line)
80
+ assert_equal([exp.shift, exp.shift], after)
81
+ end
82
+ end
83
+ end
84
+
85
+ def test_overlapping_context_from_one_file
86
+ @g.options = "A4"
87
+ @g.files = ["test/input.4"]
88
+ @g.run
89
+ assert_equal(1, @g.results.size)
90
+ assert_equal(3, @g.results[0].matches[0].after.size)
91
+ assert_equal(2, @g.results[0].matches.size)
92
+ end
93
+
94
+ def test_lines_from_multiple_files
95
+ @g.files.pop # just 3 files
96
+ @g.run
97
+ assert_equal(3, @g.results.size)
98
+ assert_equal(@g.files, @g.results.map {|r| r.file})
99
+ assert_equal("This matches abc.\n", @g.results[0].matches[0].line)
100
+ assert_equal("So does this abc.\n", @g.results[1].matches[0].line)
101
+ assert(@g.results[2].matches.empty?)
102
+ end
103
+
104
+ def test_before_buffer
105
+ @g.files = ["test/input.4"]
106
+ @g.options = "B2"
107
+ @g.run
108
+ r = @g.results[0]
109
+ assert_equal(1, @g.results.size)
110
+ assert_equal(2, r.matches.size)
111
+ assert_equal("this abc\n", r.matches[0].line)
112
+ assert_equal(["blah two\n", "blah three\n"], r.matches[1].before)
113
+ assert_equal("that abc\n", r.matches[1].line)
114
+ end
115
+
116
+ def test_before_and_after
117
+ @g.files = ["test/input.6"]
118
+ @g.options = %w{A2 B2}
119
+ @g.run
120
+
121
+ r = @g.results[0]
122
+ assert_equal(1, @g.results.size)
123
+ assert_equal(3, r.matches.size)
124
+ assert_equal(["one\n", "two\n"], r.matches[0].before)
125
+ assert(r.matches.all? {|no,b,l,a| l == "abc\n"})
126
+ assert_equal(["three\n", "four\n"], r.matches[0].after)
127
+ assert_equal(["five\n", "six\n"], r.matches[1].after)
128
+ end
129
+
130
+ def test_line_numbering
131
+ test_basic_lines_from_one_file
132
+ assert_equal(2, @g.results[0].matches[0].lineno)
133
+ end
134
+
135
+ def test_line_numbering_in_multiple_files
136
+ test_basic_lines_from_multiple_files
137
+ assert_equal(3, @g.results[1].matches[0].lineno)
138
+ end
139
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: grepper
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ platform: ruby
6
+ authors:
7
+ - David A. Black
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-12-22 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.8.2
24
+ version:
25
+ description: The Grepper class greps through files, and returns a result set of Grepper::Result objects. Each Result object represents the matches found in a single file. The Result contains a set of Grepper::Match objects. Each Match object represents a line (the line that matched) and before- and after-context arrays. If no before or after lines were requested, those context values will be nil. To use, you prepare a Grepper object; call <tt>run</tt> on it; and walk through the result set.
26
+ email:
27
+ - dblack@rubypal.com
28
+ executables: []
29
+
30
+ extensions: []
31
+
32
+ extra_rdoc_files:
33
+ - History.txt
34
+ - Manifest.txt
35
+ - README.txt
36
+ files:
37
+ - History.txt
38
+ - Manifest.txt
39
+ - README.txt
40
+ - Rakefile
41
+ - lib/grepper.rb
42
+ - test/input.1
43
+ - test/input.2
44
+ - test/input.3
45
+ - test/input.4
46
+ - test/input.6
47
+ - test/test_grepper.rb
48
+ has_rdoc: true
49
+ homepage: 0.9.0, December 21, 2008
50
+ post_install_message:
51
+ rdoc_options:
52
+ - --main
53
+ - README.txt
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ version:
68
+ requirements: []
69
+
70
+ rubyforge_project: grepper
71
+ rubygems_version: 1.2.0
72
+ signing_key:
73
+ specification_version: 2
74
+ summary: The Grepper class greps through files, and returns a result set of Grepper::Result objects
75
+ test_files:
76
+ - test/test_grepper.rb