guard 2.10.0 → 2.10.1

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.
@@ -1,83 +0,0 @@
1
- require "guard/internals/environment"
2
-
3
- require_relative "../notifiers/emacs"
4
- require_relative "../notifiers/file_notifier"
5
- require_relative "../notifiers/gntp"
6
- require_relative "../notifiers/growl"
7
- require_relative "../notifiers/libnotify"
8
- require_relative "../notifiers/notifysend"
9
- require_relative "../notifiers/rb_notifu"
10
- require_relative "../notifiers/terminal_notifier"
11
- require_relative "../notifiers/terminal_title"
12
- require_relative "../notifiers/tmux"
13
-
14
- module Guard
15
- module Notifier
16
- # @private api
17
- class Detected
18
- NO_SUPPORTED_NOTIFIERS = "Guard could not detect any of the supported" +
19
- " notification libraries."
20
-
21
- class NoneAvailableError < RuntimeError
22
- end
23
-
24
- def initialize(supported)
25
- @supported = supported
26
- @environment = Internals::Environment.new("GUARD").tap do |env|
27
- env.create_method(:notifiers=) { |data| YAML::dump(data) }
28
- env.create_method(:notifiers) { |data| data ? YAML::load(data) : [] }
29
- end
30
- end
31
-
32
- def reset
33
- @environment.notifiers = nil
34
- end
35
-
36
- def detect
37
- return unless _data.empty?
38
- @supported.each do |group|
39
- group.detect { |name, _| add(name, silent: true) }
40
- end
41
-
42
- fail NoneAvailableError, NO_SUPPORTED_NOTIFIERS if _data.empty?
43
- end
44
-
45
- def available
46
- _data.map { |entry| [_to_module(entry[:name]), entry[:options]] }
47
- end
48
-
49
- def add(name, opts)
50
- klass = _to_module(name)
51
- return false unless klass
52
-
53
- all = @environment.notifiers
54
-
55
- # Silently skip if it's already available, because otherwise
56
- # we'd have to do :turn_off, then configure, then :turn_on
57
- names = all.map(&:first).map(&:last)
58
- unless names.include?(name)
59
- return false unless klass.available?(opts)
60
- @environment.notifiers = all << { name: name, options: opts }
61
- true
62
- end
63
-
64
- # Just overwrite the options (without turning the notifier off or on),
65
- # so those options will be passed in next calls to notify()
66
- all.each { |item| item[:options] = opts if item[:name] == name }
67
- true
68
- end
69
-
70
- def _to_module(name)
71
- @supported.each do |group|
72
- next unless (notifier = group.detect { |n, _| n == name })
73
- return notifier.last
74
- end
75
- nil
76
- end
77
-
78
- def _data
79
- @environment.notifiers || []
80
- end
81
- end
82
- end
83
- end
@@ -1,300 +0,0 @@
1
- module Guard
2
- # Base class from which every Guard plugin implementation must inherit.
3
- #
4
- # Guard will trigger the {#start}, {#stop}, {#reload}, {#run_all} and
5
- # {#run_on_changes} ({#run_on_additions}, {#run_on_modifications} and
6
- # {#run_on_removals}) task methods depending on user interaction and file
7
- # modification.
8
- #
9
- # {#run_on_changes} could be implemented to handle all the changes task case
10
- # (additions, modifications, removals) in once, or each task can be
11
- # implemented separately with a specific behavior.
12
- #
13
- # In each of these Guard task methods you have to implement some work when
14
- # you want to support this kind of task. The return value of each Guard task
15
- # method is not evaluated by Guard, but it'll be passed to the "_end" hook
16
- # for further evaluation. You can throw `:task_has_failed` to indicate that
17
- # your Guard plugin method was not successful, and successive Guard plugin
18
- # tasks will be aborted when the group has set the `:halt_on_fail` option.
19
- #
20
- # @see Guard::Group
21
- #
22
- # @example Throw :task_has_failed
23
- #
24
- # def run_all
25
- # if !runner.run(['all'])
26
- # throw :task_has_failed
27
- # end
28
- # end
29
- #
30
- # Each Guard plugin should provide a template Guardfile located within the Gem
31
- # at `lib/guard/guard-name/templates/Guardfile`.
32
- #
33
- # Watchers for a Guard plugin should return a file path or an array of files
34
- # paths to Guard, but if your Guard plugin wants to allow any return value
35
- # from a watcher, you can set the `any_return` option to true.
36
- #
37
- # If one of those methods raises an exception other than `:task_has_failed`,
38
- # the `Guard::GuardName` instance will be removed from the active Guard
39
- # plugins.
40
- #
41
- class Plugin
42
- TEMPLATE_FORMAT = "%s/lib/guard/%s/templates/Guardfile"
43
-
44
- require "guard/ui"
45
-
46
- # Get all callbacks registered for all Guard plugins present in the
47
- # Guardfile.
48
- #
49
- def self.callbacks
50
- @callbacks ||= Hash.new { |hash, key| hash[key] = [] }
51
- end
52
-
53
- # Add a callback.
54
- #
55
- # @param [Block] listener the listener to notify
56
- # @param [Guard::Plugin] guard_plugin the Guard plugin to add the callback
57
- # @param [Array<Symbol>] events the events to register
58
- #
59
- def self.add_callback(listener, guard_plugin, events)
60
- Array(events).each do |event|
61
- callbacks[[guard_plugin, event]] << listener
62
- end
63
- end
64
-
65
- # Notify a callback.
66
- #
67
- # @param [Guard::Plugin] guard_plugin the Guard plugin to add the callback
68
- # @param [Symbol] event the event to trigger
69
- # @param [Array] args the arguments for the listener
70
- #
71
- def self.notify(guard_plugin, event, *args)
72
- callbacks[[guard_plugin, event]].each do |listener|
73
- listener.call(guard_plugin, event, *args)
74
- end
75
- end
76
-
77
- # Reset all callbacks.
78
- #
79
- # TODO: remove (not used anywhere)
80
- def self.reset_callbacks!
81
- @callbacks = nil
82
- end
83
-
84
- # When event is a Symbol, {#hook} will generate a hook name
85
- # by concatenating the method name from where {#hook} is called
86
- # with the given Symbol.
87
- #
88
- # @example Add a hook with a Symbol
89
- #
90
- # def run_all
91
- # hook :foo
92
- # end
93
- #
94
- # Here, when {Guard::Plugin::Base#run_all} is called, {#hook} will notify
95
- # callbacks registered for the "run_all_foo" event.
96
- #
97
- # When event is a String, {#hook} will directly turn the String
98
- # into a Symbol.
99
- #
100
- # @example Add a hook with a String
101
- #
102
- # def run_all
103
- # hook "foo_bar"
104
- # end
105
- #
106
- # When {Guard::Plugin::Base#run_all} is called, {#hook} will notify
107
- # callbacks registered for the "foo_bar" event.
108
- #
109
- # @param [Symbol, String] event the name of the Guard event
110
- # @param [Array] args the parameters are passed as is to the callbacks
111
- # registered for the given event.
112
- #
113
- def hook(event, *args)
114
- hook_name = if event.is_a? Symbol
115
- calling_method = caller[0][/`([^']*)'/, 1]
116
- "#{ calling_method }_#{ event }"
117
- else
118
- event
119
- end
120
-
121
- UI.debug "Hook :#{ hook_name } executed for #{ self.class }"
122
-
123
- self.class.notify(self, hook_name.to_sym, *args)
124
- end
125
-
126
- attr_accessor :group, :watchers, :callbacks, :options
127
-
128
- # Returns the non-namespaced class name of the plugin
129
- #
130
- #
131
- # @example Non-namespaced class name for Guard::RSpec
132
- # Guard::RSpec.non_namespaced_classname
133
- # #=> "RSpec"
134
- #
135
- # @return [String]
136
- #
137
- def self.non_namespaced_classname
138
- to_s.sub("Guard::", "")
139
- end
140
-
141
- # Returns the non-namespaced name of the plugin
142
- #
143
- #
144
- # @example Non-namespaced name for Guard::RSpec
145
- # Guard::RSpec.non_namespaced_name
146
- # #=> "rspec"
147
- #
148
- # @return [String]
149
- #
150
- def self.non_namespaced_name
151
- non_namespaced_classname.downcase
152
- end
153
-
154
- # Specify the source for the Guardfile template.
155
- # Each Guard plugin can redefine this method to add its own logic.
156
- #
157
- # @param [String] plugin_location the plugin location
158
- #
159
- def self.template(plugin_location)
160
- File.read TEMPLATE_FORMAT % [plugin_location, non_namespaced_name]
161
- end
162
-
163
- # Called once when Guard starts. Please override initialize method to
164
- # init stuff.
165
- #
166
- # @raise [:task_has_failed] when start has failed
167
- # @return [Object] the task result
168
- #
169
- # @!method start
170
-
171
- # Called when `stop|quit|exit|s|q|e + enter` is pressed (when Guard
172
- # quits).
173
- #
174
- # @raise [:task_has_failed] when stop has failed
175
- # @return [Object] the task result
176
- #
177
- # @!method stop
178
-
179
- # Called when `reload|r|z + enter` is pressed.
180
- # This method should be mainly used for "reload" (really!) actions like
181
- # reloading passenger/spork/bundler/...
182
- #
183
- # @raise [:task_has_failed] when reload has failed
184
- # @return [Object] the task result
185
- #
186
- # @!method reload
187
-
188
- # Called when just `enter` is pressed
189
- # This method should be principally used for long action like running all
190
- # specs/tests/...
191
- #
192
- # @raise [:task_has_failed] when run_all has failed
193
- # @return [Object] the task result
194
- #
195
- # @!method run_all
196
-
197
- # Default behaviour on file(s) changes that the Guard plugin watches.
198
- #
199
- # @param [Array<String>] paths the changes files or paths
200
- # @raise [:task_has_failed] when run_on_changes has failed
201
- # @return [Object] the task result
202
- #
203
- # @!method run_on_changes(paths)
204
-
205
- # Called on file(s) additions that the Guard plugin watches.
206
- #
207
- # @param [Array<String>] paths the changes files or paths
208
- # @raise [:task_has_failed] when run_on_additions has failed
209
- # @return [Object] the task result
210
- #
211
- # @!method run_on_additions(paths)
212
-
213
- # Called on file(s) modifications that the Guard plugin watches.
214
- #
215
- # @param [Array<String>] paths the changes files or paths
216
- # @raise [:task_has_failed] when run_on_modifications has failed
217
- # @return [Object] the task result
218
- #
219
- # @!method run_on_modifications(paths)
220
-
221
- # Called on file(s) removals that the Guard plugin watches.
222
- #
223
- # @param [Array<String>] paths the changes files or paths
224
- # @raise [:task_has_failed] when run_on_removals has failed
225
- # @return [Object] the task result
226
- #
227
- # @!method run_on_removals(paths)
228
-
229
- # Returns the plugin's name (without "guard-").
230
- #
231
- # @example Name for Guard::RSpec
232
- # Guard::RSpec.new.name
233
- # #=> "rspec"
234
- #
235
- # @return [String]
236
- #
237
- def name
238
- @name ||= self.class.non_namespaced_name
239
- end
240
-
241
- # Returns the plugin's class name without the Guard:: namespace.
242
- #
243
- # @example Title for Guard::RSpec
244
- # Guard::RSpec.new.title
245
- # #=> "RSpec"
246
- #
247
- # @return [String]
248
- #
249
- def title
250
- @title ||= self.class.non_namespaced_classname
251
- end
252
-
253
- # String representation of the plugin.
254
- #
255
- # @example String representation of an instance of the Guard::RSpec plugin
256
- #
257
- # Guard::RSpec.new.title
258
- # #=> "#<Guard::RSpec @name=rspec @group=#<Guard::Group @name=default
259
- # @options={}> @watchers=[] @callbacks=[] @options={all_after_pass:
260
- # true}>"
261
- #
262
- # @return [String] the string representation
263
- #
264
- def to_s
265
- "#<#{self.class} @name=#{name} @group=#{group} @watchers=#{watchers}"\
266
- " @callbacks=#{callbacks} @options=#{options}>"
267
- end
268
-
269
- private
270
-
271
- # Initializes a Guard plugin.
272
- # Don't do any work here, especially as Guard plugins get initialized even
273
- # if they are not in an active group!
274
- #
275
- # @param [Hash] options the Guard plugin options
276
- # @option options [Array<Guard::Watcher>] watchers the Guard plugin file
277
- # watchers
278
- # @option options [Symbol] group the group this Guard plugin belongs to
279
- # @option options [Boolean] any_return allow any object to be returned from
280
- # a watcher
281
- #
282
- def initialize(options = {})
283
- group_name = options.delete(:group) { :default }
284
- @group = Guard.state.session.groups.add(group_name)
285
- @watchers = options.delete(:watchers) { [] }
286
- @callbacks = options.delete(:callbacks) { [] }
287
- @options = options
288
- _register_callbacks
289
- end
290
-
291
- # Add all the Guard::Plugin's callbacks to the global @callbacks array
292
- # that's used by Guard to know which callbacks to notify.
293
- #
294
- def _register_callbacks
295
- callbacks.each do |callback|
296
- Hooker.add_callback(callback[:listener], self, callback[:events])
297
- end
298
- end
299
- end
300
- end
@@ -1,22 +0,0 @@
1
- require "guard/plugin"
2
- require "guard/guardfile/evaluator"
3
-
4
- module Guard
5
- class Reevaluator < Plugin
6
- def run_on_modifications(files)
7
- STDERR.puts files.inspect
8
- return unless ::Guard::Watcher.match_guardfile?(files)
9
- ::Guard.save_scope
10
- Guard::Guardfile::Evaluator.new.reevaluate_guardfile
11
- rescue ScriptError, StandardError => e
12
- ::Guard::UI.warning("Failed to reevaluate file: #{e}")
13
-
14
- options = { watchers: [::Guard::Watcher.new("Guardfile")] }
15
- ::Guard.add_plugin(:reevaluator, options)
16
-
17
- throw :task_has_failed
18
- ensure
19
- ::Guard.restore_scope
20
- end
21
- end
22
- end
@@ -1,2 +0,0 @@
1
- # A sample Guardfile
2
- # More info at https://github.com/guard/guard#readme
data/lib/guard/ui.rb.orig DELETED
@@ -1,274 +0,0 @@
1
- require "lumberjack"
2
-
3
- require "guard/internals/state"
4
-
5
- require "guard/options"
6
-
7
- require "guard/ui/colors"
8
-
9
- require "guard/terminal"
10
-
11
- module Guard
12
- # The UI class helps to format messages for the user. Everything that is
13
- # logged through this class is considered either as an error message or a
14
- # diagnostic message and is written to standard error ($stderr).
15
- #
16
- # If your Guard plugin does some output that is piped into another process
17
- # for further processing, please just write it to STDOUT with `puts`.
18
- #
19
- module UI
20
- include Colors
21
-
22
- class << self
23
- # Get the Guard::UI logger instance
24
- #
25
- def logger
26
- @logger ||= begin
27
- Lumberjack::Logger.new(
28
- options.fetch(:device) { $stderr },
29
- options)
30
- end
31
- end
32
-
33
- # Since logger is global, for Aruba in-process to properly
34
- # separate output between calls, we need to reset
35
- #
36
- # We don't use logger=() since it's expected to be a Lumberjack instance
37
- def reset_logger
38
- @logger = nil
39
- end
40
-
41
- # Get the logger options
42
- #
43
- # @return [Hash] the logger options
44
- #
45
- def options
46
- @options ||= ::Guard::Options.new(
47
- level: :info,
48
- template: ":time - :severity - :message",
49
- time_format: "%H:%M:%S")
50
- end
51
-
52
- # Set the logger options
53
- #
54
- # @param [Hash] options the logger options
55
- # @option options [Symbol] level the log level
56
- # @option options [String] template the logger template
57
- # @option options [String] time_format the time format
58
- #
59
- # TODO: deprecate?
60
- def options=(options)
61
- @options = ::Guard::Options.new(options)
62
- end
63
-
64
- # Assigns a log level
65
- def level=(new_level)
66
- logger.level = new_level
67
- end
68
-
69
- # Show an info message.
70
- #
71
- # @param [String] message the message to show
72
- # @option options [Boolean] reset whether to clean the output before
73
- # @option options [String] plugin manually define the calling plugin
74
- #
75
- def info(message, options = {})
76
- _filtered_logger_message(message, :info, nil, options)
77
- end
78
-
79
- # Show a yellow warning message that is prefixed with WARNING.
80
- #
81
- # @param [String] message the message to show
82
- # @option options [Boolean] reset whether to clean the output before
83
- # @option options [String] plugin manually define the calling plugin
84
- #
85
- def warning(message, options = {})
86
- _filtered_logger_message(message, :warn, :yellow, options)
87
- end
88
-
89
- # Show a red error message that is prefixed with ERROR.
90
- #
91
- # @param [String] message the message to show
92
- # @option options [Boolean] reset whether to clean the output before
93
- # @option options [String] plugin manually define the calling plugin
94
- #
95
- def error(message, options = {})
96
- _filtered_logger_message(message, :error, :red, options)
97
- end
98
-
99
- # Show a red deprecation message that is prefixed with DEPRECATION.
100
- # It has a log level of `warn`.
101
- #
102
- # @param [String] message the message to show
103
- # @option options [Boolean] reset whether to clean the output before
104
- # @option options [String] plugin manually define the calling plugin
105
- #
106
- def deprecation(message, options = {})
107
- unless ENV["GUARD_GEM_SILENCE_DEPRECATIONS"] == "1"
108
- backtrace = Thread.current.backtrace[1..5].join("\n\t >")
109
- msg = format("%s\nDeprecation backtrace: %s", message, backtrace)
110
- warning(msg, options)
111
- end
112
- end
113
-
114
- # Show a debug message that is prefixed with DEBUG and a timestamp.
115
- #
116
- # @param [String] message the message to show
117
- # @option options [Boolean] reset whether to clean the output before
118
- # @option options [String] plugin manually define the calling plugin
119
- #
120
- def debug(message, options = {})
121
- _filtered_logger_message(message, :debug, :yellow, options)
122
- end
123
-
124
- # Reset a line.
125
- #
126
- def reset_line
127
- $stderr.print(color_enabled? ? "\r\e[0m" : "\r\n")
128
- end
129
-
130
- # Clear the output if clearable.
131
- #
132
- def clear(opts = {})
133
- return unless Guard.state.session.clear?
134
-
135
- fail "UI not set up!" if @clearable.nil?
136
- return unless @clearable || opts[:force]
137
-
138
- @clearable = false
139
- Terminal.clear
140
- rescue Errno::ENOENT => e
141
- warning("Failed to clear the screen: #{e.inspect}")
142
- end
143
-
144
- # TODO: arguments: UI uses Guard::options anyway
145
- # @private api
146
- def reset_and_clear
147
- @clearable = false
148
- clear(force: true)
149
- end
150
-
151
- # Allow the screen to be cleared again.
152
- #
153
- def clearable
154
- @clearable = true
155
- end
156
-
157
- # Show a scoped action message.
158
- #
159
- # @param [String] action the action to show
160
- # @param [Hash] scope hash with a guard or a group scope
161
- #
162
- def action_with_scopes(action, scope)
163
- titles = Guard.state.scope.titles(scope)
164
- info "#{action} #{titles.join(", ")}"
165
- end
166
-
167
- private
168
-
169
- # Filters log messages depending on either the
170
- # `:only`` or `:except` option.
171
- #
172
- # @param [String] plugin the calling plugin name
173
- # @yield When the message should be logged
174
- # @yieldparam [String] param the calling plugin name
175
- #
176
- def _filter(plugin)
177
- only = options[:only]
178
- except = options[:except]
179
- plugin ||= calling_plugin_name
180
-
181
- match = !(only || except)
182
- match ||= (only && only.match(plugin))
183
- match ||= (except && !except.match(plugin))
184
- return unless match
185
- yield plugin
186
- end
187
-
188
- # Display a message of the type `method` and with the color `color_name`
189
- # (no color by default) conditionnaly given a `plugin_name`.
190
- #
191
- # @param [String] plugin_name the calling plugin name
192
- # @option options [Boolean] reset whether to clean the output before
193
- # @option options [String] plugin manually define the calling plugin
194
- #
195
- def _filtered_logger_message(message, method, color_name, options = {})
196
- message = color(message, color_name) if color_name
197
-
198
- _filter(options[:plugin]) do |plugin|
199
- reset_line if options[:reset]
200
- logger.send(method, message, plugin)
201
- end
202
- end
203
-
204
- # Tries to extract the calling Guard plugin name
205
- # from the call stack.
206
- #
207
- # @param [Integer] depth the stack depth
208
- # @return [String] the Guard plugin name
209
- #
210
- def calling_plugin_name(depth = 2)
211
- name = /(guard\/[a-z_]*)(\/[a-z_]*)?.rb:/i.match(caller[depth])
212
- return "Guard" unless name
213
- name[1].split("/").map do |part|
214
- part.split(/[^a-z0-9]/i).map(&:capitalize).join
215
- end.join("::")
216
- end
217
-
218
- # Checks if color output can be enabled.
219
- #
220
- # @return [Boolean] whether color is enabled or not
221
- #
222
- def color_enabled?
223
- @color_enabled_initialized ||= false
224
- @color_enabled = nil unless @color_enabled_initialized
225
- @color_enabled_initialized = true
226
- if @color_enabled.nil?
227
- if Gem.win_platform?
228
- if ENV["ANSICON"]
229
- @color_enabled = true
230
- else
231
- begin
232
- require "rubygems" unless ENV["NO_RUBYGEMS"]
233
- require "Win32/Console/ANSI"
234
- @color_enabled = true
235
- rescue LoadError
236
- @color_enabled = false
237
- info "Run 'gem install win32console' to use color on Windows"
238
- end
239
- end
240
- else
241
- @color_enabled = true
242
- end
243
- end
244
-
245
- @color_enabled
246
- end
247
-
248
- # Colorizes a text message. See the constant in the UI class for possible
249
- # color_options parameters. You can pass optionally :bright, a foreground
250
- # color and a background color.
251
- #
252
- # @example
253
- #
254
- # color('Hello World', :red, :bright)
255
- #
256
- # @param [String] text the text to colorize
257
- # @param [Array] color_options the color options
258
- #
259
- def color(text, *color_options)
260
- color_code = ""
261
- color_options.each do |color_option|
262
- color_option = color_option.to_s
263
- next if color_option == ""
264
-
265
- unless color_option =~ /\d+/
266
- color_option = const_get("ANSI_ESCAPE_#{ color_option.upcase }")
267
- end
268
- color_code += ";" + color_option
269
- end
270
- color_enabled? ? "\e[0#{ color_code }m#{ text }\e[0m" : text
271
- end
272
- end
273
- end
274
- end