guard 2.8.2 → 2.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -7
  3. data/lib/guard.rb +220 -152
  4. data/lib/guard.rb.orig +213 -155
  5. data/lib/guard/aruba_adapter.rb +2 -2
  6. data/lib/guard/cli.rb +8 -13
  7. data/lib/guard/cli.rb.orig +12 -10
  8. data/lib/guard/commander.rb +15 -7
  9. data/lib/guard/commands/all.rb +3 -0
  10. data/lib/guard/commands/change.rb +3 -0
  11. data/lib/guard/commands/pause.rb +2 -0
  12. data/lib/guard/commands/reload.rb +4 -0
  13. data/lib/guard/commands/scope.rb +3 -0
  14. data/lib/guard/config.rb +24 -0
  15. data/lib/guard/deprecated/dsl.rb +45 -0
  16. data/lib/guard/deprecated/guard.rb +166 -0
  17. data/lib/guard/deprecated/guardfile.rb +84 -0
  18. data/lib/guard/dsl.rb +24 -13
  19. data/lib/guard/dsl.rb.orig +378 -0
  20. data/lib/guard/dsl_describer.rb +8 -2
  21. data/lib/guard/dsl_describer.rb.orig +11 -3
  22. data/lib/guard/guardfile.rb +32 -44
  23. data/lib/guard/guardfile/evaluator.rb +13 -6
  24. data/lib/guard/guardfile/generator.rb +4 -3
  25. data/lib/guard/interactor.rb +7 -3
  26. data/lib/guard/internals/debugging.rb +1 -0
  27. data/lib/guard/internals/environment.rb +93 -0
  28. data/lib/guard/internals/helpers.rb +13 -0
  29. data/lib/guard/internals/traps.rb +10 -0
  30. data/lib/guard/jobs/pry_wrapper.rb +4 -3
  31. data/lib/guard/jobs/sleep.rb +2 -0
  32. data/lib/guard/metadata.rb +190 -0
  33. data/lib/guard/notifier.rb +124 -99
  34. data/lib/guard/notifier.rb.orig +124 -99
  35. data/lib/guard/notifier/detected.rb +83 -0
  36. data/lib/guard/notifiers/emacs.rb +2 -1
  37. data/lib/guard/notifiers/tmux.rb +173 -177
  38. data/lib/guard/plugin/base.rb +2 -0
  39. data/lib/guard/plugin_util.rb +26 -32
  40. data/lib/guard/reevaluator.rb +3 -3
  41. data/lib/guard/reevaluator.rb.orig +22 -0
  42. data/lib/guard/runner.rb +1 -0
  43. data/lib/guard/session.rb +5 -0
  44. data/lib/guard/sheller.rb +2 -2
  45. data/lib/guard/templates/Guardfile +4 -0
  46. data/lib/guard/templates/Guardfile.orig +2 -0
  47. data/lib/guard/terminal.rb +1 -0
  48. data/lib/guard/ui.rb +4 -1
  49. data/lib/guard/version.rb +1 -1
  50. data/lib/guard/version.rb.orig +1 -1
  51. data/lib/guard/watcher.rb +3 -1
  52. data/lib/guard/watcher.rb.orig +122 -0
  53. data/man/guard.1 +1 -4
  54. data/man/guard.1.html +1 -4
  55. metadata +17 -25
  56. data/lib/guard/commander.rb.orig +0 -103
  57. data/lib/guard/commands/all.rb.orig +0 -36
  58. data/lib/guard/commands/reload.rb.orig +0 -34
  59. data/lib/guard/commands/scope.rb.orig +0 -36
  60. data/lib/guard/deprecated_methods.rb +0 -72
  61. data/lib/guard/deprecated_methods.rb.orig +0 -71
  62. data/lib/guard/deprecator.rb +0 -133
  63. data/lib/guard/deprecator.rb.orig +0 -206
  64. data/lib/guard/guard.rb +0 -100
  65. data/lib/guard/guard.rb.orig +0 -42
  66. data/lib/guard/guardfile.rb.orig +0 -43
  67. data/lib/guard/guardfile/evaluator.rb.orig +0 -275
  68. data/lib/guard/internals/debugging.rb.orig +0 -0
  69. data/lib/guard/internals/environment.rb.orig +0 -0
  70. data/lib/guard/internals/tracing.rb.orig +0 -0
  71. data/lib/guard/notifiers/base.rb.orig +0 -221
  72. data/lib/guard/notifiers/tmux.rb.orig +0 -339
  73. data/lib/guard/plugin_util.rb.orig +0 -186
  74. data/lib/guard/runner.rb.orig +0 -210
  75. data/lib/guard/setuper.rb +0 -359
  76. data/lib/guard/setuper.rb.orig +0 -395
  77. data/lib/guard/ui.rb.orig +0 -278
@@ -1,395 +0,0 @@
1
- require "thread"
2
- require "listen"
3
- require "guard/options"
4
-
5
- module Guard
6
- # Sets up initial variables and options
7
- module Setuper
8
- DEFAULT_OPTIONS = {
9
- clear: false,
10
- notify: true,
11
- debug: false,
12
- group: [],
13
- plugin: [],
14
- watchdir: nil,
15
- guardfile: nil,
16
- no_interactions: false,
17
- no_bundler_warning: false,
18
- show_deprecations: false,
19
- latency: nil,
20
- force_polling: false,
21
- wait_for_delay: nil,
22
- listen_on: nil
23
- }
24
- DEFAULT_GROUPS = [:common, :default]
25
-
26
- # Initializes the Guard singleton:
27
- #
28
- # * Initialize the internal Guard state;
29
- # * Create the interactor
30
- # * Select and initialize the file change listener.
31
- #
32
- # @option options [Boolean] clear if auto clear the UI should be done
33
- # @option options [Boolean] notify if system notifications should be shown
34
- # @option options [Boolean] debug if debug output should be shown
35
- # @option options [Array<String>] group the list of groups to start
36
- # @option options [Array<String>] watchdir the directories to watch
37
- # @option options [String] guardfile the path to the Guardfile
38
- # @option options [Boolean] watch_all_modifications **[deprecated]** watches all file modifications if true
39
- # @option options [Boolean] no_vendor **[deprecated]** ignore vendored dependencies
40
- #
41
- # @return [Guard] the Guard singleton
42
- #
43
-
44
- # TODO: this method has too many instance variables
45
- # and some are mock and leak between tests,
46
- # so ideally there should be a guard "instance"
47
- # object that can be created anew between tests
48
- def setup(opts = {})
49
- reset_options(opts)
50
- reset_evaluator(opts)
51
-
52
- @queue = Queue.new
53
- @runner = ::Guard::Runner.new
54
- @watchdirs = _setup_watchdirs
55
-
56
- ::Guard::UI.setup(options)
57
-
58
- <<<<<<< HEAD
59
- _setup_debug if options[:debug]
60
- @listener = _setup_listener
61
- _setup_signal_traps
62
- =======
63
- ::Guard::Deprecator.deprecated_options_warning(options)
64
- ::Guard::Deprecator.deprecated_plugin_methods_warning
65
-
66
- _setup_notifier
67
- _setup_interactor
68
- >>>>>>> parent of a5162d2... Remove deprecated methods and options. Fixes #425.
69
-
70
- _load_guardfile
71
- @interactor = _setup_interactor
72
- self
73
- end
74
-
75
- attr_reader :options, :interactor
76
-
77
- # Used only by tests (for all I know...)
78
- def clear_options
79
- @options = nil
80
- end
81
-
82
- # Initializes the groups array with the default group(s).
83
- #
84
- # @see DEFAULT_GROUPS
85
- #
86
- def reset_groups
87
- @groups = DEFAULT_GROUPS.map { |name| Group.new(name) }
88
- end
89
-
90
- # Initializes the plugins array to an empty array.
91
- #
92
- # @see Guard.plugins
93
- #
94
- def reset_plugins
95
- @plugins = []
96
- end
97
-
98
- # Initializes the scope hash to `{ groups: [], plugins: [] }`.
99
- #
100
- # @see Guard.setup_scope
101
- #
102
- def reset_scope
103
- # calls Guard.scope=() to set the instance variable directly, as opposed
104
- # to Guard.scope()
105
- ::Guard.scope = { groups: [], plugins: [] }
106
- end
107
-
108
- # Used to merge CLI options with Setuper defaults
109
- def reset_options(new_options)
110
- @options = ::Guard::Options.new(new_options, DEFAULT_OPTIONS)
111
- end
112
-
113
- # TODO: code smell - too many reset_* methods
114
- def reset_evaluator(new_options)
115
- @evaluator = ::Guard::Guardfile::Evaluator.new(new_options)
116
- end
117
-
118
- def save_scope
119
- # This actually replaces scope from command line,
120
- # so scope set by 'scope' Pry command will be reset
121
- @saved_scope = _prepare_scope(::Guard.scope)
122
- end
123
-
124
- def restore_scope
125
- ::Guard.setup_scope(@saved_scope)
126
- end
127
-
128
- attr_reader :watchdirs
129
-
130
- # Stores the scopes defined by the user via the `--group` / `-g` option (to
131
- # run only a specific group) or the `--plugin` / `-P` option (to run only a
132
- # specific plugin).
133
- #
134
- # @see CLI#start
135
- # @see Dsl#scope
136
- #
137
- def setup_scope(scope = {})
138
- # TODO: there should be a special Scope class instead
139
- scope = _prepare_scope(scope)
140
-
141
- ::Guard.scope = {
142
- groups: scope[:groups].map { |item| ::Guard.add_group(item) },
143
- plugins: scope[:plugins].map { |item| ::Guard.plugin(item) },
144
- }
145
- end
146
-
147
- # Evaluates the Guardfile content. It displays an error message if no
148
- # Guard plugins are instantiated after the Guardfile evaluation.
149
- #
150
- # @see Guard::Guardfile::Evaluator#evaluate_guardfile
151
- #
152
- def evaluate_guardfile
153
- evaluator.evaluate_guardfile
154
- msg = "No plugins found in Guardfile, please add at least one."
155
- ::Guard::UI.error msg unless _pluginless_guardfile?
156
- end
157
-
158
- # Asynchronously trigger changes
159
- #
160
- # Currently supported args:
161
- #
162
- # old style hash: {modified: ['foo'], added: ['bar'], removed: []}
163
- #
164
- # new style signals with args: [:guard_pause, :unpaused ]
165
- #
166
- def async_queue_add(changes)
167
- @queue << changes
168
-
169
- # Putting interactor in background puts guard into foreground
170
- # so it can handle change notifications
171
- Thread.new { interactor.background }
172
- end
173
-
174
- def pending_changes?
175
- ! @queue.empty?
176
- end
177
-
178
- def add_builtin_plugins(guardfile)
179
- return unless guardfile
180
-
181
- pattern = _relative_pathname(guardfile).to_s
182
- watcher = ::Guard::Watcher.new(pattern)
183
- ::Guard.add_plugin(:reevaluator, watchers: [watcher], group: :common)
184
- end
185
-
186
- private
187
-
188
- # Sets up various debug behaviors:
189
- #
190
- # * Abort threads on exception;
191
- # * Set the logging level to `:debug`;
192
- # * Modify the system and ` methods to log themselves before being executed
193
- #
194
- # @see #_debug_command_execution
195
- #
196
- def _setup_debug
197
- Thread.abort_on_exception = true
198
- ::Guard::UI.options[:level] = :debug
199
- _debug_command_execution
200
- end
201
-
202
- # Initializes the listener and registers a callback for changes.
203
- #
204
- def _setup_listener
205
- if options[:listen_on]
206
- Listen.on(options[:listen_on], &_listener_callback)
207
- else
208
- listener_options = {}
209
- [:latency, :force_polling, :wait_for_delay].each do |option|
210
- listener_options[option] = options[option] if options[option]
211
- end
212
- listen_args = watchdirs + [listener_options]
213
- Listen.to(*listen_args, &_listener_callback)
214
- end
215
- end
216
-
217
- # Process the change queue, running tasks within the main Guard thread
218
- def _process_queue
219
- actions, changes = [], { modified: [], added: [], removed: [] }
220
-
221
- while pending_changes?
222
- if (item = @queue.pop).first.is_a?(Symbol)
223
- actions << item
224
- else
225
- item.each { |key, value| changes[key] += value }
226
- end
227
- end
228
-
229
- _run_actions(actions)
230
- return if changes.values.all?(&:empty?)
231
- runner.run_on_changes(*changes.values)
232
- end
233
-
234
- # Sets up traps to catch signals used to control Guard.
235
- #
236
- # Currently two signals are caught:
237
- # - `USR1` which pauses listening to changes.
238
- # - `USR2` which resumes listening to changes.
239
- # - 'INT' which is delegated to Pry if active, otherwise stops Guard.
240
- #
241
- def _setup_signal_traps
242
- return if defined?(JRUBY_VERSION)
243
-
244
- if Signal.list.keys.include?("USR1")
245
- Signal.trap("USR1") { async_queue_add([:guard_pause, :paused]) }
246
- end
247
-
248
- if Signal.list.keys.include?("USR2")
249
- Signal.trap("USR2") { async_queue_add([:guard_pause, :unpaused]) }
250
- end
251
-
252
- return unless Signal.list.keys.include?("INT")
253
- Signal.trap("INT") { interactor.handle_interrupt }
254
- end
255
-
256
- # Enables or disables the notifier based on user's configurations.
257
- #
258
- def _setup_notifier
259
- if options[:notify] && ENV["GUARD_NOTIFY"] != "false"
260
- ::Guard::Notifier.turn_on
261
- else
262
- ::Guard::Notifier.turn_off
263
- end
264
- end
265
-
266
- # Adds a command logger in debug mode. This wraps common command
267
- # execution functions and logs the executed command before execution.
268
- #
269
- def _debug_command_execution
270
- Kernel.send(:alias_method, :original_system, :system)
271
- Kernel.send(:define_method, :system) do |command, *args|
272
- ::Guard::UI.debug "Command execution: #{ command } #{ args.join(" ") }"
273
- Kernel.send :original_system, command, *args
274
- end
275
-
276
- Kernel.send(:alias_method, :original_backtick, :'`')
277
- Kernel.send(:define_method, :'`') do |command|
278
- ::Guard::UI.debug "Command execution: #{ command }"
279
- Kernel.send :original_backtick, command
280
- end
281
- end
282
-
283
- # TODO: Guard::Watch or Guard::Scope should provide this
284
- def _scoped_watchers
285
- watchers = []
286
- runner.send(:_scoped_plugins) { |guard| watchers += guard.watchers }
287
- watchers
288
- end
289
-
290
- # Check if any of the changes are actually watched for
291
- def _relevant_changes?(changes)
292
- files = changes.values.flatten(1)
293
- watchers = _scoped_watchers
294
- watchers.any? { |watcher| files.any? { |file| watcher.match(file) } }
295
- end
296
-
297
- def _relative_pathname(path)
298
- full_path = Pathname(path)
299
- full_path.relative_path_from(Pathname.pwd)
300
- rescue ArgumentError
301
- full_path
302
- end
303
-
304
- def _relative_pathnames(paths)
305
- paths.map { |path| _relative_pathname(path) }
306
- end
307
-
308
- def _run_actions(actions)
309
- actions.each do |action_args|
310
- args = action_args.dup
311
- namespaced_action = args.shift
312
- action = namespaced_action.to_s.sub(/^guard_/, "")
313
- if ::Guard.respond_to?(action)
314
- ::Guard.send(action, *args)
315
- else
316
- fail "Unknown action: #{action.inspect}"
317
- end
318
- end
319
- end
320
-
321
- def _setup_watchdirs
322
- dirs = Array(options[:watchdir])
323
- dirs.empty? ? [Dir.pwd] : dirs.map { |dir| File.expand_path dir }
324
- end
325
-
326
- def _listener_callback
327
- lambda do |modified, added, removed|
328
- relative_paths = {
329
- modified: _relative_pathnames(modified),
330
- added: _relative_pathnames(added),
331
- removed: _relative_pathnames(removed)
332
- }
333
-
334
- async_queue_add(relative_paths) if _relevant_changes?(relative_paths)
335
- end
336
- end
337
-
338
- def _reset_all
339
- reset_groups
340
- reset_plugins
341
- reset_scope
342
- end
343
-
344
- def _setup_interactor
345
- ::Guard::Interactor.new(options[:no_interactions])
346
- end
347
-
348
- def _load_guardfile
349
- _reset_all
350
- evaluate_guardfile
351
- setup_scope
352
- _setup_notifier
353
- end
354
-
355
- def _prepare_scope(scope)
356
- fail "Guard::setup() not called!" if options.nil?
357
- plugins = Array(options[:plugin])
358
- plugins = Array(scope[:plugins] || scope[:plugin]) if plugins.empty?
359
-
360
- # Convert objects to names
361
- plugins.map! { |p| p.respond_to?(:name) ? p.name : p }
362
-
363
- groups = Array(options[:group])
364
- groups = Array(scope[:groups] || scope[:group]) if groups.empty?
365
-
366
- # Convert objects to names
367
- groups.map! { |g| g.respond_to?(:name) ? g.name : g }
368
-
369
- { plugins: plugins, groups: groups }
370
- end
371
-
372
- def _pluginless_guardfile?
373
- # no Reevaluator means there was no Guardfile configured that could be
374
- # reevaluated, so we don't have a pluginless guardfile, because we don't
375
- # have a Guardfile to begin with...
376
- #
377
- # But, if we have a Guardfile, we'll at least have the built-in
378
- # Reevaluator, so the following will work:
379
-
380
- plugins.map(&:name) != ["reevaluator"]
381
- end
382
-
383
- def _reset_for_tests
384
- @options = nil
385
- @queue = nil
386
- @runner = nil
387
- @evaluator = nil
388
- @watchdirs = nil
389
- @watchdirs = nil
390
- @listener = nil
391
- @interactor = nil
392
- @scope = nil
393
- end
394
- end
395
- end
data/lib/guard/ui.rb.orig DELETED
@@ -1,278 +0,0 @@
1
- require "lumberjack"
2
-
3
- require "guard/options"
4
- require "guard/ui/colors"
5
-
6
- require "guard/terminal"
7
-
8
- module Guard
9
- # The UI class helps to format messages for the user. Everything that is
10
- # logged through this class is considered either as an error message or a
11
- # diagnostic message and is written to standard error ($stderr).
12
- #
13
- # If your Guard plugin does some output that is piped into another process
14
- # for further processing, please just write it to STDOUT with `puts`.
15
- #
16
- module UI
17
- include Colors
18
-
19
- class << self
20
- # Get the Guard::UI logger instance
21
- #
22
- def logger
23
- @logger ||= begin
24
- Lumberjack::Logger.new(
25
- options.fetch(:device) { $stderr },
26
- options)
27
- end
28
- end
29
-
30
- # Since logger is global, for Aruba in-process to properly
31
- # separate output between calls, we need to reset
32
- #
33
- # We don't use logger=() since it's expected to be a Lumberjack instance
34
- def reset_logger
35
- @logger = nil
36
- end
37
-
38
- # Get the logger options
39
- #
40
- # @return [Hash] the logger options
41
- #
42
- def options
43
- @options ||= ::Guard::Options.new(
44
- level: :info,
45
- template: ":time - :severity - :message",
46
- time_format: "%H:%M:%S")
47
- end
48
-
49
- # Set the logger options
50
- #
51
- # @param [Hash] options the logger options
52
- # @option options [Symbol] level the log level
53
- # @option options [String] template the logger template
54
- # @option options [String] time_format the time format
55
- #
56
- def options=(options)
57
- @options = ::Guard::Options.new(options)
58
- end
59
-
60
- # Show an info message.
61
- #
62
- # @param [String] message the message to show
63
- # @option options [Boolean] reset whether to clean the output before
64
- # @option options [String] plugin manually define the calling plugin
65
- #
66
- def info(message, options = {})
67
- _filtered_logger_message(message, :info, nil, options)
68
- end
69
-
70
- # Show a yellow warning message that is prefixed with WARNING.
71
- #
72
- # @param [String] message the message to show
73
- # @option options [Boolean] reset whether to clean the output before
74
- # @option options [String] plugin manually define the calling plugin
75
- #
76
- def warning(message, options = {})
77
- _filtered_logger_message(message, :warn, :yellow, options)
78
- end
79
-
80
- # Show a red error message that is prefixed with ERROR.
81
- #
82
- # @param [String] message the message to show
83
- # @option options [Boolean] reset whether to clean the output before
84
- # @option options [String] plugin manually define the calling plugin
85
- #
86
- def error(message, options = {})
87
- _filtered_logger_message(message, :error, :red, options)
88
- end
89
-
90
- # Show a red deprecation message that is prefixed with DEPRECATION.
91
- # It has a log level of `warn`.
92
- #
93
- # @param [String] message the message to show
94
- # @option options [Boolean] reset whether to clean the output before
95
- # @option options [String] plugin manually define the calling plugin
96
- #
97
- def deprecation(message, options = {})
98
- msg = "neither ::Guard.setup nor ::Guard.reset_options was called"
99
- fail msg if ::Guard.options.nil?
100
- warning(message, options) if ::Guard.options[:show_deprecations]
101
- end
102
-
103
- # Show a debug message that is prefixed with DEBUG and a timestamp.
104
- #
105
- # @param [String] message the message to show
106
- # @option options [Boolean] reset whether to clean the output before
107
- # @option options [String] plugin manually define the calling plugin
108
- #
109
- def debug(message, options = {})
110
- _filtered_logger_message(message, :debug, :yellow, options)
111
- end
112
-
113
- # Reset a line.
114
- #
115
- def reset_line
116
- $stderr.print(color_enabled? ? "\r\e[0m" : "\r\n")
117
- end
118
-
119
- # Clear the output if clearable.
120
- #
121
- def clear(opts = {})
122
- return unless ::Guard.options[:clear]
123
-
124
- fail "UI not set up!" if @clearable.nil?
125
- return unless @clearable || opts[:force]
126
-
127
- @clearable = false
128
- ::Guard::Terminal.clear
129
- rescue Errno::ENOENT => e
130
- warning("Failed to clear the screen: #{e.inspect}")
131
- end
132
-
133
- # TODO: arguments: UI uses Guard::options anyway
134
- def setup(_options)
135
- @clearable = false
136
- clear(force: true)
137
- end
138
-
139
- # Allow the screen to be cleared again.
140
- #
141
- def clearable
142
- @clearable = true
143
- end
144
-
145
- # Show a scoped action message.
146
- #
147
- # @param [String] action the action to show
148
- # @param [Hash] scope hash with a guard or a group scope
149
- #
150
- def action_with_scopes(action, scope)
151
- first_non_blank_scope = _first_non_blank_scope(scope)
152
- unless first_non_blank_scope.nil?
153
- scope_message = first_non_blank_scope.map(&:title).join(", ")
154
- end
155
-
156
- info "#{ action } #{ scope_message || "all" }"
157
- end
158
-
159
- private
160
-
161
- # Returns the first non-blank scope by searching in the given `scope`
162
- # hash and in Guard.scope. Returns nil if no non-blank scope is found.
163
- #
164
- def _first_non_blank_scope(scope)
165
- [:plugins, :groups].each do |scope_name|
166
- s = scope[scope_name] || ::Guard.scope[scope_name]
167
- return s if !s.nil? && !s.empty?
168
- end
169
-
170
- nil
171
- end
172
-
173
- # Filters log messages depending on either the
174
- # `:only`` or `:except` option.
175
- #
176
- # @param [String] plugin the calling plugin name
177
- # @yield When the message should be logged
178
- # @yieldparam [String] param the calling plugin name
179
- #
180
- def _filter(plugin)
181
- only = options[:only]
182
- except = options[:except]
183
- plugin ||= calling_plugin_name
184
-
185
- match = !(only || except)
186
- match ||= (only && only.match(plugin))
187
- match ||= (except && !except.match(plugin))
188
- return unless match
189
- yield plugin
190
- end
191
-
192
- # Display a message of the type `method` and with the color `color_name`
193
- # (no color by default) conditionnaly given a `plugin_name`.
194
- #
195
- # @param [String] plugin_name the calling plugin name
196
- # @option options [Boolean] reset whether to clean the output before
197
- # @option options [String] plugin manually define the calling plugin
198
- #
199
- def _filtered_logger_message(message, method, color_name, options = {})
200
- message = color(message, color_name) if color_name
201
-
202
- _filter(options[:plugin]) do |plugin|
203
- reset_line if options[:reset]
204
- logger.send(method, message, plugin)
205
- end
206
- end
207
-
208
- # Tries to extract the calling Guard plugin name
209
- # from the call stack.
210
- #
211
- # @param [Integer] depth the stack depth
212
- # @return [String] the Guard plugin name
213
- #
214
- def calling_plugin_name(depth = 2)
215
- name = /(guard\/[a-z_]*)(\/[a-z_]*)?.rb:/i.match(caller[depth])
216
- return "Guard" unless name
217
- name[1].split("/").map do |part|
218
- part.split(/[^a-z0-9]/i).map(&:capitalize).join
219
- end.join("::")
220
- end
221
-
222
- # Checks if color output can be enabled.
223
- #
224
- # @return [Boolean] whether color is enabled or not
225
- #
226
- def color_enabled?
227
- @color_enabled_initialized ||= false
228
- @color_enabled = nil unless @color_enabled_initialized
229
- @color_enabled_initialized = true
230
- if @color_enabled.nil?
231
- if Gem.win_platform?
232
- if ENV["ANSICON"]
233
- @color_enabled = true
234
- else
235
- begin
236
- require "rubygems" unless ENV["NO_RUBYGEMS"]
237
- require "Win32/Console/ANSI"
238
- @color_enabled = true
239
- rescue LoadError
240
- @color_enabled = false
241
- info "Run 'gem install win32console' to use color on Windows"
242
- end
243
- end
244
- else
245
- @color_enabled = true
246
- end
247
- end
248
-
249
- @color_enabled
250
- end
251
-
252
- # Colorizes a text message. See the constant in the UI class for possible
253
- # color_options parameters. You can pass optionally :bright, a foreground
254
- # color and a background color.
255
- #
256
- # @example
257
- #
258
- # color('Hello World', :red, :bright)
259
- #
260
- # @param [String] text the text to colorize
261
- # @param [Array] color_options the color options
262
- #
263
- def color(text, *color_options)
264
- color_code = ""
265
- color_options.each do |color_option|
266
- color_option = color_option.to_s
267
- next if color_option == ""
268
-
269
- unless color_option =~ /\d+/
270
- color_option = const_get("ANSI_ESCAPE_#{ color_option.upcase }")
271
- end
272
- color_code += ";" + color_option
273
- end
274
- color_enabled? ? "\e[0#{ color_code }m#{ text }\e[0m" : text
275
- end
276
- end
277
- end
278
- end