Class: Backticks::Runner
- Inherits:
-
Object
- Object
- Backticks::Runner
- Defined in:
- lib/backticks/runner.rb
Overview
An easy-to-use interface for invoking commands and capturing their output. Instances of Runner can be interactive, which prints the command’s output to the terminal and also allows the user to interact with the command. By default commands are unbuffered, using a pseudoterminal to capture the output with no delay.
Constant Summary collapse
- BUFFERED =
Default streams to buffer if someone calls bufferered= with Boolean.
[:stdin, :stdout, :stderr].freeze
Instance Attribute Summary collapse
-
#buffered ⇒ Array
List of I/O streams that should be captured using a pipe instead of a pseudoterminal.
-
#chdir ⇒ String?
PWD for new child processes, default is Dir.pwd.
-
#cli ⇒ #parameters
readonly
The CLI-translation object used by this runner.
-
#interactive ⇒ Boolean
If true, commands will have their stdio streams tied to the parent process so the user can view their output and send input to them.
Instance Method Summary collapse
-
#initialize(options = {}) ⇒ Runner
constructor
Create an instance of Runner.
-
#run(*sugar) ⇒ Command
Run a command whose parameters are expressed using some Rubyish sugar.
-
#run_without_sugar(argv) ⇒ Command
Run a command whose argv is specified in the same manner as Kernel#exec, with no Rubyish sugar.
Constructor Details
#initialize(options = {}) ⇒ Runner
Create an instance of Runner.
55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/backticks/runner.rb', line 55 def initialize(={}) = { :buffered => false, :cli => Backticks::CLI::Getopt, :interactive => false, }.merge() @cli = [:cli] @chdir = nil self.buffered = [:buffered] self.interactive = [:interactive] end |
Instance Attribute Details
#buffered ⇒ Array
List of I/O streams that should be captured using a pipe instead of a pseudoterminal.
When read, this attribute is always an Array of stream names from the set ‘[:stdin, :stdout, :stderr]`.
Note: if you set ‘interactive` to true, then stdin and stdout are unbuffered regardless of how you have set `buffered`!
39 40 41 |
# File 'lib/backticks/runner.rb', line 39 def buffered @buffered end |
#chdir ⇒ String?
Returns PWD for new child processes, default is Dir.pwd.
42 43 44 |
# File 'lib/backticks/runner.rb', line 42 def chdir @chdir end |
#cli ⇒ #parameters (readonly)
Returns the CLI-translation object used by this runner.
45 46 47 |
# File 'lib/backticks/runner.rb', line 45 def cli @cli end |
#interactive ⇒ Boolean
If true, commands will have their stdio streams tied to the parent process so the user can view their output and send input to them. Commands’ output is still captured normally when they are interactive.
Note: if you set ‘interactive` to true, then stdin and stdout will be unbuffered regardless of how you have set `buffered`!
27 28 29 |
# File 'lib/backticks/runner.rb', line 27 def interactive @interactive end |
Instance Method Details
#run(*sugar) ⇒ Command
Run a command whose parameters are expressed using some Rubyish sugar. This method accepts an arbitrary number of positional parameters; each parameter can be a Hash, an array, or a simple Object. Arrays and simple objects are appended to argv as words of the command; Hashes are translated to command-line options and then appended to argv.
Hashes are processed by @cli, defaulting to Backticks::CLI::Getopt and easily overridden by passing the ‘cli` option to #initialize.
102 103 104 |
# File 'lib/backticks/runner.rb', line 102 def run(*sugar) run_without_sugar(@cli.parameters(*sugar)) end |
#run_without_sugar(argv) ⇒ Command
Run a command whose argv is specified in the same manner as Kernel#exec, with no Rubyish sugar.
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/backticks/runner.rb', line 112 def run_without_sugar(argv) nopty = !defined?(PTY) stdin_r, stdin = if nopty || (buffered.include?(:stdin) && !interactive) IO.pipe else PTY.open end stdout, stdout_w = if nopty || (buffered.include?(:stdout) && !interactive) IO.pipe else PTY.open end stderr, stderr_w = if nopty || buffered.include?(:stderr) IO.pipe else PTY.open end dir = @chdir || Dir.pwd pid = spawn(*argv, in: stdin_r, out: stdout_w, err: stderr_w, chdir: dir) stdin_r.close stdout_w.close stderr_w.close unless interactive stdin.close stdin = nil end Command.new(pid, stdin, stdout, stderr, interactive:interactive) end |