guard 0.8.1 → 0.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.
- data/CHANGELOG.md +320 -310
- data/LICENSE +19 -19
- data/README.md +431 -434
- data/bin/guard +6 -6
- data/lib/guard.rb +390 -384
- data/lib/guard/cli.rb +178 -178
- data/lib/guard/dsl.rb +370 -370
- data/lib/guard/dsl_describer.rb +60 -60
- data/lib/guard/group.rb +37 -22
- data/lib/guard/guard.rb +113 -98
- data/lib/guard/hook.rb +118 -118
- data/lib/guard/interactor.rb +78 -78
- data/lib/guard/listener.rb +346 -346
- data/lib/guard/listeners/darwin.rb +66 -66
- data/lib/guard/listeners/linux.rb +97 -98
- data/lib/guard/listeners/polling.rb +55 -55
- data/lib/guard/listeners/windows.rb +61 -61
- data/lib/guard/notifier.rb +211 -211
- data/lib/guard/templates/Guardfile +2 -2
- data/lib/guard/ui.rb +188 -188
- data/lib/guard/version.rb +6 -6
- data/lib/guard/watcher.rb +110 -110
- data/man/guard.1 +93 -93
- data/man/guard.1.html +176 -176
- metadata +15 -15
data/lib/guard/dsl_describer.rb
CHANGED
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
require 'guard/dsl'
|
|
2
|
-
|
|
3
|
-
module Guard
|
|
4
|
-
|
|
5
|
-
# The DslDescriber overrides methods to create an internal structure
|
|
6
|
-
# of the Guardfile that is used in some inspection utility methods
|
|
7
|
-
# like the CLI commands `show` and `list`.
|
|
8
|
-
#
|
|
9
|
-
# @see Guard::Dsl
|
|
10
|
-
# @see Guard::CLI
|
|
11
|
-
#
|
|
12
|
-
class DslDescriber < Dsl
|
|
13
|
-
|
|
14
|
-
@@guardfile_structure = [ { :guards => [] } ]
|
|
15
|
-
|
|
16
|
-
class << self
|
|
17
|
-
|
|
18
|
-
# Get the Guardfile structure.
|
|
19
|
-
#
|
|
20
|
-
# @return [Array<Hash>] the structure
|
|
21
|
-
#
|
|
22
|
-
def guardfile_structure
|
|
23
|
-
@@guardfile_structure
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
private
|
|
28
|
-
|
|
29
|
-
# Declares a group of guards.
|
|
30
|
-
#
|
|
31
|
-
# @param [String] name the group's name called from the CLI
|
|
32
|
-
# @yield a block where you can declare several guards
|
|
33
|
-
#
|
|
34
|
-
# @see Guard::Dsl#group
|
|
35
|
-
#
|
|
36
|
-
def group(name)
|
|
37
|
-
@@guardfile_structure << { :group => name.to_sym, :guards => [] }
|
|
38
|
-
@group = true
|
|
39
|
-
|
|
40
|
-
yield if block_given?
|
|
41
|
-
|
|
42
|
-
@group = false
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# Declares a Guard.
|
|
46
|
-
#
|
|
47
|
-
# @param [String] name the Guard name
|
|
48
|
-
# @param [Hash] options the options accepted by the Guard
|
|
49
|
-
# @yield a block where you can declare several watch patterns and actions
|
|
50
|
-
#
|
|
51
|
-
# @see Guard::Dsl#guard
|
|
52
|
-
#
|
|
53
|
-
def guard(name, options = {})
|
|
54
|
-
node = (@group ? @@guardfile_structure.last : @@guardfile_structure.first)
|
|
55
|
-
|
|
56
|
-
node[:guards] << { :name => name, :options => options }
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
end
|
|
60
|
-
end
|
|
1
|
+
require 'guard/dsl'
|
|
2
|
+
|
|
3
|
+
module Guard
|
|
4
|
+
|
|
5
|
+
# The DslDescriber overrides methods to create an internal structure
|
|
6
|
+
# of the Guardfile that is used in some inspection utility methods
|
|
7
|
+
# like the CLI commands `show` and `list`.
|
|
8
|
+
#
|
|
9
|
+
# @see Guard::Dsl
|
|
10
|
+
# @see Guard::CLI
|
|
11
|
+
#
|
|
12
|
+
class DslDescriber < Dsl
|
|
13
|
+
|
|
14
|
+
@@guardfile_structure = [ { :guards => [] } ]
|
|
15
|
+
|
|
16
|
+
class << self
|
|
17
|
+
|
|
18
|
+
# Get the Guardfile structure.
|
|
19
|
+
#
|
|
20
|
+
# @return [Array<Hash>] the structure
|
|
21
|
+
#
|
|
22
|
+
def guardfile_structure
|
|
23
|
+
@@guardfile_structure
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
# Declares a group of guards.
|
|
30
|
+
#
|
|
31
|
+
# @param [String] name the group's name called from the CLI
|
|
32
|
+
# @yield a block where you can declare several guards
|
|
33
|
+
#
|
|
34
|
+
# @see Guard::Dsl#group
|
|
35
|
+
#
|
|
36
|
+
def group(name)
|
|
37
|
+
@@guardfile_structure << { :group => name.to_sym, :guards => [] }
|
|
38
|
+
@group = true
|
|
39
|
+
|
|
40
|
+
yield if block_given?
|
|
41
|
+
|
|
42
|
+
@group = false
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Declares a Guard.
|
|
46
|
+
#
|
|
47
|
+
# @param [String] name the Guard name
|
|
48
|
+
# @param [Hash] options the options accepted by the Guard
|
|
49
|
+
# @yield a block where you can declare several watch patterns and actions
|
|
50
|
+
#
|
|
51
|
+
# @see Guard::Dsl#guard
|
|
52
|
+
#
|
|
53
|
+
def guard(name, options = {})
|
|
54
|
+
node = (@group ? @@guardfile_structure.last : @@guardfile_structure.first)
|
|
55
|
+
|
|
56
|
+
node[:guards] << { :name => name, :options => options }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
end
|
data/lib/guard/group.rb
CHANGED
|
@@ -1,22 +1,37 @@
|
|
|
1
|
-
module Guard
|
|
2
|
-
|
|
3
|
-
# A group of Guards.
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
1
|
+
module Guard
|
|
2
|
+
|
|
3
|
+
# A group of Guards. There are two reasons why you want to group your guards:
|
|
4
|
+
#
|
|
5
|
+
# - You can start only certain Groups from the command line by passing the `--group` option.
|
|
6
|
+
# - Abort task execution chain on failure within a group.
|
|
7
|
+
#
|
|
8
|
+
# @example Group that aborts on failure
|
|
9
|
+
#
|
|
10
|
+
# group :frontend, :halt_on_fail => true do
|
|
11
|
+
# guard 'coffeescript', :input => 'spec/coffeescripts', :output => 'spec/javascripts'
|
|
12
|
+
# guard 'jasmine-headless-webkit' do
|
|
13
|
+
# watch(%r{^spec/javascripts/(.*)\..*}) { |m| newest_js_file("spec/javascripts/#{m[1]}_spec") }
|
|
14
|
+
# end
|
|
15
|
+
# end
|
|
16
|
+
#
|
|
17
|
+
# @see Guard::CLI
|
|
18
|
+
#
|
|
19
|
+
class Group
|
|
20
|
+
|
|
21
|
+
attr_accessor :name, :options
|
|
22
|
+
|
|
23
|
+
# Initialize a Group.
|
|
24
|
+
#
|
|
25
|
+
# @param [String] name the name of the group
|
|
26
|
+
# @param [Hash] options the group options
|
|
27
|
+
# @option options [Boolean] halt_on_fail if a task execution
|
|
28
|
+
# should be halted for all Guards in this group if one Guard throws `:task_has_failed`
|
|
29
|
+
#
|
|
30
|
+
def initialize(name, options = {})
|
|
31
|
+
@name = name.to_sym
|
|
32
|
+
@options = options
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
data/lib/guard/guard.rb
CHANGED
|
@@ -1,98 +1,113 @@
|
|
|
1
|
-
module Guard
|
|
2
|
-
|
|
3
|
-
# Main class that every Guard implementation must subclass.
|
|
4
|
-
#
|
|
5
|
-
# Guard will trigger the `start`, `stop`, `reload`, `run_all
|
|
6
|
-
# methods depending on user interaction and file modification.
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
#
|
|
47
|
-
#
|
|
48
|
-
# @
|
|
49
|
-
#
|
|
50
|
-
def
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
#
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
#
|
|
73
|
-
#
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
#
|
|
80
|
-
#
|
|
81
|
-
#
|
|
82
|
-
#
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
#
|
|
88
|
-
#
|
|
89
|
-
#
|
|
90
|
-
# @
|
|
91
|
-
#
|
|
92
|
-
def
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
1
|
+
module Guard
|
|
2
|
+
|
|
3
|
+
# Main class that every Guard implementation must subclass.
|
|
4
|
+
#
|
|
5
|
+
# Guard will trigger the `start`, `stop`, `reload`, `run_all`, `run_on_change` and
|
|
6
|
+
# `run_on_deletion` methods depending on user interaction and file modification.
|
|
7
|
+
#
|
|
8
|
+
# In each of these Guard methods you have to implement some work when you want to
|
|
9
|
+
# support this kind of task. The return value of each Guard method is ignored, but
|
|
10
|
+
# you can throw `:task_has_failed` to indicate that your Guard method was
|
|
11
|
+
# not successful. When `:task_has_failed` is thrown, successive guard tasks
|
|
12
|
+
# can be aborted when the group has set the `:halt_on_fail` option.
|
|
13
|
+
#
|
|
14
|
+
# @see Guard::Group
|
|
15
|
+
#
|
|
16
|
+
# @example Throw :task_has_failed
|
|
17
|
+
#
|
|
18
|
+
# def run_all
|
|
19
|
+
# if !runner.run(['all'])
|
|
20
|
+
# throw :task_has_failed
|
|
21
|
+
# end
|
|
22
|
+
# end
|
|
23
|
+
#
|
|
24
|
+
# Each Guard should provide a template Guardfile located within the Gem
|
|
25
|
+
# at `lib/guard/guard-name/templates/Guardfile`.
|
|
26
|
+
#
|
|
27
|
+
# If one of those methods raise an exception other than `:task_has_failed`,
|
|
28
|
+
# the Guard::GuardName instance will be removed from the active guards.
|
|
29
|
+
#
|
|
30
|
+
class Guard
|
|
31
|
+
include Hook
|
|
32
|
+
|
|
33
|
+
attr_accessor :watchers, :options, :group
|
|
34
|
+
|
|
35
|
+
# Initialize a Guard.
|
|
36
|
+
#
|
|
37
|
+
# @param [Array<Guard::Watcher>] watchers the Guard file watchers
|
|
38
|
+
# @param [Hash] options the custom Guard options
|
|
39
|
+
#
|
|
40
|
+
def initialize(watchers = [], options = {})
|
|
41
|
+
@group = options[:group] ? options.delete(:group).to_sym : :default
|
|
42
|
+
@watchers, @options = watchers, options
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Initialize the Guard. This will copy the Guardfile template inside the Guard gem.
|
|
46
|
+
# The template Guardfile must be located within the Gem at `lib/guard/guard-name/templates/Guardfile`.
|
|
47
|
+
#
|
|
48
|
+
# @param [String] name the name of the Guard
|
|
49
|
+
#
|
|
50
|
+
def self.init(name)
|
|
51
|
+
if ::Guard::Dsl.guardfile_include?(name)
|
|
52
|
+
::Guard::UI.info "Guardfile already includes #{ name } guard"
|
|
53
|
+
else
|
|
54
|
+
content = File.read('Guardfile')
|
|
55
|
+
guard = File.read("#{ ::Guard.locate_guard(name) }/lib/guard/#{ name }/templates/Guardfile")
|
|
56
|
+
File.open('Guardfile', 'wb') do |f|
|
|
57
|
+
f.puts(content)
|
|
58
|
+
f.puts("")
|
|
59
|
+
f.puts(guard)
|
|
60
|
+
end
|
|
61
|
+
::Guard::UI.info "#{name} guard added to Guardfile, feel free to edit it"
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Call once when Guard starts. Please override initialize method to init stuff.
|
|
66
|
+
#
|
|
67
|
+
# @raise [:task_has_failed] when start has failed
|
|
68
|
+
#
|
|
69
|
+
def start
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Called when `stop|quit|exit|s|q|e + enter` is pressed (when Guard quits).
|
|
73
|
+
#
|
|
74
|
+
# @raise [:task_has_failed] when stop has failed
|
|
75
|
+
#
|
|
76
|
+
def stop
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Called when `reload|r|z + enter` is pressed.
|
|
80
|
+
# This method should be mainly used for "reload" (really!) actions like reloading passenger/spork/bundler/...
|
|
81
|
+
#
|
|
82
|
+
# @raise [:task_has_failed] when reload has failed
|
|
83
|
+
#
|
|
84
|
+
def reload
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Called when just `enter` is pressed
|
|
88
|
+
# This method should be principally used for long action like running all specs/tests/...
|
|
89
|
+
#
|
|
90
|
+
# @raise [:task_has_failed] when run_all has failed
|
|
91
|
+
#
|
|
92
|
+
def run_all
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Called on file(s) modifications that the Guard watches.
|
|
96
|
+
#
|
|
97
|
+
# @param [Array<String>] paths the changes files or paths
|
|
98
|
+
# @raise [:task_has_failed] when run_on_change has failed
|
|
99
|
+
#
|
|
100
|
+
def run_on_change(paths)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Called on file(s) deletions that the Guard watches.
|
|
104
|
+
#
|
|
105
|
+
# @param [Array<String>] paths the deleted files or paths
|
|
106
|
+
# @raise [:task_has_failed] when run_on_change has failed
|
|
107
|
+
#
|
|
108
|
+
def run_on_deletion(paths)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
end
|
data/lib/guard/hook.rb
CHANGED
|
@@ -1,118 +1,118 @@
|
|
|
1
|
-
module Guard
|
|
2
|
-
|
|
3
|
-
# Guard has a hook mechanism that allows you to insert callbacks for individual Guards.
|
|
4
|
-
# By default, each of the Guard instance methods has a "_begin" and an "_end" hook.
|
|
5
|
-
# For example, the Guard::Guard#start method has a :start_begin hook that is runs immediately
|
|
6
|
-
# before Guard::Guard#start, and a :start_end hook that runs immediately after Guard::Guard#start.
|
|
7
|
-
#
|
|
8
|
-
# Read more about [hooks and callbacks on the wiki](https://github.com/guard/guard/wiki/Hooks-and-callbacks).
|
|
9
|
-
#
|
|
10
|
-
module Hook
|
|
11
|
-
|
|
12
|
-
# The Hook module gets included.
|
|
13
|
-
#
|
|
14
|
-
# @param [Class] base the class that includes the module
|
|
15
|
-
#
|
|
16
|
-
def self.included(base)
|
|
17
|
-
base.send :include, InstanceMethods
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
# Instance methods that gets included in the base class.
|
|
21
|
-
#
|
|
22
|
-
module InstanceMethods
|
|
23
|
-
|
|
24
|
-
# When event is a Symbol, {#hook} will generate a hook name
|
|
25
|
-
# by concatenating the method name from where {#hook} is called
|
|
26
|
-
# with the given Symbol.
|
|
27
|
-
#
|
|
28
|
-
# @example Add a hook with a Symbol
|
|
29
|
-
#
|
|
30
|
-
# def run_all
|
|
31
|
-
# hook :foo
|
|
32
|
-
# end
|
|
33
|
-
#
|
|
34
|
-
# Here, when {Guard::Guard#run_all} is called, {#hook} will notify callbacks
|
|
35
|
-
# registered for the "run_all_foo" event.
|
|
36
|
-
#
|
|
37
|
-
# When event is a String, {#hook} will directly turn the String
|
|
38
|
-
# into a Symbol.
|
|
39
|
-
#
|
|
40
|
-
# @example Add a hook with a String
|
|
41
|
-
#
|
|
42
|
-
# def run_all
|
|
43
|
-
# hook "foo_bar"
|
|
44
|
-
# end
|
|
45
|
-
#
|
|
46
|
-
# When {Guard::Guard#run_all} is called, {#hook} will notify callbacks
|
|
47
|
-
# registered for the "foo_bar" event.
|
|
48
|
-
#
|
|
49
|
-
# @param [Symbol, String] event the name of the Guard event
|
|
50
|
-
# @param [Array] args the parameters are passed as is to the callbacks registered for the given event.
|
|
51
|
-
#
|
|
52
|
-
def hook(event, *args)
|
|
53
|
-
hook_name = if event.is_a? Symbol
|
|
54
|
-
calling_method = caller[0][/`([^']*)'/, 1]
|
|
55
|
-
"#{ calling_method }_#{ event }"
|
|
56
|
-
else
|
|
57
|
-
event
|
|
58
|
-
end.to_sym
|
|
59
|
-
|
|
60
|
-
UI.debug "Hook :#{ hook_name } executed for #{ self.class }"
|
|
61
|
-
|
|
62
|
-
Hook.notify(self.class, hook_name, *args)
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
class << self
|
|
67
|
-
|
|
68
|
-
# Get all callbacks.
|
|
69
|
-
#
|
|
70
|
-
def callbacks
|
|
71
|
-
@callbacks ||= Hash.new { |hash, key| hash[key] = [] }
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
# Add a callback.
|
|
75
|
-
#
|
|
76
|
-
# @param [Block] listener the listener to notify
|
|
77
|
-
# @param [Guard::Guard] guard_class the Guard class to add the callback
|
|
78
|
-
# @param [Array<Symbol>] events the events to register
|
|
79
|
-
#
|
|
80
|
-
def add_callback(listener, guard_class, events)
|
|
81
|
-
_events = events.is_a?(Array) ? events : [events]
|
|
82
|
-
_events.each do |event|
|
|
83
|
-
callbacks[[guard_class, event]] << listener
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
# Checks if a callback has been registered.
|
|
88
|
-
#
|
|
89
|
-
# @param [Block] listener the listener to notify
|
|
90
|
-
# @param [Guard::Guard] guard_class the Guard class to add the callback
|
|
91
|
-
# @param [Symbol] event the event to look for
|
|
92
|
-
#
|
|
93
|
-
def has_callback?(listener, guard_class, event)
|
|
94
|
-
callbacks[[guard_class, event]].include?(listener)
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
# Notify a callback.
|
|
98
|
-
#
|
|
99
|
-
# @param [Guard::Guard] guard_class the Guard class to add the callback
|
|
100
|
-
# @param [Symbol] event the event to trigger
|
|
101
|
-
# @param [Array] args the arguments for the listener
|
|
102
|
-
#
|
|
103
|
-
def notify(guard_class, event, *args)
|
|
104
|
-
callbacks[[guard_class, event]].each do |listener|
|
|
105
|
-
listener.call(guard_class, event, *args)
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
# Reset all callbacks.
|
|
110
|
-
#
|
|
111
|
-
def reset_callbacks!
|
|
112
|
-
@callbacks = nil
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
end
|
|
118
|
-
end
|
|
1
|
+
module Guard
|
|
2
|
+
|
|
3
|
+
# Guard has a hook mechanism that allows you to insert callbacks for individual Guards.
|
|
4
|
+
# By default, each of the Guard instance methods has a "_begin" and an "_end" hook.
|
|
5
|
+
# For example, the Guard::Guard#start method has a :start_begin hook that is runs immediately
|
|
6
|
+
# before Guard::Guard#start, and a :start_end hook that runs immediately after Guard::Guard#start.
|
|
7
|
+
#
|
|
8
|
+
# Read more about [hooks and callbacks on the wiki](https://github.com/guard/guard/wiki/Hooks-and-callbacks).
|
|
9
|
+
#
|
|
10
|
+
module Hook
|
|
11
|
+
|
|
12
|
+
# The Hook module gets included.
|
|
13
|
+
#
|
|
14
|
+
# @param [Class] base the class that includes the module
|
|
15
|
+
#
|
|
16
|
+
def self.included(base)
|
|
17
|
+
base.send :include, InstanceMethods
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Instance methods that gets included in the base class.
|
|
21
|
+
#
|
|
22
|
+
module InstanceMethods
|
|
23
|
+
|
|
24
|
+
# When event is a Symbol, {#hook} will generate a hook name
|
|
25
|
+
# by concatenating the method name from where {#hook} is called
|
|
26
|
+
# with the given Symbol.
|
|
27
|
+
#
|
|
28
|
+
# @example Add a hook with a Symbol
|
|
29
|
+
#
|
|
30
|
+
# def run_all
|
|
31
|
+
# hook :foo
|
|
32
|
+
# end
|
|
33
|
+
#
|
|
34
|
+
# Here, when {Guard::Guard#run_all} is called, {#hook} will notify callbacks
|
|
35
|
+
# registered for the "run_all_foo" event.
|
|
36
|
+
#
|
|
37
|
+
# When event is a String, {#hook} will directly turn the String
|
|
38
|
+
# into a Symbol.
|
|
39
|
+
#
|
|
40
|
+
# @example Add a hook with a String
|
|
41
|
+
#
|
|
42
|
+
# def run_all
|
|
43
|
+
# hook "foo_bar"
|
|
44
|
+
# end
|
|
45
|
+
#
|
|
46
|
+
# When {Guard::Guard#run_all} is called, {#hook} will notify callbacks
|
|
47
|
+
# registered for the "foo_bar" event.
|
|
48
|
+
#
|
|
49
|
+
# @param [Symbol, String] event the name of the Guard event
|
|
50
|
+
# @param [Array] args the parameters are passed as is to the callbacks registered for the given event.
|
|
51
|
+
#
|
|
52
|
+
def hook(event, *args)
|
|
53
|
+
hook_name = if event.is_a? Symbol
|
|
54
|
+
calling_method = caller[0][/`([^']*)'/, 1]
|
|
55
|
+
"#{ calling_method }_#{ event }"
|
|
56
|
+
else
|
|
57
|
+
event
|
|
58
|
+
end.to_sym
|
|
59
|
+
|
|
60
|
+
UI.debug "Hook :#{ hook_name } executed for #{ self.class }"
|
|
61
|
+
|
|
62
|
+
Hook.notify(self.class, hook_name, *args)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
class << self
|
|
67
|
+
|
|
68
|
+
# Get all callbacks.
|
|
69
|
+
#
|
|
70
|
+
def callbacks
|
|
71
|
+
@callbacks ||= Hash.new { |hash, key| hash[key] = [] }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Add a callback.
|
|
75
|
+
#
|
|
76
|
+
# @param [Block] listener the listener to notify
|
|
77
|
+
# @param [Guard::Guard] guard_class the Guard class to add the callback
|
|
78
|
+
# @param [Array<Symbol>] events the events to register
|
|
79
|
+
#
|
|
80
|
+
def add_callback(listener, guard_class, events)
|
|
81
|
+
_events = events.is_a?(Array) ? events : [events]
|
|
82
|
+
_events.each do |event|
|
|
83
|
+
callbacks[[guard_class, event]] << listener
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Checks if a callback has been registered.
|
|
88
|
+
#
|
|
89
|
+
# @param [Block] listener the listener to notify
|
|
90
|
+
# @param [Guard::Guard] guard_class the Guard class to add the callback
|
|
91
|
+
# @param [Symbol] event the event to look for
|
|
92
|
+
#
|
|
93
|
+
def has_callback?(listener, guard_class, event)
|
|
94
|
+
callbacks[[guard_class, event]].include?(listener)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Notify a callback.
|
|
98
|
+
#
|
|
99
|
+
# @param [Guard::Guard] guard_class the Guard class to add the callback
|
|
100
|
+
# @param [Symbol] event the event to trigger
|
|
101
|
+
# @param [Array] args the arguments for the listener
|
|
102
|
+
#
|
|
103
|
+
def notify(guard_class, event, *args)
|
|
104
|
+
callbacks[[guard_class, event]].each do |listener|
|
|
105
|
+
listener.call(guard_class, event, *args)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Reset all callbacks.
|
|
110
|
+
#
|
|
111
|
+
def reset_callbacks!
|
|
112
|
+
@callbacks = nil
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
end
|
|
118
|
+
end
|