interactive_grep 0.0.2 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/README.txt CHANGED
@@ -1,14 +1,11 @@
1
1
  Interactively Grep for patterns.
2
2
 
3
- This works particularly well for files with muli-line patterns (like
4
- weblogs) and it handles zipped files.
3
+ This works particularly well for exploring multi-line pattern even in gzip'd files (i.e. weblogs)
5
4
 
6
- The code: pretty-yucky. This is based on my very first Ruby program (and
7
- the code was a total hack)!
5
+ Why? This is based on my very first Ruby program (the code was a total hack)!
8
6
 
9
- But I've kept it because it's actually useful.
10
- And hopefully by the time you see this the code will serve as an example
11
- of the power of refactoring ;)
7
+ I kept it because it's actually useful.
8
+ Hopefully by the time you get this the code (v1.0), it will serve as an example of the power of refactoring ;)
12
9
 
13
10
  Basic use-case(s):
14
11
  gem install interactive_grep
@@ -17,41 +14,47 @@ Basic use-case(s):
17
14
 
18
15
  # OR in your code:
19
16
  irb
20
- # normal ('grep') mode - support(s) regular or gzipped files
21
- ig = InteractiveGrep::Grepper.new("files" => "/path/to/weblog.gz",
22
- "pattern" => search_string
17
+ # normal ('grep') mode
18
+ ig = InteractiveGrep::Grepper.new(
19
+ "files" => "/path/to/weblog.gz",
20
+ "pattern" => search_string
23
21
  )
24
22
  puts ig.run
25
- # => [matching_line1, matching_line2, matching_line3, etc...]
23
+ # => [matching_line1, ..., matching_lineN]
26
24
 
27
- # count ('grep -c') mode - support(s) regular or gzipped files
28
- ig = InteractiveGrep::Grepper.new("files" => "/path/to/weblog.gz",
29
- "pattern" => search_string,
30
- "mode" => "count"
25
+ # count ('grep -c') mode
26
+ ig = InteractiveGrep::Grepper.new(
27
+ "files" => "/path/to/weblog.gz",
28
+ "pattern" => search_string,
29
+ "mode" => "count"
31
30
  )
32
31
  ig.run
33
32
  # => 20
34
33
 
35
34
  # interactive mode - oh yeah!!!
36
- ig = InteractiveGrep::Grepper.new(files => "/path/to/weblog.gz",
37
- "pattern" => search_string
35
+ ig = InteractiveGrep::Grepper.new(
36
+ files => "/path/to/weblog.gz",
37
+ "pattern" => search_string
38
+ "mode" => "interactive"
38
39
  )
39
- ig.interactive = true
40
40
  ig.run
41
- # every time your *current* pattern is matched,
42
- # the match is displayed
43
- # and you are prompted to:
44
- # repeat the same search pattern (press enter)
45
- # 'S'ee what's on the next line of the file (enter S)
46
- # adjust the search pattern (whatever you enter)
47
- # turn 'O'ff interactive-mode (enter O)
48
- # ...at which point the rest of the results will be
49
- # automatically matched using the current pattern
41
+ # every line matching the current pattern is displayed
42
+ # and you're prompted to:
43
+ # repeat the current search (press enter)
44
+ #
45
+ # turn off interactive-mode (enter '-'*)
46
+ # -- grep remainder of file(s) for current pattern
47
+ #
48
+ # modify the current pattern (whatever you enter)
49
+ # e.g. to explore one-line at a time enter "." (dot)
50
+ # *note: to search for a dash, escape it (i.e. "\-")
50
51
 
51
52
  (See specs for more detailed use-cases ...and short-comings)
52
53
  rake rspec
53
54
 
54
55
  # TODO:
55
- # add specs for the behavior I described above
56
+ # specs the behavior I've already described
56
57
  # test-drive an API I can be proud of ;-)
57
- # ability to record & replay grep-sessions
58
+ # refactor (DRY-up and modularize)
59
+ # add ability to record & replay grep-sessions
60
+ # add support for zip, bzip, etc..
data/bin/igrep CHANGED
@@ -1,46 +1,47 @@
1
1
  #!/usr/bin/env ruby
2
-
3
2
  # the "i" is for interactive
3
+
4
4
  begin
5
5
  require 'rubygems'
6
6
  gem 'interactive_grep'
7
+ require 'interactive_grep'
7
8
  rescue LoadError
9
+ require File.expand_path( '../../lib/interactive_grep/grepper.rb', __FILE__ )
8
10
  end
9
- file_or_gem = File.expand_path( '../../lib/interactive_grep/grepper.rb', __FILE__ )
10
- file_or_gem = 'interactive_grep' unless File.exists?( file_or_gem )
11
- require file_or_gem
11
+ require 'optparse'
12
12
 
13
- # TODO: replace this w/ a real cmd-line options parser!
14
- if 0 == ARGV.size || InteractiveGrep::Grepper.contains_option?(ARGV,'h')
15
- puts InteractiveGrep::Grepper.usage
16
- end
13
+ options = {}
14
+ options["verbose"] = true
17
15
 
18
- pattern = nil; interactive = true
16
+ opt_parser = OptionParser.new do |opts|
17
+ opts.banner = "Usage: #{$0} [OPTIONS] A_FILEGLOB or FILE(S)"
19
18
 
20
- in_file = ARGV[0]
19
+ options["pattern"] = nil
20
+ opts.on( "--pattern [PATTERN]", "Regex to grep with") do |p|
21
+ options["pattern"] = p
22
+ end
21
23
 
22
- if 2 <= ARGV.size
23
- pattern = ARGV[1]
24
- end
24
+ options["mode"] = 'interactive'
25
+ opts.on( "--mode [MODE]", ['interactive', 'count', 'normal'], "'interactive', 'count' or 'normal'") do |m|
26
+ options["mode"] = m
27
+ end
25
28
 
26
- if 3 <= ARGV.size
27
- mode = case ARGV[2]
28
- when /^i/i
29
- interactive = true
30
- "interactive"
31
- when /^c/i
32
- interactive = false
33
- "count"
34
- else
35
- interactive = false
36
- "normal"
37
- end
29
+ opts.on_tail( '-h', '--help', 'This help screen' ) do
30
+ puts opts
31
+ exit
32
+ end
38
33
  end
39
34
 
40
- mode ||= interactive ? "interactive" : "normal"
41
- igrep = InteractiveGrep::Grepper.new( { "files" => in_file, "pattern" => pattern, "mode" => mode, "verbose" => "true" } )
35
+ opt_parser.parse!
36
+
37
+ options["files"] = ARGV
38
+ if options["files"].empty?
39
+ puts opt_parser
40
+ exit
41
+ end
42
42
 
43
- puts "Welcome..." if interactive
43
+ igrep = InteractiveGrep::Grepper.new( options )
44
+ puts "Welcome..." if :interactive == options["mode"]
44
45
  igrep.run()
45
46
 
46
47
  exit
@@ -19,4 +19,5 @@ Gem::Specification.new do |s|
19
19
 
20
20
  # specify any dependencies here; for example:
21
21
  s.add_development_dependency "rspec", "~> 2.11.0"
22
+ s.add_development_dependency "ruby-debug19"
22
23
  end
@@ -3,56 +3,34 @@ require 'zlib'
3
3
  module InteractiveGrep
4
4
  class Grepper
5
5
  DEFAULT_PATTERN = %r{.}.freeze
6
- DEFAULT_NUMBER_OF_LINES_TO_INDICATE = 100.freeze
6
+ DEFAULT_PROGRESS_INDICATOR_COUNT = 100.freeze # in verbose mode, show signs of life after processing every N lines
7
7
  DEBUG = false.freeze
8
8
 
9
- attr_accessor :file_names, :current_pattern, :initial_pattern, :gz, :file_index, :enough_lines_to_indicate
9
+ attr_reader :file_names, :current_pattern, :file_index
10
+ attr_accessor :progress_indicator_count, :initial_pattern
10
11
 
11
12
  def initialize( options = nil )
12
13
  options ||= {}
13
- @enough_lines_to_indicate = options[:line_indicator_count] || DEFAULT_NUMBER_OF_LINES_TO_INDICATE
14
- @verbose = DEBUG || !!options[ "verbose" ]
15
- reset_file_index
16
- @file_names = options[ "files" ]
17
- if ( !@file_names.is_a?( Array ) ) && @file_names[/\*/]
18
- @file_names = Dir.glob( @file_names ).map{|fname| fname}
19
- end
20
- @file_names = [ @file_names ] unless @file_names.is_a? Array
21
- unless current_file && File.exists?( current_file )
22
- raise "must specify at least one valid file (and/or file_glob)"
23
- end
24
-
25
- @initial_pattern = !!options[ "pattern" ] ? %r{#{options[ "pattern" ]}} : DEFAULT_PATTERN
26
- @current_pattern = @initial_pattern
27
14
 
15
+ @progress_indicator_count = options[:progress_indicator_count] || DEFAULT_PROGRESS_INDICATOR_COUNT
16
+ @verbose = DEBUG || !!options[ "verbose" ]
28
17
  @mode = options[ "mode" ] || "normal"
29
-
30
18
  @gz = options[ "gz" ]
19
+ @initial_pattern = !!options[ "pattern" ] ? %r{#{options[ "pattern" ]}} : DEFAULT_PATTERN
20
+ @current_pattern = @initial_pattern
21
+ reset_file_index
22
+ @file_names = self.class.globs_to_files( options[ "files" ] )
31
23
 
32
- if verbose?
33
- puts "using:\n\tfiles: #{file_names}\n\tending in: #{ending}\n\tinitial_pattern: #{current_pattern_string}\n"
24
+ if !current_file || !File.exists?( current_file )
25
+ raise "must specify at least one valid file (and/or file_glob)"
34
26
  end
35
- end
36
27
 
37
- def self.contains_option?(input_options, option_string)
38
- input_options.any?{|o| o[/^\s*\-+#{option_string}/] }
28
+ puts "using:\n\tfiles: #{file_names}\n\tending in: #{ending}\n\tinitial_pattern: #{current_pattern_string}\n" if verbose?
39
29
  end
40
30
 
41
- def self.usage
42
- puts "usage $0 [-h]"
43
- puts "\tproduces this help-message"
44
- puts ""
45
-
46
- puts "usage $0 <input_file> [<pattern>] [<mode>]"
47
- puts ""
48
- puts "modes: 'interactive' (default), 'count', or 'normal'"
49
- puts "e.g."
50
- puts "./igrep.rb big_test.txt.gz"
51
- puts './igrep.rb "/reporting/access*.gz" cvsfa=63 interactive'
52
- puts './igrep.rb "/reporting/access*.gz" cvsfa=63 count'
53
- puts './igrep.rb "/reporting/access*.gz" cvsfa=63 # normal-grep mode'
54
- puts ""
55
- exit
31
+ def self.globs_to_files( files_or_globs )
32
+ files_or_globs = files_or_globs.is_a?( Array ) ? files_or_globs : [ files_or_globs ]
33
+ files_or_globs.map {|file_or_glob| Dir.glob( file_or_glob ) }.flatten
56
34
  end
57
35
 
58
36
  def default_pattern?
@@ -96,17 +74,12 @@ module InteractiveGrep
96
74
  end
97
75
  @current_pattern = prompt( line )
98
76
  end
99
- if verbose?
100
- puts "." if 0 == (counter % enough_lines_to_indicate)
101
- end
77
+ puts "." if verbose? && 0 == (counter % progress_indicator_count)
102
78
  end
103
79
  reset_file_index
104
80
  puts "no more files.\n" if verbose?
105
81
  if just_count?
106
- if verbose?
107
- puts "matched #{counter} line(s)"
108
- puts "done.\n"
109
- end
82
+ puts "matched #{counter} line(s)\ndone.\n" if verbose?
110
83
  counter
111
84
  else
112
85
  puts "done.\n" if verbose?
@@ -116,6 +89,8 @@ module InteractiveGrep
116
89
 
117
90
  private
118
91
 
92
+ attr_reader :current_pattern, :file_index
93
+
119
94
  def verbose?
120
95
  !!@verbose
121
96
  end
@@ -129,39 +104,24 @@ module InteractiveGrep
129
104
  end
130
105
 
131
106
  def prompt( msg )
132
- if verbose? && msg && !just_count?
133
- puts "\n>>\n#{msg}\n<<"
134
- end
107
+ puts "\n>>\n#{msg}\n<<" if verbose? && msg && !just_count?
135
108
 
136
109
  if interactive?
137
- puts "S | O | <pattern: [#{current_pattern_string}]> ? "
138
- user_input = STDIN.gets.strip
110
+ puts ". | O | <pattern: [#{current_pattern_string}]> ? "
111
+ user_input = STDIN.gets.chomp
139
112
  puts ""
140
- if DEBUG
141
- puts "user_input: >>#{user_input.inspect}<<"
142
- end
113
+ puts "user_input: >>#{user_input.inspect}<<" if DEBUG
143
114
 
144
115
  case
145
116
  when /^\s*$/.match( user_input ) #corresponds w/ <enter> (or <return>)
146
- if verbose?
147
- puts " => continuing w/ the previous pattern"
148
- end
117
+ puts " => continuing w/ the previous pattern" if verbose?
149
118
  @current_pattern
150
- when [ "O", "o" ].include?( user_input ) #interactive mode Off
119
+ when "-" == user_input #interactive mode Off
151
120
  @mode = "normal"
152
- if verbose?
153
- puts " => interactive switched mode off"
154
- end
121
+ puts " => interactive switched mode off" if verbose?
155
122
  @current_pattern
156
- when [ "S", "s" ].include?( user_input ) #Show every line
157
- if verbose?
158
- puts " => showing the next line"
159
- end
160
- /./
161
123
  else #use whatever was entered
162
- if verbose?
163
- puts " => using your input as the new search pattern"
164
- end
124
+ puts " => using your input as the new search pattern" if verbose?
165
125
  %r{#{user_input}}
166
126
  end
167
127
  else
@@ -1,3 +1,3 @@
1
1
  module InteractiveGrep
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -26,7 +26,7 @@ describe InteractiveGrep::Grepper do
26
26
  end
27
27
 
28
28
  it "should have gz set to false" do
29
- grepper.gz.should be_false
29
+ grepper.should_not be_gz
30
30
  end
31
31
  end
32
32
 
@@ -38,7 +38,7 @@ describe InteractiveGrep::Grepper do
38
38
  end
39
39
 
40
40
  it "should have gz set to true" do
41
- grepper.gz.should be_true
41
+ grepper.should be_gz
42
42
  end
43
43
  end
44
44
 
@@ -50,7 +50,7 @@ describe InteractiveGrep::Grepper do
50
50
  end
51
51
 
52
52
  it "should have gz set to true" do
53
- grepper.gz.should be_true
53
+ grepper.should be_gz
54
54
  end
55
55
  end
56
56
 
@@ -62,7 +62,7 @@ describe InteractiveGrep::Grepper do
62
62
  end
63
63
 
64
64
  it "should have gz set to false" do
65
- grepper.gz.should be_false
65
+ grepper.should_not be_gz
66
66
  end
67
67
  end
68
68
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: interactive_grep
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-07-21 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70175694399860 !ruby/object:Gem::Requirement
16
+ requirement: &70136989126620 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,7 +21,18 @@ dependencies:
21
21
  version: 2.11.0
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70175694399860
24
+ version_requirements: *70136989126620
25
+ - !ruby/object:Gem::Dependency
26
+ name: ruby-debug19
27
+ requirement: &70136989126200 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70136989126200
25
36
  description: grep for stuff in (optionally gzipped) files ...even before you fully
26
37
  know what that 'stuff' looks like
27
38
  email: