Class: Sprout::Executable::Session
- Inherits:
-
Base
- Object
- Base
- Sprout::Executable::Session
- Defined in:
- lib/sprout/executable/session.rb
Overview
The Sprout::Daemon class exposes the Domain Specific Language provided by the Sprout::Executable, along with enhancements (and modifications) to support long-lived processes (like FDB and FCSH).
##
# The Foo class extends Sprout::Daemon
class Foo < Sprout::Daemon
##
# Keep in mind that we're still working
# with Executable, so add_param is available
# for the initialization of the process.
add_param :input, File
##
# Expose the do_something action after
# the process is started.
add_action :do_something
##
# Expose the do_something_else action after
# the process is started.
add_action :do_something_else
end
You can also create a globally-accessible rake task to use your new Daemon instance by creating a method like the following:
def foo *args, &block
foo_tool = Foo.new
foo_tool.to_rake *args, &block
end
The previous Rake task could be used like:
foo 'Bar.txt' do |t|
t.do_something
t.do_something_else
end
Constant Summary
Constant Summary
Constants included from Sprout::Executable
DEFAULT_FILE_EXPRESSION, DEFAULT_PREFIX, DEFAULT_SHORT_PREFIX
Instance Attribute Summary (collapse)
-
- (Object) process_runner
readonly
The Sprout::ProcessRunner that delegates to the long-running process, via stdin, stdout and stderr.
-
- (Object) process_thread
readonly
The Thread that contains the forked running process.
-
- (Regexp) prompt
The prompt expression for this daemon process.
Attributes inherited from Base
#abort_on_failure, #default_prefix, #default_short_prefix, #executable, #param_hash, #params, #pkg_name, #pkg_version, #prerequisites, #rake_task_name
Class Method Summary (collapse)
-
+ (nil) add_action(name, arguments = nil, options = nil)
Add an action that can be called while the long-lived process is active.
-
+ (nil) add_action_alias(alias_name, source_name)
Create an (often shorter) alias to an existing action name.
Instance Method Summary (collapse)
-
- (Array<Hash>) action_stack
Return or create a new array.
-
- (Rake::Task) create_outer_task(*args)
protected
This is the override of the underlying Sprout::Executable template method so that we create a ‘task’ instead of a ‘file’ task.
-
- (Object) execute(should_wait = true)
Execute the Daemon executable, followed by the collection of stored actions in the order they were called.
-
- (Object) handle_user_input
Expose the running process to manual input on the terminal, and write stdout back to the user.
- - (Boolean) process_launched? protected
-
- (Boolean) prompted?
If executable is awaiting input.
-
- (Thread) system_execute(binary, params)
protected
This is the override of the underlying Sprout::Executable template method so that we create the process in a thread in order to read and write to it.
-
- (String) update_rake_task_name_from_args(*args)
protected
This is the override of the underlying Sprout::Executable template method so that we are NOT added to the CLEAN collection.
- - (Object) wait
-
- (Object) wait_for_prompt
Wait for the underlying process to present an input prompt, so that another action can be submitted, or user input can be collected.
Methods inherited from Base
add_param, add_param_alias, #binary_path, #binary_path=, #default_file_expression, #execute_delegate, #from_hash, #initialize, #initialize_defaults, #library_added, #parse!, #parse_extra_options!, #parse_rake_task_arg, #prepare, set, static_default_value_collection, static_parameter_collection, #stderr, #stderr=, #stdout, #stdout=, #to_hash, #to_help, #to_rake, #to_shell
Methods included from Concern
#append_features, extended, #included
Constructor Details
This class inherits a constructor from Sprout::Executable::Base
Instance Attribute Details
- (Object) process_runner (readonly)
The Sprout::ProcessRunner that delegates to the long-running process, via stdin, stdout and stderr.
148 149 150 |
# File 'lib/sprout/executable/session.rb', line 148 def process_runner @process_runner end |
- (Object) process_thread (readonly)
The Thread that contains the forked running process.
152 153 154 |
# File 'lib/sprout/executable/session.rb', line 152 def process_thread @process_thread end |
- (Regexp) prompt
The prompt expression for this daemon process.
When executing a series of commands, the wrapper will wait until it matches this expression on stdout before continuing the series.
For FDB, this value is set like:
set :prompt, /^\(fdb\) /
Most processes can trigger a variety of different prompts, these can be expressed here using the | (or) operator.
FDB actually uses the following:
set :prompt, /^\(fdb\) |\(y or n\) /
142 143 144 |
# File 'lib/sprout/executable/session.rb', line 142 def prompt @prompt end |
Class Method Details
+ (nil) add_action(name, arguments = nil, options = nil)
Add an action that can be called while the long-lived process is active.
This method should raise a Sprout::Errors::UsageError if the provided action name is already defined for the provided instance.
70 71 72 73 74 75 76 |
# File 'lib/sprout/executable/session.rb', line 70 def add_action name, arguments=nil, =nil ||= {} [:name] = name [:arguments] = arguments create_action_method nil end |
+ (nil) add_action_alias(alias_name, source_name)
Create an (often shorter) alias to an existing action name.
85 86 87 88 89 90 |
# File 'lib/sprout/executable/session.rb', line 85 def add_action_alias alias_name, source_name define_method(alias_name) do |*params| self.send(source_name, params) end nil end |
Instance Method Details
- (Array<Hash>) action_stack
Return or create a new array.
156 157 158 |
# File 'lib/sprout/executable/session.rb', line 156 def action_stack @action_stack ||= [] end |
- (Rake::Task) create_outer_task(*args) (protected)
This is the override of the underlying Sprout::Executable template method so that we create a ‘task’ instead of a ‘file’ task.
250 251 252 253 254 |
# File 'lib/sprout/executable/session.rb', line 250 def create_outer_task *args Rake::Task.define_task *args do execute end end |
- (Object) execute(should_wait = true)
Execute the Daemon executable, followed by the collection of stored actions in the order they were called.
If none of the stored actions result in terminating the process, the underlying daemon will be connected to the terminal for user (manual) input.
You can also send wait=false to connect to a daemon process from Ruby and execute actions over time. This might look like:
fdb = FlashSDK::FDB.new
fdb.execute false
# Do something else while FDB
# is open, then:
fdb.run
fdb.break "AsUnitRunner:12"
fdb.continue
fdb.kill
fdb.confirm
fdb.quit
196 197 198 199 200 201 202 |
# File 'lib/sprout/executable/session.rb', line 196 def execute should_wait=true @process_runner = super() @process_launched = true wait_for_prompt execute_actions handle_user_input if should_wait end |
- (Object) handle_user_input
Expose the running process to manual input on the terminal, and write stdout back to the user.
225 226 227 228 229 230 231 232 233 234 235 236 |
# File 'lib/sprout/executable/session.rb', line 225 def handle_user_input while true begin break if !wait_for_prompt input = $stdin.gets.chomp! execute_action(input, true) rescue SignalException => e return false end end wait end |
- (Boolean) process_launched? (protected)
240 241 242 |
# File 'lib/sprout/executable/session.rb', line 240 def process_launched? @process_launched end |
- (Boolean) prompted?
If executable is awaiting input.
162 163 164 |
# File 'lib/sprout/executable/session.rb', line 162 def prompted? @prompted end |
- (Thread) system_execute(binary, params) (protected)
This is the override of the underlying Sprout::Executable template method so that we create the process in a thread in order to read and write to it.
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 |
# File 'lib/sprout/executable/session.rb', line 274 def system_execute binary, params # Combine the stderr and stdout for long-lived # processes so that they are both written to # stdout, this allows us to collect these streams # without threads or blocking eternally. # # Thanks to https://github.com/apinstein for this # solution. #params = "#{params} " + '2>&1' @process_thread = Sprout.current_system.execute_thread binary, params, prompt do || yield if block_given? Sprout.stdout.printf @prompted = true if prompt.match end @process_runner = process_thread['runner'] end |
- (String) update_rake_task_name_from_args(*args) (protected)
This is the override of the underlying Sprout::Executable template method so that we are NOT added to the CLEAN collection. (Work performed in the Executable)
263 264 265 |
# File 'lib/sprout/executable/session.rb', line 263 def update_rake_task_name_from_args *args self.rake_task_name = parse_rake_task_arg args.last end |
- (Object) wait
204 205 206 207 |
# File 'lib/sprout/executable/session.rb', line 204 def wait Process.wait process_runner.pid rescue Errno::ECHILD end |
- (Object) wait_for_prompt
Wait for the underlying process to present an input prompt, so that another action can be submitted, or user input can be collected.
214 215 216 217 218 219 |
# File 'lib/sprout/executable/session.rb', line 214 def wait_for_prompt while process_thread.alive? && !prompted? sleep 0.2 end process_thread.alive? end |