interactive_grep 0.0.2 → 0.0.4

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.
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: