lib/backticks/command.rb in backticks-0.1.1 vs lib/backticks/command.rb in backticks-0.3.0
- old
+ new
@@ -22,31 +22,34 @@
# @return [String] all data captured (so far) from child's stdin/stdout/stderr
attr_reader :captured_input, :captured_output, :captured_error, :status
# Watch a running command.
- def initialize(pid, stdin, stdout, stderr, interactive:false)
+ def initialize(pid, stdin, stdout, stderr)
@pid = pid
@stdin = stdin
@stdout = stdout
@stderr = stderr
- @interactive = interactive
- stdin.close unless @interactive
-
@captured_input = String.new.force_encoding(Encoding::BINARY)
@captured_output = String.new.force_encoding(Encoding::BINARY)
@captured_error = String.new.force_encoding(Encoding::BINARY)
end
+ def interactive?
+ !@stdin.nil?
+ end
+
# Block until the command exits, or until limit seconds have passed. If
# interactive is true, pass user input to the command and print its output
# to Ruby's output streams. If the time limit expires, return `nil`;
# otherwise, return self.
#
# @param [Float,Integer] limit number of seconds to wait before returning
def join(limit=nil)
+ return self if @status # preserve idempotency
+
if limit
tf = Time.now + limit
else
tf = FOREVER
end
@@ -74,11 +77,11 @@
#
# @param [Float,Integer] number of seconds to wait before returning nil
# @return [String,nil] fresh bytes from stdout/stderr, or nil if no output
private def capture(limit=nil)
streams = [@stdout, @stderr]
- streams << STDIN if @interactive
+ streams << STDIN if interactive?
if limit
tf = Time.now + limit
else
tf = FOREVER
@@ -101,26 +104,29 @@
# capture child's stdout and maybe proxy to STDOUT
if ready && ready.include?(@stdout)
data = @stdout.readpartial(CHUNK) rescue nil
if data
@captured_output << data
- STDOUT.write(data) if @interactive
+ STDOUT.write(data) if interactive?
fresh_output = data
end
end
# capture child's stderr and maybe proxy to STDERR
if ready && ready.include?(@stderr)
data = @stderr.readpartial(CHUNK) rescue nil
if data
@captured_error << data
- STDERR.write(data) if @interactive
+ STDERR.write(data) if interactive?
+ fresh_error = data
end
end
- fresh_output
+
+ # return freshly-captured text(if any)
+ fresh_output || fresh_error
rescue Interrupt
# Proxy Ctrl+C to the child
(Process.kill('INT', @pid) rescue nil) if @interactive
raise
end
end
-end
\ No newline at end of file
+end