guard 2.8.1 → 2.8.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: 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