guard 2.8.1 → 2.8.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: eba722e0d98149098d042a096e5df4dc7abd495b
4
- data.tar.gz: 76421bb7bdc9c176c22ba3207460104d37090439
3
+ metadata.gz: 5623a43a66b46a5d8137215f562d99c05a3235a4
4
+ data.tar.gz: 5d49353627874560143c223d57e2d426bc8f8639
5
5
  SHA512:
6
- metadata.gz: c4f95478bc1293ff711721d8d8ed42b6a81b15daf2d17a3dcffa4f72dca1e6bbdfdbdf881e5f6993b3c5955bf08a5b8d608f3985650ad39248dfd2bf28e59b2c
7
- data.tar.gz: 7a8cdcd97b6619ddc3c9ecf219229710107bf5fb58ebccbd457888711af57053f424998a82d5ffe92de72f3c40658535edd396890c64a948ef09390ed785f833
6
+ metadata.gz: 9364e851605d579463afe517ccbc56c6bde7c7b0353a5a6199f93520e23fc55ac029a923ef679af561510b4c38ddf3c947bd7d8bd2330aaf273f35573065a05a
7
+ data.tar.gz: c01ce4150b9fd551263893f9ce80e768a1694afc182ded540089781041dce167f9452819768f9f621f54969a9e62d3d7710a491321663eaed2d1ab8eb01a4421
@@ -28,7 +28,15 @@ module Guard
28
28
  watched = ::Guard.watchdirs.join("', '")
29
29
  ::Guard::UI.info "Guard is now watching at '#{ watched }'"
30
30
 
31
- _interactor_loop
31
+ # TODO: remove (left to avoid breaking too many specs)
32
+ begin
33
+ while interactor.foreground != :exit
34
+ _process_queue while pending_changes?
35
+ end
36
+ rescue Interrupt
37
+ end
38
+
39
+ stop
32
40
  end
33
41
 
34
42
  # TODO: refactor (left to avoid breaking too many specs)
@@ -84,16 +92,5 @@ module Guard
84
92
  def show
85
93
  ::Guard::DslDescriber.new(::Guard.options).show
86
94
  end
87
-
88
- private
89
-
90
- # TODO: remove (left to avoid breaking too many specs)
91
- def _interactor_loop
92
- while interactor.foreground != :exit
93
- _process_queue while pending_changes?
94
- end
95
- rescue Interrupt
96
- stop
97
- end
98
95
  end
99
96
  end
File without changes
@@ -0,0 +1,222 @@
1
+ require "yaml"
2
+ require "rbconfig"
3
+ require "pathname"
4
+
5
+ require "guard/ui"
6
+ require "guard/notifiers/emacs"
7
+ require "guard/notifiers/file_notifier"
8
+ require "guard/notifiers/gntp"
9
+ require "guard/notifiers/growl"
10
+ require "guard/notifiers/libnotify"
11
+ require "guard/notifiers/notifysend"
12
+ require "guard/notifiers/rb_notifu"
13
+ require "guard/notifiers/terminal_notifier"
14
+ require "guard/notifiers/terminal_title"
15
+ require "guard/notifiers/tmux"
16
+
17
+ module Guard
18
+ # The notifier handles sending messages to different notifiers. Currently the
19
+ # following
20
+ # libraries are supported:
21
+ #
22
+ # * Ruby GNTP
23
+ # * Growl
24
+ # * Libnotify
25
+ # * rb-notifu
26
+ # * emacs
27
+ # * Terminal Notifier
28
+ # * Terminal Title
29
+ # * Tmux
30
+ #
31
+ # Please see the documentation of each notifier for more information about
32
+ # the requirements
33
+ # and configuration possibilities.
34
+ #
35
+ # Guard knows four different notification types:
36
+ #
37
+ # * success
38
+ # * pending
39
+ # * failed
40
+ # * notify
41
+ #
42
+ # The notification type selection is based on the image option that is
43
+ # sent to {#notify}. Each image type has its own notification type, and
44
+ # notifications with custom images goes all sent as type `notify`. The
45
+ # `gntp` notifier is able to register these types
46
+ # at Growl and allows customization of each notification type.
47
+ #
48
+ # Guard can be configured to make use of more than one notifier at once.
49
+ #
50
+ # @see Guard::Dsl
51
+ #
52
+ module Notifier
53
+ extend self
54
+
55
+ # List of available notifiers, grouped by functionality
56
+ NOTIFIERS = [
57
+ {
58
+ gntp: GNTP,
59
+ growl: Growl,
60
+ terminal_notifier: TerminalNotifier,
61
+ libnotify: Libnotify,
62
+ notifysend: NotifySend,
63
+ notifu: Notifu
64
+ },
65
+ { emacs: Emacs },
66
+ { tmux: Tmux },
67
+ { terminal_title: TerminalTitle },
68
+ { file: FileNotifier }
69
+ ]
70
+
71
+ def notifiers
72
+ ENV["GUARD_NOTIFIERS"] ? YAML::load(ENV["GUARD_NOTIFIERS"]) : []
73
+ end
74
+
75
+ def notifiers=(notifiers)
76
+ ENV["GUARD_NOTIFIERS"] = YAML::dump(notifiers)
77
+ end
78
+
79
+ # Clear available notifications.
80
+ #
81
+ def clear_notifiers
82
+ ENV["GUARD_NOTIFIERS"] = nil
83
+ end
84
+
85
+ # Turn notifications on. If no notifications are defined in the `Guardfile`
86
+ # Guard auto detects the first available library.
87
+ #
88
+ # @param [Hash] options the turn_on options
89
+ # @option options [Boolean] silent disable any logging
90
+ #
91
+ def turn_on(opts = {})
92
+ if notifiers.empty? && (::Guard.options || {})[:notify]
93
+ _auto_detect_notification
94
+ end
95
+
96
+ if notifiers.empty?
97
+ turn_off
98
+ else
99
+ notifiers.each do |notifier|
100
+ notifier_class = _get_notifier_module(notifier[:name])
101
+ unless opts[:silent]
102
+ ::Guard::UI.info \
103
+ "Guard is using #{ notifier_class.title } to send notifications."
104
+ end
105
+
106
+ notifier_class.turn_on if notifier_class.respond_to?(:turn_on)
107
+ end
108
+
109
+ ENV["GUARD_NOTIFY"] = "true"
110
+ end
111
+ end
112
+
113
+ # Turn notifications off.
114
+ #
115
+ def turn_off
116
+ notifiers.each do |notifier|
117
+ notifier_class = _get_notifier_module(notifier[:name])
118
+
119
+ notifier_class.turn_off if notifier_class.respond_to?(:turn_off)
120
+ end
121
+
122
+ ENV["GUARD_NOTIFY"] = "false"
123
+ end
124
+
125
+ # Toggle the system notifications on/off
126
+ #
127
+ def toggle
128
+ if enabled?
129
+ ::Guard::UI.info "Turn off notifications"
130
+ turn_off
131
+ else
132
+ turn_on
133
+ end
134
+ end
135
+
136
+ # Test if the notifications are on.
137
+ #
138
+ # @return [Boolean] whether the notifications are on
139
+ #
140
+ def enabled?
141
+ ENV["GUARD_NOTIFY"] == "true"
142
+ end
143
+
144
+ # Add a notification library to be used.
145
+ #
146
+ # @param [Symbol] name the name of the notifier to use
147
+ # @param [Hash] options the notifier options
148
+ # @option options [String] silent disable any error message
149
+ # @return [Boolean] if the notification could be added
150
+ #
151
+ def add_notifier(name, opts = {})
152
+ return turn_off if name == :off
153
+
154
+ notifier_class = _get_notifier_module(name)
155
+
156
+ if notifier_class && notifier_class.available?(opts)
157
+ self.notifiers = notifiers << { name: name, options: opts }
158
+ true
159
+ else
160
+ false
161
+ end
162
+ end
163
+
164
+ # Show a system notification with all configured notifiers.
165
+ #
166
+ # @param [String] message the message to show
167
+ # @option opts [Symbol, String] image the image symbol or path to an image
168
+ # @option opts [String] title the notification title
169
+ #
170
+ def notify(message, opts = {})
171
+ return unless enabled?
172
+
173
+ notifiers.each do |notifier|
174
+ notifier = _get_notifier_module(notifier[:name]).new(notifier[:options])
175
+
176
+ begin
177
+ notifier.notify(message, opts.dup)
178
+ rescue RuntimeError => e
179
+ ::Guard::UI.error \
180
+ "Error sending notification with #{ notifier.name }: #{ e.message }"
181
+
182
+ ::Guard::UI.debug e.backtrace.join("\n")
183
+ end
184
+ end
185
+ end
186
+
187
+ private
188
+
189
+ # Get the notifier module for the given name.
190
+ #
191
+ # @param [Symbol] name the notifier name
192
+ # @return [Module] the notifier module
193
+ #
194
+ def _get_notifier_module(name)
195
+ NOTIFIERS.each do |group|
196
+ next unless (notifier = group.detect { |n, _| n == name })
197
+ return notifier.last
198
+ end
199
+ nil
200
+ end
201
+
202
+ # Auto detect the available notification library. This goes through
203
+ # the list of supported notification gems and picks the first that
204
+ # is available in each notification group.
205
+ #
206
+ def _auto_detect_notification
207
+ self.notifiers = []
208
+ available = nil
209
+
210
+ NOTIFIERS.each do |group|
211
+ notifier_added = group.detect do |name, _|
212
+ add_notifier(name, silent: true)
213
+ end
214
+ available ||= notifier_added
215
+ end
216
+
217
+ return if available
218
+ ::Guard::UI.info \
219
+ "Guard could not detect any of the supported notification libraries."
220
+ end
221
+ end
222
+ end
@@ -0,0 +1,339 @@
1
+ require "guard/notifiers/base"
2
+
3
+ module Guard
4
+ module Notifier
5
+ # Changes the color of the Tmux status bar and optionally
6
+ # shows messages in the status bar.
7
+ #
8
+ # @example Add the `:tmux` notifier to your `Guardfile`
9
+ # notification :tmux
10
+ #
11
+ # @example Enable text messages
12
+ # notification :tmux, display_message: true
13
+ #
14
+ # @example Customize the tmux status colored for notifications
15
+ # notification :tmux, color_location: 'status-right-bg'
16
+ #
17
+ class Tmux < Base
18
+ # Default options for the tmux notifications.
19
+ DEFAULTS = {
20
+ client: "tmux",
21
+ tmux_environment: "TMUX",
22
+ success: "green",
23
+ failed: "red",
24
+ pending: "yellow",
25
+ default: "green",
26
+ timeout: 5,
27
+ display_message: false,
28
+ default_message_format: "%s - %s",
29
+ default_message_color: "white",
30
+ display_on_all_clients: false,
31
+ display_title: false,
32
+ default_title_format: "%s - %s",
33
+ line_separator: " - ",
34
+ change_color: true,
35
+ color_location: "status-left-bg"
36
+ }
37
+
38
+ ERROR_NOT_INSIDE_SESSION = "The :tmux notifier runs only on when Guard"\
39
+ " is executed inside of a tmux session."
40
+
41
+ def self.available?(opts = {})
42
+ super && _register!(opts)
43
+ end
44
+
45
+ # @private
46
+ #
47
+ # @return [Boolean] whether or not a TMUX environment is available
48
+ #
49
+ def self._tmux_environment_available?(opts)
50
+ !ENV[opts.fetch(:tmux_environment, DEFAULTS[:tmux_environment])].nil?
51
+ end
52
+
53
+ # @private
54
+ #
55
+ # Detects if a TMUX environment is available and if not,
56
+ # displays an error message unless `opts[:silent]` is true.
57
+ #
58
+ # @return [Boolean] whether or not a TMUX environment is available
59
+ #
60
+ def self._register!(opts)
61
+ @options_stored = false
62
+ if _tmux_environment_available?(opts)
63
+ true
64
+ else
65
+ unless opts[:silent]
66
+ ::Guard::UI.error ERROR_NOT_INSIDE_SESSION
67
+ end
68
+ false
69
+ end
70
+ end
71
+
72
+ # Shows a system notification.
73
+ #
74
+ # By default, the Tmux notifier only makes
75
+ # use of a color based notification, changing the background color of the
76
+ # `color_location` to the color defined in either the `success`,
77
+ # `failed`, `pending` or `default`, depending on the notification type.
78
+ #
79
+ # You may enable an extra explicit message by setting `display_message`
80
+ # to true, and may further disable the colorization by setting
81
+ # `change_color` to false.
82
+ #
83
+ # @param [String] title the notification title
84
+ # @param [Hash] opts additional notification library options
85
+ # @option opts [String] type the notification type. Either 'success',
86
+ # 'pending', 'failed' or 'notify'
87
+ # @option opts [String] message the notification message body
88
+ # @option opts [String] image the path to the notification image
89
+ # @option opts [Boolean] change_color whether to show a color
90
+ # notification
91
+ # @option opts [String,Array] color_location the location where to draw
92
+ # the color notification
93
+ # @option opts [Boolean] display_message whether to display a message
94
+ # or not
95
+ # @option opts [Boolean] display_on_all_clients whether to display a
96
+ # message on all tmux clients or not
97
+ #
98
+ def notify(message, opts = {})
99
+ super
100
+ opts.delete(:image)
101
+
102
+ if opts.fetch(:change_color, DEFAULTS[:change_color])
103
+ options = opts.fetch(:color_location, DEFAULTS[:color_location])
104
+ color_locations = Array(options)
105
+ color = tmux_color(opts[:type], opts)
106
+
107
+ color_locations.each do |color_location|
108
+ _run_client "set", "#{self.class._quiet_option}"\
109
+ "#{color_location} #{color}"
110
+ end
111
+ end
112
+
113
+ type = opts.delete(:type).to_s
114
+ title = opts.delete(:title)
115
+
116
+ if opts.fetch(:display_title, DEFAULTS[:display_title])
117
+ display_title(type, title, message, opts)
118
+ end
119
+
120
+ return unless opts.fetch(:display_message, DEFAULTS[:display_message])
121
+ display_message(type, title, message, opts)
122
+ end
123
+
124
+ # Displays a message in the title bar of the terminal.
125
+ #
126
+ # @param [String] title the notification title
127
+ # @param [String] message the notification message body
128
+ # @param [Hash] options additional notification library options
129
+ # @option options [String] success_message_format a string to use as
130
+ # formatter for the success message.
131
+ # @option options [String] failed_message_format a string to use as
132
+ # formatter for the failed message.
133
+ # @option options [String] pending_message_format a string to use as
134
+ # formatter for the pending message.
135
+ # @option options [String] default_message_format a string to use as
136
+ # formatter when no format per type is defined.
137
+ #
138
+ def display_title(type, title, message, opts = {})
139
+ format = "#{type}_title_format".to_sym
140
+ defaults = DEFAULTS[:default_title_format]
141
+ options = opts.fetch(:default_title_format, defaults)
142
+ title_format = opts.fetch(format, options)
143
+ teaser_message = message.split("\n").first
144
+ display_title = title_format % [title, teaser_message]
145
+
146
+ _run_client "set-option", "#{self.class._quiet_option}"\
147
+ "set-titles-string '#{display_title}'"
148
+ end
149
+
150
+ # Displays a message in the status bar of tmux.
151
+ #
152
+ # @param [String] type the notification type. Either 'success',
153
+ # 'pending', 'failed' or 'notify'
154
+ # @param [String] title the notification title
155
+ # @param [String] message the notification message body
156
+ # @param [Hash] options additional notification library options
157
+ # @option options [Integer] timeout the amount of seconds to show the
158
+ # message in the status bar
159
+ # @option options [String] success_message_format a string to use as
160
+ # formatter for the success message.
161
+ # @option options [String] failed_message_format a string to use as
162
+ # formatter for the failed message.
163
+ # @option options [String] pending_message_format a string to use as
164
+ # formatter for the pending message.
165
+ # @option options [String] default_message_format a string to use as
166
+ # formatter when no format per type is defined.
167
+ # @option options [String] success_message_color the success notification
168
+ # foreground color name.
169
+ # @option options [String] failed_message_color the failed notification
170
+ # foreground color name.
171
+ # @option options [String] pending_message_color the pending notification
172
+ # foreground color name.
173
+ # @option options [String] default_message_color a notification
174
+ # foreground color to use when no color per type is defined.
175
+ # @option options [String] line_separator a string to use instead of a
176
+ # line-break.
177
+ #
178
+ def display_message(type, title, message, opts = {})
179
+ default_format = DEFAULTS[:default_message_format]
180
+ default_format = opts.fetch(:default_message_format, default_format)
181
+ format = "#{type}_message_format".to_sym
182
+ message_format = opts.fetch(format, default_format)
183
+
184
+ default_color = DEFAULTS[:default_message_color]
185
+ default_color = opts.fetch(:default_message_color, default_color)
186
+ color = "#{type}_message_color".to_sym
187
+ message_color = opts.fetch(color, default_color)
188
+
189
+ display_time = opts.fetch(:timeout, DEFAULTS[:timeout])
190
+ separator = opts.fetch(:line_separator, DEFAULTS[:line_separator])
191
+
192
+ color = tmux_color type, opts
193
+ formatted_message = message.split("\n").join(separator)
194
+ display_message = message_format % [title, formatted_message]
195
+
196
+ _run_client(
197
+ "set",
198
+ "#{self.class._quiet_option}display-time #{display_time * 1000}")
199
+
200
+ _run_client "set", "#{self.class._quiet_option}"\
201
+ "message-fg #{message_color}"
202
+ _run_client "set", "#{self.class._quiet_option}"\
203
+ "message-bg #{color}"
204
+ _run_client "display-message", "'#{display_message}'"
205
+ end
206
+
207
+ # Get the Tmux color for the notification type.
208
+ # You can configure your own color by overwriting the defaults.
209
+ #
210
+ # @param [String] type the notification type
211
+ # @return [String] the name of the emacs color
212
+ #
213
+ def tmux_color(type, opts = {})
214
+ type = type.to_sym
215
+
216
+ opts[type] || DEFAULTS[type] || opts[:default] || DEFAULTS[:default]
217
+ end
218
+
219
+ # Notification starting, save the current Tmux settings
220
+ # and quiet the Tmux output.
221
+ #
222
+ def self.turn_on
223
+ unless @options_stored
224
+ _reset_options_store
225
+
226
+ _clients.each do |client|
227
+ @options_store[client].merge!(_options_for_client(client))
228
+ end
229
+
230
+ @options_stored = true
231
+ end
232
+ end
233
+
234
+ # Notification stopping. Restore the previous Tmux state
235
+ # if available (existing options are restored, new options
236
+ # are unset) and unquiet the Tmux output.
237
+ #
238
+ def self.turn_off
239
+ if @options_stored
240
+ @options_store.each do |client, options|
241
+ options.each do |key, value|
242
+ args = [
243
+ DEFAULTS[:client], "set", "-t",
244
+ client, _quiet_option.strip
245
+ ]
246
+ args << "-u" unless value
247
+ args << key
248
+ args << value if value
249
+ Sheller.run(args.join(" "))
250
+ end
251
+ end
252
+ _reset_options_store
253
+ end
254
+ end
255
+
256
+ def self.options_store
257
+ @options_store ||= {}
258
+ end
259
+
260
+ private
261
+
262
+ def self._clients
263
+ args = [DEFAULTS[:client], "list-clients", "-F", "'\#{client_tty}'"]
264
+ ttys = Sheller.stdout(args.join(" "))
265
+ ttys = ttys.split(/\n/)
266
+
267
+ # if user is running 'tmux -C' remove this client from list
268
+ ttys.delete("(null)")
269
+
270
+ ttys
271
+ end
272
+
273
+ def self._options_for_client(client)
274
+ options = {}
275
+
276
+ lines = Sheller.stdout("#{DEFAULTS[:client]} show -t #{client}")
277
+
278
+ lines.each_line do |line|
279
+ option, _, setting = line.chomp.partition(" ")
280
+ options[option] = setting
281
+ end
282
+
283
+ options
284
+ end
285
+
286
+ def _clients
287
+ self.class._clients
288
+ end
289
+
290
+ def _run_client(cmd, args)
291
+ default = DEFAULTS[:display_on_all_clients]
292
+ all_clients = @options.fetch(:display_on_all_clients, default)
293
+ clients = all_clients ? _clients : [nil]
294
+ clients.each do |client|
295
+ cmd_args = if client
296
+ "#{_client_cmd_flag(cmd)} #{client.strip} #{args}"
297
+ else
298
+ args
299
+ end
300
+ Sheller.run("#{DEFAULTS[:client]} #{cmd} #{cmd_args}")
301
+ end
302
+ end
303
+
304
+ def _client_cmd_flag(cmd)
305
+ case cmd
306
+ when "set", "set-option" then "-t"
307
+ when "display-message" then "-c"
308
+ end
309
+ end
310
+
311
+ # Reset the internal Tmux options store defaults.
312
+ #
313
+ def self._reset_options_store
314
+ @options_stored = false
315
+ @options_store = {}
316
+
317
+ _clients.each do |client|
318
+ @options_store[client] = {
319
+ "status-left-bg" => nil,
320
+ "status-right-bg" => nil,
321
+ "status-left-fg" => nil,
322
+ "status-right-fg" => nil,
323
+ "message-bg" => nil,
324
+ "message-fg" => nil,
325
+ "display-time" => nil
326
+ }
327
+ end
328
+ end
329
+
330
+ def self._tmux_version
331
+ @@tmux_version ||= Float(Sheller.stdout("tmux -V")[/\d+\.\d+/])
332
+ end
333
+
334
+ def self._quiet_option
335
+ "-q " if _tmux_version >= 1.7
336
+ end
337
+ end
338
+ end
339
+ end
data/lib/guard/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Guard
2
- VERSION = "2.8.1"
2
+ VERSION = "2.8.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.8.1
4
+ version: 2.8.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-11-05 00:00:00.000000000 Z
11
+ date: 2014-11-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -131,12 +131,14 @@ files:
131
131
  - lib/guard/interactor.rb
132
132
  - lib/guard/internals/debugging.rb
133
133
  - lib/guard/internals/debugging.rb.orig
134
+ - lib/guard/internals/environment.rb.orig
134
135
  - lib/guard/internals/tracing.rb
135
136
  - lib/guard/internals/tracing.rb.orig
136
137
  - lib/guard/jobs/base.rb
137
138
  - lib/guard/jobs/pry_wrapper.rb
138
139
  - lib/guard/jobs/sleep.rb
139
140
  - lib/guard/notifier.rb
141
+ - lib/guard/notifier.rb.orig
140
142
  - lib/guard/notifiers/base.rb
141
143
  - lib/guard/notifiers/base.rb.orig
142
144
  - lib/guard/notifiers/emacs.rb
@@ -149,6 +151,7 @@ files:
149
151
  - lib/guard/notifiers/terminal_notifier.rb
150
152
  - lib/guard/notifiers/terminal_title.rb
151
153
  - lib/guard/notifiers/tmux.rb
154
+ - lib/guard/notifiers/tmux.rb.orig
152
155
  - lib/guard/options.rb
153
156
  - lib/guard/plugin.rb
154
157
  - lib/guard/plugin/base.rb