joshbuddy-guard 0.10.0

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.
Files changed (70) hide show
  1. data/CHANGELOG.md +370 -0
  2. data/LICENSE +20 -0
  3. data/README.md +470 -0
  4. data/bin/fsevent_watch_guard +0 -0
  5. data/bin/guard +6 -0
  6. data/images/failed.png +0 -0
  7. data/images/pending.png +0 -0
  8. data/images/success.png +0 -0
  9. data/lib/guard.rb +463 -0
  10. data/lib/guard/cli.rb +125 -0
  11. data/lib/guard/dsl.rb +370 -0
  12. data/lib/guard/dsl_describer.rb +150 -0
  13. data/lib/guard/group.rb +37 -0
  14. data/lib/guard/guard.rb +129 -0
  15. data/lib/guard/hook.rb +118 -0
  16. data/lib/guard/interactor.rb +116 -0
  17. data/lib/guard/listener.rb +351 -0
  18. data/lib/guard/listeners/darwin.rb +60 -0
  19. data/lib/guard/listeners/linux.rb +91 -0
  20. data/lib/guard/listeners/polling.rb +55 -0
  21. data/lib/guard/listeners/windows.rb +61 -0
  22. data/lib/guard/notifier.rb +290 -0
  23. data/lib/guard/templates/Guardfile +2 -0
  24. data/lib/guard/ui.rb +193 -0
  25. data/lib/guard/version.rb +6 -0
  26. data/lib/guard/watcher.rb +114 -0
  27. data/lib/vendor/darwin/Gemfile +6 -0
  28. data/lib/vendor/darwin/Guardfile +8 -0
  29. data/lib/vendor/darwin/LICENSE +20 -0
  30. data/lib/vendor/darwin/README.rdoc +254 -0
  31. data/lib/vendor/darwin/Rakefile +21 -0
  32. data/lib/vendor/darwin/ext/extconf.rb +61 -0
  33. data/lib/vendor/darwin/ext/fsevent/fsevent_watch.c +226 -0
  34. data/lib/vendor/darwin/lib/rb-fsevent.rb +2 -0
  35. data/lib/vendor/darwin/lib/rb-fsevent/fsevent.rb +105 -0
  36. data/lib/vendor/darwin/lib/rb-fsevent/version.rb +3 -0
  37. data/lib/vendor/darwin/rb-fsevent.gemspec +24 -0
  38. data/lib/vendor/darwin/spec/fixtures/folder1/file1.txt +0 -0
  39. data/lib/vendor/darwin/spec/fixtures/folder1/folder2/file2.txt +0 -0
  40. data/lib/vendor/darwin/spec/rb-fsevent/fsevent_spec.rb +75 -0
  41. data/lib/vendor/darwin/spec/spec_helper.rb +24 -0
  42. data/lib/vendor/linux/MIT-LICENSE +20 -0
  43. data/lib/vendor/linux/README.md +66 -0
  44. data/lib/vendor/linux/Rakefile +54 -0
  45. data/lib/vendor/linux/VERSION +1 -0
  46. data/lib/vendor/linux/lib/rb-inotify.rb +17 -0
  47. data/lib/vendor/linux/lib/rb-inotify/event.rb +139 -0
  48. data/lib/vendor/linux/lib/rb-inotify/native.rb +31 -0
  49. data/lib/vendor/linux/lib/rb-inotify/native/flags.rb +89 -0
  50. data/lib/vendor/linux/lib/rb-inotify/notifier.rb +308 -0
  51. data/lib/vendor/linux/lib/rb-inotify/watcher.rb +83 -0
  52. data/lib/vendor/linux/rb-inotify.gemspec +53 -0
  53. data/lib/vendor/windows/Gemfile +4 -0
  54. data/lib/vendor/windows/README.md +34 -0
  55. data/lib/vendor/windows/Rakefile +18 -0
  56. data/lib/vendor/windows/lib/rb-fchange.rb +14 -0
  57. data/lib/vendor/windows/lib/rb-fchange/event.rb +29 -0
  58. data/lib/vendor/windows/lib/rb-fchange/native.rb +45 -0
  59. data/lib/vendor/windows/lib/rb-fchange/native/flags.rb +78 -0
  60. data/lib/vendor/windows/lib/rb-fchange/notifier.rb +149 -0
  61. data/lib/vendor/windows/lib/rb-fchange/version.rb +3 -0
  62. data/lib/vendor/windows/lib/rb-fchange/watcher.rb +99 -0
  63. data/lib/vendor/windows/rb-fchange.gemspec +34 -0
  64. data/lib/vendor/windows/spec/fixtures/folder1/file1.txt +0 -0
  65. data/lib/vendor/windows/spec/fixtures/folder1/folder2/file2.txt +0 -0
  66. data/lib/vendor/windows/spec/rb-fchange/fchange_spec.rb +119 -0
  67. data/lib/vendor/windows/spec/spec_helper.rb +21 -0
  68. data/man/guard.1 +96 -0
  69. data/man/guard.1.html +181 -0
  70. metadata +193 -0
@@ -0,0 +1,55 @@
1
+ module Guard
2
+
3
+ # Polling listener that works cross-platform and
4
+ # has no dependencies. This is the listener that
5
+ # uses the most CPU processing power and has higher
6
+ # file IO that the other implementations.
7
+ #
8
+ class Polling < Listener
9
+
10
+ # Initialize the Listener.
11
+ #
12
+ def initialize(*)
13
+ super
14
+ @latency = 1.5
15
+ end
16
+
17
+ # Start the listener.
18
+ #
19
+ def start
20
+ @stop = false
21
+ super
22
+ watch_change
23
+ end
24
+
25
+ # Stop the listener.
26
+ #
27
+ def stop
28
+ super
29
+ @stop = true
30
+ end
31
+
32
+ # Watch the given directory for file changes.
33
+ #
34
+ # @param [String] directory the directory to watch
35
+ #
36
+ def watch(directory)
37
+ @existing = all_files
38
+ end
39
+
40
+ private
41
+
42
+ # Watch for file system changes.
43
+ #
44
+ def watch_change
45
+ until @stop
46
+ start = Time.now.to_f
47
+ files = modified_files([@directory], :all => true)
48
+ @callback.call(files) unless files.empty?
49
+ nap_time = @latency - (Time.now.to_f - start)
50
+ sleep(nap_time) if nap_time > 0
51
+ end
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,61 @@
1
+ module Guard
2
+
3
+ # Listener implementation for Windows `fchange`.
4
+ #
5
+ class Windows < Listener
6
+
7
+ # Initialize the Listener.
8
+ #
9
+ def initialize(*)
10
+ super
11
+ @fchange = FChange::Notifier.new
12
+ end
13
+
14
+ # Start the listener.
15
+ #
16
+ def start
17
+ super
18
+ worker.run
19
+ end
20
+
21
+ # Stop the listener.
22
+ #
23
+ def stop
24
+ super
25
+ worker.stop
26
+ end
27
+
28
+ # Check if the listener is usable on the current OS.
29
+ #
30
+ # @return [Boolean] whether usable or not
31
+ #
32
+ def self.usable?(no_vendor = false)
33
+ $LOAD_PATH << File.expand_path('../../../vendor/windows/lib', __FILE__) unless no_vendor
34
+ require 'rb-fchange'
35
+ true
36
+ rescue LoadError
37
+ false
38
+ end
39
+
40
+ private
41
+
42
+ # Watch the given directory for file changes.
43
+ #
44
+ # @param [String] directory the directory to watch
45
+ #
46
+ def watch(directory)
47
+ worker.watch(directory, :all_events, :recursive) do |event|
48
+ paths = [File.expand_path(event.watcher.path)]
49
+ files = modified_files(paths, :all => true)
50
+ @callback.call(files) unless files.empty?
51
+ end
52
+ end
53
+
54
+ # Get the listener worker.
55
+ #
56
+ def worker
57
+ @fchange
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,290 @@
1
+ require 'rbconfig'
2
+ require 'pathname'
3
+ require 'guard/ui'
4
+
5
+ module Guard
6
+
7
+ # The notifier class handles cross-platform system notifications that supports:
8
+ #
9
+ # - Growl on Mac OS X
10
+ # - Libnotify on Linux
11
+ # - Notifu on Windows
12
+ #
13
+ module Notifier
14
+
15
+ # Application name as shown in the specific notification settings
16
+ APPLICATION_NAME = "Guard"
17
+
18
+ class << self
19
+
20
+ attr_accessor :growl_library, :gntp
21
+
22
+ # Turn notifications off.
23
+ #
24
+ def turn_off
25
+ ENV["GUARD_NOTIFY"] = 'false'
26
+ end
27
+
28
+ # Turn notifications on. This tries to load the platform
29
+ # specific notification library.
30
+ #
31
+ # @return [Boolean] whether the notification could be enabled.
32
+ #
33
+ def turn_on
34
+ ENV["GUARD_NOTIFY"] = 'true'
35
+ case RbConfig::CONFIG['target_os']
36
+ when /darwin/i
37
+ require_growl
38
+ when /linux/i
39
+ require_libnotify
40
+ when /mswin|mingw/i
41
+ require_rbnotifu
42
+ end
43
+ end
44
+
45
+ # Show a message with the system notification.
46
+ #
47
+ # @see .image_path
48
+ #
49
+ # @param [String] the message to show
50
+ # @option options [Symbol, String] image the image symbol or path to an image
51
+ # @option options [String] title the notification title
52
+ #
53
+ def notify(message, options = { })
54
+ if enabled?
55
+ image = options.delete(:image) || :success
56
+ title = options.delete(:title) || "Guard"
57
+
58
+ case RbConfig::CONFIG['target_os']
59
+ when /darwin/i
60
+ notify_mac(title, message, image, options)
61
+ when /linux/i
62
+ notify_linux(title, message, image, options)
63
+ when /mswin|mingw/i
64
+ notify_windows(title, message, image, options)
65
+ end
66
+ end
67
+ end
68
+
69
+ # Test if the notifications are enabled and available.
70
+ #
71
+ # @return [Boolean] whether the notifications are available
72
+ #
73
+ def enabled?
74
+ ENV["GUARD_NOTIFY"] == 'true'
75
+ end
76
+
77
+ private
78
+
79
+ # Send a message to Growl either with the `growl` gem or the `growl_notify` gem.
80
+ #
81
+ # @param [String] title the notification title
82
+ # @param [String] message the message to show
83
+ # @param [Symbol, String] the image to user
84
+ # @param [Hash] options the growl options
85
+ #
86
+ def notify_mac(title, message, image, options = { })
87
+ require_growl # need for guard-rspec formatter that is called out of guard scope
88
+
89
+ notification = { :title => title, :icon => image_path(image) }.merge(options)
90
+
91
+ case self.growl_library
92
+ when :growl_notify
93
+ notification.delete(:name)
94
+
95
+ GrowlNotify.send_notification({
96
+ :description => message,
97
+ :application_name => APPLICATION_NAME
98
+ }.merge(notification))
99
+
100
+ when :ruby_gntp
101
+ icon = "file://#{ notification.delete(:icon) }"
102
+
103
+ self.gntp.notify({
104
+ :name => [:pending, :success, :failed].include?(image) ? image.to_s : 'notify',
105
+ :text => message,
106
+ :icon => icon
107
+ }.merge(notification))
108
+
109
+ when :growl
110
+ Growl.notify(message, {
111
+ :name => APPLICATION_NAME
112
+ }.merge(notification))
113
+ end
114
+ end
115
+
116
+ # Send a message to libnotify.
117
+ #
118
+ # @param [String] title the notification title
119
+ # @param [String] message the message to show
120
+ # @param [Symbol, String] the image to user
121
+ # @param [Hash] options the libnotify options
122
+ #
123
+ def notify_linux(title, message, image, options = { })
124
+ require_libnotify # need for guard-rspec formatter that is called out of guard scope
125
+
126
+ notification = { :body => message, :summary => title, :icon_path => image_path(image), :transient => true }
127
+ Libnotify.show notification.merge(options)
128
+ end
129
+
130
+ # Send a message to notifu.
131
+ #
132
+ # @param [String] title the notification title
133
+ # @param [String] message the message to show
134
+ # @param [Symbol, String] the image to user
135
+ # @param [Hash] options the notifu options
136
+ #
137
+ def notify_windows(title, message, image, options = { })
138
+ require_rbnotifu # need for guard-rspec formatter that is called out of guard scope
139
+
140
+ notification = { :message => message, :title => title, :type => image_level(image), :time => 3 }
141
+ Notifu.show notification.merge(options)
142
+ end
143
+
144
+ # Get the image path for an image symbol.
145
+ #
146
+ # Known symbols are:
147
+ #
148
+ # - failed
149
+ # - pending
150
+ # - success
151
+ #
152
+ # @param [Symbol] image the image name
153
+ # @return [String] the image path
154
+ #
155
+ def image_path(image)
156
+ images_path = Pathname.new(File.dirname(__FILE__)).join('../../images')
157
+ case image
158
+ when :failed
159
+ images_path.join("failed.png").to_s
160
+ when :pending
161
+ images_path.join("pending.png").to_s
162
+ when :success
163
+ images_path.join("success.png").to_s
164
+ else
165
+ # path given
166
+ image
167
+ end
168
+ end
169
+
170
+ # The notification level type for the given image.
171
+ #
172
+ # @param [Symbol] image the image
173
+ # @return [Symbol] the level
174
+ #
175
+ def image_level(image)
176
+ case image
177
+ when :failed
178
+ :error
179
+ when :pending
180
+ :warn
181
+ when :success
182
+ :info
183
+ else
184
+ :info
185
+ end
186
+ end
187
+
188
+ # Try to safely load growl and turns notifications off on load failure.
189
+ # The Guard notifier knows three different library to handle sending
190
+ # Growl messages and tries to loading them in the given order:
191
+ #
192
+ # - [Growl Notify](https://github.com/scottdavis/growl_notify)
193
+ # - [Ruby GNTP](https://github.com/snaka/ruby_gntp)
194
+ # - [Growl](https://github.com/visionmedia/growl)
195
+ #
196
+ # On successful loading of any of the libraries, the active library name is
197
+ # accessible through `.growl_library`.
198
+ #
199
+ def require_growl
200
+ self.growl_library = try_growl_notify || try_ruby_gntp || try_growl
201
+
202
+ unless self.growl_library
203
+ turn_off
204
+ UI.info "Please install growl_notify or growl gem for Mac OS X notification support and add it to your Gemfile"
205
+ end
206
+ end
207
+
208
+ # Try to load the `growl_notify` gem.
209
+ #
210
+ # @return [Symbol, nil] A symbol with the name of the loaded library
211
+ #
212
+ def try_growl_notify
213
+ require 'growl_notify'
214
+
215
+ begin
216
+ if GrowlNotify.application_name != APPLICATION_NAME
217
+ GrowlNotify.config do |c|
218
+ c.notifications = c.default_notifications = [APPLICATION_NAME]
219
+ c.application_name = c.notifications.first
220
+ end
221
+ end
222
+
223
+ rescue ::GrowlNotify::GrowlNotFound
224
+ turn_off
225
+ UI.info "Please install Growl from http://growl.info"
226
+ end
227
+
228
+ :growl_notify
229
+
230
+ rescue LoadError
231
+ end
232
+
233
+ # Try to load the `ruby_gntp` gem and register the available
234
+ # notification channels.
235
+ #
236
+ # @return [Symbol, nil] A symbol with the name of the loaded library
237
+ #
238
+ def try_ruby_gntp
239
+ require 'ruby_gntp'
240
+
241
+ self.gntp = GNTP.new(APPLICATION_NAME)
242
+ self.gntp.register(:notifications => [
243
+ { :name => 'notify', :enabled => true },
244
+ { :name => 'failed', :enabled => true },
245
+ { :name => 'pending', :enabled => true },
246
+ { :name => 'success', :enabled => true }
247
+ ])
248
+
249
+ :ruby_gntp
250
+
251
+ rescue LoadError
252
+ end
253
+
254
+ # Try to load the `growl_notify` gem.
255
+ #
256
+ # @return [Symbol, nil] A symbol with the name of the loaded library
257
+ #
258
+ def try_growl
259
+ require 'growl'
260
+
261
+ :growl
262
+
263
+ rescue LoadError
264
+ end
265
+
266
+ # Try to safely load libnotify and turns notifications
267
+ # off on load failure.
268
+ #
269
+ def require_libnotify
270
+ require 'libnotify'
271
+
272
+ rescue LoadError
273
+ turn_off
274
+ UI.info "Please install libnotify gem for Linux notification support and add it to your Gemfile"
275
+ end
276
+
277
+ # Try to safely load rb-notifu and turns notifications
278
+ # off on load failure.
279
+ #
280
+ def require_rbnotifu
281
+ require 'rb-notifu'
282
+
283
+ rescue LoadError
284
+ turn_off
285
+ UI.info "Please install rb-notifu gem for Windows notification support and add it to your Gemfile"
286
+ end
287
+
288
+ end
289
+ end
290
+ end
@@ -0,0 +1,2 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
@@ -0,0 +1,193 @@
1
+ module Guard
2
+
3
+ # The UI class helps to format messages for the user. Everything that is logged
4
+ # through this class is considered either as an error message or a diagnostic
5
+ # message and is written to standard error (STDERR).
6
+ #
7
+ # If your Guard does some output that is piped into another process for further
8
+ # processing, please just write it to STDOUT with `puts`.
9
+ #
10
+ module UI
11
+ class << self
12
+
13
+ color_enabled = nil
14
+
15
+ # Show an info message.
16
+ #
17
+ # @param [String] message the message to show
18
+ # @option options [Boolean] reset whether to clean the output before
19
+ #
20
+ def info(message, options = { })
21
+ unless ENV['GUARD_ENV'] == 'test'
22
+ reset_line if options[:reset]
23
+ STDERR.puts color(message) if message != ''
24
+ end
25
+ end
26
+
27
+ # Show a red error message that is prefixed with ERROR.
28
+ #
29
+ # @param [String] message the message to show
30
+ # @option options [Boolean] reset whether to clean the output before
31
+ #
32
+ def error(message, options = { })
33
+ unless ENV['GUARD_ENV'] == 'test'
34
+ reset_line if options[:reset]
35
+ STDERR.puts color('ERROR: ', :red) + message
36
+ end
37
+ end
38
+
39
+ # Show a red deprecation message that is prefixed with DEPRECATION.
40
+ #
41
+ # @param [String] message the message to show
42
+ # @option options [Boolean] reset whether to clean the output before
43
+ #
44
+ def deprecation(message, options = { })
45
+ unless ENV['GUARD_ENV'] == 'test'
46
+ reset_line if options[:reset]
47
+ STDERR.puts color('DEPRECATION: ', :red) + message
48
+ end
49
+ end
50
+
51
+ # Show a debug message that is prefixed with DEBUG and a timestamp.
52
+ #
53
+ # @param [String] message the message to show
54
+ # @option options [Boolean] reset whether to clean the output before
55
+ #
56
+ def debug(message, options = { })
57
+ unless ENV['GUARD_ENV'] == 'test'
58
+ reset_line if options[:reset]
59
+ STDERR.puts color("DEBUG (#{Time.now.strftime('%T')}): ", :yellow) + message if ::Guard.options && ::Guard.options[:debug]
60
+ end
61
+ end
62
+
63
+ # Reset a line.
64
+ #
65
+ def reset_line
66
+ STDERR.print(color_enabled? ? "\r\e[0m" : "\r\n")
67
+ end
68
+
69
+ # Clear the output.
70
+ #
71
+ def clear
72
+ system('clear;')
73
+ end
74
+
75
+ private
76
+
77
+ # Reset a color sequence.
78
+ #
79
+ # @deprecated
80
+ # @param [String] text the text
81
+ #
82
+ def reset_color(text)
83
+ deprecation('UI.reset_color(text) is deprecated, please use color(text, ' ') instead.')
84
+ color(text, '')
85
+ end
86
+
87
+ # Checks if color output can be enabled.
88
+ #
89
+ # @return [Boolean] whether color is enabled or not
90
+ #
91
+ def color_enabled?
92
+ if @color_enabled.nil?
93
+ if RbConfig::CONFIG['target_os'] =~ /mswin|mingw/i
94
+ if ENV['ANSICON']
95
+ @color_enabled = true
96
+ else
97
+ begin
98
+ require 'rubygems' unless ENV['NO_RUBYGEMS']
99
+ require 'Win32/Console/ANSI'
100
+ @color_enabled = true
101
+ rescue LoadError
102
+ @color_enabled = false
103
+ info "You must 'gem install win32console' to use color on Windows"
104
+ end
105
+ end
106
+ else
107
+ @color_enabled = true
108
+ end
109
+ end
110
+
111
+ @color_enabled
112
+ end
113
+
114
+ # Colorizes a text message. See the constant in the UI class for possible
115
+ # color_options parameters. You can pass optionally :bright, a foreground
116
+ # color and a background color.
117
+ #
118
+ # @example
119
+ #
120
+ # color('Hello World', :red, :bright)
121
+ #
122
+ # @param [String] the text to colorize
123
+ # @param [Array] color_options the color options
124
+ #
125
+ def color(text, *color_options)
126
+ color_code = ''
127
+ color_options.each do |color_option|
128
+ color_option = color_option.to_s
129
+ if color_option != ''
130
+ if !(color_option =~ /\d+/)
131
+ color_option = const_get("ANSI_ESCAPE_#{ color_option.upcase }")
132
+ end
133
+ color_code += ';' + color_option
134
+ end
135
+ end
136
+ color_enabled? ? "\e[0#{ color_code }m#{ text }\e[0m" : text
137
+ end
138
+
139
+ end
140
+
141
+ # Brighten the color
142
+ ANSI_ESCAPE_BRIGHT = '1'
143
+
144
+ # Black foreground color
145
+ ANSI_ESCAPE_BLACK = '30'
146
+
147
+ # Red foreground color
148
+ ANSI_ESCAPE_RED = '31'
149
+
150
+ # Green foreground color
151
+ ANSI_ESCAPE_GREEN = '32'
152
+
153
+ # Yellow foreground color
154
+ ANSI_ESCAPE_YELLOW = '33'
155
+
156
+ # Blue foreground color
157
+ ANSI_ESCAPE_BLUE = '34'
158
+
159
+ # Magenta foreground color
160
+ ANSI_ESCAPE_MAGENTA = '35'
161
+
162
+ # Cyan foreground color
163
+ ANSI_ESCAPE_CYAN = '36'
164
+
165
+ # White foreground color
166
+ ANSI_ESCAPE_WHITE = '37'
167
+
168
+ # Black background color
169
+ ANSI_ESCAPE_BGBLACK = '40'
170
+
171
+ # Red background color
172
+ ANSI_ESCAPE_BGRED = '41'
173
+
174
+ # Green background color
175
+ ANSI_ESCAPE_BGGREEN = '42'
176
+
177
+ # Yellow background color
178
+ ANSI_ESCAPE_BGYELLOW = '43'
179
+
180
+ # Blue background color
181
+ ANSI_ESCAPE_BGBLUE = '44'
182
+
183
+ # Magenta background color
184
+ ANSI_ESCAPE_BGMAGENTA = '45'
185
+
186
+ # Cyan background color
187
+ ANSI_ESCAPE_BGCYAN = '46'
188
+
189
+ # White background color
190
+ ANSI_ESCAPE_BGWHITE = '47'
191
+
192
+ end
193
+ end