guard 2.7.2 → 2.7.3
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 +4 -4
- data/lib/guard.rb.orig +213 -0
- data/lib/guard/cli.rb +7 -0
- data/lib/guard/cli.rb.orig +218 -0
- data/lib/guard/commander.rb.orig +103 -0
- data/lib/guard/commands/all.rb.orig +36 -0
- data/lib/guard/commands/reload.rb.orig +34 -0
- data/lib/guard/commands/scope.rb.orig +36 -0
- data/lib/guard/deprecated_methods.rb.orig +71 -0
- data/lib/guard/deprecator.rb.orig +206 -0
- data/lib/guard/guard.rb.orig +42 -0
- data/lib/guard/guardfile.rb.orig +43 -0
- data/lib/guard/guardfile/evaluator.rb +5 -2
- data/lib/guard/guardfile/evaluator.rb.orig +275 -0
- data/lib/guard/notifiers/base.rb.orig +221 -0
- data/lib/guard/plugin_util.rb.orig +186 -0
- data/lib/guard/runner.rb.orig +210 -0
- data/lib/guard/setuper.rb.orig +395 -0
- data/lib/guard/ui.rb.orig +278 -0
- data/lib/guard/version.rb +1 -1
- metadata +18 -2
@@ -0,0 +1,42 @@
|
|
1
|
+
require "guard/plugin/base"
|
2
|
+
|
3
|
+
module Guard
|
4
|
+
# @deprecated Inheriting from `Guard::Guard` is deprecated, please inherit
|
5
|
+
# from {Plugin} instead. Please note that the constructor signature has
|
6
|
+
# changed from `Guard::Guard#initialize(watchers = [], options = {})` to
|
7
|
+
# `Guard::Plugin#initialize(options = {})`.
|
8
|
+
#
|
9
|
+
# @see https://github.com/guard/guard/wiki/Upgrading-to-Guard-2.0 How to
|
10
|
+
# upgrade for Guard 2.0
|
11
|
+
#
|
12
|
+
class Guard
|
13
|
+
include ::Guard::Plugin::Base
|
14
|
+
|
15
|
+
# @deprecated Inheriting from `Guard::Guard` is deprecated, please inherit
|
16
|
+
# from {Plugin} instead. Please note that the constructor signature
|
17
|
+
# has changed from `Guard::Guard#initialize(watchers = [], options = {})`
|
18
|
+
# to `Guard::Plugin#initialize(options = {})`.
|
19
|
+
#
|
20
|
+
# Initializes a Guard plugin. Don't do any work here,
|
21
|
+
# especially as Guard plugins get initialized even if they are not in an
|
22
|
+
# active group!
|
23
|
+
#
|
24
|
+
# @see https://github.com/guard/guard/wiki/Upgrading-to-Guard-2.0 How to
|
25
|
+
# upgrade for Guard 2.0
|
26
|
+
#
|
27
|
+
# @param [Array<Guard::Watcher>] watchers the Guard plugin file watchers
|
28
|
+
# @param [Hash] options the custom Guard plugin options
|
29
|
+
# @option options [Symbol] group the group this Guard plugin belongs to
|
30
|
+
# @option options [Boolean] any_return allow any object to be returned from
|
31
|
+
# a watcher
|
32
|
+
# @option options [Boolean] first_match stop after the first watcher that
|
33
|
+
# returns a valid result
|
34
|
+
#
|
35
|
+
def initialize(watchers = [], options = {})
|
36
|
+
UI.deprecation(Deprecator::GUARD_GUARD_DEPRECATION % title)
|
37
|
+
|
38
|
+
_set_instance_variables_from_options(options.merge(watchers: watchers))
|
39
|
+
_register_callbacks
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require "guard/guardfile/evaluator"
|
2
|
+
require "guard/guardfile/generator"
|
3
|
+
require "guard/ui"
|
4
|
+
|
5
|
+
module Guard
|
6
|
+
# @deprecated Use instance methods of {Guardfile::Evaluator} and
|
7
|
+
# {Guardfile::Generator} instead.
|
8
|
+
#
|
9
|
+
# @see Guardfile::Evaluator
|
10
|
+
# @see Guardfile::Generator
|
11
|
+
#
|
12
|
+
module Guardfile
|
13
|
+
# @deprecated Use {Guardfile::Generator#create_guardfile} instead.
|
14
|
+
#
|
15
|
+
# @see https://github.com/guard/guard/wiki/Upgrading-to-Guard-2.0 How to
|
16
|
+
# upgrade for Guard 2.0
|
17
|
+
#
|
18
|
+
def self.create_guardfile(options = {})
|
19
|
+
UI.deprecation(Deprecator::CREATE_GUARDFILE_DEPRECATION)
|
20
|
+
Generator.new(options).create_guardfile
|
21
|
+
end
|
22
|
+
|
23
|
+
# @deprecated Use {Guardfile::Generator#initialize_template} instead.
|
24
|
+
#
|
25
|
+
# @see https://github.com/guard/guard/wiki/Upgrading-to-Guard-2.0 How to
|
26
|
+
# upgrade for Guard 2.0
|
27
|
+
#
|
28
|
+
def self.initialize_template(plugin_name)
|
29
|
+
UI.deprecation(Deprecator::INITIALIZE_TEMPLATE_DEPRECATION)
|
30
|
+
Generator.new.initialize_template(plugin_name)
|
31
|
+
end
|
32
|
+
|
33
|
+
# @deprecated Use {Guardfile::Generator#initialize_all_templates} instead.
|
34
|
+
#
|
35
|
+
# @see https://github.com/guard/guard/wiki/Upgrading-to-Guard-2.0 How to
|
36
|
+
# upgrade for Guard 2.0
|
37
|
+
#
|
38
|
+
def self.initialize_all_templates
|
39
|
+
UI.deprecation(Deprecator::INITIALIZE_ALL_TEMPLATES_DEPRECATION)
|
40
|
+
Generator.new.initialize_all_templates
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -22,6 +22,7 @@ module Guard
|
|
22
22
|
# content of a valid Guardfile
|
23
23
|
#
|
24
24
|
def initialize(opts = {})
|
25
|
+
@evaluated = false
|
25
26
|
@source = nil
|
26
27
|
@guardfile_path = nil
|
27
28
|
|
@@ -81,8 +82,8 @@ module Guard
|
|
81
82
|
# @return [Boolean] whether the Guard plugin has been declared
|
82
83
|
#
|
83
84
|
def guardfile_include?(plugin_name)
|
84
|
-
|
85
|
-
|
85
|
+
/^\s*guard\s*\(?\s*['":]#{ plugin_name }['"]?/.
|
86
|
+
match _guardfile_contents_without_user_config
|
86
87
|
end
|
87
88
|
|
88
89
|
# Gets the content of the `Guardfile` concatenated with the global
|
@@ -106,6 +107,7 @@ module Guard
|
|
106
107
|
# @return [String] the Guardfile content
|
107
108
|
#
|
108
109
|
def _guardfile_contents_without_user_config
|
110
|
+
fail "BUG: no data - Guardfile wasn't evaluated" unless @evaluated
|
109
111
|
@guardfile_contents || ""
|
110
112
|
end
|
111
113
|
|
@@ -124,6 +126,7 @@ module Guard
|
|
124
126
|
#
|
125
127
|
def _fetch_guardfile_contents
|
126
128
|
_use_inline || _use_provided || _use_default
|
129
|
+
@evaluated = true
|
127
130
|
|
128
131
|
return if _guardfile_contents_usable?
|
129
132
|
::Guard::UI.error "No Guard plugins found in Guardfile,"\
|
@@ -0,0 +1,275 @@
|
|
1
|
+
require "guard/options"
|
2
|
+
require "guard/plugin"
|
3
|
+
|
4
|
+
module Guard
|
5
|
+
module Guardfile
|
6
|
+
# This class is responsible for evaluating the Guardfile. It delegates to
|
7
|
+
# Guard::Dsl for the actual objects generation from the Guardfile content.
|
8
|
+
#
|
9
|
+
# @see Guard::Dsl
|
10
|
+
#
|
11
|
+
class Evaluator
|
12
|
+
attr_reader :options, :guardfile_path
|
13
|
+
|
14
|
+
def guardfile_source
|
15
|
+
@source
|
16
|
+
end
|
17
|
+
|
18
|
+
# Initializes a new Guard::Guardfile::Evaluator object.
|
19
|
+
#
|
20
|
+
# @option opts [String] guardfile the path to a valid Guardfile
|
21
|
+
# @option opts [String] guardfile_contents a string representing the
|
22
|
+
# content of a valid Guardfile
|
23
|
+
#
|
24
|
+
def initialize(opts = {})
|
25
|
+
@source = nil
|
26
|
+
@guardfile_path = nil
|
27
|
+
|
28
|
+
valid_options = opts.select do |k, _|
|
29
|
+
[:guardfile, :guardfile_contents].include?(k.to_sym)
|
30
|
+
end
|
31
|
+
|
32
|
+
@options = ::Guard::Options.new(valid_options)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Evaluates the DSL methods in the `Guardfile`.
|
36
|
+
#
|
37
|
+
# @example Programmatically evaluate a Guardfile
|
38
|
+
# Guard::Guardfile::Evaluator.new.evaluate_guardfile
|
39
|
+
#
|
40
|
+
# @example Programmatically evaluate a Guardfile with a custom Guardfile
|
41
|
+
# path
|
42
|
+
#
|
43
|
+
# options = { guardfile: '/Users/guardfile/MyAwesomeGuardfile' }
|
44
|
+
# Guard::Guardfile::Evaluator.new(options).evaluate_guardfile
|
45
|
+
#
|
46
|
+
# @example Programmatically evaluate a Guardfile with an inline Guardfile
|
47
|
+
#
|
48
|
+
# options = { guardfile_contents: 'guard :rspec' }
|
49
|
+
# Guard::Guardfile::Evaluator.new(options).evaluate_guardfile
|
50
|
+
#
|
51
|
+
def evaluate_guardfile
|
52
|
+
_fetch_guardfile_contents
|
53
|
+
_instance_eval_guardfile(guardfile_contents)
|
54
|
+
::Guard.add_builtin_plugins(guardfile_path)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Re-evaluates the `Guardfile` to update
|
58
|
+
# the current Guard configuration.
|
59
|
+
#
|
60
|
+
def reevaluate_guardfile
|
61
|
+
# Don't re-evaluate inline Guardfile
|
62
|
+
return if @source == :inline
|
63
|
+
|
64
|
+
_before_reevaluate_guardfile
|
65
|
+
evaluate_guardfile
|
66
|
+
_after_reevaluate_guardfile
|
67
|
+
end
|
68
|
+
|
69
|
+
# Tests if the current `Guardfile` contains a specific Guard plugin.
|
70
|
+
#
|
71
|
+
# @example Programmatically test if a Guardfile contains a specific Guard
|
72
|
+
# plugin
|
73
|
+
#
|
74
|
+
# File.read('Guardfile')
|
75
|
+
# => "guard :rspec"
|
76
|
+
#
|
77
|
+
# Guard::Guardfile::Evaluator.new.guardfile_include?('rspec)
|
78
|
+
# => true
|
79
|
+
#
|
80
|
+
# @param [String] plugin_name the name of the Guard
|
81
|
+
# @return [Boolean] whether the Guard plugin has been declared
|
82
|
+
#
|
83
|
+
def guardfile_include?(plugin_name)
|
84
|
+
regexp = /^guard\s*\(?\s*['":]#{ plugin_name }['"]?/
|
85
|
+
_guardfile_contents_without_user_config.match(regexp)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Gets the content of the `Guardfile` concatenated with the global
|
89
|
+
# user configuration file.
|
90
|
+
#
|
91
|
+
# @example Programmatically get the content of the current Guardfile
|
92
|
+
# Guard::Guardfile::Evaluator.new.guardfile_contents
|
93
|
+
# => "guard :rspec"
|
94
|
+
#
|
95
|
+
# @return [String] the Guardfile content
|
96
|
+
#
|
97
|
+
def guardfile_contents
|
98
|
+
config = File.read(_user_config_path) if File.exist?(_user_config_path)
|
99
|
+
[_guardfile_contents_without_user_config, config].compact.join("\n")
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
# Gets the content of the `Guardfile`.
|
105
|
+
#
|
106
|
+
# @return [String] the Guardfile content
|
107
|
+
#
|
108
|
+
def _guardfile_contents_without_user_config
|
109
|
+
@guardfile_contents || ""
|
110
|
+
end
|
111
|
+
|
112
|
+
# Evaluates the content of the `Guardfile`.
|
113
|
+
#
|
114
|
+
# @param [String] contents the content to evaluate.
|
115
|
+
#
|
116
|
+
def _instance_eval_guardfile(contents)
|
117
|
+
::Guard::Dsl.new.instance_eval(contents, @guardfile_path || "", 1)
|
118
|
+
rescue => ex
|
119
|
+
::Guard::UI.error "Invalid Guardfile, original error is:\n#{ $! }"
|
120
|
+
raise ex
|
121
|
+
end
|
122
|
+
|
123
|
+
# Gets the content to evaluate and stores it into @guardfile_contents.
|
124
|
+
#
|
125
|
+
def _fetch_guardfile_contents
|
126
|
+
_use_inline || _use_provided || _use_default
|
127
|
+
|
128
|
+
return if _guardfile_contents_usable?
|
129
|
+
::Guard::UI.error "No Guard plugins found in Guardfile,"\
|
130
|
+
" please add at least one."
|
131
|
+
end
|
132
|
+
|
133
|
+
# Use the provided inline Guardfile if provided.
|
134
|
+
#
|
135
|
+
def _use_inline
|
136
|
+
source_from_option = @source.nil? && options[:guardfile_contents]
|
137
|
+
inline = @source == :inline
|
138
|
+
|
139
|
+
return false unless (source_from_option) || inline
|
140
|
+
|
141
|
+
@source = :inline
|
142
|
+
@guardfile_contents = options[:guardfile_contents]
|
143
|
+
|
144
|
+
::Guard::UI.info "Using inline Guardfile."
|
145
|
+
true
|
146
|
+
end
|
147
|
+
|
148
|
+
# Try to use the provided Guardfile. Exits Guard if the Guardfile cannot
|
149
|
+
# be found.
|
150
|
+
#
|
151
|
+
def _use_provided
|
152
|
+
source_from_file = @source.nil? && options[:guardfile]
|
153
|
+
return false unless source_from_file || (@source == :custom)
|
154
|
+
|
155
|
+
@source = :custom
|
156
|
+
|
157
|
+
options[:guardfile] = File.expand_path(options[:guardfile])
|
158
|
+
if File.exist?(options[:guardfile])
|
159
|
+
_read_guardfile(options[:guardfile])
|
160
|
+
::Guard::UI.info "Using Guardfile at #{ options[:guardfile] }."
|
161
|
+
true
|
162
|
+
else
|
163
|
+
::Guard::UI.error "No Guardfile exists at #{ options[:guardfile] }."
|
164
|
+
exit 1
|
165
|
+
end
|
166
|
+
|
167
|
+
true
|
168
|
+
end
|
169
|
+
|
170
|
+
# Try to use one of the default Guardfiles (local or home Guardfile).
|
171
|
+
# Exits Guard if no Guardfile is found.
|
172
|
+
#
|
173
|
+
def _use_default
|
174
|
+
if guardfile_path = _find_default_guardfile
|
175
|
+
@source = :default
|
176
|
+
_read_guardfile(guardfile_path)
|
177
|
+
else
|
178
|
+
::Guard::UI.error \
|
179
|
+
"No Guardfile found, please create one with `guard init`."
|
180
|
+
exit 1
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# Returns the first default Guardfile (either local or home Guardfile)
|
185
|
+
# or nil otherwise.
|
186
|
+
#
|
187
|
+
def _find_default_guardfile
|
188
|
+
[_local_guardfile_path, _home_guardfile_path].detect do |path|
|
189
|
+
File.exist?(path)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
# Reads the current `Guardfile` content.
|
194
|
+
#
|
195
|
+
# @param [String] guardfile_path the path to the Guardfile
|
196
|
+
#
|
197
|
+
def _read_guardfile(guardfile_path)
|
198
|
+
@guardfile_path = guardfile_path
|
199
|
+
@guardfile_contents = File.read(guardfile_path)
|
200
|
+
rescue => ex
|
201
|
+
::Guard::UI.error "Error reading file #{ guardfile_path }:"
|
202
|
+
::Guard::UI.error ex.inspect
|
203
|
+
::Guard::UI.error ex.backtrace
|
204
|
+
exit 1
|
205
|
+
end
|
206
|
+
|
207
|
+
# Stops Guard and clear internal state
|
208
|
+
# before the Guardfile will be re-evaluated.
|
209
|
+
#
|
210
|
+
def _before_reevaluate_guardfile
|
211
|
+
::Guard.runner.run(:stop)
|
212
|
+
::Guard.reset_groups
|
213
|
+
::Guard.reset_plugins
|
214
|
+
::Guard.reset_scope
|
215
|
+
::Guard::Notifier.clear_notifiers
|
216
|
+
end
|
217
|
+
|
218
|
+
# Starts Guard and notification and show a message
|
219
|
+
# after the Guardfile has been re-evaluated.
|
220
|
+
#
|
221
|
+
def _after_reevaluate_guardfile
|
222
|
+
::Guard::Notifier.turn_on if ::Guard::Notifier.enabled?
|
223
|
+
|
224
|
+
if !::Guard.send(:_pluginless_guardfile?)
|
225
|
+
::Guard::Notifier.notify(
|
226
|
+
"No plugins found in Guardfile, please add at least one.",
|
227
|
+
title: "Guard re-evaluate",
|
228
|
+
image: :failed)
|
229
|
+
else
|
230
|
+
msg = "Guardfile has been re-evaluated."
|
231
|
+
::Guard::UI.info(msg)
|
232
|
+
::Guard::Notifier.notify(msg, title: "Guard re-evaluate")
|
233
|
+
|
234
|
+
::Guard.setup_scope
|
235
|
+
::Guard.runner.run(:start)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
# Tests if the current `Guardfile` content is usable.
|
240
|
+
#
|
241
|
+
# @return [Boolean] if the Guardfile is usable
|
242
|
+
#
|
243
|
+
def _guardfile_contents_usable?
|
244
|
+
guardfile_contents && guardfile_contents =~ /guard/m
|
245
|
+
end
|
246
|
+
|
247
|
+
# The path to the `Guardfile` that is located at
|
248
|
+
# the directory, where Guard has been started from.
|
249
|
+
#
|
250
|
+
# @return [String] the path to the local Guardfile
|
251
|
+
#
|
252
|
+
def _local_guardfile_path
|
253
|
+
File.expand_path(File.join(Dir.pwd, "Guardfile"))
|
254
|
+
end
|
255
|
+
|
256
|
+
# The path to the `.Guardfile` that is located at
|
257
|
+
# the users home directory.
|
258
|
+
#
|
259
|
+
# @return [String] the path to `~/.Guardfile`
|
260
|
+
#
|
261
|
+
def _home_guardfile_path
|
262
|
+
File.expand_path(File.join("~", ".Guardfile"))
|
263
|
+
end
|
264
|
+
|
265
|
+
# The path to the user configuration `.guard.rb`
|
266
|
+
# that is located at the users home directory.
|
267
|
+
#
|
268
|
+
# @return [String] the path to `~/.guard.rb`
|
269
|
+
#
|
270
|
+
def _user_config_path
|
271
|
+
File.expand_path(File.join("~", ".guard.rb"))
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
@@ -0,0 +1,221 @@
|
|
1
|
+
require "rbconfig"
|
2
|
+
require "guard/ui"
|
3
|
+
|
4
|
+
module Guard
|
5
|
+
module Notifier
|
6
|
+
# Base class for all notifiers.
|
7
|
+
#
|
8
|
+
class Base
|
9
|
+
HOSTS = {
|
10
|
+
darwin: "Mac OS X",
|
11
|
+
linux: "Linux",
|
12
|
+
freebsd: "FreeBSD",
|
13
|
+
openbsd: "OpenBSD",
|
14
|
+
sunos: "SunOS",
|
15
|
+
solaris: "Solaris",
|
16
|
+
mswin: "Windows",
|
17
|
+
mingw: "Windows",
|
18
|
+
cygwin: "Windows"
|
19
|
+
}
|
20
|
+
|
21
|
+
ERROR_ADD_GEM_AND_RUN_BUNDLE = "Please add \"gem '%s'\" to your Gemfile "\
|
22
|
+
"and run Guard with \"bundle exec\"."
|
23
|
+
|
24
|
+
attr_reader :options
|
25
|
+
|
26
|
+
def initialize(opts = {})
|
27
|
+
@options = opts
|
28
|
+
end
|
29
|
+
|
30
|
+
# This method should be overriden by subclasses and return an array of
|
31
|
+
# OSes the notifier supports. By default, it returns :all which mean
|
32
|
+
# there's no check against the current OS.
|
33
|
+
#
|
34
|
+
# @see HOSTS for the list of possible OSes
|
35
|
+
#
|
36
|
+
def self.supported_hosts
|
37
|
+
:all
|
38
|
+
end
|
39
|
+
|
40
|
+
# Test if the notifier can be used.
|
41
|
+
#
|
42
|
+
# @param [Hash] opts notifier options
|
43
|
+
# @option opts [Boolean] silent true if no error messages should be shown
|
44
|
+
# @return [Boolean] the availability status
|
45
|
+
#
|
46
|
+
def self.available?(opts = {})
|
47
|
+
if _supported_host?
|
48
|
+
true
|
49
|
+
else
|
50
|
+
hosts = supported_hosts.map { |host| HOSTS[host.to_sym] }.join(", ")
|
51
|
+
unless opts.fetch(:silent) { false }
|
52
|
+
::Guard::UI.error "The :#{name} notifier runs only on #{hosts}."
|
53
|
+
end
|
54
|
+
false
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# This method must be overriden.
|
59
|
+
#
|
60
|
+
def notify(_message, opts = {})
|
61
|
+
options.delete(:silent)
|
62
|
+
opts.replace(options.merge(opts))
|
63
|
+
normalize_standard_options!(opts)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns the title of the notifier.
|
67
|
+
#
|
68
|
+
# @example Un-modulize the class name
|
69
|
+
# Guard::Notifier::FileNotifier.title
|
70
|
+
# #=> 'FileNotifier'
|
71
|
+
#
|
72
|
+
# @return [String] the title of the notifier
|
73
|
+
#
|
74
|
+
def self.title
|
75
|
+
to_s.sub(/.+::(\w+)$/, '\1')
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns the name of the notifier.
|
79
|
+
#
|
80
|
+
# @example Un-modulize, underscorize and downcase the class name
|
81
|
+
# Guard::Notifier::FileNotifier.name
|
82
|
+
# #=> 'file_notifier'
|
83
|
+
#
|
84
|
+
# @return [String] the name of the notifier
|
85
|
+
#
|
86
|
+
def self.name
|
87
|
+
title.gsub(/([a-z])([A-Z])/, '\1_\2').downcase
|
88
|
+
end
|
89
|
+
|
90
|
+
# Returns the name of the notifier's gem. By default it returns the
|
91
|
+
# notifier name. This method can be overriden by subclasses.
|
92
|
+
#
|
93
|
+
# @example Un-modulize, underscorize and downcase the class name
|
94
|
+
# Guard::Notifier::FileNotifier.gem_name
|
95
|
+
# #=> 'file_notifier'
|
96
|
+
#
|
97
|
+
# @return [String] the name of the notifier's gem
|
98
|
+
#
|
99
|
+
def self.gem_name
|
100
|
+
name
|
101
|
+
end
|
102
|
+
|
103
|
+
# This method tries to require the gem whose name is returned by
|
104
|
+
# `.gem_name`. If a LoadError or NameError occurs, it displays an error
|
105
|
+
# message (unless opts[:silent] is true) and returns false.
|
106
|
+
#
|
107
|
+
# @param [Hash] opts some options
|
108
|
+
# @option opts [Boolean] silent true if no error messages should be shown
|
109
|
+
#
|
110
|
+
# @return [Boolean] whether or not the gem is loaded
|
111
|
+
#
|
112
|
+
def self.require_gem_safely(opts = {})
|
113
|
+
require gem_name
|
114
|
+
true
|
115
|
+
rescue LoadError, NameError
|
116
|
+
unless opts[:silent]
|
117
|
+
UI.error ERROR_ADD_GEM_AND_RUN_BUNDLE % [gem_name]
|
118
|
+
end
|
119
|
+
false
|
120
|
+
end
|
121
|
+
|
122
|
+
# Returns the title of the notifier.
|
123
|
+
#
|
124
|
+
# @example Un-modulize the class name
|
125
|
+
# Guard::Notifier::FileNotifier.new.title
|
126
|
+
# #=> 'FileNotifier'
|
127
|
+
#
|
128
|
+
# @return [String] the title of the notifier
|
129
|
+
#
|
130
|
+
def title
|
131
|
+
self.class.title
|
132
|
+
end
|
133
|
+
|
134
|
+
# Returns the name of the notifier.
|
135
|
+
#
|
136
|
+
# @example Un-modulize, underscorize and downcase the class name
|
137
|
+
# Guard::Notifier::FileNotifier.new.name
|
138
|
+
# #=> 'file_notifier'
|
139
|
+
#
|
140
|
+
# @return [String] the name of the notifier
|
141
|
+
#
|
142
|
+
def name
|
143
|
+
self.class.name
|
144
|
+
end
|
145
|
+
|
146
|
+
# Paths where all Guard images are located
|
147
|
+
#
|
148
|
+
# @return [Pathname] the path to the images directory
|
149
|
+
#
|
150
|
+
def images_path
|
151
|
+
@images_path ||= Pathname.new(__FILE__).dirname + "../../../images"
|
152
|
+
end
|
153
|
+
|
154
|
+
# @private
|
155
|
+
#
|
156
|
+
# Checks if the current OS is supported by the notifier.
|
157
|
+
#
|
158
|
+
# @see .supported_hosts
|
159
|
+
#
|
160
|
+
def self._supported_host?
|
161
|
+
supported_hosts == :all ||
|
162
|
+
RbConfig::CONFIG["host_os"] =~ /#{supported_hosts.join('|')}/
|
163
|
+
end
|
164
|
+
|
165
|
+
# Set or modify the `:title`, `:type` and `:image` options for a
|
166
|
+
# notification. Should be used in `#notify`.
|
167
|
+
#
|
168
|
+
# @param [Hash] opts additional notification library options
|
169
|
+
# @option opts [String] type the notification type. Either 'success',
|
170
|
+
# 'pending', 'failed' or 'notify'
|
171
|
+
# @option opts [String] title the notification title
|
172
|
+
# @option opts [String] image the path to the notification image
|
173
|
+
#
|
174
|
+
def normalize_standard_options!(opts)
|
175
|
+
opts[:title] ||= "Guard"
|
176
|
+
opts[:type] ||= _notification_type(opts.fetch(:image, :success))
|
177
|
+
opts[:image] = _image_path(opts.delete(:image) { :success })
|
178
|
+
end
|
179
|
+
|
180
|
+
private
|
181
|
+
|
182
|
+
# Get the image path for an image symbol for the following
|
183
|
+
# known image types:
|
184
|
+
#
|
185
|
+
# - failed
|
186
|
+
# - pending
|
187
|
+
# - success
|
188
|
+
#
|
189
|
+
# If the image is not a known symbol, it will be returned unmodified.
|
190
|
+
#
|
191
|
+
# @param [Symbol, String] image the image symbol or path to an image
|
192
|
+
#
|
193
|
+
# @return [String] the image path
|
194
|
+
#
|
195
|
+
def _image_path(image)
|
196
|
+
case image
|
197
|
+
when :failed, :pending, :success
|
198
|
+
images_path.join("#{image}.png").to_s
|
199
|
+
else
|
200
|
+
image
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
# Get the notification type depending on the
|
205
|
+
# image that has been selected for the notification.
|
206
|
+
#
|
207
|
+
# @param [Symbol, String] image the image symbol or path to an image
|
208
|
+
#
|
209
|
+
# @return [String] the notification type
|
210
|
+
#
|
211
|
+
def _notification_type(image)
|
212
|
+
case image
|
213
|
+
when :failed, :pending, :success
|
214
|
+
image
|
215
|
+
else
|
216
|
+
:notify
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|