Class: Pry::Hooks

Inherits:
Object show all
Defined in:
lib/pry/hooks.rb

Overview

Implements a hooks system for Pry. A hook is a callable that is associated with an event. A number of events are currently provided by Pry, these include: :when_started, :before_session, :after_session. A hook must have a name, and is connected with an event by the Pry::Hooks#add_hook method.

Examples:

Adding a hook for the :before_session event.

Pry.config.hooks.add_hook(:before_session, :say_hi) do
  puts "hello"
end

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeHooks



29
30
31
# File 'lib/pry/hooks.rb', line 29

def initialize
  @hooks = {}
end

Class Method Details

.from_hash(hash) ⇒ Pry::Hooks

Converts a hash to a Pry::Hooks instance. All hooks defined this way are anonymous. This functionality is primarily to provide backwards-compatibility with the old hash-based hook system in Pry versions < 0.9.8



20
21
22
23
24
25
26
27
# File 'lib/pry/hooks.rb', line 20

def self.from_hash(hash)
  return hash if hash.instance_of?(self)
  instance = new
  hash.each do |k, v|
    instance.add_hook(k, nil, v)
  end
  instance
end

Instance Method Details

#[](event_name) ⇒ Object

FIXME: This is a hack to alert people of the new API.



54
55
56
57
58
# File 'lib/pry/hooks.rb', line 54

def [](event_name)
  warn "`Pry.hooks[]` is deprecated! Please use the new `Pry::Hooks` API! http://rubydoc.info/github/pry/pry/master/Pry/Hooks"

  get_hook(event_name, nil)
end

#[]=(event_name, callable) ⇒ Object

FIXME: This is a hack to alert people of the new API.



62
63
64
65
66
# File 'lib/pry/hooks.rb', line 62

def []=(event_name, callable)
  warn "`Pry.hooks[]=` is deprecated! Please use the new `Pry::Hooks` API! http://rubydoc.info/github/pry/pry/master/Pry/Hooks"

  add_hook(event_name, nil, callable)
end

#add_hook(event_name, hook_name, callable = nil) { ... } ⇒ Pry:Hooks

Add a new hook to be executed for the name even.

Examples:

Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }

Yields:

  • The block to use as the callable (if callable parameter not provided)



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/pry/hooks.rb', line 114

def add_hook(event_name, hook_name, callable=nil, &block)
  @hooks[event_name] ||= []

  # do not allow duplicates, but allow multiple `nil` hooks
  # (anonymous hooks)
  if hook_exists?(event_name, hook_name) && !hook_name.nil?
    raise ArgumentError, "Hook with name '#{hook_name}' already defined!"
  end

  if !block && !callable
    raise ArgumentError, "Must provide a block or callable."
  end

  # ensure we only have one anonymous hook
  @hooks[event_name].delete_if { |h, k| h.nil? } if hook_name.nil?

  if block
    @hooks[event_name] << [hook_name, block]
  elsif callable
    @hooks[event_name] << [hook_name, callable]
  end

  self
end

#clear_allObject

Remove all events and hooks, clearing out the Pry::Hooks instance completely.

Examples:

my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
my_hooks.clear_all


235
236
237
# File 'lib/pry/hooks.rb', line 235

def clear_all
  @hooks = {}
end

#delete_hook(event_name, hook_name) ⇒ #call

Delete a hook for an event.

Examples:

my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
my_hooks.delete_hook(:before_session, :say_hi)


204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/pry/hooks.rb', line 204

def delete_hook(event_name, hook_name)
  @hooks[event_name] ||= []
  deleted_callable = nil

  @hooks[event_name].delete_if do |current_hook_name, callable|
    if current_hook_name == hook_name
      deleted_callable = callable
      true
    else
      false
    end
  end
  deleted_callable
end

#delete_hooks(event_name) ⇒ Object Also known as: clear

Clear all hooks functions for a given event.

Examples:

my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
my_hooks.delete_hook(:before_session)


224
225
226
# File 'lib/pry/hooks.rb', line 224

def delete_hooks(event_name)
  @hooks[event_name] = []
end

#errorsObject



48
49
50
# File 'lib/pry/hooks.rb', line 48

def errors
  @errors ||= []
end

#exec_hook(event_name, *args, &block) ⇒ Object

Execute the list of hooks for the event_name event.

Examples:

my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
my_hooks.exec_hook(:before_session) #=> OUTPUT: "hi!"


146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/pry/hooks.rb', line 146

def exec_hook(event_name, *args, &block)
  @hooks[event_name] ||= []

  @hooks[event_name].map do |hook_name, callable|
    begin
      callable.call(*args, &block)
    rescue RescuableException => e
      errors << e
      e
    end
  end.last
end

#get_hook(event_name, hook_name) ⇒ #call

Return a specific hook for a given event.

Examples:

my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
my_hooks.get_hook(:before_session, :say_hi).call #=> "hi!"


177
178
179
180
181
# File 'lib/pry/hooks.rb', line 177

def get_hook(event_name, hook_name)
  @hooks[event_name] ||= []
  hook = @hooks[event_name].find { |current_hook_name, callable| current_hook_name == hook_name }
  hook.last if hook
end

#get_hooks(event_name) ⇒ Hash

Return the hash of hook names / hook functions for a given event. (Note that modifying the returned hash does not alter the hooks, use add_hook/delete_hook for that).

Examples:

my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
my_hooks.get_hooks(:before_session) #=> {:say_hi=>#<Proc:0x00000101645e18@(pry):9>}


191
192
193
194
# File 'lib/pry/hooks.rb', line 191

def get_hooks(event_name)
  @hooks[event_name] ||= []
  Hash[@hooks[event_name]]
end

#hook_count(event_name) ⇒ Fixnum

Return the number of hook functions registered for the event_name event.

Examples:

my_hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
my_hooks.count(:before_session) #=> 1


165
166
167
168
# File 'lib/pry/hooks.rb', line 165

def hook_count(event_name)
  @hooks[event_name] ||= []
  @hooks[event_name].size
end

#hook_exists?(event_name, hook_name) ⇒ Boolean



242
243
244
# File 'lib/pry/hooks.rb', line 242

def hook_exists?(event_name, hook_name)
  !!(@hooks[event_name] && @hooks[event_name].find { |name, _| name == hook_name })
end

#initialize_copy(orig) ⇒ Object

Ensure that duplicates have their @hooks object



34
35
36
37
38
39
40
41
# File 'lib/pry/hooks.rb', line 34

def initialize_copy(orig)
  hooks_dup = @hooks.dup
  @hooks.each do |k, v|
    hooks_dup[k] = v.dup
  end

  @hooks = hooks_dup
end

#merge(other) ⇒ Pry::Hooks

Return a new Pry::Hooks instance containing a merge of the contents of two Pry:Hooks instances,

Examples:

hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
Pry::Hooks.new.merge(hooks)


100
101
102
103
104
# File 'lib/pry/hooks.rb', line 100

def merge(other)
  self.dup.tap do |v|
    v.merge!(other)
  end
end

#merge!(other) ⇒ Pry:Hooks

Destructively merge the contents of two Pry:Hooks instances.

Examples:

hooks = Pry::Hooks.new.add_hook(:before_session, :say_hi) { puts "hi!" }
Pry::Hooks.new.merge!(hooks)


74
75
76
77
78
79
80
# File 'lib/pry/hooks.rb', line 74

def merge!(other)
  @hooks.merge!(other.dup.hooks) do |key, v1, v2|
    merge_arrays(v1, v2)
  end

  self
end

#merge_arrays(array1, array2) ⇒ Object (private)



82
83
84
# File 'lib/pry/hooks.rb', line 82

def merge_arrays(array1, array2)
  uniq_keeping_last(array1 + array2, &:first)
end

#uniq_keeping_last(input, &block) ⇒ Object (private)



87
88
89
90
91
# File 'lib/pry/hooks.rb', line 87

def uniq_keeping_last(input, &block)
  hash, output = {}, []
  input.reverse.each{ |i| hash[block[i]] ||= (output.unshift i) }
  output
end