Skip to content

Instantly share code, notes, and snippets.

@nsmmrs
Last active September 3, 2022 13:42
Show Gist options
  • Save nsmmrs/4e73b23850ed884527ddc3e01da4a066 to your computer and use it in GitHub Desktop.
Save nsmmrs/4e73b23850ed884527ddc3e01da4a066 to your computer and use it in GitHub Desktop.
A convenience wrapper around `Open3.capture3` for easily running commands, capturing the output, and handling failures.
require "open3"
require "json"
class ShellCommand
attr_reader :line, :stdin, :binmode, :stdout, :stderr, :status
def initialize(line, stdin, binmode, stdout, stderr, status)
@line = line
@stdin = stdin
@binmode = binmode
@stdout = stdout
@stderr = stderr
@status = status
end
private_class_method :new
def success?() status.success? end
def pid() status.pid end
def exit_code() status.exitstatus end
def self.run(*line, **options)
line = line.map(&:to_s)
stdin = options[:stdin_data] || ""
binmode = options[:binmode] || false
args = line + [options]
captures = begin
Open3.capture3(*args)
rescue
raise Invalid.new(args)
end
command = new(line, stdin, binmode, *captures)
case
when block_given?
yield command
when command.success?
command.stdout.rstrip
else
raise Failed.new(command)
end
end
class Failed < StandardError
attr_reader :command
def initialize(command)
@command = command
end
def message
"Shell command failed: #{command.to_json}"
end
end
class Invalid < StandardError
def initialize(line)
super "Shell command invalid (did not run): #{line.to_json}"
end
end
def as_json
{
line: line,
stdin: stdin,
binmode: binmode,
stdout: stdout,
stderr: stderr,
pid: pid,
exit_code: exit_code,
}
end
def to_json(*args)
as_json.to_json(*args)
end
end
@ShalokShalom
Copy link

Thanks a lot!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment