bahuvrihi-tap 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. data/History +69 -0
  2. data/MIT-LICENSE +21 -0
  3. data/README +119 -0
  4. data/bin/tap +114 -0
  5. data/cmd/console.rb +42 -0
  6. data/cmd/destroy.rb +16 -0
  7. data/cmd/generate.rb +16 -0
  8. data/cmd/run.rb +126 -0
  9. data/doc/Class Reference +362 -0
  10. data/doc/Command Reference +153 -0
  11. data/doc/Tutorial +237 -0
  12. data/lib/tap.rb +32 -0
  13. data/lib/tap/app.rb +720 -0
  14. data/lib/tap/constants.rb +8 -0
  15. data/lib/tap/env.rb +640 -0
  16. data/lib/tap/file_task.rb +547 -0
  17. data/lib/tap/generator/base.rb +109 -0
  18. data/lib/tap/generator/destroy.rb +37 -0
  19. data/lib/tap/generator/generate.rb +61 -0
  20. data/lib/tap/generator/generators/command/command_generator.rb +21 -0
  21. data/lib/tap/generator/generators/command/templates/command.erb +32 -0
  22. data/lib/tap/generator/generators/config/config_generator.rb +26 -0
  23. data/lib/tap/generator/generators/config/templates/doc.erb +12 -0
  24. data/lib/tap/generator/generators/config/templates/nodoc.erb +8 -0
  25. data/lib/tap/generator/generators/file_task/file_task_generator.rb +27 -0
  26. data/lib/tap/generator/generators/file_task/templates/file.txt +11 -0
  27. data/lib/tap/generator/generators/file_task/templates/result.yml +6 -0
  28. data/lib/tap/generator/generators/file_task/templates/task.erb +33 -0
  29. data/lib/tap/generator/generators/file_task/templates/test.erb +29 -0
  30. data/lib/tap/generator/generators/root/root_generator.rb +55 -0
  31. data/lib/tap/generator/generators/root/templates/Rakefile +86 -0
  32. data/lib/tap/generator/generators/root/templates/gemspec +27 -0
  33. data/lib/tap/generator/generators/root/templates/tapfile +8 -0
  34. data/lib/tap/generator/generators/root/templates/test/tap_test_helper.rb +3 -0
  35. data/lib/tap/generator/generators/root/templates/test/tap_test_suite.rb +5 -0
  36. data/lib/tap/generator/generators/root/templates/test/tapfile_test.rb +15 -0
  37. data/lib/tap/generator/generators/task/task_generator.rb +27 -0
  38. data/lib/tap/generator/generators/task/templates/task.erb +14 -0
  39. data/lib/tap/generator/generators/task/templates/test.erb +21 -0
  40. data/lib/tap/generator/manifest.rb +14 -0
  41. data/lib/tap/patches/rake/rake_test_loader.rb +8 -0
  42. data/lib/tap/patches/rake/testtask.rb +55 -0
  43. data/lib/tap/patches/ruby19/backtrace_filter.rb +51 -0
  44. data/lib/tap/patches/ruby19/parsedate.rb +16 -0
  45. data/lib/tap/root.rb +581 -0
  46. data/lib/tap/support/aggregator.rb +55 -0
  47. data/lib/tap/support/assignments.rb +172 -0
  48. data/lib/tap/support/audit.rb +418 -0
  49. data/lib/tap/support/batchable.rb +47 -0
  50. data/lib/tap/support/batchable_class.rb +107 -0
  51. data/lib/tap/support/class_configuration.rb +194 -0
  52. data/lib/tap/support/command_line.rb +98 -0
  53. data/lib/tap/support/comment.rb +270 -0
  54. data/lib/tap/support/configurable.rb +114 -0
  55. data/lib/tap/support/configurable_class.rb +296 -0
  56. data/lib/tap/support/configuration.rb +122 -0
  57. data/lib/tap/support/constant.rb +70 -0
  58. data/lib/tap/support/constant_utils.rb +127 -0
  59. data/lib/tap/support/declarations.rb +111 -0
  60. data/lib/tap/support/executable.rb +111 -0
  61. data/lib/tap/support/executable_queue.rb +82 -0
  62. data/lib/tap/support/framework.rb +71 -0
  63. data/lib/tap/support/framework_class.rb +199 -0
  64. data/lib/tap/support/instance_configuration.rb +147 -0
  65. data/lib/tap/support/lazydoc.rb +428 -0
  66. data/lib/tap/support/manifest.rb +89 -0
  67. data/lib/tap/support/run_error.rb +39 -0
  68. data/lib/tap/support/shell_utils.rb +71 -0
  69. data/lib/tap/support/summary.rb +30 -0
  70. data/lib/tap/support/tdoc.rb +404 -0
  71. data/lib/tap/support/tdoc/tdoc_html_generator.rb +38 -0
  72. data/lib/tap/support/tdoc/tdoc_html_template.rb +42 -0
  73. data/lib/tap/support/templater.rb +180 -0
  74. data/lib/tap/support/validation.rb +410 -0
  75. data/lib/tap/support/versions.rb +97 -0
  76. data/lib/tap/task.rb +259 -0
  77. data/lib/tap/tasks/dump.rb +56 -0
  78. data/lib/tap/tasks/rake.rb +93 -0
  79. data/lib/tap/test.rb +37 -0
  80. data/lib/tap/test/env_vars.rb +29 -0
  81. data/lib/tap/test/file_methods.rb +377 -0
  82. data/lib/tap/test/script_methods.rb +144 -0
  83. data/lib/tap/test/subset_methods.rb +420 -0
  84. data/lib/tap/test/tap_methods.rb +237 -0
  85. data/lib/tap/workflow.rb +187 -0
  86. metadata +145 -0
data/History ADDED
@@ -0,0 +1,69 @@
1
+ == 0.10.0 / 2008-08-08
2
+
3
+ Major revision. Reworked configurations and the execution
4
+ environment. Added Lazydoc documentation. Backwards incompatible.
5
+ Development is now on GitHub.
6
+
7
+ == 0.9.1 / 2008-04-26 revision 253
8
+
9
+ Relatively minor update, but with one important refactoring that
10
+ removes the Tap::Script module. This breaks backward compatibility
11
+ but only should affect people who have made their own commands.
12
+ Simply sub Tap::Support::CommandLine for Tap::Script to fix.
13
+
14
+ * Added constants methods (ex try_constantize) to String
15
+ * Added gem discovery when no tap.yml file is present
16
+ * Cleanup and refactoring -- removal of Tap::Script
17
+ * Bug fix for JRuby 1.1.1
18
+
19
+ == 0.9.0 / 2008-04-09 revision 246
20
+
21
+ Major update to Tap. Many changes in this release ARE NOT BACKWARD COMPATIBLE.
22
+
23
+ * Reworked Task and App such that methods, are
24
+ enqued and executed. Made the Executable module
25
+ to allow any Method to be enqued and executed.
26
+ * App now aggregates results for methods that have no
27
+ on_complete block; enabled access through App#results
28
+ and App#_results.
29
+ * Removed iteration from tasks
30
+ * Task no longer templates app.config_templates. Templating code
31
+ removed from this distribution.
32
+ * Work to improve audit usability and visualization
33
+ * Removed methods forwarding from Audit to Audit#_current,
34
+ as well as ambiguous Audit methods
35
+ * Root [] now returns expanded paths unchanged. Example:
36
+ app['relative/path'] # => File.join(app.root, 'relative/path')
37
+ app['/expanded/path'] # => '/expanded/path'
38
+ * Generalized rake support; now supports version 0.8.1
39
+ * Fixes in generators
40
+ * Improvements in running of multithread tasks
41
+ * Removed condition blocks from tasks
42
+ * many other things also...
43
+
44
+ == 0.8.0 / 2007-12-08 revision 138
45
+
46
+ Major update to Tap. Many changes in this release ARE NOT BACKWARD COMPATIBLE.
47
+ Documentation is still patchy, but improving.
48
+
49
+ * Expanded/reworked application configuration, allowing specification of gems
50
+ to be loaded as task libraries.
51
+ * Default app config file is now tap.yml (from app.yml)
52
+ * Updated and improved generators
53
+ * Included rails_generators in distribution, removing rails dependency
54
+ * Reworked many classes to clean up interface
55
+ * Reworked testing methods
56
+ * Improved configuration for tasks
57
+ * Optimized loading
58
+ * Reworked threading model
59
+ * Addition of TDoc documentation
60
+ * Reworked tap command and subcommands
61
+ * Added packaging into executables
62
+ * Updated to ActiveSupport 2.0.1
63
+ * documentation, documentation, documentation
64
+ * many other things as well...
65
+
66
+ == 0.7.9 / 2007-09-14
67
+
68
+ * Initial testing release with partial documentation
69
+
data/MIT-LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2006-2008, Regents of the University of Colorado.
2
+ Developer:: Simon Chiang, Biomolecular Structure Program, Hansen Lab
3
+ Support:: CU Denver School of Medicine Deans Academic Enrichment Fund
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
6
+ software and associated documentation files (the "Software"), to deal in the Software
7
+ without restriction, including without limitation the rights to use, copy, modify, merge,
8
+ publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
9
+ to whom the Software is furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all copies or
12
+ substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21
+ OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,119 @@
1
+ = {Tap (Task Application)}[http://tap.rubyforge.org]
2
+
3
+ A framework for creating configurable, distributable tasks and workflows.
4
+
5
+ == Description
6
+
7
+ Tap tasks are designed to be easy to test, subclass, use in scripts, and run
8
+ from the command line. Tap provides methods to generate and utilize config
9
+ files, join tasks into workflows, as well as dump and reuse results. Task
10
+ libraries are readily shared as gems. Check out the links for tutorials,
11
+ development, and bug tracking.
12
+
13
+ * {Tutorial}[link:files/doc/Tutorial.html], {Class}[link:files/doc/Class%20Reference.html] and {Command}[link:files/doc/Command%20Reference.html] Reference
14
+ * Website[http://tap.rubyforge.org]
15
+ * Lighthouse[http://bahuvrihi.lighthouseapp.com/projects/9908-tap-task-application/overview]
16
+ * Github[http://github.com/bahuvrihi/tap/tree/master]
17
+
18
+ === Additional Notes:
19
+
20
+ - Tap and Rake[http://rake.rubyforge.org/] are targeted at different problems,
21
+ but play well together. See Tap::Tasks::Rake to use rake tasks in tap.
22
+ - Tap is tested on MRI (the standard Ruby interpreter, versions 1.8.6 and
23
+ 1.9.0) and JRuby[http://jruby.codehaus.org/].
24
+
25
+ === Usage
26
+
27
+ A simple task illustrates the usage of tap:
28
+
29
+ # Goodnight::manifest your basic goodnight moon task
30
+ # Says goodnight with a configurable message.
31
+ class Goodnight < Tap::Task
32
+
33
+ config :message, 'goodnight' # a goodnight message
34
+
35
+ def process(name)
36
+ log(message, name)
37
+ "#{message} #{name}"
38
+ end
39
+ end
40
+
41
+ Tap pulls documentation out of task classes to generate manifests:
42
+
43
+ % tap run -T
44
+ sample:
45
+ goodnight # your basic goodnight moon task
46
+ tap:
47
+ dump # the default dump task
48
+ rake # run rake tasks
49
+
50
+ And help:
51
+
52
+ % tap run -- goodnight --help
53
+ Goodnight -- your basic goodnight moon task
54
+ --------------------------------------------------------------------------------
55
+ Says goodnight with a configurable message.
56
+ --------------------------------------------------------------------------------
57
+ usage: tap run -- goodnight NAME
58
+
59
+ configurations:
60
+ --message MESSAGE a goodnight message
61
+
62
+ options:
63
+ -h, --help Print this help
64
+ --name NAME Specify a name
65
+ --use FILE Loads inputs from file
66
+
67
+
68
+ Tasks are immediately available to run:
69
+
70
+ % tap run -- goodnight moon
71
+ I[00:09:55] goodnight moon
72
+
73
+
74
+ % tap run -- goodnight moon --message hello
75
+ I[00:10:01] hello moon
76
+
77
+ Tap comes with generators and allows distribution of task libraries as gems.
78
+ This can be illustrated by installing the
79
+ {sample_tasks}[http://tap.rubyforge.org/sample_tasks] gem:
80
+
81
+ % gem install sample_tasks
82
+ % tap run -T
83
+ sample:
84
+ goodnight # your basic goodnight moon task
85
+ sample_tasks:
86
+ concat # concatenate files with formatting
87
+ copy # copies files
88
+ grep # search for lines matching a pattern
89
+ print_tree # print a directory tree
90
+ tap:
91
+ dump # the default dump task
92
+ rake # run rake tasks
93
+
94
+ === Bugs/Known Issues
95
+
96
+ - Some inconsequential tests on JRuby fail due to bugs in JRuby itself.
97
+ - Several patches are required so that Tap runs properly on MRI 1.9.0. These
98
+ will likely resolve themselves as 1.9.0 becomes stable.
99
+ - Despite the talk of workflows, the Workflow class should still be considered
100
+ in progress. Tasks themselves are stable.
101
+
102
+ == Installation
103
+
104
+ Tap is available as a gem on RubyForge[http://rubyforge.org/projects/tap]. Use:
105
+
106
+ % gem install tap
107
+
108
+ Tap requires an updated version of RubyGems[http://docs.rubygems.org/] (>= 1.2.0). To check the version and update RubyGems:
109
+
110
+ % gem --version
111
+ % gem --update system
112
+
113
+ == Info
114
+
115
+ Copyright (c) 2006-2008, Regents of the University of Colorado.
116
+ Developer:: {Simon Chiang}[http://bahuvrihi.wordpress.com], {Biomolecular Structure Program}[http://biomol.uchsc.edu/], {Hansen Lab}[http://hsc-proteomics.uchsc.edu/hansenlab/]
117
+ Support:: CU Denver School of Medicine Deans Academic Enrichment Fund
118
+ Licence:: {MIT-Style}[link:files/MIT-LICENSE.html]
119
+
data/bin/tap ADDED
@@ -0,0 +1,114 @@
1
+ #!/usr/local/bin/ruby
2
+ # usage: tap <command> {options} [args]
3
+ #
4
+ # examples:
5
+ # tap generate root . # generates a root dir
6
+ # tap run taskname --option input # runs the 'taskname' task
7
+ #
8
+ # help:
9
+ # tap help # prints this help
10
+ # tap command --help # prints help for 'command'
11
+ #
12
+
13
+ tap_root_dir = File.dirname(__FILE__) + "/.."
14
+ require "#{tap_root_dir}/lib/tap.rb"
15
+
16
+ # setup the environment
17
+ begin
18
+
19
+ $DEBUG = true if ARGV.delete('-d-')
20
+ before = nil
21
+ after = nil
22
+ aliases = nil
23
+
24
+ app = Tap::App.instance
25
+ env = Tap::Env.instantiate(app, Tap::Env.load_config(Tap::Env::GLOBAL_CONFIG_FILE), app.logger) do |unhandled_configs|
26
+ before = unhandled_configs.delete(:before)
27
+ after = unhandled_configs.delete(:after)
28
+
29
+ aliases = unhandled_configs.delete(:alias)
30
+ Tap::Support::Validation.validate(aliases, [Hash]) if aliases
31
+
32
+ unless unhandled_configs.empty?
33
+ local.log(:warn, "ignoring non-env configs: #{unhandled_configs.keys.join(',')}", Logger::DEBUG)
34
+ end
35
+ end
36
+
37
+ # add all gems if no gems are specified (Note this is VERY SLOW ~ 1/3 the overhead for tap)
38
+ if !File.exists?(Tap::Env::DEFAULT_CONFIG_FILE)
39
+ env.gems = Tap::Env.known_gems(true)
40
+ end
41
+
42
+ tap = Tap::Env.instance_for(tap_root_dir)
43
+ env.push(tap)
44
+
45
+ rescue(Tap::Env::ConfigError)
46
+ # catch errors and exit gracefully
47
+ # (errors usu from gem loading errors)
48
+ puts $!.message
49
+ exit(1)
50
+ end
51
+
52
+ #
53
+ # setup after script
54
+ #
55
+
56
+ at_exit do
57
+ begin
58
+ eval(after) if after != nil
59
+ rescue(Exception)
60
+ puts "Error in after script."
61
+ env.handle_error($!)
62
+ exit(1)
63
+ end
64
+ end
65
+
66
+ #
67
+ # run before script
68
+ #
69
+
70
+ begin
71
+ eval(before) if before != nil
72
+ rescue(Exception)
73
+ puts "Error in before script."
74
+ env.handle_error($!)
75
+ exit(1)
76
+ end
77
+
78
+ #
79
+ # run tap
80
+ #
81
+
82
+ begin
83
+ env.activate
84
+
85
+ command = ARGV.shift
86
+ if aliases && aliases.has_key?(command)
87
+ aliases[command].reverse_each {|arg| ARGV.unshift(arg)}
88
+ command = ARGV.shift
89
+ end
90
+
91
+ case command
92
+ when nil, '--help'
93
+ # give some help
94
+ require 'tap/support/command_line'
95
+
96
+ puts Tap::Support::CommandLine.usage(__FILE__)
97
+ puts
98
+ puts "available commands:"
99
+ puts env.summarize(:commands)
100
+ puts
101
+ puts "version #{Tap::VERSION} -- #{Tap::WEBSITE}"
102
+ else
103
+ if path = env.search(:commands, command)
104
+ load path # run the command, if it exists
105
+ else
106
+ puts "Unknown command: '#{command}'"
107
+ puts "Type 'tap help' for usage information."
108
+ end
109
+ end
110
+ rescue
111
+ env.handle_error($!)
112
+ end
113
+
114
+ exit(0)
data/cmd/console.rb ADDED
@@ -0,0 +1,42 @@
1
+ # tap console {options}
2
+ #
3
+ # Opens up an IRB session with Tap initialized to the configurations
4
+ # in tap.yml. Access the Tap::App.instance through 'app'.
5
+
6
+ #
7
+ # handle options
8
+ #
9
+
10
+ OptionParser.new do |opts|
11
+ opts.separator ""
12
+ opts.separator "options:"
13
+
14
+ opts.on("-h", "--help", "Show this message") do
15
+ opts.banner = Tap::Support::CommandLine.usage(__FILE__)
16
+ puts opts
17
+ exit
18
+ end
19
+ end.parse!(ARGV)
20
+
21
+ require "irb"
22
+
23
+ def app
24
+ Tap::App.instance
25
+ end
26
+
27
+ def env
28
+ Tap::Env.instance
29
+ end
30
+
31
+ IRB.start
32
+
33
+ # Handles a bug in IRB that causes exit to throw :IRB_EXIT
34
+ # and consequentially make a warning message, even on a
35
+ # clean exit. This module resets exit to the original
36
+ # aliased method.
37
+ module CleanExit # :nodoc:
38
+ def exit(ret = 0)
39
+ __exit__(ret)
40
+ end
41
+ end
42
+ IRB.CurrentContext.extend CleanExit
data/cmd/destroy.rb ADDED
@@ -0,0 +1,16 @@
1
+ require 'tap/generator/base'
2
+ require 'tap/generator/destroy'
3
+
4
+ env = Tap::Env.instance
5
+
6
+ if ARGV.empty? || ARGV == ['-T']
7
+ puts env.summarize(:generators) {|const| const.document[const.name]['generator'] }
8
+ exit
9
+ end
10
+
11
+ name = ARGV.shift
12
+ const = env.search(:generators, name) or raise "unknown generator: #{name}"
13
+
14
+ generator_class = const.constantize
15
+ generator, argv = generator_class.instantiate(ARGV)
16
+ generator.extend(Tap::Generator::Destroy).process(*argv)
data/cmd/generate.rb ADDED
@@ -0,0 +1,16 @@
1
+ require 'tap/generator/base'
2
+ require 'tap/generator/generate'
3
+
4
+ env = Tap::Env.instance
5
+
6
+ if ARGV.empty? || ARGV == ['-T']
7
+ puts env.summarize(:generators) {|const| const.document[const.name]['generator'] }
8
+ exit
9
+ end
10
+
11
+ name = ARGV.shift
12
+ const = env.search(:generators, name) or raise "unknown generator: #{name}"
13
+
14
+ generator_class = const.constantize
15
+ generator, argv = generator_class.instantiate(ARGV)
16
+ generator.extend(Tap::Generator::Generate).process(*argv)
data/cmd/run.rb ADDED
@@ -0,0 +1,126 @@
1
+ # tap run {options} -- {task options} task INPUTS...
2
+ #
3
+ # examples:
4
+ # tap run --help Prints this help
5
+ # tap run -- task --help Prints help for task
6
+ #
7
+
8
+ env = Tap::Env.instance
9
+ app = Tap::App.instance
10
+ cmdline = Tap::Support::CommandLine
11
+
12
+ #
13
+ # handle options
14
+ #
15
+
16
+ dump = false
17
+ OptionParser.new do |opts|
18
+
19
+ opts.separator ""
20
+ opts.separator "configurations:"
21
+
22
+ Tap::App.configurations.each do |receiver, key, config|
23
+ next if receiver == Tap::Root
24
+
25
+ opts.on(*cmdline.configv(config)) do |value|
26
+ app.send(configuration.writer, value)
27
+ end
28
+ end
29
+
30
+ opts.separator ""
31
+ opts.separator "options:"
32
+
33
+ opts.on("-h", "--help", "Show this message") do
34
+ opts.banner = cmdline.usage(__FILE__)
35
+ Tap::App.lazydoc.resolve
36
+ puts opts
37
+ exit
38
+ end
39
+
40
+ opts.on('-T', '--manifest', 'Print a list of available tasks') do |v|
41
+ puts env.summarize(:tasks) {|const| const.document[const.name]['manifest'] }
42
+ exit
43
+ end
44
+
45
+ end.parse!(ARGV)
46
+
47
+ #
48
+ # handle options for each specified task
49
+ #
50
+
51
+ rounds = cmdline.split(ARGV).collect do |argvs|
52
+ argvs.each do |argv|
53
+ ARGV.clear
54
+ ARGV.concat(argv)
55
+
56
+ unless td = cmdline.shift(ARGV)
57
+ # warn nil?
58
+ next
59
+ end
60
+
61
+ # attempt lookup the task class
62
+ const = env.search(:tasks, td) or raise "unknown task: #{td}"
63
+ task_class = const.constantize or raise "unknown task: #{td}"
64
+
65
+ # now let the class handle the argv
66
+ task, argv = task_class.instantiate(ARGV, app)
67
+ task.enq *argv.collect! {|str| cmdline.parse_yaml(str) }
68
+ end
69
+
70
+ app.queue.clear
71
+ end
72
+ ARGV.clear
73
+
74
+ rounds.delete_if {|round| round.empty? }
75
+ if rounds.empty?
76
+ puts "no task specified"
77
+ exit
78
+ end
79
+
80
+ #
81
+ # set signals
82
+ #
83
+
84
+ # info signal -- Note: some systems do
85
+ # not support the INFO signal
86
+ # (windows, fedora, at least)
87
+ signals = Signal.list.keys
88
+ if signals.include?("INFO")
89
+ Signal.trap("INFO") do
90
+ puts app.info
91
+ end
92
+ end
93
+
94
+ # interuption signal
95
+ if signals.include?("INT")
96
+ Signal.trap("INT") do
97
+ puts " interrupted!"
98
+ # prompt for decision
99
+ while true
100
+ print "stop, terminate, exit, or resume? (s/t/e/r):"
101
+ case gets.strip
102
+ when /s(top)?/i
103
+ app.stop
104
+ break
105
+ when /t(erminate)?/i
106
+ app.terminate
107
+ break
108
+ when /e(xit)?/i
109
+ exit
110
+ when /r(esume)?/i
111
+ break
112
+ else
113
+ puts "unexpected response..."
114
+ end
115
+ end
116
+ end
117
+ end
118
+
119
+ #
120
+ # enque tasks and run!
121
+ #
122
+
123
+ rounds.each_with_index do |queue, i|
124
+ app.queue.concat(queue)
125
+ app.run
126
+ end