/
hooker.rb
108 lines (99 loc) · 3.42 KB
/
hooker.rb
1
2
3
4
5
6
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
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
module Guard
class Plugin
# Guard has a hook mechanism that allows you to insert callbacks for
# individual Guard plugins.
# By default, each of the Guard plugin instance methods has a "_begin" and
# an "_end" hook.
# For example, the Guard::Plugin#start method has a :start_begin hook that
# is runs immediately before Guard::Plugin#start, and a :start_end hook
# that runs immediately after Guard::Plugin#start.
#
# Read more about [hooks and callbacks on the
# wiki](https://github.com/guard/guard/wiki/Hooks-and-callbacks).
#
module Hooker
require "guard/ui"
# Get all callbacks registered for all Guard plugins present in the
# Guardfile.
#
def self.callbacks
@callbacks ||= Hash.new { |hash, key| hash[key] = [] }
end
# Add a callback.
#
# @param [Block] listener the listener to notify
# @param [Guard::Plugin] guard_plugin the Guard plugin to add the callback
# @param [Array<Symbol>] events the events to register
#
def self.add_callback(listener, guard_plugin, events)
Array(events).each do |event|
callbacks[[guard_plugin, event]] << listener
end
end
# Notify a callback.
#
# @param [Guard::Plugin] guard_plugin the Guard plugin to add the callback
# @param [Symbol] event the event to trigger
# @param [Array] args the arguments for the listener
#
def self.notify(guard_plugin, event, *args)
callbacks[[guard_plugin, event]].each do |listener|
listener.call(guard_plugin, event, *args)
end
end
# Reset all callbacks.
#
def self.reset_callbacks!
@callbacks = nil
end
# When event is a Symbol, {#hook} will generate a hook name
# by concatenating the method name from where {#hook} is called
# with the given Symbol.
#
# @example Add a hook with a Symbol
#
# def run_all
# hook :foo
# end
#
# Here, when {Guard::Plugin::Base#run_all} is called, {#hook} will notify
# callbacks registered for the "run_all_foo" event.
#
# When event is a String, {#hook} will directly turn the String
# into a Symbol.
#
# @example Add a hook with a String
#
# def run_all
# hook "foo_bar"
# end
#
# When {Guard::Plugin::Base#run_all} is called, {#hook} will notify
# callbacks registered for the "foo_bar" event.
#
# @param [Symbol, String] event the name of the Guard event
# @param [Array] args the parameters are passed as is to the callbacks
# registered for the given event.
#
def hook(event, *args)
hook_name = if event.is_a? Symbol
calling_method = caller[0][/`([^']*)'/, 1]
"#{ calling_method }_#{ event }"
else
event
end
::Guard::UI.debug "Hook :#{ hook_name } executed for #{ self.class }"
Hooker.notify(self, hook_name.to_sym, *args)
end
private
# Add all the Guard::Plugin's callbacks to the global @callbacks array
# that's used by Guard to know which callbacks to notify.
#
def _register_callbacks
callbacks.each do |callback|
Hooker.add_callback(callback[:listener], self, callback[:events])
end
end
end
end
end