1
0
Fork 0
mirror of https://github.com/pry/pry.git synced 2022-11-09 12:35:05 -05:00

added basic skeleton for hooks system (yet to add many hook callsites)

This commit is contained in:
John Mair 2011-11-13 02:03:02 +13:00
commit c02772af19
9 changed files with 167 additions and 31 deletions

View file

@ -4,19 +4,19 @@
require 'pp' require 'pp'
require 'pry/helpers/base_helpers' require 'pry/helpers/base_helpers'
require 'pry/hooks'
class Pry class Pry
# The default hooks - display messages when beginning and ending Pry sessions. # The default hooks - display messages when beginning and ending Pry sessions.
DEFAULT_HOOKS = { DEFAULT_HOOKS = Pry::Hooks.new.add_hook(:before_session) do |out, target, _pry_|
:before_session => proc do |out, target, _pry_|
# ensure we're actually in a method # ensure we're actually in a method
file = target.eval('__FILE__') file = target.eval('__FILE__')
# /unknown/ for rbx # /unknown/ for rbx
if file == Pry.eval_path || (file !~ /(\(.*\))|<.*>/ && file !~ /__unknown__/ && file != "" && file != "-e") if file !~ /(\(.*\))|<.*>/ && file !~ /__unknown__/ && file != "" && file != "-e"
_pry_.process_line("whereami 5", "", target) _pry_.process_line("whereami 5", "", target)
end end
end end
}
# The default print # The default print
DEFAULT_PRINT = proc do |output, value| DEFAULT_PRINT = proc do |output, value|

52
lib/pry/hooks.rb Normal file
View file

@ -0,0 +1,52 @@
class Pry
class Hooks
def initialize
@hooks = {}
end
# Add a new callable to be executed for the `name` hook.
# @param [Symbol] name The name of the hook.
# @param [#call] callable The callable.
# @yield The block to use as the callable (if `callable` parameter not provided)
def add_hook(name, callable=nil, &block)
@hooks[name] ||= []
if block
@hooks[name] << block
elsif callable
@hooks[name] << callable
else
raise ArgumentError, "Must provide a block or callable."
end
self
end
# Execute the list of callables for the `name` hook.
# @param [Symbol] name The name of the hook to execute.
# @param [Array] args The arguments to pass to each callable.
def exec_hook(name, *args, &block)
Array(@hooks[name]).each { |v| v.call(*args, &block) }
end
# Return the number of callables registered for the `name` hook.
# @param [Symbol] name The name of the hook.
def hook_count(name)
@hooks[name] ||= []
@hooks[name].size
end
# Clear the list of callables for the `name` hook.
# @param [Symbol] The name of the hook to delete.
def delete_hook(name)
@hooks[name] = []
end
# Clear all hooks.
def reset
@hooks = {}
end
end
end

View file

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
class Pry class Pry
class Method class Method
include RbxMethod if Helpers::BaseHelpers.rbx? include RbxMethod if Helpers::BaseHelpers.rbx?
@ -178,7 +179,7 @@ class Pry
if Helpers::BaseHelpers.rbx? && core? if Helpers::BaseHelpers.rbx? && core?
code = core_code code = core_code
elsif pry_method? elsif pry_method?
code = Pry.new(:input => StringIO.new(Pry.line_buffer[source_line..-1].join), :prompt => proc {""}, :hooks => {}).r code = Pry.new(:input => StringIO.new(Pry.line_buffer[source_line..-1].join), :prompt => proc {""}, :hooks => Pry::Hooks.new).r
else else
code = @method.source code = @method.source
end end

View file

@ -165,7 +165,7 @@ class Pry
output = options[:show_output] ? options[:output] : StringIO.new output = options[:show_output] ? options[:output] : StringIO.new
Pry.new(:output => output, :input => StringIO.new(command_string), :commands => options[:commands], :prompt => proc {""}, :hooks => {}).rep(options[:context]) Pry.new(:output => output, :input => StringIO.new(command_string), :commands => options[:commands], :prompt => proc {""}, :hooks => Pry::Hooks.new).rep(options[:context])
end end
def self.default_editor_for_platform def self.default_editor_for_platform

View file

@ -149,7 +149,7 @@ class Pry
# Initialize the repl session. # Initialize the repl session.
# @param [Binding] target The target binding for the session. # @param [Binding] target The target binding for the session.
def repl_prologue(target) def repl_prologue(target)
exec_hook :before_session, output, target, self hooks.exec_hook :before_session, output, target, self
initialize_special_locals(target) initialize_special_locals(target)
@input_array << nil # add empty input so _in_ and _out_ match @input_array << nil # add empty input so _in_ and _out_ match
@ -161,7 +161,7 @@ class Pry
# Clean-up after the repl session. # Clean-up after the repl session.
# @param [Binding] target The target binding for the session. # @param [Binding] target The target binding for the session.
def repl_epilogue(target) def repl_epilogue(target)
exec_hook :after_session, output, target, self hooks.exec_hook :after_session, output, target, self
Pry.active_sessions -= 1 Pry.active_sessions -= 1
binding_stack.pop binding_stack.pop
@ -235,9 +235,10 @@ class Pry
result = set_last_result(target.eval(code, Pry.eval_path, Pry.current_line), target) result = set_last_result(target.eval(code, Pry.eval_path, Pry.current_line), target)
result result
rescue RescuableException => e rescue RescuableException => e
set_last_exception(e, target) result = set_last_exception(e, target)
ensure ensure
update_input_history(code) update_input_history(code)
hooks.exec_hook :after_eval, result, self
end end
# Perform a read. # Perform a read.
@ -270,6 +271,7 @@ class Pry
@suppress_output = true if eval_string =~ /;\Z/ || eval_string.empty? @suppress_output = true if eval_string =~ /;\Z/ || eval_string.empty?
hooks.exec_hook :after_read, eval_string, self
eval_string eval_string
end end

View file

@ -25,7 +25,7 @@ class << Pry
Pry.config.history.should_load = false Pry.config.history.should_load = false
Pry.config.history.should_save = false Pry.config.history.should_save = false
Pry.config.auto_indent = false Pry.config.auto_indent = false
Pry.config.hooks = { } Pry.config.hooks = Pry::Hooks.new
end end
end end

View file

@ -154,7 +154,7 @@ describe "Pry::DefaultCommands::Input" do
b = binding b = binding
b.eval('x = "\"hello\""') b.eval('x = "\"hello\""')
redirect_pry_io(InputTester.new("play x", "exit-all"), str_output = StringIO.new) do redirect_pry_io(InputTester.new("play x", "exit-all"), str_output = StringIO.new) do
Pry.start b, :hooks => {} Pry.start b, :hooks => Pry::Hooks.new
end end
str_output.string.should =~ /hello/ str_output.string.should =~ /hello/
end end
@ -163,7 +163,7 @@ describe "Pry::DefaultCommands::Input" do
b = binding b = binding
b.eval('x = "\"hello\"\n\"goodbye\"\n\"love\""') b.eval('x = "\"hello\"\n\"goodbye\"\n\"love\""')
redirect_pry_io(InputTester.new("play x --lines 1", "exit-all"), str_output = StringIO.new) do redirect_pry_io(InputTester.new("play x --lines 1", "exit-all"), str_output = StringIO.new) do
Pry.start b, :hooks => {} Pry.start b, :hooks => Pry::Hooks.new
end end
str_output.string.should =~ /hello/ str_output.string.should =~ /hello/
str_output.string.should.not =~ /love/ str_output.string.should.not =~ /love/

85
test/test_hooks.rb Normal file
View file

@ -0,0 +1,85 @@
require 'helper'
describe Pry::Hooks do
before do
@hooks = Pry::Hooks.new
end
describe "adding a new hook" do
it 'should not execute hook while adding it' do
@hooks.add_hook(:test_hook) { @test_var = true }
@test_var.should == nil
end
it 'should return a count of 0 for an empty hook' do
@hooks.hook_count(:test_hook).should == 0
end
it 'should create a new hook with a block' do
@hooks.add_hook(:test_hook) { }
@hooks.hook_count(:test_hook).should == 1
end
it 'should create a new hook with a callable' do
@hooks.add_hook(:test_hook, proc { })
@hooks.hook_count(:test_hook).should == 1
end
it 'should use just block if given both block and callable' do
@hooks.add_hook(:test_hook, proc { }) { }
@hooks.hook_count(:test_hook).should == 1
end
it 'should raise if not given a block or any other object' do
lambda { @hooks.add_hook(:test_hook) }.should.raise ArgumentError
end
it 'should create a hook with multiple callables' do
@hooks.add_hook(:test_hook) {}
@hooks.add_hook(:test_hook) {}
@hooks.hook_count(:test_hook).should == 2
end
end
describe "executing a hook" do
before do
@test_var = nil
end
it 'should execute block hook' do
@hooks.add_hook(:test_hook) { @test_var = true }
@hooks.exec_hook(:test_hook)
@test_var.should == true
end
it 'should execute proc hook' do
@hooks.add_hook(:test_hook, proc { @test_var = true })
@hooks.exec_hook(:test_hook)
@test_var.should == true
end
it 'should execute a general callable hook' do
callable = Object.new.tap do |obj|
obj.instance_variable_set(:@test_var, nil)
class << obj
attr_accessor :test_var
def call() @test_var = true; end
end
end
@hooks.add_hook(:test_hook, callable)
@hooks.exec_hook(:test_hook)
callable.test_var.should == true
end
it 'should execute multiple callables for a hook if more than one is defined' do
x = nil
y = nil
@hooks.add_hook(:test_hook) { x = true }
@hooks.add_hook(:test_hook) { y = true }
@hooks.exec_hook(:test_hook)
x.should == true
y.should == true
end
end
end

View file

@ -1281,10 +1281,9 @@ describe Pry do
it 'should set the hooks default, and the default should be overridable' do it 'should set the hooks default, and the default should be overridable' do
Pry.input = InputTester.new("exit-all") Pry.input = InputTester.new("exit-all")
Pry.hooks = { Pry.hooks = Pry::Hooks.new.
:before_session => proc { |out,_,_| out.puts "HELLO" }, add_hook(:before_session) { |out,_,_| out.puts "HELLO" }.
:after_session => proc { |out,_,_| out.puts "BYE" } add_hook(:after_session) { |out,_,_| out.puts "BYE" }
}
str_output = StringIO.new str_output = StringIO.new
Pry.new(:output => str_output).repl Pry.new(:output => str_output).repl
@ -1295,10 +1294,9 @@ describe Pry do
str_output = StringIO.new str_output = StringIO.new
Pry.new(:output => str_output, Pry.new(:output => str_output,
:hooks => { :hooks => Pry::Hooks.new.
:before_session => proc { |out,_,_| out.puts "MORNING" }, add_hook( :before_session) { |out,_,_| out.puts "MORNING" }.
:after_session => proc { |out,_,_| out.puts "EVENING" } add_hook(:after_session) { |out,_,_| out.puts "EVENING" }
}
).repl ).repl
str_output.string.should =~ /MORNING/ str_output.string.should =~ /MORNING/
@ -1308,9 +1306,8 @@ describe Pry do
Pry.input.rewind Pry.input.rewind
str_output = StringIO.new str_output = StringIO.new
Pry.new(:output => str_output, Pry.new(:output => str_output,
:hooks => { :hooks => Pry::Hooks.new.
:before_session => proc { |out,_,_| out.puts "OPEN" } add_hook(:before_session) { |out,_,_| out.puts "OPEN" }
}
).repl ).repl
str_output.string.should =~ /OPEN/ str_output.string.should =~ /OPEN/
@ -1318,9 +1315,8 @@ describe Pry do
Pry.input.rewind Pry.input.rewind
str_output = StringIO.new str_output = StringIO.new
Pry.new(:output => str_output, Pry.new(:output => str_output,
:hooks => { :hooks => Pry::Hooks.new.
:after_session => proc { |out,_,_| out.puts "CLOSE" } add_hook(:after_session) { |out,_,_| out.puts "CLOSE" }
}
).repl ).repl
str_output.string.should =~ /CLOSE/ str_output.string.should =~ /CLOSE/