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,120 @@
1
+ #!/usr/bin/ruby -w
2
+ #!ruby -w
3
+ # vim: set filetype=ruby : set sw=2
4
+
5
+ # Options for input.
6
+
7
+ require 'rubygems'
8
+ require 'glark/input/spec'
9
+ require 'glark/util/io/fileset'
10
+ require 'glark/util/options'
11
+
12
+ module Glark
13
+ class InputOptions < InputSpec
14
+ include OptionUtil, Loggable
15
+
16
+ def initialize optdata
17
+ super()
18
+ add_as_options optdata
19
+ end
20
+
21
+ def create_fileset files
22
+ fsargs = Hash.new
23
+ fsargs[:max_depth] = @max_depth
24
+ fsargs[:binary_files] = @binary_files
25
+ fsargs[:dir_criteria] = @dir_criteria
26
+ fsargs[:file_criteria] = @file_criteria
27
+ fsargs[:split_as_path] = @split_as_path
28
+
29
+ FileSet.new files, fsargs
30
+ end
31
+
32
+ def set_record_separator sep
33
+ $/ = if sep && sep.to_i > 0
34
+ begin
35
+ sep.oct.chr
36
+ rescue RangeError => e
37
+ # out of range (e.g., 777) means nil:
38
+ nil
39
+ end
40
+ else
41
+ "\n\n"
42
+ end
43
+ end
44
+
45
+ def config_fields
46
+ fields = {
47
+ "binary-files" => binary_files,
48
+ "split-as-path" => @split_as_path,
49
+ }
50
+ fields.merge! @dir_criteria.config_fields
51
+ fields.merge! @file_criteria.config_fields
52
+ end
53
+
54
+ def dump_fields
55
+ fields = {
56
+ "binary_files" => binary_files,
57
+ "directory" => @directory,
58
+ "exclude_matching" => @exclude_matching,
59
+ "split-as-path" => @split_as_path,
60
+ }
61
+ fields.merge! @dir_criteria.dump_fields
62
+ fields.merge! @file_criteria.dump_fields
63
+ fields
64
+ end
65
+
66
+ def update_fields fields
67
+ @dir_criteria.update_fields fields
68
+ @file_criteria.update_fields fields
69
+
70
+ fields.each do |name, value|
71
+ case name
72
+ when 'split-as-path'
73
+ @split_as_path = to_boolean value
74
+ end
75
+ end
76
+ end
77
+
78
+ def set_directory val
79
+ @max_depth = val == 'list' ? 0 : nil
80
+ @dir_criteria.skip_all = val == 'skip'
81
+ # otherwise, it's recurse
82
+ end
83
+
84
+ def add_as_options optdata
85
+ optdata << record_separator_option = {
86
+ :res => [ Regexp.new('^ -0 (\d{1,3})? $ ', Regexp::EXTENDED) ],
87
+ :set => Proc.new { |md| rs = md ? md[1] : 0; set_record_separator rs }
88
+ }
89
+
90
+ @range.add_as_option optdata
91
+
92
+ optdata << recurse_option = {
93
+ :tags => %w{ -r --recurse },
94
+ :set => Proc.new { set_directory("recurse") }
95
+ }
96
+
97
+ optdata << directories_option = {
98
+ :tags => %w{ --directories -d },
99
+ :arg => [ :string ],
100
+ :set => Proc.new { |val| set_directory val },
101
+ }
102
+
103
+ re = Regexp.new '^[\'\"]?(' + VALID_BINARY_FILE_TYPES.join('|') + ')[\'\"]?$'
104
+ optdata << binary_files_option = {
105
+ :tags => %w{ --binary-files },
106
+ :arg => [ :required, :regexp, re ],
107
+ :set => Proc.new { |md| @binary_files = md[1] },
108
+ :rc => %w{ binary-files },
109
+ }
110
+
111
+ @file_criteria.add_as_options optdata
112
+ @dir_criteria.add_as_options optdata
113
+
114
+ add_opt_true optdata, :exclude_matching, %w{ -M --exclude-matching }
115
+
116
+ add_opt_false optdata, :split_as_path, %w{ --no-split-as-path }
117
+ add_opt_true optdata, :split_as_path, %w{ --split-as-path }
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ module Glark
5
+ class RangeError < RuntimeError
6
+ end
7
+
8
+ class Range
9
+ include Loggable, Comparable
10
+
11
+ PCT_RE = Regexp.new '([\.\d]+)%'
12
+
13
+ attr_accessor :from
14
+ attr_accessor :to
15
+
16
+ def initialize from = nil, to = nil
17
+ @from = from
18
+ @to = to
19
+ end
20
+
21
+ def bound?
22
+ @from.nil? && @to.nil?
23
+ end
24
+
25
+ def to_line var, linecount
26
+ return nil unless var
27
+
28
+ if pct = as_pct(var)
29
+ count = linecount
30
+ count * pct.to_f / 100
31
+ else
32
+ var.to_f
33
+ end
34
+ end
35
+
36
+ def as_pct val
37
+ (md = PCT_RE.match(val)) && md[1]
38
+ end
39
+
40
+ def validate!
41
+ return true if @from.nil? || @to.nil?
42
+
43
+ frompct, topct = [ @from, @to ].collect { |val| as_pct val }
44
+
45
+ # both or neither are percentages:
46
+ return true if frompct.nil? != topct.nil?
47
+
48
+ if frompct
49
+ check_range! frompct, topct
50
+ else
51
+ check_range! @from, @to
52
+ end
53
+ true
54
+ end
55
+
56
+ def check_range! from, to
57
+ if from.to_f > to.to_f
58
+ raise RangeError.new "error: range start (#{@from}) follows range end (#{@to})"
59
+ end
60
+ end
61
+
62
+ # there is no nil <=> nil in Ruby
63
+ def compare x, y
64
+ x.nil? && y.nil? ? nil : (x <=> y).nonzero?
65
+ end
66
+
67
+ def <=> other
68
+ compare(from, other.from) || compare(to, other.to) || 0
69
+ end
70
+
71
+ def clear
72
+ @from = nil
73
+ @to = nil
74
+ end
75
+
76
+ def add_as_option optdata
77
+ optdata << range_after_option = {
78
+ :tags => %w{ --after },
79
+ :arg => [ :required, :regexp, %r{ (\d+%?) $ }x ],
80
+ :set => Proc.new { |md| @from = md[1] }
81
+ }
82
+
83
+ optdata << range_before_option = {
84
+ :tags => %w{ --before },
85
+ :arg => [ :required, :regexp, %r{ (\d+%?) $ }x ],
86
+ :set => Proc.new { |md| @to = md[1] }
87
+ }
88
+
89
+ optdata << range_option = {
90
+ :tags => %w{ -R --range },
91
+ :arg => [ :required, :regexp, Regexp.new('(\d+%?),(\d+%?)') ],
92
+ :set => Proc.new do |md, opt, args|
93
+ if md && md[1] && md[2]
94
+ @from = md[1]
95
+ @to = md[2]
96
+ else
97
+ @from = args.shift
98
+ @to = args.shift
99
+ end
100
+ end
101
+ }
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/ruby -w
2
+ #!ruby -w
3
+ # vim: set filetype=ruby : set sw=2
4
+
5
+ require 'glark/input/range'
6
+ require 'glark/input/filter/dir_criteria_opts'
7
+ require 'glark/input/filter/file_criteria_opts'
8
+
9
+ module Glark
10
+ class InputSpec
11
+ VALID_BINARY_FILE_TYPES = [ 'text', 'without-match', 'skip', 'binary', 'list', 'decompress', 'read' ]
12
+
13
+ attr_accessor :binary_files # how to handle binary files
14
+ attr_accessor :directory # read, skip, or recurse, a la grep
15
+ attr_accessor :exclude_matching # exclude files whose names match the expression
16
+ attr_accessor :range # range to start and stop searching; nil => the entire file
17
+ attr_accessor :split_as_path # use file arguments as path elements
18
+
19
+ attr_accessor :dir_criteria
20
+ attr_accessor :file_criteria
21
+ attr_accessor :max_depth
22
+
23
+ def initialize
24
+ @binary_files = 'skip'
25
+ @directory = 'list'
26
+ @exclude_matching = false
27
+
28
+ @range = Range.new
29
+ @split_as_path = true
30
+
31
+ @file_criteria = FileCriteriaOpts.new
32
+ @dir_criteria = DirCriteriaOpts.new nil
33
+
34
+ @max_depth = 0 # list directories
35
+
36
+ $/ = "\n"
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'glark/io/file/file'
5
+
6
+ module Glark
7
+ class ArchiveFile
8
+ def initialize fname, range
9
+ @fname = fname
10
+ @range = range
11
+ end
12
+
13
+ def search_list expr, output_cls, output_opts
14
+ contents = StringIO.new list.collect { |x| x + "\n" }.join('')
15
+ contents.rewind
16
+
17
+ file = Glark::File.new @fname, contents, @range
18
+ output_type = output_cls.new file, output_opts
19
+ file.search expr, output_type
20
+ end
21
+
22
+ def list
23
+ contents = Array.new
24
+ each do |entry|
25
+ contents << entry_name(entry)
26
+ end
27
+ contents
28
+ end
29
+
30
+ def each &blk
31
+ reader = get_reader
32
+ reader.each do |entry|
33
+ blk.call entry
34
+ end
35
+ reader.close
36
+ end
37
+
38
+ def search_archive_file expr, entry, output_type_cls, output_opts
39
+ name = entry_name entry
40
+ data = read entry
41
+ contents = StringIO.new data
42
+
43
+ file = Glark::File.new name + " (in #{@fname})", contents, @range
44
+ output = output_type_cls.new file, output_opts
45
+ file.search expr, output
46
+ end
47
+
48
+ def read entry
49
+ entry.read
50
+ end
51
+
52
+ def search expr, output_type_cls, output_opts
53
+ matched = nil
54
+ each do |entry|
55
+ # a glitch with zlib doesn't seem to recognize some tarball entries
56
+ # (with entry.header.typeflag == "") as being a file, so we test for
57
+ # directory:
58
+ next if entry.directory?
59
+ matched = search_archive_file(expr, entry, output_type_cls, output_opts) || matched
60
+ end
61
+ matched
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'glark/io/file/file'
5
+
6
+ module Glark
7
+ class BinaryFile < Glark::File
8
+ def initialize fname
9
+ file = ::File.new fname
10
+ file.binmode # for MSDOS/WinWhatever
11
+ super fname, file, nil
12
+ end
13
+
14
+ def search_as_binary expr, output_opts
15
+ output_type = BinaryFileSummary.new self, output_opts
16
+ search expr, output_type
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/ruby -w
2
+ #!ruby -w
3
+ # vim: set filetype=ruby : set sw=2
4
+
5
+ require 'glark/util/io/lines'
6
+
7
+ module Glark
8
+ # A thing that can be grepped (er, glarked).
9
+ class File
10
+ attr_reader :fname
11
+
12
+ def initialize fname, io, range
13
+ @fname = fname
14
+ @range = range
15
+
16
+ linescls = $/ == "\n" ? Glark::IO::LinesCR : Glark::IO::LinesNonCR
17
+ @lines = linescls.new fname, io
18
+ end
19
+
20
+ def linecount
21
+ @lines.count
22
+ end
23
+
24
+ def each_line &blk
25
+ @lines.each_line(&blk)
26
+ end
27
+
28
+ # Returns the lines for this file, separated by end of line sequences.
29
+ def get_lines
30
+ @lines.get_lines
31
+ end
32
+
33
+ # Returns the given line for this file. For this method, a line ends with a
34
+ # CR, as opposed to the "lines" method, which ends with $/.
35
+ def get_line lnum
36
+ @lines.get_line lnum
37
+ end
38
+
39
+ # Returns the region/range that is represented by the region number.
40
+ def get_region rnum
41
+ @lines.get_region rnum
42
+ end
43
+
44
+ def get_range_start
45
+ @range && @range.from && @range.to_line(@range.from, linecount)
46
+ end
47
+
48
+ def get_range_end
49
+ @range && @range.to && @range.to_line(@range.to, linecount)
50
+ end
51
+
52
+ def search expr, output
53
+ expr.process self, output
54
+ output.matched?
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'glark/io/file/file'
5
+ require 'zlib'
6
+
7
+ module Glark
8
+ class GzFile < Glark::File
9
+ def initialize fname, range, &blk
10
+ if blk
11
+ Zlib::GzipReader.open(fname) do |gz|
12
+ super fname, gz, range
13
+ blk.call [ self, gz ]
14
+ end
15
+ else
16
+ gz = Zlib::GzipReader.new fname
17
+ super fname, gz, range
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'glark/io/file/file'
5
+ require 'glark/io/file/archive_file'
6
+
7
+ module Glark
8
+ class TarFile < ArchiveFile
9
+ def initialize fname, range, io = nil, &blk
10
+ super fname, range
11
+
12
+ # Given that this is a gem, I'm not sure if it is installed with other
13
+ # package managers. So the require is down here, used only if needed.
14
+
15
+ # module Gem::Package is declared in 'rubygems/package', not in
16
+ # .../tar_reader.
17
+ require 'rubygems/package'
18
+ require 'rubygems/package/tar_reader'
19
+ @io = io
20
+ end
21
+
22
+ def get_reader
23
+ io = @io || ::File.new(@fname)
24
+ Gem::Package::TarReader.new io
25
+ end
26
+
27
+ def entry_name entry
28
+ entry.full_name
29
+ end
30
+
31
+ def read entry
32
+ entry.read
33
+ end
34
+ end
35
+ end