guard 1.2.3 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +16 -1
- data/README.md +46 -7
- data/lib/guard.rb +45 -44
- data/lib/guard/cli.rb +15 -9
- data/lib/guard/dsl.rb +16 -9
- data/lib/guard/dsl_describer.rb +12 -13
- data/lib/guard/group.rb +4 -1
- data/lib/guard/guard.rb +4 -1
- data/lib/guard/guardfile.rb +3 -0
- data/lib/guard/hook.rb +3 -1
- data/lib/guard/interactor.rb +15 -11
- data/lib/guard/interactors/coolline.rb +7 -5
- data/lib/guard/interactors/helpers/completion.rb +2 -0
- data/lib/guard/interactors/readline.rb +14 -8
- data/lib/guard/interactors/simple.rb +3 -1
- data/lib/guard/notifier.rb +56 -37
- data/lib/guard/notifiers/emacs.rb +69 -0
- data/lib/guard/notifiers/gntp.rb +2 -1
- data/lib/guard/notifiers/growl.rb +1 -0
- data/lib/guard/notifiers/growl_notify.rb +2 -1
- data/lib/guard/notifiers/libnotify.rb +1 -0
- data/lib/guard/notifiers/notifysend.rb +1 -0
- data/lib/guard/notifiers/rb_notifu.rb +1 -0
- data/lib/guard/notifiers/terminal_notifier.rb +65 -0
- data/lib/guard/runner.rb +14 -10
- data/lib/guard/ui.rb +1 -1
- data/lib/guard/version.rb +1 -1
- data/lib/guard/version.rbc +1 -1
- data/lib/guard/watcher.rb +7 -5
- data/man/guard.1 +2 -2
- data/man/guard.1.html +3 -3
- metadata +5 -3
data/lib/guard/dsl_describer.rb
CHANGED
@@ -1,9 +1,5 @@
|
|
1
|
-
require 'guard/dsl'
|
2
|
-
|
3
1
|
module Guard
|
4
2
|
|
5
|
-
autoload :UI, 'guard/ui'
|
6
|
-
|
7
3
|
# The DslDescriber overrides methods to create an internal structure
|
8
4
|
# of the Guardfile that is used in some inspection utility methods
|
9
5
|
# like the CLI commands `show` and `list`.
|
@@ -13,6 +9,9 @@ module Guard
|
|
13
9
|
#
|
14
10
|
class DslDescriber < Dsl
|
15
11
|
|
12
|
+
require 'guard/dsl'
|
13
|
+
require 'guard/ui'
|
14
|
+
|
16
15
|
class << self
|
17
16
|
|
18
17
|
# Evaluate the DSL methods in the `Guardfile`.
|
@@ -52,15 +51,15 @@ module Guard
|
|
52
51
|
installed
|
53
52
|
end
|
54
53
|
|
55
|
-
UI.info 'Available guards:'
|
54
|
+
::Guard::UI.info 'Available guards:'
|
56
55
|
|
57
56
|
::Guard.guard_gem_names.sort.uniq.each do |name|
|
58
|
-
UI.info " #{ name }#{ installed_guards.include?(name) ? '*' : '' }"
|
57
|
+
::Guard::UI.info " #{ name }#{ installed_guards.include?(name) ? '*' : '' }"
|
59
58
|
end
|
60
59
|
|
61
|
-
UI.info ''
|
62
|
-
UI.info 'See also https://github.com/guard/guard/wiki/List-of-available-Guards'
|
63
|
-
UI.info '* denotes ones already in your Guardfile'
|
60
|
+
::Guard::UI.info ''
|
61
|
+
::Guard::UI.info 'See also https://github.com/guard/guard/wiki/List-of-available-Guards'
|
62
|
+
::Guard::UI.info '* denotes ones already in your Guardfile'
|
64
63
|
end
|
65
64
|
|
66
65
|
# Shows all Guard plugins and their options that are defined in
|
@@ -82,9 +81,9 @@ module Guard
|
|
82
81
|
guardfile_structure.each do |group|
|
83
82
|
unless group[:guards].empty?
|
84
83
|
if group[:group]
|
85
|
-
UI.info "Group #{ group[:group] }:"
|
84
|
+
::Guard::UI.info "Group #{ group[:group] }:"
|
86
85
|
else
|
87
|
-
UI.info '(global):'
|
86
|
+
::Guard::UI.info '(global):'
|
88
87
|
end
|
89
88
|
|
90
89
|
group[:guards].each do |guard|
|
@@ -94,12 +93,12 @@ module Guard
|
|
94
93
|
line += ": #{ guard[:options].inject({}) { |options, (k, v)| options[k.to_s] = v; options }.sort.collect { |k, v| "#{ k } => #{ v.inspect }" }.join(', ') }"
|
95
94
|
end
|
96
95
|
|
97
|
-
UI.info line
|
96
|
+
::Guard::UI.info line
|
98
97
|
end
|
99
98
|
end
|
100
99
|
end
|
101
100
|
|
102
|
-
UI.info ''
|
101
|
+
::Guard::UI.info ''
|
103
102
|
end
|
104
103
|
|
105
104
|
private
|
data/lib/guard/group.rb
CHANGED
data/lib/guard/guard.rb
CHANGED
data/lib/guard/guardfile.rb
CHANGED
data/lib/guard/hook.rb
CHANGED
@@ -9,6 +9,8 @@ module Guard
|
|
9
9
|
#
|
10
10
|
module Hook
|
11
11
|
|
12
|
+
require 'guard/ui'
|
13
|
+
|
12
14
|
# The Hook module gets included.
|
13
15
|
#
|
14
16
|
# @param [Class] base the class that includes the module
|
@@ -57,7 +59,7 @@ module Guard
|
|
57
59
|
event
|
58
60
|
end.to_sym
|
59
61
|
|
60
|
-
UI.debug "Hook :#{ hook_name } executed for #{ self.class }"
|
62
|
+
::Guard::UI.debug "Hook :#{ hook_name } executed for #{ self.class }"
|
61
63
|
|
62
64
|
Hook.notify(self.class, hook_name, *args)
|
63
65
|
end
|
data/lib/guard/interactor.rb
CHANGED
@@ -1,11 +1,5 @@
|
|
1
1
|
module Guard
|
2
2
|
|
3
|
-
autoload :ReadlineInteractor, 'guard/interactors/readline'
|
4
|
-
autoload :CoollineInteractor, 'guard/interactors/coolline'
|
5
|
-
autoload :SimpleInteractor, 'guard/interactors/simple'
|
6
|
-
autoload :DslDescriber, 'guard/dsl_describer'
|
7
|
-
autoload :UI, 'guard/ui'
|
8
|
-
|
9
3
|
# The interactor triggers specific action from input
|
10
4
|
# read by a interactor implementation.
|
11
5
|
#
|
@@ -38,6 +32,14 @@ module Guard
|
|
38
32
|
#
|
39
33
|
class Interactor
|
40
34
|
|
35
|
+
require 'guard'
|
36
|
+
require 'guard/ui'
|
37
|
+
require 'guard/dsl_describer'
|
38
|
+
require 'guard/notifier'
|
39
|
+
require 'guard/interactors/readline'
|
40
|
+
require 'guard/interactors/coolline'
|
41
|
+
require 'guard/interactors/simple'
|
42
|
+
|
41
43
|
ACTIONS = {
|
42
44
|
:help => %w[help h],
|
43
45
|
:reload => %w[reload r],
|
@@ -64,11 +66,11 @@ module Guard
|
|
64
66
|
def self.fabricate
|
65
67
|
case @interactor
|
66
68
|
when :coolline
|
67
|
-
CoollineInteractor.new if CoollineInteractor.available?
|
69
|
+
::Guard::CoollineInteractor.new if ::Guard::CoollineInteractor.available?
|
68
70
|
when :readline
|
69
|
-
ReadlineInteractor.new if ReadlineInteractor.available?
|
71
|
+
::Guard::ReadlineInteractor.new if ::Guard::ReadlineInteractor.available?
|
70
72
|
when :simple
|
71
|
-
SimpleInteractor.new
|
73
|
+
::Guard::SimpleInteractor.new
|
72
74
|
when :off
|
73
75
|
nil
|
74
76
|
else
|
@@ -90,7 +92,9 @@ module Guard
|
|
90
92
|
# @return [Interactor] an interactor implementation
|
91
93
|
#
|
92
94
|
def self.auto_detect
|
93
|
-
[CoollineInteractor, ReadlineInteractor, SimpleInteractor].detect
|
95
|
+
[::Guard::CoollineInteractor, ::Guard::ReadlineInteractor, ::Guard::SimpleInteractor].detect do |interactor|
|
96
|
+
interactor.available?(true)
|
97
|
+
end.new
|
94
98
|
end
|
95
99
|
|
96
100
|
# Template method for checking if the Interactor is
|
@@ -143,7 +147,7 @@ module Guard
|
|
143
147
|
when :help
|
144
148
|
help
|
145
149
|
when :show
|
146
|
-
DslDescriber.show(::Guard.options)
|
150
|
+
::Guard::DslDescriber.show(::Guard.options)
|
147
151
|
when :stop
|
148
152
|
::Guard.stop
|
149
153
|
exit
|
@@ -1,13 +1,15 @@
|
|
1
|
-
|
1
|
+
require 'guard'
|
2
|
+
require 'guard/ui'
|
3
|
+
require 'guard/interactor'
|
4
|
+
require 'guard/interactors/helpers/terminal'
|
5
|
+
require 'guard/interactors/helpers/completion'
|
2
6
|
|
3
|
-
|
4
|
-
autoload :CompletionHelper, 'guard/interactors/helpers/completion'
|
5
|
-
autoload :UI, 'guard/ui'
|
7
|
+
module Guard
|
6
8
|
|
7
9
|
# Interactor that uses coolline for getting the user input.
|
8
10
|
# This enables history support and auto-completion,
|
9
11
|
#
|
10
|
-
class CoollineInteractor < Interactor
|
12
|
+
class CoollineInteractor < ::Guard::Interactor
|
11
13
|
include ::Guard::CompletionHelper
|
12
14
|
include ::Guard::TerminalHelper
|
13
15
|
|
@@ -1,8 +1,10 @@
|
|
1
|
-
|
1
|
+
require 'guard'
|
2
|
+
require 'guard/ui'
|
3
|
+
require 'guard/interactor'
|
4
|
+
require 'guard/interactors/helpers/terminal'
|
5
|
+
require 'guard/interactors/helpers/completion'
|
2
6
|
|
3
|
-
|
4
|
-
autoload :CompletionHelper, 'guard/interactors/helpers/completion'
|
5
|
-
autoload :UI, 'guard/ui'
|
7
|
+
module Guard
|
6
8
|
|
7
9
|
# Interactor that used readline for getting the user input.
|
8
10
|
# This enables history support and auto-completion, but is
|
@@ -10,7 +12,7 @@ module Guard
|
|
10
12
|
#
|
11
13
|
# @see http://bugs.ruby-lang.org/issues/5539
|
12
14
|
#
|
13
|
-
class ReadlineInteractor < Interactor
|
15
|
+
class ReadlineInteractor < ::Guard::Interactor
|
14
16
|
include ::Guard::CompletionHelper
|
15
17
|
include ::Guard::TerminalHelper
|
16
18
|
|
@@ -29,6 +31,10 @@ module Guard
|
|
29
31
|
::Guard::UI.error 'The :readline interactor runs only fine on JRuby, Linux or with the gem \'rb-readline\' installed.' unless silent
|
30
32
|
false
|
31
33
|
end
|
34
|
+
|
35
|
+
rescue LoadError => e
|
36
|
+
::Guard::UI.error "Please install Ruby Readline support or add \"gem 'rb-readline'\" to your Gemfile and run Guard with \"bundle exec\"." unless silent
|
37
|
+
false
|
32
38
|
end
|
33
39
|
|
34
40
|
# Initialize the interactor.
|
@@ -49,10 +55,10 @@ module Guard
|
|
49
55
|
#
|
50
56
|
def stop
|
51
57
|
# Erase the current line for Ruby Readline
|
52
|
-
if Readline.respond_to?(:refresh_line)
|
58
|
+
if Readline.respond_to?(:refresh_line) && !defined?(::JRUBY_VERSION)
|
53
59
|
Readline.refresh_line
|
54
60
|
end
|
55
|
-
|
61
|
+
|
56
62
|
# Erase the current line for Rb-Readline
|
57
63
|
if defined?(RbReadline) && RbReadline.rl_outstream
|
58
64
|
RbReadline._rl_erase_entire_line
|
@@ -60,7 +66,7 @@ module Guard
|
|
60
66
|
|
61
67
|
super
|
62
68
|
end
|
63
|
-
|
69
|
+
|
64
70
|
# Read a line from stdin with Readline.
|
65
71
|
#
|
66
72
|
def read_line
|
@@ -1,9 +1,11 @@
|
|
1
|
+
require 'guard/interactor'
|
2
|
+
|
1
3
|
module Guard
|
2
4
|
|
3
5
|
# Simple interactor that that reads user
|
4
6
|
# input from standard input.
|
5
7
|
#
|
6
|
-
class SimpleInteractor < Interactor
|
8
|
+
class SimpleInteractor < ::Guard::Interactor
|
7
9
|
|
8
10
|
# Read a line from stdin with Readline.
|
9
11
|
#
|
data/lib/guard/notifier.rb
CHANGED
@@ -1,14 +1,6 @@
|
|
1
1
|
require 'yaml'
|
2
|
-
|
3
2
|
require 'rbconfig'
|
4
3
|
require 'pathname'
|
5
|
-
require 'guard/ui'
|
6
|
-
require 'guard/notifiers/gntp'
|
7
|
-
require 'guard/notifiers/growl'
|
8
|
-
require 'guard/notifiers/growl_notify'
|
9
|
-
require 'guard/notifiers/libnotify'
|
10
|
-
require 'guard/notifiers/notifysend'
|
11
|
-
require 'guard/notifiers/rb_notifu'
|
12
4
|
|
13
5
|
module Guard
|
14
6
|
|
@@ -40,17 +32,32 @@ module Guard
|
|
40
32
|
# Guard can be configured to make use of more than one notifier at once, @see Guard::Dsl
|
41
33
|
#
|
42
34
|
module Notifier
|
35
|
+
|
36
|
+
require 'guard'
|
37
|
+
require 'guard/ui'
|
38
|
+
require 'guard/notifiers/gntp'
|
39
|
+
require 'guard/notifiers/growl'
|
40
|
+
require 'guard/notifiers/growl_notify'
|
41
|
+
require 'guard/notifiers/libnotify'
|
42
|
+
require 'guard/notifiers/notifysend'
|
43
|
+
require 'guard/notifiers/rb_notifu'
|
44
|
+
require 'guard/notifiers/emacs'
|
45
|
+
require 'guard/notifiers/terminal_notifier'
|
46
|
+
|
43
47
|
extend self
|
44
48
|
|
45
|
-
# List of available notifiers.
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
49
|
+
# List of available notifiers. It needs to be a nested hash instead of
|
50
|
+
# a simpler Hash, because it maintains its order on Ruby 1.8.7 also.
|
51
|
+
NOTIFIERS = [
|
52
|
+
[:growl, ::Guard::Notifier::Growl],
|
53
|
+
[:gntp, ::Guard::Notifier::GNTP],
|
54
|
+
[:growl_notify, ::Guard::Notifier::GrowlNotify],
|
55
|
+
[:libnotify, ::Guard::Notifier::Libnotify],
|
56
|
+
[:notifysend, ::Guard::Notifier::NotifySend],
|
57
|
+
[:notifu, ::Guard::Notifier::Notifu],
|
58
|
+
[:emacs, ::Guard::Notifier::Emacs],
|
59
|
+
[:terminal_notifier, ::Guard::Notifier::TerminalNotifier]
|
60
|
+
]
|
54
61
|
|
55
62
|
# Get the available notifications.
|
56
63
|
#
|
@@ -85,7 +92,7 @@ module Guard
|
|
85
92
|
ENV['GUARD_NOTIFY'] = 'false'
|
86
93
|
else
|
87
94
|
notifications.each do |notification|
|
88
|
-
::Guard::UI.info "Guard uses #{
|
95
|
+
::Guard::UI.info "Guard uses #{ get_notifier_module(notification[:name]).to_s.split('::').last } to send notifications."
|
89
96
|
end
|
90
97
|
|
91
98
|
ENV['GUARD_NOTIFY'] = 'true'
|
@@ -116,7 +123,9 @@ module Guard
|
|
116
123
|
def add_notification(name, options = { }, silent = false)
|
117
124
|
return turn_off if name == :off
|
118
125
|
|
119
|
-
|
126
|
+
notifier = get_notifier_module(name)
|
127
|
+
|
128
|
+
if notifier && notifier.available?(silent)
|
120
129
|
self.notifications = notifications << { :name => name, :options => options }
|
121
130
|
true
|
122
131
|
else
|
@@ -138,7 +147,7 @@ module Guard
|
|
138
147
|
|
139
148
|
notifications.each do |notification|
|
140
149
|
begin
|
141
|
-
|
150
|
+
get_notifier_module(notification[:name]).notify(type, title, message, image, options.merge(notification[:options]))
|
142
151
|
rescue Exception => e
|
143
152
|
::Guard::UI.error "Error sending notification with #{ notification[:name] }: #{ e.message }"
|
144
153
|
end
|
@@ -148,12 +157,22 @@ module Guard
|
|
148
157
|
|
149
158
|
private
|
150
159
|
|
160
|
+
# Get the notifier module for the given name.
|
161
|
+
#
|
162
|
+
# @param [Symbol] the notifier name
|
163
|
+
# @return [Module] the notifier module
|
164
|
+
#
|
165
|
+
def get_notifier_module(name)
|
166
|
+
notifier = NOTIFIERS.detect { |n| n.first == name }
|
167
|
+
notifier ? notifier.last : notifier
|
168
|
+
end
|
169
|
+
|
151
170
|
# Auto detect the available notification library. This goes through
|
152
171
|
# the list of supported notification gems and picks the first that
|
153
172
|
# is available.
|
154
173
|
#
|
155
174
|
def auto_detect_notification
|
156
|
-
available =
|
175
|
+
available = NOTIFIERS.map { |n| n.first }.any? { |notifier| add_notification(notifier, { }, true) }
|
157
176
|
::Guard::UI.info('Guard could not detect any of the supported notification libraries.') unless available
|
158
177
|
end
|
159
178
|
|
@@ -171,14 +190,14 @@ module Guard
|
|
171
190
|
#
|
172
191
|
def image_path(image)
|
173
192
|
case image
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
193
|
+
when :failed
|
194
|
+
images_path.join('failed.png').to_s
|
195
|
+
when :pending
|
196
|
+
images_path.join('pending.png').to_s
|
197
|
+
when :success
|
198
|
+
images_path.join('success.png').to_s
|
199
|
+
else
|
200
|
+
image
|
182
201
|
end
|
183
202
|
end
|
184
203
|
|
@@ -198,14 +217,14 @@ module Guard
|
|
198
217
|
#
|
199
218
|
def notification_type(image)
|
200
219
|
case image
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
220
|
+
when :failed
|
221
|
+
'failed'
|
222
|
+
when :pending
|
223
|
+
'pending'
|
224
|
+
when :success
|
225
|
+
'success'
|
226
|
+
else
|
227
|
+
'notify'
|
209
228
|
end
|
210
229
|
end
|
211
230
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
|
3
|
+
module Guard
|
4
|
+
module Notifier
|
5
|
+
|
6
|
+
# Default options for EmacsClient
|
7
|
+
DEFAULTS = {
|
8
|
+
:client => 'emacsclient',
|
9
|
+
:success => 'ForestGreen',
|
10
|
+
:failed => 'Firebrick',
|
11
|
+
:default => 'Black',
|
12
|
+
}
|
13
|
+
|
14
|
+
# Send a notification to Emacs with emacsclient (http://www.emacswiki.org/emacs/EmacsClient).
|
15
|
+
#
|
16
|
+
# @example Add the `:emacs` notifier to your `Guardfile`
|
17
|
+
# notification :emacs
|
18
|
+
#
|
19
|
+
module Emacs
|
20
|
+
extend self
|
21
|
+
|
22
|
+
# Test if Emacs with running server is available.
|
23
|
+
#
|
24
|
+
# @param [Boolean] silent true if no error messages should be shown
|
25
|
+
# @return [Boolean] the availability status
|
26
|
+
#
|
27
|
+
def available?(silent = false)
|
28
|
+
result = `#{DEFAULTS[:client]} --eval '1' 2> /dev/null || echo 0`
|
29
|
+
|
30
|
+
if result.chomp! == "1"
|
31
|
+
true
|
32
|
+
else
|
33
|
+
false
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Show a system notification.
|
38
|
+
#
|
39
|
+
# @param [String] type the notification type. Either 'success', 'pending', 'failed' or 'notify'
|
40
|
+
# @param [String] title the notification title
|
41
|
+
# @param [String] message the notification message body
|
42
|
+
# @param [String] image the path to the notification image
|
43
|
+
# @param [Hash] options additional notification library options
|
44
|
+
# @option options [Boolean] sticky make the notification sticky
|
45
|
+
# @option options [String, Integer] priority specify an int or named key (default is 0)
|
46
|
+
#
|
47
|
+
def notify(type, title, message, image, options = { })
|
48
|
+
system(%(#{DEFAULTS[:client]} --eval "(set-face-background 'modeline \\"#{emacs_color(type)}\\")"))
|
49
|
+
end
|
50
|
+
|
51
|
+
# Get the Emacs color for the notification type.
|
52
|
+
# You can configure your own color by overwrite the defaults.
|
53
|
+
#
|
54
|
+
# @param [String] type the notification type
|
55
|
+
# @return [String] the name of the emacs color
|
56
|
+
#
|
57
|
+
def emacs_color(type)
|
58
|
+
case type
|
59
|
+
when 'success'
|
60
|
+
DEFAULTS[:success]
|
61
|
+
when 'failed'
|
62
|
+
DEFAULTS[:failed]
|
63
|
+
else
|
64
|
+
DEFAULTS[:default]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|