class Shellany::Sheller

The Guard sheller abstract the actual subshell calls and allow easier stubbing.

Attributes

status[R]

Public Class Methods

_shellize_if_needed(args) click to toggle source

Only needed on JRUBY, because MRI properly detects ‘;’ and metachars

# File lib/shellany/sheller.rb, line 128
def self._shellize_if_needed(args)
  return args unless RUBY_PLATFORM == "java"
  return args unless args.size == 1
  return args unless /[;<>]/ =~ args.first

  # NOTE: Sheller was originally meant for Guard (which basically only uses
  # UNIX commands anyway) and JRuby doesn't support options to
  # Kernel.system (and doesn't automatically shell when there's a
  # metacharacter in the command).
  #
  # So ... I'm assuming /bin/sh exists - if not, PRs are welcome,
  # because I have no clue what to do if /bin/sh doesn't exist.
  # (use ENV["RUBYSHELL"] ? Detect cmd.exe ?)
  ["/bin/sh", "-c", args.first]
end
_system_with_capture(*args) click to toggle source
# File lib/shellany/sheller.rb, line 110
def self._system_with_capture(*args)
  # We use popen3, because it started working on recent versions
  # of JRuby, while JRuby doesn't handle options to Kernel.system
  args = _shellize_if_needed(args)

  stdout, stderr, status = nil
  Open3.popen3(*args) do |_stdin, _stdout, _stderr, _thr|
    stdout = _stdout.read
    stderr = _stderr.read
    status = _thr.value
  end

  [status, stdout, stderr]
rescue Errno::ENOENT, IOError => e
  [nil, nil, "Guard::Sheller failed (#{e.inspect})"]
end
_system_with_no_capture(*args) click to toggle source
# File lib/shellany/sheller.rb, line 103
def self._system_with_no_capture(*args)
  Kernel.system(*args)
  result = $?
  errors = (result == 0) || "Guard failed to run: #{args.inspect}"
  [result, nil, errors]
end
new(*args) click to toggle source

Creates a new Guard::Sheller object.

@param [String] args a command to run in a subshell @param [Array<String>] args an array of command parts to run in a subshell @param [*String] args a list of command parts to run in a subshell

# File lib/shellany/sheller.rb, line 16
def initialize(*args)
  fail ArgumentError, "no command given" if args.empty?
  @command = args
  @ran = false
end
run(*args) click to toggle source

Shortcut for new(command).run

# File lib/shellany/sheller.rb, line 24
def self.run(*args)
  new(*args).run
end
stderr(*args) click to toggle source

Shortcut for new(command).run.stderr

# File lib/shellany/sheller.rb, line 36
def self.stderr(*args)
  new(*args).stderr
end
stdout(*args) click to toggle source

Shortcut for new(command).run.stdout

# File lib/shellany/sheller.rb, line 30
def self.stdout(*args)
  new(*args).stdout
end
system(*args) click to toggle source

No output capturing

NOTE: ‘$stdout.puts system(’cls’)‘ on Windows won’t work like it does for on systems with ansi terminals, so we need to be able to call Kernel.system directly.

# File lib/shellany/sheller.rb, line 99
def self.system(*args)
  _system_with_no_capture(*args)
end

Public Instance Methods

ok?() click to toggle source

Returns true if the command succeeded, false otherwise.

@return [Boolean] whether or not the command succeeded

# File lib/shellany/sheller.rb, line 68
def ok?
  run unless ran?

  @status && @status.success?
end
ran?() click to toggle source

Returns true if the command has already been run, false otherwise.

@return [Boolean] whether or not the command has already been run

# File lib/shellany/sheller.rb, line 60
def ran?
  @ran
end
run() click to toggle source

Runs the command.

@return [Boolean] whether or not the command succeeded.

# File lib/shellany/sheller.rb, line 44
def run
  unless ran?
    status, output, errors = self.class._system_with_capture(*@command)
    @ran = true
    @stdout = output
    @stderr = errors
    @status = status
  end

  ok?
end
stderr() click to toggle source

Returns the command’s error output.

@return [String] the command output

# File lib/shellany/sheller.rb, line 88
def stderr
  run unless ran?

  @stderr
end
stdout() click to toggle source

Returns the command’s output.

@return [String] the command output

# File lib/shellany/sheller.rb, line 78
def stdout
  run unless ran?

  @stdout
end