class Wunderbar::BuilderClass

Public Instance Methods

system(*args) { |:stdin, echo| ... } click to toggle source

execute a system command, echoing stdin, stdout, and stderr

# File lib/wunderbar/builder.rb, line 42
def system(*args)
  opts = {}
  opts = args.pop if Hash === args.last
  command = args
  command = args.first if args.length == 1 and Array === args.first

  if command.respond_to? :flatten
    flat = command.flatten
    secret = command - flat
    begin
      # if available, use escape as it does prettier quoting
      raise LoadError if not defined? Escape
      require 'escape'
      echo = Escape.shell_command(command.compact - secret)
    rescue LoadError
      # std-lib function that gets the job done
      echo = Shellwords.join(command.compact - secret)
    end
    command = flat.compact
  else
    echo = command
    command = [command]
  end

  patterns = opts[:hilite] || []
  patterns=[patterns] if String === patterns or Regexp === patterns
  patterns.map! do |pattern|
    String === pattern ? Regexp.new(Regexp.escape(pattern)) : pattern
  end

  yield :stdin, echo unless opts[:echo] == false

  semaphore = Mutex.new
  env = {'LC_CTYPE' => 'en_US.UTF-8'}
  sys_env = opts[:system_env] || {}
  env.merge! sys_env unless sys_env.empty?
  sys_opts = opts[:system_opts] || {}
  Open3.popen3(env, *command, sys_opts) do |pin, pout, perr, wait|
    [
      Thread.new do
        until pout.eof?
          out_line = pout.readline.chomp
          semaphore.synchronize do
            if patterns.any? {|pattern| out_line =~ pattern}
              yield :hilite, out_line
            else
              yield :stdout, out_line
            end
          end
        end
      end,

      Thread.new do
        until perr.eof?
          err_line = perr.readline.chomp
          semaphore.synchronize do
            yield :stderr, err_line
          end
        end
      end,

      Thread.new do
        if opts[:stdin].respond_to? :read
          require 'fileutils'
          FileUtils.copy_stream opts[:stdin], pin
        elsif opts[:stdin]
          pin.write opts[:stdin].to_s
        end
        pin.close
      end
    ].each {|thread| thread.join}
    wait and wait.value.exitstatus
  end
end
websocket(*args, &block) click to toggle source
# File lib/wunderbar/builder.rb, line 33
def websocket(*args, &block)
  if Hash === args.last
    args.last[:locals] = Hash[instance_variables.
      map { |name| [name.to_s.sub('@',''), instance_variable_get(name)] } ]
  end
  Wunderbar.websocket(*args, &block)
end