glark 1.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.
- data/README +0 -0
- data/bin/glark +37 -0
- data/bin/jlark +63 -0
- data/lib/glark.rb +4 -0
- data/lib/glark/expression.rb +440 -0
- data/lib/glark/exprfactory.rb +248 -0
- data/lib/glark/glark.rb +297 -0
- data/lib/glark/help.rb +85 -0
- data/lib/glark/input.rb +183 -0
- data/lib/glark/options.rb +757 -0
- data/lib/glark/output.rb +266 -0
- data/test/lib/glark/glark_test.rb +317 -0
- data/test/lib/glark/options_test.rb +891 -0
- metadata +95 -0
data/lib/glark/output.rb
ADDED
@@ -0,0 +1,266 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
#!ruby -w
|
3
|
+
# vim: set filetype=ruby : set sw=2
|
4
|
+
|
5
|
+
# Glark output.
|
6
|
+
|
7
|
+
require 'English'
|
8
|
+
|
9
|
+
require 'rubygems'
|
10
|
+
require 'riel'
|
11
|
+
|
12
|
+
require 'glark/options'
|
13
|
+
require 'glark/input'
|
14
|
+
|
15
|
+
class Results
|
16
|
+
include Loggable
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
class OutputFormat < Results
|
21
|
+
|
22
|
+
attr_reader :formatted, :infile, :show_file_name, :has_context
|
23
|
+
|
24
|
+
def initialize(infile, show_file_names)
|
25
|
+
@infile = infile
|
26
|
+
@show_file_name = show_file_names
|
27
|
+
@formatted = []
|
28
|
+
@has_context = false
|
29
|
+
|
30
|
+
opts = GlarkOptions.instance
|
31
|
+
|
32
|
+
@label = opts.label
|
33
|
+
@out = opts.out
|
34
|
+
@show_break = opts.show_break
|
35
|
+
@show_line_numbers = opts.show_line_numbers
|
36
|
+
end
|
37
|
+
|
38
|
+
# Prints the line, which is assumed to be 0-indexed, and is thus adjusted by
|
39
|
+
# one.
|
40
|
+
def print_line_number(lnum)
|
41
|
+
@out.printf "%5d ", lnum + 1
|
42
|
+
end
|
43
|
+
|
44
|
+
# prints the line, and adjusts for the fact that in our world, lines are
|
45
|
+
# 0-indexed, whereas they are displayed as if 1-indexed.
|
46
|
+
def print_line(lnum, ch = nil)
|
47
|
+
log { "lnum #{lnum}, ch: '#{ch}'" }
|
48
|
+
begin
|
49
|
+
lnums = @infile.get_range(lnum)
|
50
|
+
log { "lnums(#{lnum}): #{lnums}" }
|
51
|
+
if lnums
|
52
|
+
lnums.each do |ln|
|
53
|
+
if show_line_numbers
|
54
|
+
print_line_number(ln)
|
55
|
+
if ch && has_context
|
56
|
+
@out.printf "%s ", ch
|
57
|
+
end
|
58
|
+
end
|
59
|
+
line = @formatted[ln] || @infile.get_line(ln)
|
60
|
+
@out.puts line
|
61
|
+
end
|
62
|
+
end
|
63
|
+
rescue => e
|
64
|
+
# puts e
|
65
|
+
# puts e.backtrace
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def write_matches(matching, from, to)
|
70
|
+
if @infile.count
|
71
|
+
write_count(matching)
|
72
|
+
elsif matching
|
73
|
+
firstline = from ? from : 0
|
74
|
+
lastline = to ? to : @infile.get_lines.length - 1
|
75
|
+
|
76
|
+
(firstline .. lastline).each do |ln|
|
77
|
+
if @infile.stati[ln]
|
78
|
+
unless @infile.stati[ln] == InputFile::WRITTEN
|
79
|
+
if firstline > 0 && !@infile.stati[ln - 1] && has_context && @show_break
|
80
|
+
@out.puts " ---"
|
81
|
+
end
|
82
|
+
|
83
|
+
print_line(ln, @infile.stati[ln])
|
84
|
+
|
85
|
+
@infile.stati[ln] = InputFile::WRITTEN
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
else
|
91
|
+
firstline = from ? from : 0
|
92
|
+
lastline = to ? to : @infile.get_lines.length - 1
|
93
|
+
(firstline .. lastline).each do |ln|
|
94
|
+
if @infile.stati[ln] != InputFile::WRITTEN && @infile.stati[ln] != ":"
|
95
|
+
log { "printing #{ln}" }
|
96
|
+
print_line(ln)
|
97
|
+
@infile.stati[ln] = InputFile::WRITTEN
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def write_all
|
104
|
+
(0 ... @infile.get_lines.length).each do |ln|
|
105
|
+
print_line(ln)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def get_line_to_print(lnum)
|
110
|
+
formatted[lnum] || infile.get_line(lnum)
|
111
|
+
end
|
112
|
+
|
113
|
+
def show_line_numbers
|
114
|
+
@show_line_numbers
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
# -------------------------------------------------------
|
121
|
+
# Glark output format
|
122
|
+
# -------------------------------------------------------
|
123
|
+
|
124
|
+
class GlarkOutputFormat < OutputFormat
|
125
|
+
|
126
|
+
def initialize(infile, show_file_names)
|
127
|
+
super
|
128
|
+
|
129
|
+
opts = GlarkOptions.instance
|
130
|
+
|
131
|
+
@has_context = opts.after != 0 || opts.before != 0
|
132
|
+
@file_header_shown = false
|
133
|
+
if @highlight = opts.highlight
|
134
|
+
@fname_highlighter = opts.file_highlight
|
135
|
+
end
|
136
|
+
@lnum_highlighter = opts.line_number_highlight
|
137
|
+
end
|
138
|
+
|
139
|
+
# prints the line, and adjusts for the fact that in our world, lines are
|
140
|
+
# 0-indexed, whereas they are displayed as if 1-indexed.
|
141
|
+
def print_line(lnum, ch = nil)
|
142
|
+
log { "lnum #{lnum}, ch: '#{ch}'" }
|
143
|
+
begin
|
144
|
+
lnums = @infile.get_range(lnum)
|
145
|
+
log { "lnums(#{lnum}): #{lnums}" }
|
146
|
+
if lnums
|
147
|
+
log { "printing" }
|
148
|
+
lnums.each do |ln|
|
149
|
+
println(ln, ch)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
rescue => e
|
153
|
+
# puts e
|
154
|
+
# puts e.backtrace
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def show_file_header
|
159
|
+
if show_file_name && !@file_header_shown
|
160
|
+
fname = @label || @infile.fname
|
161
|
+
fname = @fname_highlighter.highlight(fname) if @highlight
|
162
|
+
|
163
|
+
@out.puts fname
|
164
|
+
end
|
165
|
+
@file_header_shown = true
|
166
|
+
end
|
167
|
+
|
168
|
+
def print_line_number(lnum)
|
169
|
+
if @lnum_highlighter
|
170
|
+
lnumstr = (lnum + 1).to_s
|
171
|
+
pad = " " * ([5 - lnumstr.length, 0].max)
|
172
|
+
@out.print pad + " " + @lnum_highlighter.highlight(lnumstr) + " "
|
173
|
+
else
|
174
|
+
super
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def write_count(matching = true)
|
179
|
+
ct = matching ? @infile.count : @infile.get_lines.size - @infile.count
|
180
|
+
@out.puts " " + ct.to_s
|
181
|
+
end
|
182
|
+
|
183
|
+
def write_matches(matching, from = nil, to = nil)
|
184
|
+
show_file_header
|
185
|
+
super(matching, from, to)
|
186
|
+
end
|
187
|
+
|
188
|
+
def write_all
|
189
|
+
show_file_header
|
190
|
+
super
|
191
|
+
end
|
192
|
+
|
193
|
+
def println(ln, ch)
|
194
|
+
if show_line_numbers
|
195
|
+
print_line_number(ln)
|
196
|
+
end
|
197
|
+
|
198
|
+
if ch && has_context
|
199
|
+
@out.printf "%s ", ch
|
200
|
+
end
|
201
|
+
|
202
|
+
line = get_line_to_print(ln)
|
203
|
+
log { "line: #{line}" }
|
204
|
+
|
205
|
+
@out.puts line
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|
209
|
+
|
210
|
+
|
211
|
+
class GlarkMatchList < GlarkOutputFormat
|
212
|
+
attr_reader :matches
|
213
|
+
|
214
|
+
def initialize(infile, show_file_names)
|
215
|
+
super
|
216
|
+
@matches = Array.new
|
217
|
+
end
|
218
|
+
|
219
|
+
def write_matches(matching, from, to)
|
220
|
+
stack "matching: #{matching}"
|
221
|
+
from.upto(to) do |line|
|
222
|
+
@matches[line] = true
|
223
|
+
end
|
224
|
+
log { "matches: #{@matches}" }
|
225
|
+
end
|
226
|
+
|
227
|
+
end
|
228
|
+
|
229
|
+
|
230
|
+
# -------------------------------------------------------
|
231
|
+
# Grep output format
|
232
|
+
# -------------------------------------------------------
|
233
|
+
|
234
|
+
# This matches grep, mostly. It is for running within emacs, thus,
|
235
|
+
# it does not support context or highlighting.
|
236
|
+
class GrepOutputFormat < OutputFormat
|
237
|
+
|
238
|
+
def write_count(matching = true)
|
239
|
+
print_file_name
|
240
|
+
ct = matching ? @infile.count : @infile.get_lines.length - @infile.count
|
241
|
+
puts ct
|
242
|
+
end
|
243
|
+
|
244
|
+
# prints the line, and adjusts for the fact that in our world, lines are
|
245
|
+
# 0-indexed, whereas they are displayed as if 1-indexed.
|
246
|
+
def print_line(lnum, ch = nil)
|
247
|
+
ln = get_line_to_print(lnum)
|
248
|
+
|
249
|
+
if ln
|
250
|
+
print_file_name
|
251
|
+
if show_line_numbers
|
252
|
+
printf "%d: ", lnum + 1
|
253
|
+
end
|
254
|
+
|
255
|
+
print ln
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
def print_file_name
|
260
|
+
if show_file_name
|
261
|
+
fname = @label || @infile.fname
|
262
|
+
print @infile.fname, ":"
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
end
|
@@ -0,0 +1,317 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
testdir = Pathname.new(__FILE__).expand_path.dirname.to_s
|
7
|
+
$:.unshift testdir
|
8
|
+
|
9
|
+
require 'testcase'
|
10
|
+
require 'stringio'
|
11
|
+
|
12
|
+
class TC_Glark < GlarkTestCase
|
13
|
+
|
14
|
+
def do_search_test(exprargs, contents, expected)
|
15
|
+
opts = GlarkOptions.instance
|
16
|
+
|
17
|
+
# Egads, Ruby is fun. Converting a maybe-array into a definite one:
|
18
|
+
args = [ exprargs ].flatten
|
19
|
+
|
20
|
+
expr = ExpressionFactory.new.make_expression(args)
|
21
|
+
|
22
|
+
outfname = infname = nil
|
23
|
+
|
24
|
+
begin
|
25
|
+
outfname = create_file do |outfile|
|
26
|
+
opts.out = outfile
|
27
|
+
infname = write_file(contents)
|
28
|
+
|
29
|
+
files = [ infname ]
|
30
|
+
glark = Glark.new(expr, files)
|
31
|
+
glark.search(infname)
|
32
|
+
end
|
33
|
+
|
34
|
+
do_file_test(outfname, expected)
|
35
|
+
ensure
|
36
|
+
[ outfname, infname ].each do |fname|
|
37
|
+
if fname && File.exists?(fname)
|
38
|
+
File.delete(fname)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
GlarkOptions.instance.reset
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_match_invert
|
46
|
+
contents = [
|
47
|
+
"ABC",
|
48
|
+
"DEF",
|
49
|
+
"GHI",
|
50
|
+
"JKL",
|
51
|
+
"MNO",
|
52
|
+
"PQR",
|
53
|
+
"STU",
|
54
|
+
]
|
55
|
+
|
56
|
+
exprstr = "K"
|
57
|
+
|
58
|
+
expected = contents.collect_with_index do |line, idx|
|
59
|
+
if !line.index(exprstr)
|
60
|
+
sprintf("%5d %s", idx + 1, line)
|
61
|
+
end
|
62
|
+
end.compact
|
63
|
+
|
64
|
+
Log.verbose = false
|
65
|
+
|
66
|
+
opts = GlarkOptions.instance
|
67
|
+
opts.invert_match = true
|
68
|
+
opts.verbose = false
|
69
|
+
Log.verbose = false
|
70
|
+
|
71
|
+
do_search_test(exprstr, contents, expected)
|
72
|
+
end
|
73
|
+
|
74
|
+
def do_match_test(contents, patterns, regexp, exprargs)
|
75
|
+
defcolors = Text::ANSIHighlighter::DEFAULT_COLORS
|
76
|
+
|
77
|
+
patdata = patterns.collect_with_index do |pat, pidx|
|
78
|
+
color = Text::ANSIHighlighter.make(defcolors[pidx % defcolors.length])
|
79
|
+
[ pat, color ]
|
80
|
+
end
|
81
|
+
|
82
|
+
expected = contents.collect_with_index do |line, li|
|
83
|
+
if line.index(regexp)
|
84
|
+
ln = line.dup
|
85
|
+
patdata.each do |pat|
|
86
|
+
ln.gsub!(pat[0]) { pat[1].highlight(pat[0]) }
|
87
|
+
end
|
88
|
+
sprintf("%5d %s", li + 1, ln)
|
89
|
+
else
|
90
|
+
nil
|
91
|
+
end
|
92
|
+
end.compact
|
93
|
+
|
94
|
+
# Log.verbose = false
|
95
|
+
|
96
|
+
opts = GlarkOptions.instance
|
97
|
+
opts.verbose = Log.verbose = false
|
98
|
+
|
99
|
+
do_search_test(exprargs, contents, expected)
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_match_plain_old_match
|
103
|
+
contents = [
|
104
|
+
"ABC",
|
105
|
+
"DEF",
|
106
|
+
"GHI",
|
107
|
+
"JKL",
|
108
|
+
"MNO",
|
109
|
+
"PQR",
|
110
|
+
"STU",
|
111
|
+
]
|
112
|
+
|
113
|
+
do_match_test(contents, %w{K}, %r{K}, "K")
|
114
|
+
do_match_test(contents, %w{A}, %r{A}, "A")
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_match_regexp_or
|
118
|
+
contents = [
|
119
|
+
"ABC",
|
120
|
+
"DEF",
|
121
|
+
"GHI",
|
122
|
+
"JKL",
|
123
|
+
"MNO",
|
124
|
+
"PQR",
|
125
|
+
"STU",
|
126
|
+
]
|
127
|
+
|
128
|
+
do_match_test(contents, %w{K N}, %r{(K)|(N)}, '(K)|(N)')
|
129
|
+
end
|
130
|
+
|
131
|
+
def do_test_match_alteration
|
132
|
+
patternsets = [
|
133
|
+
%w{ nul },
|
134
|
+
%w{ oo ae z },
|
135
|
+
%w{ zoo },
|
136
|
+
%w{ zeff },
|
137
|
+
]
|
138
|
+
|
139
|
+
contents = [
|
140
|
+
"zaffres",
|
141
|
+
"zoaea",
|
142
|
+
"zoaea's",
|
143
|
+
"zoea",
|
144
|
+
"zoeas",
|
145
|
+
"zonulae",
|
146
|
+
"zooea",
|
147
|
+
"zooeae",
|
148
|
+
"zooeal",
|
149
|
+
"zooeas",
|
150
|
+
"zooecia",
|
151
|
+
"zooecium",
|
152
|
+
"zoogloeae",
|
153
|
+
"zoogloeal",
|
154
|
+
"zoogloeas",
|
155
|
+
"zygaenid",
|
156
|
+
]
|
157
|
+
|
158
|
+
patternsets.each do |patterns|
|
159
|
+
regexp = Regexp.new(patterns.collect { |x| "(#{x})" }.join('|'))
|
160
|
+
exprargs = yield patterns
|
161
|
+
|
162
|
+
do_match_test(contents, patterns, regexp, exprargs)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def test_match_multicolor_alt_regexp
|
167
|
+
do_test_match_alteration do |patterns|
|
168
|
+
patterns.collect { |x| "(#{x})" }.join('|')
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def test_match_multicolor_or_expression
|
173
|
+
do_test_match_alteration do |patterns|
|
174
|
+
exprargs = [ patterns[-1] ]
|
175
|
+
patterns.reverse[1 .. -1].each do |pat|
|
176
|
+
exprargs.insert(0, "--or", pat)
|
177
|
+
end
|
178
|
+
exprargs
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def do_test_match_and_expression(contents, matches, patterns, exprargs)
|
183
|
+
regexp = Regexp.new(patterns.collect { |x| "(#{x})" }.join('|'))
|
184
|
+
|
185
|
+
defcolors = Text::ANSIHighlighter::DEFAULT_COLORS
|
186
|
+
|
187
|
+
patdata = patterns.collect_with_index do |pat, pidx|
|
188
|
+
color = Text::ANSIHighlighter.make(defcolors[pidx % defcolors.length])
|
189
|
+
[ pat, color ]
|
190
|
+
end
|
191
|
+
|
192
|
+
expected = contents.collect_with_index do |line, li|
|
193
|
+
if matches.include?(line)
|
194
|
+
ln = line.dup
|
195
|
+
patdata.each do |pat|
|
196
|
+
ln.gsub!(pat[0]) { pat[1].highlight(pat[0]) }
|
197
|
+
end
|
198
|
+
sprintf("%5d %s", li + 1, ln)
|
199
|
+
else
|
200
|
+
nil
|
201
|
+
end
|
202
|
+
end.compact
|
203
|
+
|
204
|
+
if false
|
205
|
+
for line in expected
|
206
|
+
$stderr.puts line
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
Log.verbose = false
|
211
|
+
opts = GlarkOptions.instance
|
212
|
+
opts.verbose = Log.verbose = false
|
213
|
+
|
214
|
+
do_search_test(exprargs, contents, expected)
|
215
|
+
end
|
216
|
+
|
217
|
+
def test_match_and_expression_2_lines_apart
|
218
|
+
contents = [
|
219
|
+
"zaffres",
|
220
|
+
"zoaea",
|
221
|
+
"zoaea's",
|
222
|
+
"zoea",
|
223
|
+
"zoeas",
|
224
|
+
"zonulae",
|
225
|
+
"zooea",
|
226
|
+
"zooeae",
|
227
|
+
"zooeal",
|
228
|
+
"zooeas",
|
229
|
+
"zooecia",
|
230
|
+
"zooecium",
|
231
|
+
"zoogloeae",
|
232
|
+
"zoogloeal",
|
233
|
+
"zoogloeas",
|
234
|
+
"zygaenid",
|
235
|
+
]
|
236
|
+
|
237
|
+
# 'ea', 'ec' within 2 lines of each other:
|
238
|
+
matches = [
|
239
|
+
"zooeal",
|
240
|
+
"zooeas",
|
241
|
+
"zooecia",
|
242
|
+
"zooecium",
|
243
|
+
"zoogloeae",
|
244
|
+
"zoogloeal",
|
245
|
+
]
|
246
|
+
|
247
|
+
patterns = %w{ ea ec }
|
248
|
+
|
249
|
+
exprargs = [ "--and", "2" ] | patterns
|
250
|
+
|
251
|
+
do_test_match_and_expression(contents, matches, patterns, exprargs)
|
252
|
+
end
|
253
|
+
|
254
|
+
def test_match_and_expression_3_lines_apart
|
255
|
+
contents = [
|
256
|
+
"zaffres",
|
257
|
+
"zoaea",
|
258
|
+
"zoaea's",
|
259
|
+
"zoea",
|
260
|
+
"zoeas",
|
261
|
+
"zonulae",
|
262
|
+
"zooea",
|
263
|
+
"zooeae",
|
264
|
+
"zooeal",
|
265
|
+
"zooeas",
|
266
|
+
"zooecia",
|
267
|
+
"zooecium",
|
268
|
+
"zoogloeae",
|
269
|
+
"zoogloeal",
|
270
|
+
"zoogloeas",
|
271
|
+
"zygaenid",
|
272
|
+
]
|
273
|
+
|
274
|
+
matches = [
|
275
|
+
"zoaea's",
|
276
|
+
"zoea",
|
277
|
+
"zoeas",
|
278
|
+
"zonulae",
|
279
|
+
]
|
280
|
+
|
281
|
+
patterns = %w{ aea ula }
|
282
|
+
|
283
|
+
exprargs = [ "--and", "3" ] | patterns
|
284
|
+
|
285
|
+
do_test_match_and_expression(contents, matches, patterns, exprargs)
|
286
|
+
end
|
287
|
+
|
288
|
+
def test_match_and_expression_entire_file
|
289
|
+
contents = [
|
290
|
+
"zaffres",
|
291
|
+
"zoaea",
|
292
|
+
"zoaea's",
|
293
|
+
"zoea",
|
294
|
+
"zoeas",
|
295
|
+
"zonulae",
|
296
|
+
"zooea",
|
297
|
+
"zooeae",
|
298
|
+
"zooeal",
|
299
|
+
"zooeas",
|
300
|
+
"zooecia",
|
301
|
+
"zooecium",
|
302
|
+
"zoogloeae",
|
303
|
+
"zoogloeal",
|
304
|
+
"zoogloeas",
|
305
|
+
"zygaenid",
|
306
|
+
]
|
307
|
+
|
308
|
+
matches = contents
|
309
|
+
|
310
|
+
patterns = %w{ aff yga }
|
311
|
+
|
312
|
+
exprargs = [ "--and", "-1" ] | patterns
|
313
|
+
|
314
|
+
do_test_match_and_expression(contents, matches, patterns, exprargs)
|
315
|
+
end
|
316
|
+
|
317
|
+
end
|