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