guard 2.7.1 → 2.7.2

Sign up to get free protection for your applications and to get access to all the features.
File without changes
@@ -1,264 +0,0 @@
1
- require "lumberjack"
2
-
3
- require "guard/options"
4
- require "guard/ui/colors"
5
-
6
- module Guard
7
- # The UI class helps to format messages for the user. Everything that is
8
- # logged through this class is considered either as an error message or a
9
- # diagnostic message and is written to standard error ($stderr).
10
- #
11
- # If your Guard plugin does some output that is piped into another process
12
- # for further processing, please just write it to STDOUT with `puts`.
13
- #
14
- module UI
15
- include Colors
16
-
17
- class << self
18
- # Get the Guard::UI logger instance
19
- #
20
- def logger
21
- @logger ||= begin
22
- Lumberjack::Logger.new(
23
- options.fetch(:device) { $stderr },
24
- options)
25
- end
26
- end
27
-
28
- # Since logger is global, for Aruba in-process to properly
29
- # separate output between calls, we need to reset
30
- #
31
- # We don't use logger=() since it's expected to be a Lumberjack instance
32
- def reset_logger
33
- @logger = nil
34
- end
35
-
36
- # Get the logger options
37
- #
38
- # @return [Hash] the logger options
39
- #
40
- def options
41
- @options ||= ::Guard::Options.new(
42
- level: :info,
43
- template: ":time - :severity - :message",
44
- time_format: "%H:%M:%S")
45
- end
46
-
47
- # Set the logger options
48
- #
49
- # @param [Hash] options the logger options
50
- # @option options [Symbol] level the log level
51
- # @option options [String] template the logger template
52
- # @option options [String] time_format the time format
53
- #
54
- def options=(options)
55
- @options = ::Guard::Options.new(options)
56
- end
57
-
58
- # Show an info message.
59
- #
60
- # @param [String] message the message to show
61
- # @option options [Boolean] reset whether to clean the output before
62
- # @option options [String] plugin manually define the calling plugin
63
- #
64
- def info(message, options = {})
65
- _filtered_logger_message(message, :info, nil, options)
66
- end
67
-
68
- # Show a yellow warning message that is prefixed with WARNING.
69
- #
70
- # @param [String] message the message to show
71
- # @option options [Boolean] reset whether to clean the output before
72
- # @option options [String] plugin manually define the calling plugin
73
- #
74
- def warning(message, options = {})
75
- _filtered_logger_message(message, :warn, :yellow, options)
76
- end
77
-
78
- # Show a red error message that is prefixed with ERROR.
79
- #
80
- # @param [String] message the message to show
81
- # @option options [Boolean] reset whether to clean the output before
82
- # @option options [String] plugin manually define the calling plugin
83
- #
84
- def error(message, options = {})
85
- _filtered_logger_message(message, :error, :red, options)
86
- end
87
-
88
- # Show a red deprecation message that is prefixed with DEPRECATION.
89
- # It has a log level of `warn`.
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 deprecation(message, options = {})
96
- msg = "neither ::Guard.setup nor ::Guard.reset_options was called"
97
- fail msg if ::Guard.options.nil?
98
- warning(message, options) if ::Guard.options[:show_deprecations]
99
- end
100
-
101
- # Show a debug message that is prefixed with DEBUG and a timestamp.
102
- #
103
- # @param [String] message the message to show
104
- # @option options [Boolean] reset whether to clean the output before
105
- # @option options [String] plugin manually define the calling plugin
106
- #
107
- def debug(message, options = {})
108
- _filtered_logger_message(message, :debug, :yellow, options)
109
- end
110
-
111
- # Reset a line.
112
- #
113
- def reset_line
114
- $stderr.print(color_enabled? ? "\r\e[0m" : "\r\n")
115
- end
116
-
117
- # Clear the output if clearable.
118
- #
119
- def clear(options = {})
120
- return unless ::Guard.options[:clear] && (@clearable || options[:force])
121
- @clearable = false
122
- ::Guard::Sheller.run("clear;")
123
- end
124
-
125
- # Allow the screen to be cleared again.
126
- #
127
- def clearable
128
- @clearable = true
129
- end
130
-
131
- # Show a scoped action message.
132
- #
133
- # @param [String] action the action to show
134
- # @param [Hash] scope hash with a guard or a group scope
135
- #
136
- def action_with_scopes(action, scope)
137
- first_non_blank_scope = _first_non_blank_scope(scope)
138
- unless first_non_blank_scope.nil?
139
- scope_message = first_non_blank_scope.map(&:title).join(", ")
140
- end
141
-
142
- info "#{ action } #{ scope_message || "all" }"
143
- end
144
-
145
- private
146
-
147
- # Returns the first non-blank scope by searching in the given `scope`
148
- # hash and in Guard.scope. Returns nil if no non-blank scope is found.
149
- #
150
- def _first_non_blank_scope(scope)
151
- [:plugins, :groups].each do |scope_name|
152
- s = scope[scope_name] || ::Guard.scope[scope_name]
153
- return s if !s.nil? && !s.empty?
154
- end
155
-
156
- nil
157
- end
158
-
159
- # Filters log messages depending on either the
160
- # `:only`` or `:except` option.
161
- #
162
- # @param [String] plugin the calling plugin name
163
- # @yield When the message should be logged
164
- # @yieldparam [String] param the calling plugin name
165
- #
166
- def _filter(plugin)
167
- only = options[:only]
168
- except = options[:except]
169
- plugin ||= calling_plugin_name
170
-
171
- match = !(only || except)
172
- match ||= (only && only.match(plugin))
173
- match ||= (except && !except.match(plugin))
174
- return unless match
175
- yield plugin
176
- end
177
-
178
- # Display a message of the type `method` and with the color `color_name`
179
- # (no color by default) conditionnaly given a `plugin_name`.
180
- #
181
- # @param [String] plugin_name the calling plugin name
182
- # @option options [Boolean] reset whether to clean the output before
183
- # @option options [String] plugin manually define the calling plugin
184
- #
185
- def _filtered_logger_message(message, method, color_name, options = {})
186
- message = color(message, color_name) if color_name
187
-
188
- _filter(options[:plugin]) do |plugin|
189
- reset_line if options[:reset]
190
- logger.send(method, message, plugin)
191
- end
192
- end
193
-
194
- # Tries to extract the calling Guard plugin name
195
- # from the call stack.
196
- #
197
- # @param [Integer] depth the stack depth
198
- # @return [String] the Guard plugin name
199
- #
200
- def calling_plugin_name(depth = 2)
201
- name = /(guard\/[a-z_]*)(\/[a-z_]*)?.rb:/i.match(caller[depth])
202
- return "Guard" unless name
203
- name[1].split("/").map do |part|
204
- part.split(/[^a-z0-9]/i).map(&:capitalize).join
205
- end.join("::")
206
- end
207
-
208
- # Checks if color output can be enabled.
209
- #
210
- # @return [Boolean] whether color is enabled or not
211
- #
212
- def color_enabled?
213
- @color_enabled_initialized ||= false
214
- @color_enabled = nil unless @color_enabled_initialized
215
- @color_enabled_initialized = true
216
- if @color_enabled.nil?
217
- if Gem.win_platform?
218
- if ENV["ANSICON"]
219
- @color_enabled = true
220
- else
221
- begin
222
- require "rubygems" unless ENV["NO_RUBYGEMS"]
223
- require "Win32/Console/ANSI"
224
- @color_enabled = true
225
- rescue LoadError
226
- @color_enabled = false
227
- info "Run 'gem install win32console' to use color on Windows"
228
- end
229
- end
230
- else
231
- @color_enabled = true
232
- end
233
- end
234
-
235
- @color_enabled
236
- end
237
-
238
- # Colorizes a text message. See the constant in the UI class for possible
239
- # color_options parameters. You can pass optionally :bright, a foreground
240
- # color and a background color.
241
- #
242
- # @example
243
- #
244
- # color('Hello World', :red, :bright)
245
- #
246
- # @param [String] text the text to colorize
247
- # @param [Array] color_options the color options
248
- #
249
- def color(text, *color_options)
250
- color_code = ""
251
- color_options.each do |color_option|
252
- color_option = color_option.to_s
253
- next if color_option == ""
254
-
255
- unless color_option =~ /\d+/
256
- color_option = const_get("ANSI_ESCAPE_#{ color_option.upcase }")
257
- end
258
- color_code += ";" + color_option
259
- end
260
- color_enabled? ? "\e[0#{ color_code }m#{ text }\e[0m" : text
261
- end
262
- end
263
- end
264
- end
@@ -1,119 +0,0 @@
1
- require "guard/ui"
2
-
3
- module Guard
4
- # The watcher defines a RegExp that will be matched against file system
5
- # modifications.
6
- # When a watcher matches a change, an optional action block is executed to
7
- # enable processing the file system change result.
8
- #
9
- class Watcher
10
- attr_accessor :pattern, :action
11
-
12
- # Initializes a file watcher.
13
- #
14
- # @param [String, Regexp] pattern the pattern to be watched by the Guard
15
- # plugin
16
- # @param [Block] action the action to execute before passing the result to
17
- # the Guard plugin
18
- #
19
- def initialize(pattern, action = nil)
20
- @pattern, @action = pattern, action
21
- @@warning_printed ||= false
22
-
23
- # deprecation warning
24
- regexp = /(^(\^))|(>?(\\\.)|(\.\*))|(\(.*\))|(\[.*\])|(\$$)/
25
- return unless @pattern.is_a?(String) && @pattern =~ regexp
26
-
27
- unless @@warning_printed
28
- ::Guard::UI.info "*" * 20 + "\nDEPRECATION WARNING!\n" + "*" * 20
29
- ::Guard::UI.info <<-MSG
30
- You have a string in your Guardfile watch patterns that seem to
31
- represent a Regexp.
32
-
33
- Guard matches String with == and Regexp with Regexp#match.
34
-
35
- You should either use plain String (without Regexp special
36
- characters) or real Regexp.
37
- MSG
38
- @@warning_printed = true
39
- end
40
-
41
- new_regexp = Regexp.new(@pattern).inspect
42
- ::Guard::UI.info "\"#{@pattern}\" has been converted to #{ new_regexp }\n"
43
- @pattern = Regexp.new(@pattern)
44
- end
45
-
46
- # Finds the files that matches a Guard plugin.
47
- #
48
- # @param [Guard::Plugin] guard the Guard plugin which watchers are used
49
- # @param [Array<String>] files the changed files
50
- # @return [Array<Object>] the matched watcher response
51
- #
52
- def self.match_files(guard, files)
53
- return [] if files.empty?
54
-
55
- files.inject([]) do |paths, file|
56
- guard.watchers.each do |watcher|
57
- matches = watcher.match(file)
58
- next unless matches
59
-
60
- if watcher.action
61
- result = watcher.call_action(matches)
62
- if guard.options[:any_return]
63
- paths << result
64
- elsif result.respond_to?(:empty?) && !result.empty?
65
- paths << Array(result)
66
- else
67
- next
68
- end
69
- else
70
- paths << matches[0]
71
- end
72
-
73
- break if guard.options[:first_match]
74
- end
75
-
76
- guard.options[:any_return] ? paths : paths.flatten.map(&:to_s)
77
- end
78
- end
79
-
80
- # Tests if any of the files is the Guardfile.
81
- #
82
- # @param [Array<String>] files the files to test
83
- # @return [Boolean] whether one of these files is the Guardfile
84
- #
85
- def self.match_guardfile?(files)
86
- path = ::Guard.evaluator.guardfile_path
87
- files.any? { |file| File.expand_path(file) == path }
88
- end
89
-
90
- # Test the watchers pattern against a file.
91
- #
92
- # @param [String] file the file to test
93
- # @return [Array<String>] an array of matches (or containing a single path
94
- # if the pattern is a string)
95
- #
96
- def match(string_or_pathname)
97
- # TODO: use only match() - and show fnmatch example
98
- file = string_or_pathname.to_s
99
- return (file == @pattern ? [file] : nil) unless @pattern.is_a?(Regexp)
100
- return unless (m = @pattern.match(file))
101
- m = m.to_a
102
- m[0] = file
103
- m
104
- end
105
-
106
- # Executes a watcher action.
107
- #
108
- # @param [String, MatchData] matches the matched path or the match from the
109
- # Regex
110
- # @return [String] the final paths
111
- #
112
- def call_action(matches)
113
- @action.arity > 0 ? @action.call(matches) : @action.call
114
- rescue => ex
115
- ::Guard::UI.error "Problem with watch action!\n#{ ex.message }"
116
- ::Guard::UI.error ex.backtrace.join("\n")
117
- end
118
- end
119
- end