guard 2.10.1 → 2.10.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 100b160735c5c331821d9fa8119bb168ed5f907e
4
- data.tar.gz: d677f7e1a7491ff72654d415d7c571f028fbef52
3
+ metadata.gz: 3106af4e3722da1f4bd41e051e5baf1ff8ace4f7
4
+ data.tar.gz: 0ef587f058e7f02bc5b4195a0b3b3b4d25847ddd
5
5
  SHA512:
6
- metadata.gz: 0dcad099ca8bd1dca2486e078233215366c4236b8a1b0b465336d020667e041bd16e75df106efeef75a6013fcdb9601fdd35bd28eac8130c4eb3a910694004a3
7
- data.tar.gz: 835a20ae288b6c660d9cb058eeba5b2c25f999bc3790c0dfb0ccf48a7816eff2405fe82e26cc9884b2397f02a610ba73f848c63bf89eb478fd94aae632ff31f7
6
+ metadata.gz: b5f3825c29f9c01f14b50051055e105a3695288da0ce2ba2d42fdd4e4af92881afb455515da551a1faaf192b28ba8eb2e599f0640002ff9c1d2d8db0796c734a
7
+ data.tar.gz: c107a499ff6e9814b536a9c1f723c5a7badc97e33f74ae8409f5b72d082fff63c09d3eac630cd9b6b12c9591ed1210b907ea05680f2b615d62bcde31b2eb5784
File without changes
@@ -168,6 +168,7 @@ module Guard
168
168
  end
169
169
 
170
170
  def self._gem_valid?(gem)
171
+ return false if gem.name == "guard-compat"
171
172
  return true if gem.name =~ /^guard-/
172
173
  full_path = gem.full_gem_path
173
174
  file = File.join(full_path, "lib", "guard", "#{gem.name}.rb")
@@ -0,0 +1,182 @@
1
+ require "guard/ui"
2
+
3
+ module Guard
4
+ # This class contains useful methods to:
5
+ #
6
+ # * Fetch all the Guard plugins names;
7
+ # * Initialize a plugin, get its location;
8
+ # * Return its class name;
9
+ # * Add its template to the Guardfile.
10
+ #
11
+ class PluginUtil
12
+ ERROR_NO_GUARD_OR_CLASS = "Could not load 'guard/%s' or'\
13
+ ' find class Guard::%s"
14
+
15
+ INFO_ADDED_GUARD_TO_GUARDFILE = "%s guard added to Guardfile,"\
16
+ " feel free to edit it"
17
+
18
+ attr_accessor :name
19
+
20
+ # Returns a list of Guard plugin Gem names installed locally.
21
+ #
22
+ # @return [Array<String>] a list of Guard plugin gem names
23
+ #
24
+ def self.plugin_names
25
+ valid = Gem::Specification.find_all.select do |gem|
26
+ _gem_valid?(gem)
27
+ end
28
+
29
+ valid.map { |x| x.name.sub(/^guard-/, "") }.uniq
30
+ end
31
+
32
+ # Initializes a new `Guard::PluginUtil` object.
33
+ #
34
+ # @param [String] name the name of the Guard plugin
35
+ #
36
+ def initialize(name)
37
+ @name = name.to_s.sub(/^guard-/, "")
38
+ end
39
+
40
+ # Initializes a new `Guard::Plugin` with the given `options` hash. This
41
+ # methods handles plugins that inherit from the deprecated `Guard::Guard`
42
+ # class as well as plugins that inherit from `Guard::Plugin`.
43
+ #
44
+ # @see Guard::Plugin
45
+ # @see https://github.com/guard/guard/wiki/Upgrading-to-Guard-2.0 How to
46
+ # upgrade for Guard 2.0
47
+ #
48
+ # @return [Guard::Plugin] the initialized plugin
49
+ # @return [Guard::Guard] the initialized plugin. This return type is
50
+ # deprecated and the plugin's maintainer should update it to be
51
+ # compatible with Guard 2.0. For more information on how to upgrade for
52
+ # Guard 2.0, please head over to:
53
+ # https://github.com/guard/guard/wiki/Upgrading-to-Guard-2.0
54
+ #
55
+ def initialize_plugin(options)
56
+ klass = plugin_class
57
+ fail "Could not load class: #{_constant_name.inspect}" unless klass
58
+ if klass.superclass.to_s == "Guard::Guard"
59
+ klass.new(options.delete(:watchers), options)
60
+ else
61
+ begin
62
+ klass.new(options)
63
+ rescue ArgumentError => e
64
+ fail "Failed to call #{klass}.new(options): #{e}"
65
+ end
66
+ end
67
+ end
68
+
69
+ # Locates a path to a Guard plugin gem.
70
+ #
71
+ # @return [String] the full path to the plugin gem
72
+ #
73
+ def plugin_location
74
+ @plugin_location ||= _full_gem_path("guard-#{name}")
75
+ rescue Gem::LoadError
76
+ ::Guard::UI.error "Could not find 'guard-#{ name }' gem path."
77
+ end
78
+
79
+ # Tries to load the Guard plugin main class. This transforms the supplied
80
+ # plugin name into a class name:
81
+ #
82
+ # * `guardname` will become `Guard::Guardname`
83
+ # * `dashed-guard-name` will become `Guard::DashedGuardName`
84
+ # * `underscore_guard_name` will become `Guard::UnderscoreGuardName`
85
+ #
86
+ # When no class is found with the strict case sensitive rules, another
87
+ # try is made to locate the class without matching case:
88
+ #
89
+ # * `rspec` will find a class `Guard::RSpec`
90
+ #
91
+ # @option options [Boolean] fail_gracefully whether error messages should
92
+ # not be printed
93
+ #
94
+ # @return [Class, nil] the loaded class
95
+ #
96
+ def plugin_class(options = {})
97
+ options = { fail_gracefully: false }.merge(options)
98
+
99
+ const = _plugin_constant
100
+ fail TypeError, "no constant: #{_constant_name}" unless const
101
+ @plugin_class ||= Guard.const_get(const)
102
+
103
+ rescue TypeError
104
+ begin
105
+ require "guard/#{ name.downcase }"
106
+ const = _plugin_constant
107
+ @plugin_class ||= Guard.const_get(const)
108
+
109
+ rescue TypeError => error
110
+ UI.error "Could not find class Guard::#{ _constant_name }"
111
+ UI.error error.backtrace.join("\n")
112
+ rescue LoadError => error
113
+ unless options[:fail_gracefully]
114
+ UI.error ERROR_NO_GUARD_OR_CLASS % [name.downcase, _constant_name]
115
+ UI.error "Error is: #{error}"
116
+ UI.error error.backtrace.join("\n")
117
+ end
118
+ end
119
+ end
120
+
121
+ # Adds a plugin's template to the Guardfile.
122
+ #
123
+ def add_to_guardfile
124
+ klass = plugin_class # call here to avoid failing later
125
+
126
+ require "guard/guardfile/evaluator"
127
+ # TODO: move this to Generator?
128
+ options = Guard.state.session.evaluator_options
129
+ evaluator = Guardfile::Evaluator.new(options)
130
+ evaluator.evaluate
131
+ if evaluator.guardfile_include?(name)
132
+ UI.info "Guardfile already includes #{ name } guard"
133
+ else
134
+ content = File.read("Guardfile")
135
+ File.open("Guardfile", "wb") do |f|
136
+ f.puts(content)
137
+ f.puts("")
138
+ f.puts(klass.template(plugin_location))
139
+ end
140
+
141
+ UI.info INFO_ADDED_GUARD_TO_GUARDFILE % name
142
+ end
143
+ end
144
+
145
+ private
146
+
147
+ # Returns the constant for the current plugin.
148
+ #
149
+ # @example Returns the constant for a plugin
150
+ # > Guard::PluginUtil.new('rspec').send(:_plugin_constant)
151
+ # => Guard::RSpec
152
+ #
153
+ def _plugin_constant
154
+ @_plugin_constant ||= Guard.constants.detect do |c|
155
+ c.to_s.downcase == _constant_name.downcase
156
+ end
157
+ end
158
+
159
+ # Guesses the most probable name for the current plugin based on its name.
160
+ #
161
+ # @example Returns the most probable name for a plugin
162
+ # > Guard::PluginUtil.new('rspec').send(:_constant_name)
163
+ # => "Rspec"
164
+ #
165
+ def _constant_name
166
+ @_constant_name ||= name.gsub(/\/(.?)/) { "::#{ $1.upcase }" }.
167
+ gsub(/(?:^|[_-])(.)/) { $1.upcase }
168
+ end
169
+
170
+ def self._gem_valid?(gem)
171
+ return false if gem.name == 'guard-compat'
172
+ return true if gem.name =~ /^guard-/
173
+ full_path = gem.full_gem_path
174
+ file = File.join(full_path, "lib", "guard", "#{gem.name}.rb")
175
+ File.exist?(file)
176
+ end
177
+
178
+ def _full_gem_path(name)
179
+ Gem::Specification.find_by_name(name).full_gem_path
180
+ end
181
+ end
182
+ end
data/lib/guard/ui.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "lumberjack"
2
2
 
3
+ # TODO: remove this dep!
3
4
  require "guard/internals/state"
4
5
 
5
6
  require "guard/options"
@@ -0,0 +1,268 @@
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
+ # @private
189
+ def _filtered_logger_message(message, method, color_name, options = {})
190
+ message = color(message, color_name) if color_name
191
+
192
+ _filter(options[:plugin]) do |plugin|
193
+ reset_line if options[:reset]
194
+ logger.send(method, message, plugin)
195
+ end
196
+ end
197
+
198
+ # Tries to extract the calling Guard plugin name
199
+ # from the call stack.
200
+ #
201
+ # @param [Integer] depth the stack depth
202
+ # @return [String] the Guard plugin name
203
+ #
204
+ def calling_plugin_name(depth = 2)
205
+ name = /(guard\/[a-z_]*)(\/[a-z_]*)?.rb:/i.match(caller[depth])
206
+ return "Guard" unless name
207
+ name[1].split("/").map do |part|
208
+ part.split(/[^a-z0-9]/i).map(&:capitalize).join
209
+ end.join("::")
210
+ end
211
+
212
+ # Checks if color output can be enabled.
213
+ #
214
+ # @return [Boolean] whether color is enabled or not
215
+ #
216
+ def color_enabled?
217
+ @color_enabled_initialized ||= false
218
+ @color_enabled = nil unless @color_enabled_initialized
219
+ @color_enabled_initialized = true
220
+ if @color_enabled.nil?
221
+ if Gem.win_platform?
222
+ if ENV["ANSICON"]
223
+ @color_enabled = true
224
+ else
225
+ begin
226
+ require "rubygems" unless ENV["NO_RUBYGEMS"]
227
+ require "Win32/Console/ANSI"
228
+ @color_enabled = true
229
+ rescue LoadError
230
+ @color_enabled = false
231
+ info "Run 'gem install win32console' to use color on Windows"
232
+ end
233
+ end
234
+ else
235
+ @color_enabled = true
236
+ end
237
+ end
238
+
239
+ @color_enabled
240
+ end
241
+
242
+ # Colorizes a text message. See the constant in the UI class for possible
243
+ # color_options parameters. You can pass optionally :bright, a foreground
244
+ # color and a background color.
245
+ #
246
+ # @example
247
+ #
248
+ # color('Hello World', :red, :bright)
249
+ #
250
+ # @param [String] text the text to colorize
251
+ # @param [Array] color_options the color options
252
+ #
253
+ def color(text, *color_options)
254
+ color_code = ""
255
+ color_options.each do |color_option|
256
+ color_option = color_option.to_s
257
+ next if color_option == ""
258
+
259
+ unless color_option =~ /\d+/
260
+ color_option = const_get("ANSI_ESCAPE_#{ color_option.upcase }")
261
+ end
262
+ color_code += ";" + color_option
263
+ end
264
+ color_enabled? ? "\e[0#{ color_code }m#{ text }\e[0m" : text
265
+ end
266
+ end
267
+ end
268
+ end
data/lib/guard/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Guard
2
- VERSION = "2.10.1"
2
+ VERSION = "2.10.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: guard
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.10.1
4
+ version: 2.10.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thibaud Guillaume-Gentil
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-01 00:00:00.000000000 Z
11
+ date: 2014-12-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -108,6 +108,7 @@ files:
108
108
  - lib/guard/commands/reload.rb
109
109
  - lib/guard/commands/scope.rb
110
110
  - lib/guard/commands/show.rb
111
+ - lib/guard/compat/test/helper.rb.orig
111
112
  - lib/guard/config.rb
112
113
  - lib/guard/deprecated/dsl.rb
113
114
  - lib/guard/deprecated/evaluator.rb
@@ -153,6 +154,7 @@ files:
153
154
  - lib/guard/options.rb
154
155
  - lib/guard/plugin.rb
155
156
  - lib/guard/plugin_util.rb
157
+ - lib/guard/plugin_util.rb.orig
156
158
  - lib/guard/rake_task.rb
157
159
  - lib/guard/reevaluator.rb
158
160
  - lib/guard/runner.rb
@@ -160,6 +162,7 @@ files:
160
162
  - lib/guard/templates/Guardfile
161
163
  - lib/guard/terminal.rb
162
164
  - lib/guard/ui.rb
165
+ - lib/guard/ui.rb.orig
163
166
  - lib/guard/ui/colors.rb
164
167
  - lib/guard/version.rb
165
168
  - lib/guard/version.rb.orig