Class: Grepmate

Inherits:
Object
  • Object
show all
Defined in:
lib/grepmate.rb

Constant Summary collapse

CONFIG_FILE =
File.expand_path("~/.grepmate")

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(params) ⇒ Grepmate

Returns a new instance of Grepmate.



18
19
20
21
22
# File 'lib/grepmate.rb', line 18

def initialize(params)
  @params = params

  load_config
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



15
16
17
# File 'lib/grepmate.rb', line 15

def config
  @config
end

#dirsObject (readonly)

Returns the value of attribute dirs.



15
16
17
# File 'lib/grepmate.rb', line 15

def dirs
  @dirs
end

#paramsObject (readonly)

Returns the value of attribute params.



15
16
17
# File 'lib/grepmate.rb', line 15

def params
  @params
end

#queryObject (readonly)

Returns the value of attribute query.



15
16
17
# File 'lib/grepmate.rb', line 15

def query
  @query
end

#resultsObject (readonly)

Returns the value of attribute results.



15
16
17
# File 'lib/grepmate.rb', line 15

def results
  @results
end

Instance Method Details

#determine_directories_to_searchObject

use default dirs, param dirs, or files/dirs from STDIN



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/grepmate.rb', line 83

def determine_directories_to_search
  if STDIN.tty?
    @dirs = if params['only_rails'].value || params['only_gems'].value
      [] 
    else
      params['dir'].values || []
    end
    @dirs += Array(rails_path) if params['only_rails'].value || params['rails'].value
    @dirs << gems_path if params['only_gems'].value || params['gems'].value
  else
    @dirs = []
    input = STDIN.read
  
    input.split("\n").each do |ln|
      if ln =~ /^([^:]*)/ # Assume everything to the first colon is a file name
        # filename = File.expand_path($1)
        # if File.exist?(filename) # But actually check that it is
          @dirs << $1# filename
        # end
      end
    end
  end
  @dirs.uniq! # remove duplicates
  verbose "including dirs: #{@dirs.join(' ')}"
  @dirs.reject!{ |dir|
    !File.exist?(dir) || @exclude_dirs.any?{ |exclude| dir =~ /(^|\/)#{exclude}(\/|$)/i }
  }
  verbose "rejected dirs, left with: #{@dirs.join(' ')}"
end

#determine_what_to_search_forObject



113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/grepmate.rb', line 113

def determine_what_to_search_for
  # funny bunny => 'funny' 'bunny'
  # 'funny bunny' => 'funny bunny'
  if params['regex'].value
    exp = params['what_to_search_for'].value.dup
    exp.gsub!(/^\//, '')
    exp.gsub!(/\/$/, '')
    @query = %("#{exp}")
    verbose "Searching for: /#{exp}/"
  else
    verbose "Searching for: #{params['what_to_search_for'].values.inspect}"
    @query = params['what_to_search_for'].values.map {|v| "\"#{v.gsub(/"/, '\\"')}\"" }.join(" ")
  end
end

#displayObject



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/grepmate.rb', line 154

def display
  if @results.empty?
    safe_puts "Nothing found!"
    exit
  elsif params['count'].value
    puts "Matches: #{@results.size}"
    exit
  end

  output_class = case @output.to_s
  when 'html'
    Output::HTML
  when 'text'
    Output::Text
  when 'textmate'
    Output::Textmate
  when 'file_and_line'
    Output::FileAndLine
  end
  
  output_class.new(self).process
end

#findObject



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/grepmate.rb', line 128

def find
  determine_directories_to_search
  determine_what_to_search_for

  @results = []
  if @dirs.any?
    paths = `find #{@dirs.join(' ')}`.split("\n").map{|sp| sp.gsub(' ', '\\ ')} # escape spaces in found files
    paths = paths.map!{|p| p.gsub(/^\.\//, '') }.uniq
    paths.reject! { |path| 
      @exclude_exts.any?{ |exclude| path =~ /\.#{Regexp.escape(exclude)}$/i } ||
      @exclude_dirs.any?{ |exclude| path =~ /(^|\/)#{Regexp.escape(exclude)}(\/|$)/i } 
    }

    cmd = 'grep '
    cmd << '-i ' unless params['case'].value
    # 3 lines of context for html and text
    cmd << '-C 3 ' if (@output == 'html') && !params['count'].value
    cmd << '-E ' if params['regex']

    # paths get too large for grep to handle, so limit the number it has to deal with at once.
    paths.each_slice(100) {|sub_paths|
      @results += `#{cmd} -n #{query} #{sub_paths.join(' ')}`.split("\n")
    }
  end
end

#gem_pathObject



24
25
26
# File 'lib/grepmate.rb', line 24

def gem_path
  `gem environment gemdir`.chomp
end

#gems_pathObject



28
29
30
# File 'lib/grepmate.rb', line 28

def gems_path
  File.join(gem_path, 'gems')
end

#load_configObject



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/grepmate.rb', line 46

def load_config
  if !File.exist?(CONFIG_FILE)
    # create
    safe_puts "Creating config file #{CONFIG_FILE}..."
    FileUtils.cp(File.expand_path(File.join(File.dirname(__FILE__), %w(.. config dot-grepmate))), CONFIG_FILE)
  else
    verbose("Using config file #{CONFIG_FILE}...")
  end
  
  # load
  @config = YAML::load(ERB.new(File.read(CONFIG_FILE)).result)
  # set output type
  @output = @config['default_output']
  %w(html text textmate file_and_line).each{|out_type|
    @output = out_type if params[out_type].value
  }
  verbose("Output mode set to #{@output}")
  
  # set default search directories
  unless params['dir'].values.any?
    params['dir'].values = @config['include_dirs']
  end
  
  # exclude extensions
  @exclude_exts = (@config['exclude_file_extensions'] || [])
  verbose "Excluding file extensions: #{@exclude_exts.join(' ')}"
  # dir exclusions
  @exclude_dirs = (@config['exclude_dirs'] || [])
  verbose "Excluding dirs: #{@exclude_dirs.join(' ')}"
  
  @search_rails = params['rails'].given? ? params['rails'].value : @config['search_rails_source']
  verbose "Searching rails source" if @search_rails
  @search_gems = params['gems'].given? ? params['gems'].value : @config['search_gems']
  verbose "Searching gems source" if @search_gems
end

#rails_pathObject



36
37
38
39
40
41
42
43
44
# File 'lib/grepmate.rb', line 36

def rails_path
  vendor_rails = "vendor/rails"

  if File.exist?(vendor_rails)
    vendor_rails
  else
    Dir["#{gems_path}/acti*-#{rails_version}"]
  end
end

#rails_versionObject



32
33
34
# File 'lib/grepmate.rb', line 32

def rails_version
  `rails -v`.chomp.split(' ').last
end

#safe_puts(msg) ⇒ Object



177
178
179
180
181
# File 'lib/grepmate.rb', line 177

def safe_puts(msg)
  if STDOUT.tty?
    puts msg
  end
end

#verbose(msg) ⇒ Object



183
184
185
186
187
# File 'lib/grepmate.rb', line 183

def verbose(msg)
  if @params['verbose'].value
    puts msg
  end
end