glark 1.9.0 → 1.10.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.
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