Module: Toys::StandardMixins::Exec
- Includes:
- Mixin
- Defined in:
- lib/toys/standard_mixins/exec.rb
Overview
A set of helper methods for invoking subcommands. Provides shortcuts for common cases such as invoking Ruby in a subprocess or capturing output in a string. Also provides an interface for controlling a spawned process's streams.
You may make these methods available to your tool by including the following directive in your tool configuration:
include :exec
This is a frontend for Utils::Exec. More information is available in that class's documentation.
Configuration Options
Subprocesses may be configured using the options in the
Utils::Exec class. These include a variety of options supported
by Process#spawn, and some options supported by Utils::Exec
itself.
You can set default configuration by passing options to the include
directive. For example, to log commands at the debug level for all
subprocesses spawned by this tool:
include :exec, log_level: Logger::DEBUG
Two special options are also recognized by the mixin.
A :result_callback proc may take a second argument. If it does, the context object is passed as the second argument. This is useful if a
:result_callbackis applied to the entire tool by passing it to theincludedirective. In that case,selfis not set to the context object as it normally would be in a tool'srunmethod, so you cannot access it otherwise. For example, here is how to log the exit code for every subcommand:tool "mytool" do callback = proc do |result, context| context.logger.info "Exit code: #{result.exit_code}" end include :exec, result_callback: callback # ... endYou may also pass a symbol as the
:result_callback. The method with that name is then called as the callback. The method must take one argument, the result object.If :exit_on_nonzero_status is set to true, a nonzero exit code returned by the subprocess will also cause the tool to exit immediately with that same code.
This is particularly useful as an option to the
includedirective, where it causes any subprocess failure to abort the tool, similar to settingset -ein a bash script.include :exec, exit_on_nonzero_status: true:e can be used as a shortcut for :exit_on_nonzero_status
include :exec, e: true
Constant Summary collapse
- KEY =
Context key for the executor object.
::Object.new.freeze
Instance Method Summary collapse
-
#capture(cmd, **opts) {|controller| ... } ⇒ String
Execute a command.
-
#capture_proc(func, **opts) {|controller| ... } ⇒ String
Execute a proc in a forked subprocess.
-
#capture_ruby(args, **opts) {|controller| ... } ⇒ String
Spawn a ruby process and pass the given arguments to it.
-
#capture_separate_tool(cmd, **opts) {|controller| ... } ⇒ String
Execute a tool in a separately spawned process.
-
#capture_tool(cmd, **opts) {|controller| ... } ⇒ String
Execute a tool in the current CLI in a forked process.
-
#configure_exec(**opts) ⇒ self
Set default configuration keys.
-
#exec(cmd, **opts) {|controller| ... } ⇒ Toys::Utils::Exec::Controller, Toys::Utils::Exec::Result
Execute a command.
-
#exec_proc(func, **opts) {|controller| ... } ⇒ Toys::Utils::Exec::Controller, Toys::Utils::Exec::Result
Execute a proc in a forked subprocess.
-
#exec_ruby(args, **opts) {|controller| ... } ⇒ Toys::Utils::Exec::Controller, Toys::Utils::Exec::Result
(also: #ruby)
Spawn a ruby process and pass the given arguments to it.
-
#exec_separate_tool(cmd, **opts) {|controller| ... } ⇒ Toys::Utils::Exec::Controller, Toys::Utils::Exec::Result
Execute a tool in a separately spawned process.
-
#exec_tool(cmd, **opts) {|controller| ... } ⇒ Toys::Utils::Exec::Controller, Toys::Utils::Exec::Result
Execute a tool in the current CLI in a forked process.
-
#exit_on_nonzero_status(status) ⇒ Integer
Exit if the given status code is nonzero.
-
#sh(cmd, **opts) {|controller| ... } ⇒ Integer
Execute the given string in a shell.
Methods included from Mixin
Instance Method Details
#capture(cmd, **opts) {|controller| ... } ⇒ String
Execute a command. The command may be given as a single string to pass to a shell, or an array of strings indicating a posix command.
Captures standard out and returns it as a string. Cannot be run in the background.
If a block is provided, a Utils::Exec::Controller will be yielded to it.
269 270 271 272 |
# File 'lib/toys/standard_mixins/exec.rb', line 269 def capture(cmd, **opts, &block) opts = Exec._setup_exec_opts(opts, self) self[KEY].capture(cmd, **opts, &block) end |
#capture_proc(func, **opts) {|controller| ... } ⇒ String
Execute a proc in a forked subprocess.
Captures standard out and returns it as a string. Cannot be run in the background.
If a block is provided, a Utils::Exec::Controller will be yielded to it.
Beware that some Ruby environments (e.g. JRuby, and Ruby on Windows) do not support this method because they do not support fork.
318 319 320 321 |
# File 'lib/toys/standard_mixins/exec.rb', line 318 def capture_proc(func, **opts, &block) opts = Exec._setup_exec_opts(opts, self) self[KEY].capture_proc(func, **opts, &block) end |
#capture_ruby(args, **opts) {|controller| ... } ⇒ String
Spawn a ruby process and pass the given arguments to it.
Captures standard out and returns it as a string. Cannot be run in the background.
If a block is provided, a Utils::Exec::Controller will be yielded to it.
292 293 294 295 |
# File 'lib/toys/standard_mixins/exec.rb', line 292 def capture_ruby(args, **opts, &block) opts = Exec._setup_exec_opts(opts, self) self[KEY].capture_ruby(args, **opts, &block) end |
#capture_separate_tool(cmd, **opts) {|controller| ... } ⇒ String
Execute a tool in a separately spawned process.
Captures standard out and returns it as a string. Cannot be run in the background.
The command may be given as a single string or an array of strings, representing the tool to run and the arguments to pass.
If a block is provided, a Utils::Exec::Controller will be yielded to it.
An entirely separate spawned process is run for this tool, using the setting of Toys.executable_path. Thus, this method can be run only if that setting is present. The normal Toys gem does set it, but if you are writing your own executable using Toys-Core, you will need to set it explicitly for this method to work. Furthermore, Bundler, if present, is reset to its "unbundled" environment. Thus, the tool found, the behavior of the CLI, and the gem environment, might not be the same as those of the calling tool.
This method is often used if you are already in a bundle and need to run a tool that uses a different bundle. It may also be necessary on environments without "fork" (such as JRuby or Ruby on Windows).
387 388 389 390 391 |
# File 'lib/toys/standard_mixins/exec.rb', line 387 def capture_separate_tool(cmd, **opts, &block) Exec._setup_clean_process(cmd) do |clean_cmd| capture(clean_cmd, **opts, &block) end end |
#capture_tool(cmd, **opts) {|controller| ... } ⇒ String
Execute a tool in the current CLI in a forked process.
Captures standard out and returns it as a string. Cannot be run in the background.
The command may be given as a single string or an array of strings, representing the tool to run and the arguments to pass.
If a block is provided, a Utils::Exec::Controller will be yielded to it.
Beware that some Ruby environments (e.g. JRuby, and Ruby on Windows) do not support this method because they do not support fork.
347 348 349 350 351 |
# File 'lib/toys/standard_mixins/exec.rb', line 347 def capture_tool(cmd, **opts, &block) func = Exec._make_tool_caller(cmd) opts = Exec._setup_exec_opts(opts, self) self[KEY].capture_proc(func, **opts, &block) end |
#configure_exec(**opts) ⇒ self
Set default configuration keys.
All options listed in the Utils::Exec documentation are
supported, plus the exit_on_nonzero_status option.
100 101 102 103 104 |
# File 'lib/toys/standard_mixins/exec.rb', line 100 def configure_exec(**opts) opts = Exec._setup_exec_opts(opts, self) self[KEY].configure_defaults(**opts) self end |
#exec(cmd, **opts) {|controller| ... } ⇒ Toys::Utils::Exec::Controller, Toys::Utils::Exec::Result
Execute a command. The command may be given as a single string to pass to a shell, or an array of strings indicating a posix command.
If the process is not set to run in the background, and a block is provided, a Utils::Exec::Controller will be yielded to it.
125 126 127 128 |
# File 'lib/toys/standard_mixins/exec.rb', line 125 def exec(cmd, **opts, &block) opts = Exec._setup_exec_opts(opts, self) self[KEY].exec(cmd, **opts, &block) end |
#exec_proc(func, **opts) {|controller| ... } ⇒ Toys::Utils::Exec::Controller, Toys::Utils::Exec::Result
Execute a proc in a forked subprocess.
If the process is not set to run in the background, and a block is provided, a Utils::Exec::Controller will be yielded to it.
Beware that some Ruby environments (e.g. JRuby, and Ruby on Windows) do not support this method because they do not support fork.
175 176 177 178 |
# File 'lib/toys/standard_mixins/exec.rb', line 175 def exec_proc(func, **opts, &block) opts = Exec._setup_exec_opts(opts, self) self[KEY].exec_proc(func, **opts, &block) end |
#exec_ruby(args, **opts) {|controller| ... } ⇒ Toys::Utils::Exec::Controller, Toys::Utils::Exec::Result Also known as: ruby
Spawn a ruby process and pass the given arguments to it.
If the process is not set to run in the background, and a block is provided, a Utils::Exec::Controller will be yielded to it.
148 149 150 151 |
# File 'lib/toys/standard_mixins/exec.rb', line 148 def exec_ruby(args, **opts, &block) opts = Exec._setup_exec_opts(opts, self) self[KEY].exec_ruby(args, **opts, &block) end |
#exec_separate_tool(cmd, **opts) {|controller| ... } ⇒ Toys::Utils::Exec::Controller, Toys::Utils::Exec::Result
Execute a tool in a separately spawned process.
The command may be given as a single string or an array of strings, representing the tool to run and the arguments to pass.
If the process is not set to run in the background, and a block is provided, a Utils::Exec::Controller will be yielded to it.
An entirely separate spawned process is run for this tool, using the setting of Toys.executable_path. Thus, this method can be run only if that setting is present. The normal Toys gem does set it, but if you are writing your own executable using Toys-Core, you will need to set it explicitly for this method to work. Furthermore, Bundler, if present, is reset to its "unbundled" environment. Thus, the tool found, the behavior of the CLI, and the gem environment, might not be the same as those of the calling tool.
This method is often used if you are already in a bundle and need to run a tool that uses a different bundle. It may also be necessary on environments without "fork" (such as JRuby or Ruby on Windows).
244 245 246 247 248 |
# File 'lib/toys/standard_mixins/exec.rb', line 244 def exec_separate_tool(cmd, **opts, &block) Exec._setup_clean_process(cmd) do |clean_cmd| exec(clean_cmd, **opts, &block) end end |
#exec_tool(cmd, **opts) {|controller| ... } ⇒ Toys::Utils::Exec::Controller, Toys::Utils::Exec::Result
Execute a tool in the current CLI in a forked process.
The command may be given as a single string or an array of strings, representing the tool to run and the arguments to pass.
If the process is not set to run in the background, and a block is provided, a Utils::Exec::Controller will be yielded to it.
Beware that some Ruby environments (e.g. JRuby, and Ruby on Windows) do not support this method because they do not support fork.
204 205 206 207 208 |
# File 'lib/toys/standard_mixins/exec.rb', line 204 def exec_tool(cmd, **opts, &block) func = Exec._make_tool_caller(cmd) opts = Exec._setup_exec_opts(opts, self) self[KEY].exec_proc(func, **opts, &block) end |
#exit_on_nonzero_status(status) ⇒ Integer
Exit if the given status code is nonzero. Otherwise, returns 0.
420 421 422 423 424 425 |
# File 'lib/toys/standard_mixins/exec.rb', line 420 def exit_on_nonzero_status(status) status = status.exit_code if status.respond_to?(:exit_code) status = status.exitstatus if status.respond_to?(:exitstatus) Context.exit(status) unless status.zero? 0 end |
#sh(cmd, **opts) {|controller| ... } ⇒ Integer
Execute the given string in a shell. Returns the exit code. Cannot be run in the background.
If a block is provided, a Utils::Exec::Controller will be yielded to it.
409 410 411 412 |
# File 'lib/toys/standard_mixins/exec.rb', line 409 def sh(cmd, **opts, &block) opts = Exec._setup_exec_opts(opts, self) self[KEY].sh(cmd, **opts, &block) end |