grepper 0.9.1 → 0.9.2
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/History.txt +9 -0
- data/Manifest.txt +2 -1
- data/README.txt +1 -1
- data/bin/grep.rb +48 -0
- data/lib/{formatter.rb → grepper/formatter.rb} +61 -13
- data/lib/grepper.rb +8 -4
- data/test/test_formatter.rb +64 -3
- data/test/test_grepper.rb +2 -0
- metadata +6 -5
data/History.txt
CHANGED
@@ -13,3 +13,12 @@
|
|
13
13
|
* Fixed a line-counting bug that was making
|
14
14
|
Match#lineno work wrongly.
|
15
15
|
|
16
|
+
=== 0.9.2 / 2008-12-24
|
17
|
+
|
18
|
+
* Added bin/grep.rb, simple grep commandline tool
|
19
|
+
|
20
|
+
* Fixed some separator problems in formatter output
|
21
|
+
|
22
|
+
* Added some logic to the Match and Result classes
|
23
|
+
|
24
|
+
* Refactoring
|
data/Manifest.txt
CHANGED
data/README.txt
CHANGED
data/bin/grep.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
$: << '../lib'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'grepper'
|
4
|
+
require 'grepper/formatter'
|
5
|
+
|
6
|
+
require 'getoptlong'
|
7
|
+
|
8
|
+
|
9
|
+
opts = GetoptLong.new(
|
10
|
+
['--help', '-h', GetoptLong::NO_ARGUMENT],
|
11
|
+
['--line-number', '-n', GetoptLong::NO_ARGUMENT],
|
12
|
+
['--before-context', '-B', GetoptLong::REQUIRED_ARGUMENT],
|
13
|
+
['--after-context', '-A', GetoptLong::REQUIRED_ARGUMENT],
|
14
|
+
['--invert-match', '-v', GetoptLong::NO_ARGUMENT]
|
15
|
+
)
|
16
|
+
|
17
|
+
grepper = Grepper.new
|
18
|
+
formatter = Grepper::Formatter.new(grepper)
|
19
|
+
|
20
|
+
opts.each do |opt,arg|
|
21
|
+
case opt
|
22
|
+
when '--line-number'
|
23
|
+
formatter.options << "n"
|
24
|
+
when '--before-context'
|
25
|
+
grepper.options << "B#{arg}"
|
26
|
+
when '--after-context'
|
27
|
+
grepper.options << "A#{arg}"
|
28
|
+
when '--invert-match'
|
29
|
+
grepper.options << "v"
|
30
|
+
when '--help'
|
31
|
+
puts "Help"
|
32
|
+
exit 0
|
33
|
+
else
|
34
|
+
puts "Unknown option #{opt}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
if ARGV.size < 2
|
39
|
+
puts "Sorry"
|
40
|
+
exit 0
|
41
|
+
end
|
42
|
+
|
43
|
+
grepper.pattern = Regexp.new(ARGV.shift)
|
44
|
+
grepper.files = ARGV.dup
|
45
|
+
|
46
|
+
grepper.run
|
47
|
+
formatter.format
|
48
|
+
puts formatter.output
|
@@ -12,6 +12,7 @@ class Grepper
|
|
12
12
|
#
|
13
13
|
# f = Grepper::Formatter.initialize(grepper)
|
14
14
|
# f.format
|
15
|
+
# f.options = ['...'] # see below
|
15
16
|
# puts f.output
|
16
17
|
#
|
17
18
|
# Output will show filenames if there are multiple files,
|
@@ -20,6 +21,25 @@ class Grepper
|
|
20
21
|
# that the Grepper and its result set already have.
|
21
22
|
#
|
22
23
|
# For version and license information, see <tt>grepper.rb</tt>.
|
24
|
+
#
|
25
|
+
# == Options
|
26
|
+
#
|
27
|
+
# Formatters have an options array which you can set and
|
28
|
+
# add to. It's empty by default.
|
29
|
+
#
|
30
|
+
# Available options:
|
31
|
+
#
|
32
|
+
# * <tt>l</tt> -- show matching filenames only
|
33
|
+
# * <tt>c</tt> -- show match count only
|
34
|
+
# * <tt>n</tt> -- show the line number of the match
|
35
|
+
#
|
36
|
+
# Note that Grepper objects also have options ('v', 'A1', etc.).
|
37
|
+
# Both the Formatter options and the Grepper options are pulled
|
38
|
+
# from the canon of grep(1) options. Some make more sense for the
|
39
|
+
# grep operation itself (like inverting the sense of the match with
|
40
|
+
# 'v'), while some are purely a formatting thing (like including the
|
41
|
+
# filename).
|
42
|
+
|
23
43
|
class Formatter
|
24
44
|
|
25
45
|
attr_reader :output
|
@@ -28,6 +48,7 @@ class Grepper
|
|
28
48
|
def initialize(grepper)
|
29
49
|
@output = ""
|
30
50
|
@grepper = grepper
|
51
|
+
@options = []
|
31
52
|
end
|
32
53
|
|
33
54
|
def matches_are_contiguous?(first,second)
|
@@ -42,6 +63,8 @@ class Grepper
|
|
42
63
|
@output = process_grepper(@grepper)
|
43
64
|
end
|
44
65
|
|
66
|
+
private
|
67
|
+
|
45
68
|
def format_line(n,b,l,a)
|
46
69
|
case
|
47
70
|
when options.include?('n')
|
@@ -55,10 +78,28 @@ class Grepper
|
|
55
78
|
multi? ? many_string + string : string
|
56
79
|
end
|
57
80
|
|
58
|
-
def context_lines(lines,file)
|
59
|
-
|
81
|
+
def context_lines(lines,file,n,position)
|
82
|
+
str = ""
|
83
|
+
i = case position
|
84
|
+
when :before then n - lines.size
|
85
|
+
when :after then n + 1
|
86
|
+
end
|
87
|
+
lines.each do |line|
|
88
|
+
count = options.include?('n') ? "#{i}-" : ""
|
89
|
+
str << one_or_many("#{count}#{line}","#{file}-")
|
90
|
+
i += 1
|
91
|
+
end
|
92
|
+
str
|
60
93
|
end
|
61
94
|
|
95
|
+
def before_lines(*args)
|
96
|
+
context_lines(*args << :before)
|
97
|
+
end
|
98
|
+
|
99
|
+
def after_lines(*args)
|
100
|
+
context_lines(*args << :after)
|
101
|
+
end
|
102
|
+
|
62
103
|
def boundary_string_for(m1, m2, conditions_hash)
|
63
104
|
conditions = conditions_hash[:conditions]
|
64
105
|
return "" unless conditions
|
@@ -66,36 +107,43 @@ class Grepper
|
|
66
107
|
return "--\n"
|
67
108
|
end
|
68
109
|
|
69
|
-
|
70
|
-
f1 &&! (f1 == f2) ? "--\n" : ""
|
71
|
-
end
|
110
|
+
public
|
72
111
|
|
73
112
|
def process_grepper(grepper)
|
74
113
|
str = ""
|
75
114
|
last_file = nil
|
115
|
+
context = grepper.results.context?
|
116
|
+
|
76
117
|
grepper.results.each do |file,matches|
|
118
|
+
|
119
|
+
# Put in a -- boundary if this is a new file and
|
120
|
+
# there's a before- or after-context
|
121
|
+
if context && last_file &&! (file == last_file)
|
122
|
+
str << "--\n"
|
123
|
+
end
|
124
|
+
|
125
|
+
last_file = file
|
126
|
+
|
127
|
+
# 'l' -- filenames only
|
77
128
|
if options.include?('l')
|
78
129
|
str << "#{file}\n"
|
130
|
+
|
131
|
+
# 'c' -- match count only
|
79
132
|
elsif options.include?('c')
|
80
133
|
str << one_or_many("#{matches.size}\n", "#{file}:")
|
81
134
|
else
|
82
135
|
matches.each_with_index do |(n,before,line,after),m|
|
83
|
-
if (after || before)
|
84
|
-
str << file_boundary_string_for(last_file, file)
|
85
|
-
end
|
86
|
-
|
87
|
-
last_file = file
|
88
136
|
|
89
137
|
if before
|
90
138
|
prev = matches[m-1]
|
91
139
|
str << boundary_string_for(prev, matches[m], :conditions => prev &&! m.zero?)
|
92
|
-
str <<
|
140
|
+
str << before_lines(before,file,n)
|
93
141
|
end
|
94
142
|
|
95
143
|
str << one_or_many(format_line(n,before,line,after), "#{file}:")
|
96
144
|
|
97
145
|
if after
|
98
|
-
str <<
|
146
|
+
str << after_lines(after,file,n)
|
99
147
|
succ = matches[m+1]
|
100
148
|
str << boundary_string_for(matches[m], succ, :conditions => succ)
|
101
149
|
end
|
@@ -105,4 +153,4 @@ class Grepper
|
|
105
153
|
return str
|
106
154
|
end
|
107
155
|
end
|
108
|
-
end
|
156
|
+
end
|
data/lib/grepper.rb
CHANGED
@@ -84,7 +84,7 @@
|
|
84
84
|
#
|
85
85
|
# == Version
|
86
86
|
#
|
87
|
-
# 0.9.
|
87
|
+
# 0.9.2, December 24, 2008
|
88
88
|
#
|
89
89
|
# == Author
|
90
90
|
#
|
@@ -99,7 +99,7 @@
|
|
99
99
|
#
|
100
100
|
|
101
101
|
class Grepper
|
102
|
-
VERSION = '0.9.
|
102
|
+
VERSION = '0.9.2'
|
103
103
|
|
104
104
|
attr_accessor :files, :pattern, :options
|
105
105
|
attr_reader :results
|
@@ -141,8 +141,8 @@ class Grepper
|
|
141
141
|
def run
|
142
142
|
@negate = true if options.include?('v')
|
143
143
|
|
144
|
-
after_count = $1.to_i if options.find {|o| /A(\d)/.match(o) }
|
145
|
-
before_count = $1.to_i if options.find {|o| /B(\d)/.match(o) }
|
144
|
+
after_count = $1.to_i if options.find {|o| /A(\d+)/.match(o) }
|
145
|
+
before_count = $1.to_i if options.find {|o| /B(\d+)/.match(o) }
|
146
146
|
|
147
147
|
files.each do |file|
|
148
148
|
result = Result.new(file)
|
@@ -234,6 +234,10 @@ class Grepper
|
|
234
234
|
yield self[i]
|
235
235
|
end
|
236
236
|
end
|
237
|
+
|
238
|
+
def context?
|
239
|
+
any? {|f,matches| matches.any? {|n,b,l,a| b || a } }
|
240
|
+
end
|
237
241
|
end
|
238
242
|
|
239
243
|
# Provides the iteration intelligence for match sets.
|
data/test/test_formatter.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# Tests of the output of the formatter.
|
2
|
+
|
3
|
+
require 'grepper/formatter'
|
2
4
|
require 'test/unit'
|
3
5
|
|
4
6
|
class FormatterTest < Test::Unit::TestCase
|
@@ -13,7 +15,7 @@ class FormatterTest < Test::Unit::TestCase
|
|
13
15
|
grepper.run
|
14
16
|
end
|
15
17
|
|
16
|
-
def formatter_for(grepper,
|
18
|
+
def formatter_for(grepper,options = [])
|
17
19
|
f = Grepper::Formatter.new(grepper)
|
18
20
|
f.options = options
|
19
21
|
f.format
|
@@ -145,5 +147,64 @@ test/input.6:abc
|
|
145
147
|
EOM
|
146
148
|
end
|
147
149
|
|
150
|
+
def test_before_context_with_line_numbers
|
151
|
+
@g.options = ["B2"]
|
152
|
+
run_with_files(@g, %w{ test/input.6 })
|
153
|
+
f = formatter_for(@g,["n"])
|
154
|
+
assert_equal(<<EOM, f.output)
|
155
|
+
1-one
|
156
|
+
2-two
|
157
|
+
3:abc
|
158
|
+
4-three
|
159
|
+
5-four
|
160
|
+
6:abc
|
161
|
+
7-five
|
162
|
+
8-six
|
163
|
+
9:abc
|
164
|
+
EOM
|
165
|
+
end
|
166
|
+
|
167
|
+
def test_after_context_with_line_numbers
|
168
|
+
@g.options = ["A2"]
|
169
|
+
run_with_files(@g, %w{ test/input.6 })
|
170
|
+
f = formatter_for(@g,["n"])
|
171
|
+
assert_equal(<<EOM, f.output)
|
172
|
+
3:abc
|
173
|
+
4-three
|
174
|
+
5-four
|
175
|
+
6:abc
|
176
|
+
7-five
|
177
|
+
8-six
|
178
|
+
9:abc
|
179
|
+
EOM
|
180
|
+
end
|
181
|
+
|
182
|
+
def test_before_context_line_numbers_multiple_files
|
183
|
+
@g.options = ["B2"]
|
184
|
+
run_with_files(@g, %w{ test/input.1 test/input.2 })
|
185
|
+
f = formatter_for(@g,["n"])
|
186
|
+
assert_equal(<<EOM, f.output)
|
187
|
+
test/input.1-1-This is a file
|
188
|
+
test/input.1:2:This matches abc.
|
189
|
+
--
|
190
|
+
test/input.2-1-This doesn't match.
|
191
|
+
test/input.2-2-However, this:
|
192
|
+
test/input.2:3:So does this abc.
|
193
|
+
EOM
|
194
|
+
end
|
195
|
+
|
196
|
+
def test_after_context_line_numbers_multiple_files
|
197
|
+
@g.options = ["A2"]
|
198
|
+
run_with_files(@g, %w{ test/input.1 test/input.2 })
|
199
|
+
f = formatter_for(@g,["n"])
|
200
|
+
assert_equal(<<EOM, f.output)
|
201
|
+
test/input.1:2:This matches abc.
|
202
|
+
test/input.1-3-This doesn't.
|
203
|
+
--
|
204
|
+
test/input.2:3:So does this abc.
|
205
|
+
test/input.2-4-does.
|
206
|
+
EOM
|
207
|
+
end
|
148
208
|
end
|
149
|
-
|
209
|
+
|
210
|
+
|
data/test/test_grepper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: grepper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David A. Black
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-12-
|
12
|
+
date: 2008-12-24 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -25,8 +25,8 @@ dependencies:
|
|
25
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. This distribution comes with the Grepper::Formatter class, which is built on top of Grepper and provides fairly canonical-looking output by walking through Grepper objects. (See <tt>lib/formatter.rb</tt>.) Meanwhile, here are the details.
|
26
26
|
email:
|
27
27
|
- dblack@rubypal.com
|
28
|
-
executables:
|
29
|
-
|
28
|
+
executables:
|
29
|
+
- grep.rb
|
30
30
|
extensions: []
|
31
31
|
|
32
32
|
extra_rdoc_files:
|
@@ -38,8 +38,9 @@ files:
|
|
38
38
|
- Manifest.txt
|
39
39
|
- README.txt
|
40
40
|
- Rakefile
|
41
|
-
-
|
41
|
+
- bin/grep.rb
|
42
42
|
- lib/grepper.rb
|
43
|
+
- lib/grepper/formatter.rb
|
43
44
|
- test/input.1
|
44
45
|
- test/input.2
|
45
46
|
- test/input.3
|