Module: Juicer::Binary

Included in:
JsLint, Minifyer::JavaBase
Defined in:
lib/juicer/binary.rb

Overview

Defines an abstract implementation of a binary that needs to be “shelled out” to be run. Provides a starting point when wrapping and API around a shell binary.

The module requires the including class to define the default_options method. It should return a hash of options where options are keys and default values are the values. Only options defined in this hash will be allowed to set on the binary.

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(m, *args) ⇒ Object

Allows for options to be set and read directly on the object as though they were standard attributes. compressor.verbose translates to compressor.get_opt(‘verbose’) and compressor.verbose = true to compressor.set_opt(‘verbose’, true)



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/juicer/binary.rb', line 145

def method_missing(m, *args)
  if @options.key?(m)
    # Only hit method_missing once per option
    self.class.send(:define_method, m) do       # def verbose
      get_opt(m)                                #   get_opt(:verbose)
    end                                         # end

    return get_opt(m)
  end

  return super unless m.to_s =~ /=$/

  opt = m.to_s.sub(/=$/, "").to_sym

  if @options.key?(opt)
    # Only hit method_missing once per option
    self.class.send(:define_method, m) do      # def verbose=(val)
      set_opt(opt, args[0])                    #   set_opt(:verbose, val)
    end                                        # end

    return set_opt(opt, args[0])
  end

  super
end

Instance Method Details

#commandObject

Constructs the command to use



107
108
109
110
111
# File 'lib/juicer/binary.rb', line 107

def command
  return @command if !@opt_set && @command
  @opt_set = false
  @command = [@binary, options]
end

#execute(*params) ⇒ Object

Run command



32
33
34
35
36
37
# File 'lib/juicer/binary.rb', line 32

def execute(*params)
  cmd = IO.popen(([self.command] + params).flatten, "r")
  results = cmd.gets(nil)
  cmd.close
  results
end

#get_opt(opt) ⇒ Object

Return the value of a given option opt = The option to return value for



42
43
44
# File 'lib/juicer/binary.rb', line 42

def get_opt(opt)
  @options[opt] || nil
end

#initialize(binary, options = {}) ⇒ Object

Initialize binary with options options = Hash of options, optional



18
19
20
21
22
23
24
# File 'lib/juicer/binary.rb', line 18

def initialize(binary, options = {})
  @options = self.respond_to?(:default_options) ? default_options.merge(options) : options
  @opt_set = false
  @command = nil
  @binary = binary
  @path = []
end

#locate(bin_glob, env = nil) ⇒ Object

Locate the binary to execute. The binary is searched for in the following places:

1) The paths specified through my_binary.path << “/usr/bin” 2) The path specified by the given environment variable 3) Current working directory

The name of the binary may be a glob pattern, resulting in locate returning an array of matches. This is useful in cases where the path is expected to store several versions oof a binary in the same directory, like /usr/bin/ruby /usr/bin/ruby1.8 /usr/bin/ruby1.9

locate always returns an array, or nil if no binaries where found. The result is always all files matching the given pattern in one of the specified paths - ie the first path where the pattern matches something.



130
131
132
133
134
135
136
137
138
139
# File 'lib/juicer/binary.rb', line 130

def locate(bin_glob, env = nil)
  path << ENV[env] if env && ENV.key?(env) && File.exist?(ENV[env])

  (path << Dir.pwd).each do |path|
    files = Dir.glob(File.expand_path(File.join(path, bin_glob)))
    return files unless files.empty?
  end

  nil
end

#options(*excludes) ⇒ Object

Return options as a cli arguments string. Optionally accepts a list of options to exclude from the generated string



49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/juicer/binary.rb', line 49

def options(*excludes)
  excludes = excludes.flatten.collect { |exc| exc.to_sym }
  @options.inject("") do |str, opt|
    if opt[1].nil? || excludes.include?(opt[0].to_sym)
      str
    else
      val = opt[1] == true ? '' : opt[1]
      option = opt[0].to_s
      option = (option.length == 1 ? "-" : "--") + option.gsub('_', '-')
      "#{str} #{option} #{val}".strip
    end
  end
end

#pathObject



26
27
28
# File 'lib/juicer/binary.rb', line 26

def path
  @path
end

#set_opt(opt, value) ⇒ Object

Set an option. Important: you can only set options that are predefined by the implementing class opt = The option to set value = The value of the option



68
69
70
71
72
73
74
75
76
77
# File 'lib/juicer/binary.rb', line 68

def set_opt(opt, value)
  opt = opt.to_sym
  if @options.key?(opt)
    @options[opt] = value
    @opt_set = true
  else
    msg = "Illegal option '#{opt}', specify one of: #{@options.keys.join(', ')}"
    raise ArgumentError.new(msg)
  end
end

#set_opts(options) ⇒ Object

Performs simple parsing of a string of parameters. All recognized parameters are set, non-existent arguments raise an ArgumentError



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/juicer/binary.rb', line 82

def set_opts(options)
  options = options.split " "
  option = nil
  regex = /^--?([^=]*)(=(.*))?/

  while word = options.shift
    if word =~ regex
      if option
        set_opt option, true
      end

      if $3
        set_opt $1, $3
      else
        option = $1
      end
    else
      set_opt option, word
      option = nil
    end
  end
end