2010-12-08 13:49:28 +00:00
|
|
|
# (C) John Mair (banisterfiend) 2010
|
|
|
|
# MIT License
|
|
|
|
|
|
|
|
direc = File.dirname(__FILE__)
|
|
|
|
|
2010-12-07 08:11:35 +00:00
|
|
|
require 'rubygems'
|
|
|
|
require 'readline'
|
|
|
|
require 'ruby_parser'
|
2010-12-08 13:49:28 +00:00
|
|
|
require "#{direc}/pry/version"
|
2010-12-07 08:11:35 +00:00
|
|
|
|
2010-12-08 00:19:55 +00:00
|
|
|
module Pry
|
2010-12-08 11:39:06 +00:00
|
|
|
class << self
|
|
|
|
attr_accessor :default_prompt, :wait_prompt,
|
|
|
|
:session_start_msg, :session_end_msg
|
|
|
|
end
|
|
|
|
|
|
|
|
@default_prompt = proc { |v| "pry(#{v})> " }
|
|
|
|
@wait_prompt = proc { |v| "pry(#{v})* " }
|
|
|
|
@session_start_msg = proc { |v| "Beginning Pry session for #{v}" }
|
|
|
|
@session_end_msg = proc { |v| "Ending Pry session for #{v}" }
|
2010-12-08 13:49:28 +00:00
|
|
|
|
|
|
|
# useful for ending all Pry sessions currently active
|
|
|
|
@dead = false
|
2010-12-08 11:39:06 +00:00
|
|
|
|
2010-12-08 07:30:38 +00:00
|
|
|
# loop
|
|
|
|
def self.repl(target=TOPLEVEL_BINDING)
|
|
|
|
if !target.is_a?(Binding)
|
|
|
|
target = target.instance_eval { binding }
|
|
|
|
end
|
2010-12-08 13:49:28 +00:00
|
|
|
|
|
|
|
target_self = target.eval('self')
|
|
|
|
puts session_start_msg.call(target_self)
|
2010-12-08 11:39:06 +00:00
|
|
|
|
2010-12-08 07:30:38 +00:00
|
|
|
loop do
|
2010-12-08 13:49:28 +00:00
|
|
|
if catch(:pop) { rep(target) } == :return || @dead
|
|
|
|
break
|
2010-12-08 07:30:38 +00:00
|
|
|
end
|
2010-12-07 08:11:35 +00:00
|
|
|
end
|
2010-12-08 11:39:06 +00:00
|
|
|
|
2010-12-08 13:49:28 +00:00
|
|
|
puts session_end_msg.call(target_self)
|
|
|
|
|
|
|
|
target_self
|
2010-12-08 00:19:55 +00:00
|
|
|
end
|
|
|
|
|
2010-12-08 11:39:06 +00:00
|
|
|
class << self
|
|
|
|
alias_method :into, :repl
|
|
|
|
alias_method :start, :repl
|
|
|
|
end
|
|
|
|
|
2010-12-08 07:30:38 +00:00
|
|
|
# print
|
2010-12-08 12:06:49 +00:00
|
|
|
def self.rep(target=TOPLEVEL_BINDING)
|
2010-12-08 07:30:38 +00:00
|
|
|
if !target.is_a?(Binding)
|
|
|
|
target = target.instance_eval { binding }
|
|
|
|
end
|
2010-12-07 08:11:35 +00:00
|
|
|
|
2010-12-08 07:30:38 +00:00
|
|
|
value = re(target)
|
|
|
|
case value
|
|
|
|
when Exception
|
|
|
|
puts "#{value.class}: #{value.message}"
|
|
|
|
else
|
|
|
|
puts "=> #{value.inspect}"
|
|
|
|
end
|
|
|
|
end
|
2010-12-08 00:19:55 +00:00
|
|
|
|
2010-12-08 07:30:38 +00:00
|
|
|
# eval
|
|
|
|
def self.re(target=TOPLEVEL_BINDING)
|
|
|
|
target.eval r(target)
|
|
|
|
rescue StandardError => e
|
|
|
|
e
|
|
|
|
end
|
2010-12-08 00:19:55 +00:00
|
|
|
|
2010-12-08 07:30:38 +00:00
|
|
|
# read
|
|
|
|
def self.r(target=TOPLEVEL_BINDING)
|
|
|
|
eval_string = ""
|
|
|
|
loop do
|
|
|
|
val = Readline.readline(prompt(eval_string, target), true)
|
|
|
|
eval_string += "#{val}\n"
|
2010-12-08 11:39:06 +00:00
|
|
|
process_commands(val, eval_string, target)
|
2010-12-08 07:30:38 +00:00
|
|
|
|
|
|
|
break eval_string if valid_expression?(eval_string)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-12-08 11:39:06 +00:00
|
|
|
def self.process_commands(val, eval_string, target)
|
2010-12-08 07:30:38 +00:00
|
|
|
case val
|
2010-12-08 11:39:06 +00:00
|
|
|
when "#exit", "#quit"
|
2010-12-08 07:30:38 +00:00
|
|
|
exit
|
|
|
|
when "!"
|
|
|
|
eval_string.replace("")
|
|
|
|
puts "Refreshed REPL."
|
2010-12-08 11:39:06 +00:00
|
|
|
when "exit", "quit"
|
2010-12-08 07:30:38 +00:00
|
|
|
throw(:pop, :return)
|
2010-12-07 08:11:35 +00:00
|
|
|
end
|
2010-12-08 07:30:38 +00:00
|
|
|
end
|
2010-12-07 08:11:35 +00:00
|
|
|
|
2010-12-08 07:30:38 +00:00
|
|
|
def self.prompt(eval_string, target)
|
|
|
|
context = target.eval('self')
|
|
|
|
|
|
|
|
if eval_string.empty?
|
2010-12-08 11:39:06 +00:00
|
|
|
default_prompt.call(context)
|
2010-12-08 00:19:55 +00:00
|
|
|
else
|
2010-12-08 11:39:06 +00:00
|
|
|
wait_prompt.call(context)
|
2010-12-08 00:19:55 +00:00
|
|
|
end
|
2010-12-07 08:11:35 +00:00
|
|
|
end
|
2010-12-08 00:19:55 +00:00
|
|
|
|
2010-12-08 07:30:38 +00:00
|
|
|
def self.valid_expression?(code)
|
|
|
|
RubyParser.new.parse(code)
|
2010-12-08 13:49:28 +00:00
|
|
|
rescue Racc::ParseError, SyntaxError
|
2010-12-08 07:30:38 +00:00
|
|
|
false
|
|
|
|
else
|
|
|
|
true
|
|
|
|
end
|
2010-12-08 13:49:28 +00:00
|
|
|
|
|
|
|
def self.kill
|
|
|
|
@dead = true
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.revive
|
|
|
|
@dead = false
|
|
|
|
end
|
2010-12-08 00:19:55 +00:00
|
|
|
end
|