glark 1.9.0 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. data/bin/glark +2 -2
  2. data/lib/glark.rb +1 -1
  3. data/lib/glark/app/app.rb +48 -0
  4. data/lib/glark/app/help.rb +103 -0
  5. data/lib/glark/app/info/options.rb +84 -0
  6. data/lib/glark/app/options.rb +201 -0
  7. data/lib/glark/app/rcfile.rb +49 -0
  8. data/lib/glark/app/runner.rb +140 -0
  9. data/lib/glark/app/spec.rb +19 -0
  10. data/lib/glark/input/filter/criteria_opts.rb +41 -0
  11. data/lib/glark/input/filter/dir_criteria_opts.rb +37 -0
  12. data/lib/glark/input/filter/file_criteria_opts.rb +33 -0
  13. data/lib/glark/input/filter/filter.rb +59 -0
  14. data/lib/glark/input/filter/options.rb +171 -0
  15. data/lib/glark/input/options.rb +120 -0
  16. data/lib/glark/input/range.rb +104 -0
  17. data/lib/glark/input/spec.rb +39 -0
  18. data/lib/glark/io/file/archive_file.rb +64 -0
  19. data/lib/glark/io/file/binary_file.rb +19 -0
  20. data/lib/glark/io/file/file.rb +57 -0
  21. data/lib/glark/io/file/gz_file.rb +21 -0
  22. data/lib/glark/io/file/tar_file.rb +35 -0
  23. data/lib/glark/io/file/tar_gz_file.rb +52 -0
  24. data/lib/glark/io/file/zip_file.rb +39 -0
  25. data/lib/glark/match/and.rb +83 -0
  26. data/lib/glark/match/and_distance.rb +58 -0
  27. data/lib/glark/match/compound.rb +34 -0
  28. data/lib/glark/match/expression.rb +63 -0
  29. data/lib/glark/match/factory.rb +173 -0
  30. data/lib/glark/match/ior.rb +20 -0
  31. data/lib/glark/match/options.rb +74 -0
  32. data/lib/glark/match/or.rb +41 -0
  33. data/lib/glark/match/re.rb +81 -0
  34. data/lib/glark/match/re_factory.rb +44 -0
  35. data/lib/glark/match/spec.rb +59 -0
  36. data/lib/glark/match/xor.rb +20 -0
  37. data/lib/glark/output/binary_file_summary.rb +17 -0
  38. data/lib/glark/output/common.rb +43 -0
  39. data/lib/glark/output/context.rb +57 -0
  40. data/lib/glark/output/count.rb +26 -0
  41. data/lib/glark/output/file_header.rb +20 -0
  42. data/lib/glark/output/file_name_only.rb +35 -0
  43. data/lib/glark/output/formatted.rb +22 -0
  44. data/lib/glark/output/glark_count.rb +23 -0
  45. data/lib/glark/output/glark_format.rb +62 -0
  46. data/lib/glark/output/glark_lines.rb +36 -0
  47. data/lib/glark/output/grep_count.rb +18 -0
  48. data/lib/glark/output/grep_lines.rb +42 -0
  49. data/lib/glark/output/line_status.rb +46 -0
  50. data/lib/glark/output/lines.rb +100 -0
  51. data/lib/glark/output/match_list.rb +15 -0
  52. data/lib/glark/output/options.rb +103 -0
  53. data/lib/glark/output/results.rb +23 -0
  54. data/lib/glark/output/spec.rb +105 -0
  55. data/lib/glark/output/unfiltered_lines.rb +28 -0
  56. data/lib/glark/util/colors/options.rb +143 -0
  57. data/lib/glark/util/colors/spec.rb +21 -0
  58. data/lib/glark/util/highlight.rb +108 -0
  59. data/lib/glark/util/io/depth.rb +29 -0
  60. data/lib/glark/util/io/fileset.rb +162 -0
  61. data/lib/glark/util/io/filter/criteria.rb +49 -0
  62. data/lib/glark/util/io/filter/filter.rb +10 -0
  63. data/lib/glark/util/io/lines.rb +117 -0
  64. data/lib/glark/util/option.rb +34 -0
  65. data/lib/glark/util/options.rb +12 -0
  66. data/lib/glark/util/optutil.rb +69 -0
  67. data/lib/glark/util/timestamper.rb +18 -0
  68. data/man/glark.1 +1134 -0
  69. data/test/glark/app/and_test.rb +82 -0
  70. data/test/glark/app/compound_test.rb +33 -0
  71. data/test/glark/app/context_test.rb +43 -0
  72. data/test/glark/app/count_test.rb +89 -0
  73. data/test/glark/app/dump_test.rb +16 -0
  74. data/test/glark/app/expression_file_test.rb +22 -0
  75. data/test/glark/app/extended_regexp_test.rb +17 -0
  76. data/test/glark/app/extract_matches_test.rb +27 -0
  77. data/test/glark/app/files_with_match_test.rb +32 -0
  78. data/test/glark/app/files_without_match_test.rb +26 -0
  79. data/test/glark/app/filter_test.rb +118 -0
  80. data/test/glark/app/highlight_test.rb +78 -0
  81. data/test/glark/app/ignore_case_test.rb +22 -0
  82. data/test/glark/app/invert_test.rb +49 -0
  83. data/test/glark/app/ior_test.rb +21 -0
  84. data/test/glark/app/label_test.rb +28 -0
  85. data/test/glark/app/line_number_color_test.rb +42 -0
  86. data/test/glark/app/line_numbers_test.rb +42 -0
  87. data/test/glark/app/match_limit_test.rb +49 -0
  88. data/test/glark/app/options_test.rb +722 -0
  89. data/test/glark/app/range_test.rb +101 -0
  90. data/test/glark/app/rcfile_test.rb +113 -0
  91. data/test/glark/app/record_separator_test.rb +32 -0
  92. data/test/glark/app/regexp_test.rb +48 -0
  93. data/test/glark/app/tc.rb +92 -0
  94. data/test/glark/app/text_color_test.rb +31 -0
  95. data/test/glark/app/whole_lines_test.rb +17 -0
  96. data/test/glark/app/whole_words_test.rb +42 -0
  97. data/test/glark/app/xor_test.rb +19 -0
  98. data/test/glark/input/binary_file_test.rb +0 -0
  99. data/test/glark/input/directory_test.rb +202 -0
  100. data/test/glark/input/dirname_test.rb +69 -0
  101. data/test/glark/input/exclude_matching_test.rb +20 -0
  102. data/test/glark/input/ext_test.rb +65 -0
  103. data/test/glark/input/filter/criteria_test.rb +91 -0
  104. data/test/glark/input/filter/filter_spec_test.rb +27 -0
  105. data/test/glark/input/filter/filter_test.rb +21 -0
  106. data/test/glark/input/name_test.rb +75 -0
  107. data/test/glark/input/path_test.rb +72 -0
  108. data/test/glark/input/range_test.rb +82 -0
  109. data/test/glark/input/size_limit_test.rb +51 -0
  110. data/test/glark/input/split_as_path_test.rb +28 -0
  111. data/test/glark/match_test.rb +192 -0
  112. data/test/glark/resources.rb +21 -0
  113. data/test/glark/tc.rb +37 -0
  114. data/test/resources/add.rb +10 -0
  115. data/test/resources/echo.rb +2 -0
  116. data/test/resources/greet.rb +13 -0
  117. metadata +198 -28
  118. data/README +0 -0
  119. data/bin/jlark +0 -63
  120. data/lib/glark/expression.rb +0 -440
  121. data/lib/glark/exprfactory.rb +0 -248
  122. data/lib/glark/glark.rb +0 -297
  123. data/lib/glark/help.rb +0 -85
  124. data/lib/glark/input.rb +0 -183
  125. data/lib/glark/options.rb +0 -757
  126. data/lib/glark/output.rb +0 -266
  127. data/test/lib/glark/glark_test.rb +0 -317
  128. data/test/lib/glark/options_test.rb +0 -891
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'glark/io/file/gz_file'
5
+ require 'glark/io/file/tar_file'
6
+
7
+ module Glark
8
+ class TarGzFile
9
+ include Loggable
10
+
11
+ def initialize fname, range
12
+ @fname = fname
13
+ @range = range
14
+ end
15
+
16
+ def list
17
+ contents = Array.new
18
+ each_file do |entry|
19
+ contents << entry.full_name
20
+ end
21
+ contents
22
+ end
23
+
24
+ def run_search &blk
25
+ # a glitch with zlib results in a warning ("attempt to close unfinished
26
+ # zstream; reset forced.") for some tarballs, so we turn off warnings for
27
+ # a moment:
28
+ $-w = false
29
+
30
+ Zlib::GzipReader.open(@fname) do |gzio|
31
+ tarfile = Glark::TarFile.new @fname, @range, gzio
32
+ blk.call tarfile
33
+ end
34
+
35
+ $-w = true
36
+ end
37
+
38
+ def search_list expr, output_cls, output_opts
39
+ run_search do |tarfile|
40
+ tarfile.search_list expr, output_cls, output_opts
41
+ end
42
+ end
43
+
44
+ def search expr, output_type_cls, output_opts
45
+ matched = nil
46
+ run_search do |tarfile|
47
+ matched = tarfile.search(expr, output_type_cls, output_opts) || matched
48
+ end
49
+ matched
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'glark/io/file/archive_file'
5
+
6
+ module Glark
7
+ class ZipFile < ArchiveFile
8
+ include Loggable
9
+
10
+ def initialize fname, range, &blk
11
+ super fname, range
12
+
13
+ # Same caveat as ZipFile. Given that this is a gem, I'm not sure if it is
14
+ # installed with other package managers. So the require is down here, used
15
+ # only if needed.
16
+
17
+ begin
18
+ require 'zip/zip'
19
+ rescue LoadError => e
20
+ msg = "error loading zip gem: #{e}\n"
21
+ msg << "to install this dependency, run 'gem install rubyzip'"
22
+ info "msg: #{msg}".on_red
23
+ raise msg
24
+ end
25
+ end
26
+
27
+ def get_reader
28
+ @zipfile = Zip::ZipFile.new @fname
29
+ end
30
+
31
+ def read entry
32
+ @zipfile.read entry
33
+ end
34
+
35
+ def entry_name entry
36
+ entry.name
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/ruby -w
2
+ #!ruby -w
3
+ # vim: set filetype=ruby : set sw=2
4
+
5
+ require 'glark/match/compound'
6
+
7
+ # Evaluates both expressions, and is satisfied when both return true.
8
+ class AndExpression < CompoundExpression
9
+
10
+ def initialize dist, op1, op2
11
+ @dist = dist
12
+ super op1, op2
13
+ end
14
+
15
+ def match_within_distance op, lnum
16
+ op.matches.size > 0 and (op.matches[-1] - lnum <= @dist)
17
+ end
18
+
19
+ def inspect
20
+ str = "("+ @ops[0].to_s
21
+ if @dist == 0
22
+ str += " same line as "
23
+ elsif @dist.kind_of?(Float) && @dist.infinite?
24
+ str += " same file as "
25
+ else
26
+ str += " within " + @dist.to_s + " lines of "
27
+ end
28
+ str += @ops[1].to_s + ")"
29
+ str
30
+ end
31
+
32
+ def match? line, lnum, file, formatter
33
+ matches = (0 ... @ops.length).select do |oi|
34
+ @ops[oi].evaluate line, lnum, file, formatter
35
+ end
36
+
37
+ matches.each do |mi|
38
+ oidx = (1 + mi) % @ops.length
39
+ other = @ops[oidx]
40
+ if match_within_distance other, lnum
41
+ # search for the maximum match within the distance limit
42
+ other.matches.each do |m|
43
+ if lnum - m <= @dist
44
+ @last_start = m
45
+ return true
46
+ end
47
+ end
48
+ return false
49
+ end
50
+ end
51
+
52
+ false
53
+ end
54
+
55
+ def end_position
56
+ @ops.collect { |op| op.end_position }.max
57
+ end
58
+
59
+ def evaluate line, lnum, file, formatter
60
+ if match? line, lnum, file, formatter
61
+ @match_line_number = lnum
62
+ true
63
+ else
64
+ false
65
+ end
66
+ end
67
+
68
+ def explain level = 0
69
+ str = ""
70
+ if @dist == 0
71
+ str += " " * level + "on the same line:\n"
72
+ elsif @dist.kind_of?(Float) && @dist.infinite?
73
+ str += " " * level + "in the same file:\n"
74
+ else
75
+ lnstr = @dist == 1 ? "line" : "lines"
76
+ str += " " * level + "within #{@dist} #{lnstr} of each other:\n"
77
+ end
78
+ str += @ops[0].explain(level + 4)
79
+ str += " " * level + "and\n"
80
+ str += @ops[1].explain(level + 4)
81
+ str
82
+ end
83
+ end
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/ruby -w
2
+ #!ruby -w
3
+ # vim: set filetype=ruby : set sw=2
4
+
5
+ # Distance for and expression
6
+
7
+ require 'rubygems'
8
+ require 'riel/string'
9
+ require 'glark/match/re'
10
+ require 'glark/match/ior'
11
+ require 'glark/match/xor'
12
+ require 'glark/match/and'
13
+
14
+ class AndDistance
15
+ include Loggable
16
+
17
+ # signifies no limit to the distance between matches, i.e., anywhere within
18
+ # the entire file is valid.
19
+ INFINITE_DISTANCE = -1
20
+
21
+ AND_EQ_NUM_RE = Regexp.new '^--and=(\-?\d+)?$'
22
+
23
+ attr_reader :distance
24
+
25
+ def initialize arg, args
26
+ @distance = if arg == "-a"
27
+ args.shift
28
+ elsif arg == "--and"
29
+ if args.size > 0 && numeric?(args[0])
30
+ args.shift
31
+ else
32
+ "0"
33
+ end
34
+ elsif md = AND_EQ_NUM_RE.match(arg)
35
+ md[1]
36
+ else
37
+ raise "invalid 'and' option: '#{arg}'"
38
+ end
39
+
40
+ # check to ensure that this is numeric
41
+ if !numeric? @distance
42
+ raise "invalid distance for 'and' expression: '#{@distance}'\n" +
43
+ " expecting an integer, or #{INFINITE_DISTANCE} for 'infinite'"
44
+ end
45
+
46
+ if @distance.to_i == INFINITE_DISTANCE
47
+ @distance = 1.0 / 0.0 # infinity
48
+ else
49
+ @distance = @distance.to_i
50
+ end
51
+
52
+ @distance
53
+ end
54
+
55
+ def numeric? x
56
+ x && (x.kind_of?(Fixnum) || x.to_i == INFINITE_DISTANCE || x.num)
57
+ end
58
+ end
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/ruby -w
2
+ #!ruby -w
3
+ # vim: set filetype=ruby : set sw=2
4
+
5
+ require 'glark/match/expression'
6
+
7
+ # -------------------------------------------------------
8
+ # Compound expression function object
9
+ # -------------------------------------------------------
10
+
11
+ # Associates a collection of expressions.
12
+ class CompoundExpression < Expression
13
+ attr_reader :ops
14
+
15
+ def initialize(*ops)
16
+ @ops = ops
17
+ super()
18
+ end
19
+
20
+ def reset_file file
21
+ @ops.each do |op|
22
+ op.reset_file file
23
+ end
24
+ super
25
+ end
26
+
27
+ def start_position
28
+ @last_start
29
+ end
30
+
31
+ def == other
32
+ self.class == other.class && @ops == other.ops
33
+ end
34
+ end
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/ruby -w
2
+ #!ruby -w
3
+ # vim: set filetype=ruby : set sw=2
4
+
5
+ # Extended regular-expression-based expressions.
6
+
7
+ require 'rubygems'
8
+ require 'riel'
9
+
10
+ # An expression, which can be applied (processed) against a Glark::File.
11
+ class Expression
12
+ include Loggable
13
+
14
+ attr_accessor :matches
15
+
16
+ def initialize
17
+ @match_line_number = nil
18
+ @matches = Array.new
19
+ end
20
+
21
+ def add_match lnum
22
+ @matches.push lnum
23
+ end
24
+
25
+ def start_position
26
+ @match_line_number
27
+ end
28
+
29
+ def end_position
30
+ start_position
31
+ end
32
+
33
+ def reset_file file
34
+ @match_line_number = nil
35
+ @matches = Array.new
36
+ end
37
+
38
+ def process file, formatter
39
+ reset_file file.fname
40
+
41
+ rgstart = file.get_range_start
42
+ rgend = file.get_range_end
43
+
44
+ lastmatch = 0
45
+ lnum = 0
46
+ file.each_line do |line|
47
+ if ((!rgstart || lnum >= rgstart) &&
48
+ (!rgend || lnum < rgend) &&
49
+ evaluate(line, lnum, file, formatter))
50
+
51
+ break if formatter.process_match start_position, end_position, lastmatch, lnum
52
+ lastmatch = lnum + 1
53
+ end
54
+ lnum += 1
55
+ end
56
+
57
+ formatter.process_end lnum
58
+ end
59
+
60
+ def to_s
61
+ inspect
62
+ end
63
+ end
@@ -0,0 +1,173 @@
1
+ #!/usr/bin/ruby -w
2
+ #!ruby -w
3
+ # vim: set filetype=ruby : set sw=2
4
+
5
+ # Expression factory.
6
+
7
+ require 'rubygems'
8
+ require 'riel/regexp'
9
+ require 'riel/log/loggable'
10
+ require 'glark/match/and'
11
+ require 'glark/match/and_distance'
12
+ require 'glark/match/ior'
13
+ require 'glark/match/re_factory'
14
+ require 'glark/match/xor'
15
+
16
+ class ExpressionFactory
17
+ include Loggable
18
+
19
+ attr_reader :expr
20
+
21
+ def initialize matchspec
22
+ @regexp_factory = RegexpExpressionFactory.new matchspec
23
+ end
24
+
25
+ # reads a file containing one regular expression per line.
26
+ def read_file fname
27
+ expr = nil
28
+ File.open(fname) do |file|
29
+ file.each_line do |line|
30
+ line.strip!
31
+ next if line.empty?
32
+
33
+ # flatten the or expression instead of nesting it, to avoid
34
+ # stack overruns for very large files.
35
+ re = make_regular_expression line.chomp
36
+ if expr
37
+ expr.ops << re
38
+ else
39
+ expr = InclusiveOrExpression.new re
40
+ end
41
+ end
42
+ end
43
+ expr
44
+ end
45
+
46
+ def make_regular_expression pattern, negated = false
47
+ @regexp_factory.create_expression pattern, negated
48
+ end
49
+
50
+ # creates two expressions and returns them.
51
+ def make_expressions args
52
+ a1 = make_expression args
53
+ a2 = make_expression args
54
+
55
+ [ a1, a2 ]
56
+ end
57
+
58
+ # removes optional end tag
59
+ def shift_end_tag name, args
60
+ # explicit end tag is optional:
61
+ args.shift if args[0] == ("--end-of-" + name)
62
+ end
63
+
64
+ def make_not_expression args
65
+ expr = make_regular_expression args, true
66
+ unless expr
67
+ raise "'not' expression takes one argument"
68
+ end
69
+
70
+ # explicit end tag is optional:
71
+ shift_end_tag "not", args
72
+ expr
73
+ end
74
+
75
+ def make_two_expressions args, type
76
+ a1, a2 = make_expressions args
77
+ unless a1 && a2
78
+ raise "'" + type + "' expression takes two arguments"
79
+ end
80
+
81
+ shift_end_tag type, args
82
+ [ a1, a2 ]
83
+ end
84
+
85
+ def make_or_expression args
86
+ a1, a2 = make_two_expressions args, "or"
87
+ InclusiveOrExpression.new a1, a2
88
+ end
89
+
90
+ def make_xor_expression args
91
+ a1, a2 = make_two_expressions args, "xor"
92
+ ExclusiveOrExpression.new a1, a2
93
+ end
94
+
95
+ def make_and_distance arg, args
96
+ adist = AndDistance.new arg, args
97
+ adist.distance
98
+ end
99
+
100
+ def make_and_expression arg, args
101
+ dist = make_and_distance arg, args
102
+
103
+ a1, a2 = make_two_expressions args, "and"
104
+ AndExpression.new dist, a1, a2
105
+ end
106
+
107
+ def make_infix_expression arg, args = []
108
+ expr = nil
109
+
110
+ while arg
111
+ case arg
112
+ when '('
113
+ arg = args.shift
114
+ expr = make_infix_expression arg, args
115
+ when '--or', '-o'
116
+ arg = args.shift
117
+ rhs = make_infix_expression arg, args
118
+ expr = InclusiveOrExpression.new expr, rhs
119
+ when '--xor'
120
+ arg = args.shift
121
+ rhs = make_infix_expression arg, args
122
+ expr = ExclusiveOrExpression.new expr, rhs
123
+ when Regexp.new('^--and'), '-a'
124
+ dist = make_and_distance arg, args
125
+ arg = args.shift
126
+ rhs = make_infix_expression arg, args
127
+ expr = AndExpression.new dist, expr, rhs
128
+ when ')'
129
+ break
130
+ else
131
+ expr = make_regular_expression arg
132
+ break
133
+ end
134
+ arg = args.shift
135
+ end
136
+
137
+ if !expr
138
+ raise "No expression provided."
139
+ end
140
+
141
+ expr
142
+ end
143
+
144
+ def make_expression args, warn_option = false
145
+ arg = args[0]
146
+
147
+ if arg
148
+ case arg
149
+ when "--or", "-o"
150
+ args.shift
151
+ make_or_expression args
152
+ when "--xor"
153
+ args.shift
154
+ make_xor_expression args
155
+ when %r{^\-\-and}, %r{^\-a}
156
+ args.shift
157
+ make_and_expression arg, args
158
+ when '('
159
+ args.shift
160
+ make_infix_expression arg, args
161
+ else
162
+ if warn_option && arg.index(%r{^\-{1,2}\w})
163
+ raise "option not understood: #{arg}"
164
+ end
165
+
166
+ args.shift
167
+ make_regular_expression arg
168
+ end
169
+ else
170
+ nil
171
+ end
172
+ end
173
+ end