Module: Pipes

Defined in:
lib/rust/syntax/pipes.rb

Overview

require File.join(File.dirname(__FILE__), “../commands/builtins.rb”) require File.join(File.dirname(__FILE__), “../helpers/command_center.rb”)

Class Method Summary collapse

Class Method Details

.pipe_to(*args) ⇒ Object

Shamelessly borrowed from RS, written by kittensoft This totally rocks, despite it being pretty much popen3/4



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/rust/syntax/pipes.rb', line 16

def self.pipe_to(*args)
  error = nil
  # Custom streams?
  args, ios = if args.last.kind_of? Hash
    [args[0...-1], args.last]
  else
    [args, {}]
  end
  style = ios[:style]
  ios.reject! {|key, i| key == :style }

  # pipe.first is read, pipe.last is write
  in_pipe, out_pipe, err_pipe = IO.pipe, IO.pipe, IO.pipe

  # Adjust the pipes if we have custom streams
  ios.each {|n, stream| raise ArgumentError.new("#{n} must be an IO!") unless stream.kind_of? IO}

  in_pipe[0]  = ios[:stdin] if ios[:stdin]
  out_pipe[1] = ios[:stdout] if ios[:stdout]
  err_pipe[1] = ios[:stderr] if ios[:stderr]

  child = fork do
    # Reconfigure the standard I/O
    in_pipe.last.close          # Cannot write to STDIN
    (IO.open(0)).reopen in_pipe.first  # Input comes from reading in_pipe
    in_pipe.first.close         # Unnecessary, replaced above

    out_pipe.first.close        # Cannot read from STDOUT
    (IO.open(1)).reopen out_pipe.last # Output goes to writing side of out_pipe
    out_pipe.last.close         # Close old read

    err_pipe.first.close        # Cannot read from STDERR
    (IO.open(2)).reopen err_pipe.last # Error output  goes to writing side of err_pipe
    err_pipe.last.close         # Close old read

    # Run the command with the new environment

    case style
    when :standard
      ::CommandCenter.run_standard(args.join(' '))
    when :ruby
      ::CommandCenter.run_as_ruby(args.join(' '))
    when :builtin
      ::CommandCenter.run_as_builtin(args.join(' '))
    when :cmd
      arr = ::Shellwords.shellwords(args.join(''))
      cmd = arr.shift
      exec(::Paths.find_path(cmd), *arr)
    end
  end                                 # fork


  # Close unnecessary sides
  #    in_pipe.first.close           # Cannot read from other program's STDIN
  out_pipe.last.close           # Cannot write to other program's STDOUT
  err_pipe.last.close           # Cannot write to other program's STDERR

  # Do not wait for child
  res = [child, in_pipe.last, out_pipe.first, err_pipe.first] 

  # Block-form
  if block_given?
    begin
      value = yield(*res)
    ensure
      Process.waitpid child
      res[1..-1].each {|pipe| pipe.close unless pipe.closed?} 
      value
    end
    # Raw 
  else
    res
  end                               # if block_given?
end