guard 1.4.0 → 2.18.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +1 -677
- data/LICENSE +4 -2
- data/README.md +91 -753
- data/bin/_guard-core +11 -0
- data/bin/guard +108 -3
- data/lib/guard/aruba_adapter.rb +59 -0
- data/lib/guard/cli/environments/bundler.rb +22 -0
- data/lib/guard/cli/environments/evaluate_only.rb +35 -0
- data/lib/guard/cli/environments/valid.rb +69 -0
- data/lib/guard/cli.rb +129 -128
- data/lib/guard/commander.rb +104 -0
- data/lib/guard/commands/all.rb +37 -0
- data/lib/guard/commands/change.rb +31 -0
- data/lib/guard/commands/notification.rb +26 -0
- data/lib/guard/commands/pause.rb +29 -0
- data/lib/guard/commands/reload.rb +36 -0
- data/lib/guard/commands/scope.rb +38 -0
- data/lib/guard/commands/show.rb +24 -0
- data/lib/guard/config.rb +18 -0
- data/lib/guard/deprecated/dsl.rb +45 -0
- data/lib/guard/deprecated/evaluator.rb +39 -0
- data/lib/guard/deprecated/guard.rb +328 -0
- data/lib/guard/deprecated/guardfile.rb +84 -0
- data/lib/guard/deprecated/watcher.rb +27 -0
- data/lib/guard/dsl.rb +332 -363
- data/lib/guard/dsl_describer.rb +132 -122
- data/lib/guard/dsl_reader.rb +51 -0
- data/lib/guard/group.rb +34 -14
- data/lib/guard/guardfile/evaluator.rb +232 -0
- data/lib/guard/guardfile/generator.rb +128 -0
- data/lib/guard/guardfile.rb +24 -60
- data/lib/guard/interactor.rb +31 -255
- data/lib/guard/internals/debugging.rb +68 -0
- data/lib/guard/internals/groups.rb +40 -0
- data/lib/guard/internals/helpers.rb +13 -0
- data/lib/guard/internals/plugins.rb +53 -0
- data/lib/guard/internals/queue.rb +51 -0
- data/lib/guard/internals/scope.rb +121 -0
- data/lib/guard/internals/session.rb +180 -0
- data/lib/guard/internals/state.rb +25 -0
- data/lib/guard/internals/tracing.rb +33 -0
- data/lib/guard/internals/traps.rb +10 -0
- data/lib/guard/jobs/base.rb +21 -0
- data/lib/guard/jobs/pry_wrapper.rb +336 -0
- data/lib/guard/jobs/sleep.rb +26 -0
- data/lib/guard/notifier.rb +46 -212
- data/lib/guard/options.rb +22 -0
- data/lib/guard/plugin.rb +303 -0
- data/lib/guard/plugin_util.rb +191 -0
- data/lib/guard/rake_task.rb +42 -0
- data/lib/guard/runner.rb +80 -140
- data/lib/guard/templates/Guardfile +14 -0
- data/lib/guard/terminal.rb +13 -0
- data/lib/guard/ui/colors.rb +56 -0
- data/lib/guard/ui/config.rb +70 -0
- data/lib/guard/ui/logger.rb +30 -0
- data/lib/guard/ui.rb +163 -128
- data/lib/guard/version.rb +1 -2
- data/lib/guard/watcher/pattern/deprecated_regexp.rb +45 -0
- data/lib/guard/watcher/pattern/match_result.rb +18 -0
- data/lib/guard/watcher/pattern/matcher.rb +33 -0
- data/lib/guard/watcher/pattern/pathname_path.rb +15 -0
- data/lib/guard/watcher/pattern/simple_path.rb +23 -0
- data/lib/guard/watcher/pattern.rb +24 -0
- data/lib/guard/watcher.rb +52 -95
- data/lib/guard.rb +108 -376
- data/lib/tasks/releaser.rb +116 -0
- data/man/guard.1 +12 -9
- data/man/guard.1.html +18 -12
- metadata +148 -77
- data/images/guard.png +0 -0
- data/lib/guard/guard.rb +0 -156
- data/lib/guard/hook.rb +0 -120
- data/lib/guard/interactors/coolline.rb +0 -64
- data/lib/guard/interactors/helpers/completion.rb +0 -32
- data/lib/guard/interactors/helpers/terminal.rb +0 -46
- data/lib/guard/interactors/readline.rb +0 -94
- data/lib/guard/interactors/simple.rb +0 -19
- data/lib/guard/notifiers/emacs.rb +0 -69
- data/lib/guard/notifiers/gntp.rb +0 -118
- data/lib/guard/notifiers/growl.rb +0 -99
- data/lib/guard/notifiers/growl_notify.rb +0 -92
- data/lib/guard/notifiers/libnotify.rb +0 -96
- data/lib/guard/notifiers/notifysend.rb +0 -84
- data/lib/guard/notifiers/rb_notifu.rb +0 -102
- data/lib/guard/notifiers/terminal_notifier.rb +0 -66
- data/lib/guard/notifiers/tmux.rb +0 -69
- data/lib/guard/version.rbc +0 -130
@@ -0,0 +1,53 @@
|
|
1
|
+
require "guard/plugin_util"
|
2
|
+
require "guard/group"
|
3
|
+
require "guard/plugin"
|
4
|
+
|
5
|
+
module Guard
|
6
|
+
# @private api
|
7
|
+
module Internals
|
8
|
+
class Plugins
|
9
|
+
def initialize
|
10
|
+
@plugins = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def all(filter = nil)
|
14
|
+
return @plugins if filter.nil?
|
15
|
+
matcher = matcher_for(filter)
|
16
|
+
@plugins.select { |plugin| matcher.call(plugin) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def remove(plugin)
|
20
|
+
@plugins.delete(plugin)
|
21
|
+
end
|
22
|
+
|
23
|
+
# TODO: should it allow duplicates? (probably yes because of different
|
24
|
+
# configs or groups)
|
25
|
+
def add(name, options)
|
26
|
+
@plugins << PluginUtil.new(name).initialize_plugin(options)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def matcher_for(filter)
|
32
|
+
case filter
|
33
|
+
when String, Symbol
|
34
|
+
shortname = filter.to_s.downcase.delete("-")
|
35
|
+
->(plugin) { plugin.name == shortname }
|
36
|
+
when Regexp
|
37
|
+
->(plugin) { plugin.name =~ filter }
|
38
|
+
when Hash
|
39
|
+
lambda do |plugin|
|
40
|
+
filter.all? do |k, v|
|
41
|
+
case k
|
42
|
+
when :name
|
43
|
+
plugin.name == v.to_s.downcase.delete("-")
|
44
|
+
when :group
|
45
|
+
plugin.group.name == v.to_sym
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Guard
|
2
|
+
module Internals
|
3
|
+
class Queue
|
4
|
+
def initialize(commander)
|
5
|
+
@commander = commander
|
6
|
+
@queue = ::Queue.new
|
7
|
+
end
|
8
|
+
|
9
|
+
# Process the change queue, running tasks within the main Guard thread
|
10
|
+
def process
|
11
|
+
actions = []
|
12
|
+
changes = { modified: [], added: [], removed: [] }
|
13
|
+
|
14
|
+
while pending?
|
15
|
+
if (item = @queue.pop).first.is_a?(Symbol)
|
16
|
+
actions << item
|
17
|
+
else
|
18
|
+
item.each { |key, value| changes[key] += value }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
_run_actions(actions)
|
23
|
+
return if changes.values.all?(&:empty?)
|
24
|
+
Runner.new.run_on_changes(*changes.values)
|
25
|
+
end
|
26
|
+
|
27
|
+
def pending?
|
28
|
+
!@queue.empty?
|
29
|
+
end
|
30
|
+
|
31
|
+
def <<(changes)
|
32
|
+
@queue << changes
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def _run_actions(actions)
|
38
|
+
actions.each do |action_args|
|
39
|
+
args = action_args.dup
|
40
|
+
namespaced_action = args.shift
|
41
|
+
action = namespaced_action.to_s.sub(/^guard_/, "")
|
42
|
+
if @commander.respond_to?(action)
|
43
|
+
@commander.send(action, *args)
|
44
|
+
else
|
45
|
+
fail "Unknown action: #{action.inspect}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require "guard"
|
2
|
+
|
3
|
+
module Guard
|
4
|
+
# @private api
|
5
|
+
module Internals
|
6
|
+
class Scope
|
7
|
+
def initialize
|
8
|
+
@interactor_plugin_scope = []
|
9
|
+
@interactor_group_scope = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_hash
|
13
|
+
{
|
14
|
+
plugins: _hashify_scope(:plugin),
|
15
|
+
groups: _hashify_scope(:group)
|
16
|
+
}.dup.freeze
|
17
|
+
end
|
18
|
+
|
19
|
+
# TODO: refactor
|
20
|
+
def grouped_plugins(scope = { plugins: [], groups: [] })
|
21
|
+
items = nil
|
22
|
+
plugins = _find_non_empty_scope(:plugins, scope)
|
23
|
+
if plugins
|
24
|
+
items = Array(plugins).map { |plugin| _instantiate(:plugin, plugin) }
|
25
|
+
end
|
26
|
+
|
27
|
+
unless items
|
28
|
+
# TODO: no coverage here!!
|
29
|
+
found = _find_non_empty_scope(:groups, scope)
|
30
|
+
found ||= Guard.state.session.groups.all
|
31
|
+
groups = Array(found).map { |group| _instantiate(:group, group) }
|
32
|
+
if groups.any? { |g| g.name == :common }
|
33
|
+
items = groups
|
34
|
+
else
|
35
|
+
items = ([_instantiate(:group, :common)] + Array(found)).compact
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
items.map do |plugin_or_group|
|
40
|
+
group = nil
|
41
|
+
plugins = [plugin_or_group]
|
42
|
+
if plugin_or_group.is_a?(Group)
|
43
|
+
# TODO: no coverage here!
|
44
|
+
group = plugin_or_group
|
45
|
+
plugins = Guard.state.session.plugins.all(group: group.name)
|
46
|
+
end
|
47
|
+
[group, plugins]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def from_interactor(scope)
|
52
|
+
@interactor_plugin_scope = Array(scope[:plugins])
|
53
|
+
@interactor_group_scope = Array(scope[:groups])
|
54
|
+
end
|
55
|
+
|
56
|
+
def titles(scope = nil)
|
57
|
+
hash = scope || to_hash
|
58
|
+
plugins = hash[:plugins]
|
59
|
+
groups = hash[:groups]
|
60
|
+
return plugins.map(&:title) unless plugins.nil? || plugins.empty?
|
61
|
+
return hash[:groups].map(&:title) unless groups.nil? || groups.empty?
|
62
|
+
["all"]
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
# TODO: move to session
|
68
|
+
def _scope_names(new_scope, name)
|
69
|
+
items = Array(new_scope[:"#{name}s"] || new_scope[name]) if items.empty?
|
70
|
+
|
71
|
+
# Convert objects to names
|
72
|
+
items.map { |p| p.respond_to?(:name) ? p.name : p }
|
73
|
+
end
|
74
|
+
|
75
|
+
# TODO: let the Plugins and Groups classes handle this?
|
76
|
+
# TODO: why even instantiate?? just to check if it exists?
|
77
|
+
def _hashify_scope(type)
|
78
|
+
# TODO: get cmdline passed to initialize above?
|
79
|
+
cmdline = Array(Guard.state.session.send("cmdline_#{type}s"))
|
80
|
+
guardfile = Guard.state.session.send(:"guardfile_#{type}_scope")
|
81
|
+
interactor = instance_variable_get(:"@interactor_#{type}_scope")
|
82
|
+
|
83
|
+
# TODO: session should decide whether to use cmdline or guardfile -
|
84
|
+
# since it has access to both variables
|
85
|
+
items = [interactor, cmdline, guardfile].detect do |source|
|
86
|
+
!source.empty?
|
87
|
+
end
|
88
|
+
|
89
|
+
# TODO: not tested when groups/plugins given don't exist
|
90
|
+
|
91
|
+
# TODO: should already be instantiated
|
92
|
+
Array(items).map do |obj|
|
93
|
+
if obj.respond_to?(:name)
|
94
|
+
obj
|
95
|
+
else
|
96
|
+
name = obj
|
97
|
+
(type == :group ? _groups : _plugins).all(name).first
|
98
|
+
end
|
99
|
+
end.compact
|
100
|
+
end
|
101
|
+
|
102
|
+
def _instantiate(meth, obj)
|
103
|
+
# TODO: no coverage
|
104
|
+
return obj unless obj.is_a?(Symbol) || obj.is_a?(String)
|
105
|
+
Guard.state.session.send("#{meth}s".to_sym).all(obj).first
|
106
|
+
end
|
107
|
+
|
108
|
+
def _find_non_empty_scope(type, local_scope)
|
109
|
+
[Array(local_scope[type]), to_hash[type]].map(&:compact).detect(&:any?)
|
110
|
+
end
|
111
|
+
|
112
|
+
def _groups
|
113
|
+
Guard.state.session.groups
|
114
|
+
end
|
115
|
+
|
116
|
+
def _plugins
|
117
|
+
Guard.state.session.plugins
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,180 @@
|
|
1
|
+
require "guard/internals/plugins"
|
2
|
+
require "guard/internals/groups"
|
3
|
+
|
4
|
+
require "guard/options"
|
5
|
+
|
6
|
+
module Guard
|
7
|
+
# @private api
|
8
|
+
module Internals
|
9
|
+
# TODO: split into a commandline class and session (plugins, groups)
|
10
|
+
# TODO: swap session and metadata
|
11
|
+
class Session
|
12
|
+
attr_reader :plugins
|
13
|
+
attr_reader :groups
|
14
|
+
|
15
|
+
DEFAULT_OPTIONS = {
|
16
|
+
clear: false,
|
17
|
+
debug: false,
|
18
|
+
no_bundler_warning: false,
|
19
|
+
|
20
|
+
# User defined scopes
|
21
|
+
group: [],
|
22
|
+
plugin: [],
|
23
|
+
|
24
|
+
# Notifier
|
25
|
+
notify: true,
|
26
|
+
|
27
|
+
# Interactor
|
28
|
+
no_interactions: false,
|
29
|
+
|
30
|
+
# Guardfile options:
|
31
|
+
# guardfile_contents
|
32
|
+
guardfile: nil,
|
33
|
+
|
34
|
+
# Listener options
|
35
|
+
# TODO: rename to watchdirs?
|
36
|
+
watchdir: Dir.pwd,
|
37
|
+
latency: nil,
|
38
|
+
force_polling: false,
|
39
|
+
wait_for_delay: nil,
|
40
|
+
listen_on: nil
|
41
|
+
}
|
42
|
+
|
43
|
+
def cmdline_groups
|
44
|
+
@cmdline_groups.dup.freeze
|
45
|
+
end
|
46
|
+
|
47
|
+
def cmdline_plugins
|
48
|
+
@cmdline_plugins.dup.freeze
|
49
|
+
end
|
50
|
+
|
51
|
+
def initialize(new_options)
|
52
|
+
@options = Options.new(new_options, DEFAULT_OPTIONS)
|
53
|
+
|
54
|
+
@plugins = Plugins.new
|
55
|
+
@groups = Groups.new
|
56
|
+
|
57
|
+
@cmdline_groups = @options[:group]
|
58
|
+
@cmdline_plugins = @options[:plugin]
|
59
|
+
|
60
|
+
@clear = @options[:clear]
|
61
|
+
@debug = @options[:debug]
|
62
|
+
@watchdirs = Array(@options[:watchdir])
|
63
|
+
@notify = @options[:notify]
|
64
|
+
@interactor_name = @options[:no_interactions] ? :sleep : :pry_wrapper
|
65
|
+
|
66
|
+
@guardfile_plugin_scope = []
|
67
|
+
@guardfile_group_scope = []
|
68
|
+
@guardfile_ignore = []
|
69
|
+
@guardfile_ignore_bang = []
|
70
|
+
|
71
|
+
@guardfile_notifier_options = {}
|
72
|
+
end
|
73
|
+
|
74
|
+
def guardfile_scope(scope)
|
75
|
+
opts = scope.dup
|
76
|
+
|
77
|
+
groups = Array(opts.delete(:groups))
|
78
|
+
group = Array(opts.delete(:group))
|
79
|
+
@guardfile_group_scope = Array(groups) + Array(group)
|
80
|
+
|
81
|
+
plugins = Array(opts.delete(:plugins))
|
82
|
+
plugin = Array(opts.delete(:plugin))
|
83
|
+
@guardfile_plugin_scope = Array(plugins) + Array(plugin)
|
84
|
+
|
85
|
+
fail "Unknown options: #{opts.inspect}" unless opts.empty?
|
86
|
+
end
|
87
|
+
|
88
|
+
# TODO: create a EvaluatorResult class?
|
89
|
+
attr_reader :guardfile_group_scope
|
90
|
+
attr_reader :guardfile_plugin_scope
|
91
|
+
attr_accessor :guardfile_ignore_bang
|
92
|
+
|
93
|
+
attr_reader :guardfile_ignore
|
94
|
+
def guardfile_ignore=(ignores)
|
95
|
+
@guardfile_ignore += Array(ignores).flatten
|
96
|
+
end
|
97
|
+
|
98
|
+
def clearing(on)
|
99
|
+
@clear = on
|
100
|
+
end
|
101
|
+
|
102
|
+
def clearing?
|
103
|
+
@clear
|
104
|
+
end
|
105
|
+
|
106
|
+
alias :clear? :clearing?
|
107
|
+
|
108
|
+
def debug?
|
109
|
+
@debug
|
110
|
+
end
|
111
|
+
|
112
|
+
def watchdirs
|
113
|
+
@watchdirs_from_guardfile ||= nil
|
114
|
+
@watchdirs_from_guardfile || @watchdirs
|
115
|
+
end
|
116
|
+
|
117
|
+
# set by Dsl with :directories() command
|
118
|
+
def watchdirs=(dirs)
|
119
|
+
dirs = [Dir.pwd] if dirs.empty?
|
120
|
+
@watchdirs_from_guardfile = dirs.map { |dir| File.expand_path dir }
|
121
|
+
end
|
122
|
+
|
123
|
+
def listener_args
|
124
|
+
if @options[:listen_on]
|
125
|
+
[:on, @options[:listen_on]]
|
126
|
+
else
|
127
|
+
listener_options = {}
|
128
|
+
[:latency, :force_polling, :wait_for_delay].each do |option|
|
129
|
+
listener_options[option] = @options[option] if @options[option]
|
130
|
+
end
|
131
|
+
expanded_watchdirs = watchdirs.map { |dir| File.expand_path dir }
|
132
|
+
[:to, *expanded_watchdirs, listener_options]
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def evaluator_options
|
137
|
+
opts = { guardfile: @options[:guardfile] }
|
138
|
+
# TODO: deprecate :guardfile_contents
|
139
|
+
if @options[:guardfile_contents]
|
140
|
+
opts[:contents] = @options[:guardfile_contents]
|
141
|
+
end
|
142
|
+
opts
|
143
|
+
end
|
144
|
+
|
145
|
+
def notify_options
|
146
|
+
names = @guardfile_notifier_options.keys
|
147
|
+
return { notify: false } if names.include?(:off)
|
148
|
+
|
149
|
+
{
|
150
|
+
notify: @options[:notify],
|
151
|
+
notifiers: @guardfile_notifier_options
|
152
|
+
}
|
153
|
+
end
|
154
|
+
|
155
|
+
def guardfile_notification=(config)
|
156
|
+
@guardfile_notifier_options.merge!(config)
|
157
|
+
end
|
158
|
+
|
159
|
+
attr_reader :interactor_name
|
160
|
+
|
161
|
+
# TODO: call this from within action, not within interactor command
|
162
|
+
def convert_scope(entries)
|
163
|
+
scopes = { plugins: [], groups: [] }
|
164
|
+
unknown = []
|
165
|
+
|
166
|
+
entries.each do |entry|
|
167
|
+
if plugin = plugins.all(entry).first
|
168
|
+
scopes[:plugins] << plugin
|
169
|
+
elsif group = groups.all(entry).first
|
170
|
+
scopes[:groups] << group
|
171
|
+
else
|
172
|
+
unknown << entry
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
[scopes, unknown]
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "guard/group"
|
2
|
+
|
3
|
+
require "guard/plugin_util"
|
4
|
+
require "guard/internals/session"
|
5
|
+
require "guard/internals/scope"
|
6
|
+
require "guard/runner"
|
7
|
+
|
8
|
+
module Guard
|
9
|
+
module Internals
|
10
|
+
class State
|
11
|
+
# Minimal setup for non-interactive commands (list, init, show, etc.)
|
12
|
+
def initialize(cmdline_opts)
|
13
|
+
@session = Session.new(cmdline_opts)
|
14
|
+
|
15
|
+
@scope = Scope.new
|
16
|
+
|
17
|
+
# NOTE: must be set before anything calls Guard::UI.debug
|
18
|
+
Debugging.start if session.debug?
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :scope
|
22
|
+
attr_reader :session
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Guard
|
2
|
+
module Internals
|
3
|
+
module Tracing
|
4
|
+
def self.trace(mod, meth)
|
5
|
+
meta = (class << mod; self; end)
|
6
|
+
original_meth = "original_#{meth}".to_sym
|
7
|
+
|
8
|
+
if mod.respond_to?(original_meth)
|
9
|
+
fail "ALREADY TRACED: #{mod}.#{meth}"
|
10
|
+
end
|
11
|
+
|
12
|
+
meta.send(:alias_method, original_meth, meth)
|
13
|
+
meta.send(:define_method, meth) do |*args, &block|
|
14
|
+
yield(*args) if block_given?
|
15
|
+
mod.send original_meth, *args, &block
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.untrace(mod, meth)
|
20
|
+
meta = (class << mod; self; end)
|
21
|
+
original_meth = "original_#{meth}".to_sym
|
22
|
+
|
23
|
+
unless mod.respond_to?(original_meth)
|
24
|
+
fail "NOT TRACED: #{mod}.#{meth} (no method: #{original_meth})"
|
25
|
+
end
|
26
|
+
|
27
|
+
meta.send(:remove_method, meth)
|
28
|
+
meta.send(:alias_method, meth, original_meth)
|
29
|
+
meta.send(:undef_method, original_meth)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Guard
|
2
|
+
module Jobs
|
3
|
+
class Base
|
4
|
+
def initialize(_options)
|
5
|
+
end
|
6
|
+
|
7
|
+
# @return [Symbol] :stopped once job is finished
|
8
|
+
# @return [Symbol] :exit to tell Guard to terminate
|
9
|
+
def foreground
|
10
|
+
end
|
11
|
+
|
12
|
+
def background
|
13
|
+
end
|
14
|
+
|
15
|
+
# Signal handler calls this, so avoid actually doing
|
16
|
+
# anything other than signaling threads
|
17
|
+
def handle_interrupt
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|