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,108 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ $rielold = false
5
+
6
+ require 'rubygems'
7
+ require 'rainbow'
8
+ require 'singleton'
9
+
10
+ if $rielold
11
+ require 'riel/ansicolor'
12
+ else
13
+ require 'riel/text/ansi/ansi_highlight'
14
+ end
15
+
16
+ module Highlight
17
+ RESET = "\x1b[0m"
18
+
19
+ def adorn hl, str
20
+ if $rielold
21
+ hl.highlight str
22
+ else
23
+ hl + str + RESET
24
+ end
25
+ end
26
+ end
27
+
28
+ module Sickill
29
+ module Rainbow
30
+ class AnsiColor
31
+ $-w = false
32
+ # includes the aberrant color name in the error message.
33
+ def validate_color_name #:nodoc:
34
+ color_names = TERM_COLORS.keys
35
+
36
+ unless color_names.include?(@color)
37
+ raise ArgumentError.new "Unknown color name: '#{@color}'; valid names: #{color_names.join(', ')}"
38
+ end
39
+ end
40
+ $-w = true
41
+ end
42
+ end
43
+ end
44
+
45
+ class RainbowHighlighter
46
+ include Singleton
47
+
48
+ COLORS = %w{ black red green yellow blue magenta cyan white [\dA-Fa-f]{6} }
49
+ DECORATIONS = %w{ none reset bold underscore underline blink reverse inverse negative concealed }
50
+
51
+ BACKGROUND_COLORS = COLORS.collect { |color| "on_#{color}" }
52
+ FOREGROUND_COLORS = COLORS
53
+
54
+ COLORS_RE = Regexp.new('(?: ' +
55
+ # background will be in capture 0
56
+ 'on(?:\s+|_) ( ' + COLORS.join(' | ') + ' ) | ' +
57
+ # foreground will be in capture 1
58
+ '( ' + (COLORS + DECORATIONS).join(' | ') + ' ) ' +
59
+ ')', Regexp::EXTENDED)
60
+
61
+ def get_code color, type
62
+ case color
63
+ when 'bold', 'bright'
64
+ Sickill::Rainbow::TERM_EFFECTS[:bright]
65
+ when 'reverse', 'negative', 'inverse'
66
+ Sickill::Rainbow::TERM_EFFECTS[:inverse]
67
+ when 'underline'
68
+ Sickill::Rainbow::TERM_EFFECTS[:underline]
69
+ when 'blink'
70
+ Sickill::Rainbow::TERM_EFFECTS[:blink]
71
+ when %r{^[\dA-Fa-f]{6}$}
72
+ ac = Sickill::Rainbow::AnsiColor.new type, color
73
+ ac.code
74
+ else
75
+ ac = Sickill::Rainbow::AnsiColor.new type, color.to_sym
76
+ ac.code
77
+ end
78
+ end
79
+
80
+ def to_codes color
81
+ codes = ""
82
+ return codes unless Sickill::Rainbow.enabled
83
+ color.scan(COLORS_RE).collect do |md|
84
+ color, type = md[0] ? [ md[0], :background ] : [ md[1], :foreground ]
85
+ code = get_code color, type
86
+ "\e[#{code}m"
87
+ end.join ''
88
+ end
89
+ end
90
+
91
+ class HlWrapper
92
+ def initialize
93
+ # @hl = $rielold ? Text::ANSIHighlighter : Text::ANSIHighlighter.instance
94
+ @hl = RainbowHighlighter.instance
95
+ end
96
+
97
+ def make_color color
98
+ if $rielold
99
+ result = @hl.make color
100
+ else
101
+ @hl.to_codes color
102
+ end
103
+ end
104
+
105
+ def make_rgb_color red, green, blue, fgbg
106
+ @hl.instance.to_rgb_code red, green, blue, fgbg
107
+ end
108
+ end
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/ruby -w
2
+ #!ruby -w
3
+ # vim: set filetype=ruby : set sw=2
4
+
5
+ module Glark
6
+ # Depth for recursing directories.
7
+ class Depth
8
+ INFINITY = :infinity
9
+
10
+ attr_reader :value
11
+
12
+ def initialize value
13
+ @value = value
14
+ end
15
+
16
+ def infinity?
17
+ @value == INFINITY
18
+ end
19
+
20
+ def - num
21
+ return self if infinity? || @value.nil?
22
+ self.class.new @value - 1
23
+ end
24
+
25
+ def nonzero?
26
+ infinity? || @value.nil? || @value >= 0
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,162 @@
1
+ #!/usr/bin/ruby -w
2
+ #!ruby -w
3
+ # vim: set filetype=ruby : set sw=2
4
+
5
+ require 'rubygems'
6
+ require 'glark/util/io/depth'
7
+ require 'riel/filetype'
8
+
9
+ module Glark
10
+ # Files and directories. And standard input, just for fun.
11
+ class FileSet
12
+ include Loggable, Enumerable
13
+
14
+ attr_reader :files
15
+
16
+ DEPTH_RE = Regexp.new '\.\.\.(\d*)$'
17
+
18
+ def initialize fnames, args
19
+ @max_depth = Depth.new args[:max_depth]
20
+ @binary_files = args[:binary_files] || 'skip'
21
+ @dir_criteria = args[:dir_criteria]
22
+ @file_criteria = args[:file_criteria]
23
+ @split_as_path = args[:split_as_path]
24
+
25
+ @dir_to_max_depth = Hash.new
26
+ @files = Array.new
27
+
28
+ if fnames.size == 0
29
+ @files << '-'
30
+ else
31
+ add_files fnames
32
+ end
33
+ end
34
+
35
+ def size
36
+ @files.size
37
+ end
38
+
39
+ def add_files fnames
40
+ fnames.each do |fname|
41
+ if @split_as_path
42
+ add_as_path fname
43
+ else
44
+ add_fd fname
45
+ end
46
+ end
47
+ end
48
+
49
+ # this is a path in the form /usr/bin:/home/me/projects
50
+ def add_as_path path
51
+ path.to_s.split(::File::PATH_SEPARATOR).each do |element|
52
+ add_fd element
53
+ end
54
+ end
55
+
56
+ def add_fd fname
57
+ pn = nil
58
+
59
+ if md = DEPTH_RE.match(fname)
60
+ val = md[1].empty? ? nil : md[1].to_i
61
+ fname.sub! DEPTH_RE, ''
62
+ fname = '.' if fname.empty?
63
+ pn = Pathname.new fname
64
+ @dir_to_max_depth[pn] = Depth.new val
65
+ else
66
+ pn = Pathname.new fname
67
+ end
68
+
69
+ return if pn.file? && @file_criteria.skipped?(pn)
70
+ @files << pn
71
+ end
72
+
73
+ def stdin?
74
+ @files.size == 1 && @files.first == '-'
75
+ end
76
+
77
+ def each &blk
78
+ # to keep from cycling through links:
79
+ @yielded_files = Array.new
80
+
81
+ (0 ... @files.size).each do |idx|
82
+ pn = @files[idx]
83
+ type = FileType.type pn.to_s
84
+
85
+ if stdin?
86
+ blk.call [ :text, '-' ]
87
+ next
88
+ end
89
+
90
+ unless pn.readable?
91
+ write "directory not readable: #{pn}"
92
+ next
93
+ end
94
+
95
+ dirmax = @dir_to_max_depth[pn] || @max_depth
96
+ handle_pathname pn, dirmax, &blk
97
+ end
98
+ end
99
+
100
+ def handle_pathname pn, depth, &blk
101
+ if pn.directory?
102
+ handle_directory pn, depth, &blk
103
+ elsif pn.file?
104
+ handle_file pn, &blk
105
+ else
106
+ write "unknown file type: #{pn}"
107
+ end
108
+ end
109
+
110
+ def handle_directory pn, depth, &blk
111
+ return if @dir_criteria.skipped? pn, depth
112
+
113
+ subdepth = depth - 1
114
+
115
+ pn.children.sort.each do |entry|
116
+ next if @yielded_files.include?(entry)
117
+ if entry.file?
118
+ type = FileType.type entry.to_s
119
+ next if type == FileType::BINARY && @binary_files == 'skip'
120
+ end
121
+ @yielded_files << entry
122
+ handle_pathname entry, subdepth, &blk
123
+ end
124
+ end
125
+
126
+ def handle_file pn, &blk
127
+ return if @file_criteria.skipped? pn
128
+
129
+ type = FileType.type pn.to_s
130
+ case type
131
+ when FileType::TEXT
132
+ handle_text pn, &blk
133
+ when FileType::BINARY
134
+ handle_binary pn, &blk
135
+ when FileType::NONE
136
+ write "no such file: #{pn}"
137
+ when FileType::UNKNOWN
138
+ write "unknown file type: #{pn}"
139
+ end
140
+ end
141
+
142
+ def handle_text pn, &blk
143
+ blk.call [ :text, pn ]
144
+ end
145
+
146
+ def handle_binary pn, &blk
147
+ type = case @binary_files
148
+ when 'binary'
149
+ :binary
150
+ when 'skip', 'without-match'
151
+ return
152
+ when 'decompress', 'read'
153
+ :read
154
+ when 'list'
155
+ :list
156
+ else
157
+ :text
158
+ end
159
+ blk.call [ type, pn ]
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/ruby -w
2
+ #!ruby -w
3
+ # vim: set filetype=ruby : set sw=2
4
+
5
+ require 'glark/util/io/filter/filter'
6
+
7
+ module Glark
8
+ class Criteria
9
+ include Loggable
10
+
11
+ def initialize
12
+ # by type (hash) => by positive/negative (hash) => filter list (array)
13
+ @type_to_posneg = Hash.new
14
+ end
15
+
16
+ def add type, posneg, filter
17
+ posneg_to_filters = (@type_to_posneg[type] ||= Hash.new)
18
+ filters = (posneg_to_filters[posneg] ||= Array.new)
19
+ filters << filter
20
+ end
21
+
22
+ def get type, posneg
23
+ return nil unless posneg_to_filters = @type_to_posneg[type]
24
+ posneg_to_filters[posneg]
25
+ end
26
+
27
+ def find_by_class type, posneg, cls
28
+ return unless filters = get(type, posneg)
29
+ filters.detect { |filter| filter.kind_of? cls }
30
+ end
31
+
32
+ def skipped? pn
33
+ !match? pn
34
+ end
35
+
36
+ def match? pn
37
+ @type_to_posneg.values.each do |typefilters|
38
+ if (posf = typefilters[:positive]) && !posf.empty?
39
+ return false unless posf.detect { |fl| fl.match? pn }
40
+ end
41
+
42
+ if (negf = typefilters[:negative]) && !negf.empty?
43
+ return false if negf.detect { |fl| fl.match? pn }
44
+ end
45
+ end
46
+ true
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/ruby -w
2
+ #!ruby -w
3
+ # vim: set filetype=ruby : set sw=2
4
+
5
+ module Glark
6
+ class Filter
7
+ def match? pn
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,117 @@
1
+ #!/usr/bin/ruby -w
2
+ #!ruby -w
3
+ # vim: set filetype=ruby : set sw=2
4
+
5
+ module Glark
6
+ module IO
7
+ # Lines of input. Handles non-default ("\n") record separator.
8
+ class Lines
9
+ def initialize fname
10
+ @fname = fname
11
+ @count = nil
12
+ end
13
+
14
+ # Returns the given line for this file. For this method, a line ends with a
15
+ # CR, as opposed to the "lines" method, which ends with $/.
16
+ def get_line lnum
17
+ get_lines[lnum]
18
+ end
19
+
20
+ # this reads the entire file and returns the number of lines
21
+ def count
22
+ unless @count
23
+ @count = ::IO::readlines(@fname).size
24
+ end
25
+ @count
26
+ end
27
+ end
28
+
29
+ class LinesCR < Lines
30
+ def initialize fname, io
31
+ super fname
32
+ @lines = Array.new
33
+ @io = io
34
+ end
35
+
36
+ # Returns the lines for this file, separated by end of line sequences.
37
+ def get_lines
38
+ return @lines
39
+ end
40
+
41
+ def each_line &blk
42
+ while (line = @io.gets) && line.length > 0
43
+ @lines << line
44
+ blk.call line
45
+ end
46
+ @io.close
47
+ end
48
+
49
+ def get_region rnum
50
+ # easy case: range is the range number, unless it is out of range.
51
+ return rnum < @lines.length ? (rnum .. rnum) : nil
52
+ end
53
+ end
54
+
55
+ class LinesNonCR < Lines
56
+ # cross-platform end of line: DOS UNIX MAC
57
+ ANY_END_OF_LINE = Regexp.new '(?:\r\n|\n|\r)'
58
+
59
+ def initialize fname, io
60
+ super fname
61
+ @extracted = nil
62
+ @regions = nil
63
+ @lines = ::IO::readlines fname
64
+ end
65
+
66
+ def each_line &blk
67
+ @lines.each do |line|
68
+ blk.call line
69
+ end
70
+ end
71
+
72
+ # Returns the lines for this file, separated by end of line sequences.
73
+ def get_lines
74
+ @extracted ||= create_extracted
75
+ end
76
+
77
+ # returns the region/range that is represented by the region number
78
+ def get_region rnum
79
+ @regions ||= create_regions
80
+ @regions[rnum]
81
+ end
82
+
83
+ private
84
+ def create_extracted
85
+ # This is much easier. Just resplit the whole thing at end of line
86
+ # sequences.
87
+
88
+ eoline = "\n" # should be OS-dependent
89
+ srclines = @lines
90
+ reallines = @lines.join("").split ANY_END_OF_LINE
91
+
92
+ # "\n" after all but the last line
93
+ @extracted = (0 ... (reallines.length - 1)).collect { |lnum| reallines[lnum] + eoline }
94
+ @extracted << reallines[-1]
95
+
96
+ @extracted
97
+ end
98
+
99
+ def create_regions
100
+ @regions = [] # keys = region number; values = range of lines
101
+
102
+ lstart = 0
103
+ @lines.each do |line|
104
+ lend = lstart
105
+ line.scan(ANY_END_OF_LINE).each do |cr|
106
+ lend += 1
107
+ end
108
+
109
+ @regions << ::Range.new(lstart, lend - 1)
110
+
111
+ lstart = lend
112
+ end
113
+ @regions
114
+ end
115
+ end
116
+ end
117
+ end