mirror of
https://github.com/pry/pry.git
synced 2022-11-09 12:35:05 -05:00
adding READMEs and CHANGELOG etc
This commit is contained in:
parent
a3399b96ed
commit
2dc06b23c8
6 changed files with 242 additions and 70 deletions
3
CHANGELOG
Normal file
3
CHANGELOG
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
8/12/2010 version 0.1.0
|
||||||
|
* release!
|
||||||
|
|
105
README.markdown
Normal file
105
README.markdown
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
Pry
|
||||||
|
=============
|
||||||
|
|
||||||
|
(C) John Mair (banisterfiend) 2010
|
||||||
|
|
||||||
|
_attach an irb-like session to any object_
|
||||||
|
|
||||||
|
Pry is a simple Ruby REPL that specializes in interactively manipulates objects during the running of the program.
|
||||||
|
|
||||||
|
Based on some ideas found in this [Ruby-Forum thread](http://www.ruby-forum.com/topic/179060)
|
||||||
|
|
||||||
|
`Tweak` provides the `using` method.
|
||||||
|
|
||||||
|
* Install the [gem](https://rubygems.org/gems/tweak): `gem install tweak`
|
||||||
|
* Read the [documentation](http://rdoc.info/github/banister/tweak/master/file/README.markdown)
|
||||||
|
* See the [source code](http://github.com/banister/tweak)
|
||||||
|
|
||||||
|
example: using
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
With the `using` method we can enhance a core class for the duration
|
||||||
|
of a block:
|
||||||
|
|
||||||
|
module Tweaks
|
||||||
|
|
||||||
|
class String
|
||||||
|
def hello
|
||||||
|
:hello
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Fixnum
|
||||||
|
Hello = :hello
|
||||||
|
|
||||||
|
def bye
|
||||||
|
:bye
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
using Tweaks do
|
||||||
|
"john".hello #=> :hello
|
||||||
|
5.bye #=> :bye
|
||||||
|
Fixnum::Hello #=> :hello
|
||||||
|
end
|
||||||
|
|
||||||
|
"john".hello #=> NameError
|
||||||
|
|
||||||
|
How it works
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Makes use of the `Remix` and `Object2module` libraries. Note that `Tweak`
|
||||||
|
modifies core classes by what is effectively a module inclusion, this
|
||||||
|
means you cannot use `Tweak` to override existing functionality but
|
||||||
|
more to augment and supplement that functionality.
|
||||||
|
|
||||||
|
`Tweak` works by doing the following:
|
||||||
|
|
||||||
|
* Looks for top-level classes and modules with the same name as those
|
||||||
|
defined under the using-module.
|
||||||
|
* Uses `Object2module` to include the corresponding class/module
|
||||||
|
defined under the using-module into the top-level class/module of the
|
||||||
|
same name.
|
||||||
|
* Uses `Remix` to uninclude that functionality at the end of the
|
||||||
|
`using` block.
|
||||||
|
|
||||||
|
Also look at the [Remix](http://github.com/banister/remix) library's
|
||||||
|
`temp_include` and `temp_extend` methods for a more general solution than `Tweak`.
|
||||||
|
|
||||||
|
Thread Safety
|
||||||
|
--------------
|
||||||
|
|
||||||
|
`Tweak` is not threadsafe.
|
||||||
|
|
||||||
|
Limitations
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Does not work with nested modules, e.g `class String::SomethingElse`
|
||||||
|
|
||||||
|
This is not intended to be a robust or serious solution, it's just a
|
||||||
|
little experiment. :)
|
||||||
|
|
||||||
|
Companion Libraries
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Tweak is one of a series of experimental libraries that mess with
|
||||||
|
the internals of Ruby to bring new and interesting functionality to
|
||||||
|
the language, see also:
|
||||||
|
|
||||||
|
* [Remix](http://github.com/banister/remix) - Makes ancestor chains read/write
|
||||||
|
* [Object2module](http://github.com/banister/object2module) - Enables you to include/extend Object/Classes.
|
||||||
|
* [Include Complete](http://github.com/banister/include_complete) - Brings in
|
||||||
|
module singleton classes during an include. No more ugly ClassMethods and included() hook hacks.
|
||||||
|
* [Prepend](http://github.com/banister/prepend) - Prepends modules in front of a class; so method lookup starts with the module
|
||||||
|
* [GenEval](http://github.com/banister/gen_eval) - A strange new breed of instance_eval
|
||||||
|
* [LocalEval](http://github.com/banister/local_eval) - instance_eval without changing self
|
||||||
|
|
||||||
|
Contact
|
||||||
|
-------
|
||||||
|
|
||||||
|
Problems or questions contact me at [github](http://github.com/banister)
|
||||||
|
|
||||||
|
|
||||||
|
|
58
Rakefile
Normal file
58
Rakefile
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
dlext = Config::CONFIG['DLEXT']
|
||||||
|
direc = File.dirname(__FILE__)
|
||||||
|
|
||||||
|
require 'rake/clean'
|
||||||
|
require 'rake/gempackagetask'
|
||||||
|
require "#{direc}/lib/pry/version"
|
||||||
|
|
||||||
|
CLOBBER.include("**/*.#{dlext}", "**/*~", "**/*#*", "**/*.log", "**/*.o")
|
||||||
|
CLEAN.include("ext/**/*.#{dlext}", "ext/**/*.log", "ext/**/*.o",
|
||||||
|
"ext/**/*~", "ext/**/*#*", "ext/**/*.obj",
|
||||||
|
"ext/**/*.def", "ext/**/*.pdb", "**/*_flymake*.*", "**/*_flymake")
|
||||||
|
|
||||||
|
def apply_spec_defaults(s)
|
||||||
|
s.name = "pry"
|
||||||
|
s.summary = "Open an irb-like session on any object"
|
||||||
|
s.version = Pry::VERSION
|
||||||
|
s.date = Time.now.strftime '%Y-%m-%d'
|
||||||
|
s.author = "John Mair (banisterfiend)"
|
||||||
|
s.email = 'jrmair@gmail.com'
|
||||||
|
s.description = s.summary
|
||||||
|
s.require_path = 'lib'
|
||||||
|
s.add_dependency("ruby_parser",">=2.0.5")
|
||||||
|
s.homepage = "http://banisterfiend.wordpress.com"
|
||||||
|
s.has_rdoc = 'yard'
|
||||||
|
s.files = Dir["ext/**/extconf.rb", "ext/**/*.h", "ext/**/*.c", "lib/**/*.rb",
|
||||||
|
"test/*.rb", "CHANGELOG", "README.markdown", "Rakefile"]
|
||||||
|
end
|
||||||
|
|
||||||
|
task :test do
|
||||||
|
sh "bacon -k #{direc}/test/test.rb"
|
||||||
|
end
|
||||||
|
|
||||||
|
namespace :ruby do
|
||||||
|
spec = Gem::Specification.new do |s|
|
||||||
|
apply_spec_defaults(s)
|
||||||
|
s.platform = Gem::Platform::RUBY
|
||||||
|
end
|
||||||
|
|
||||||
|
Rake::GemPackageTask.new(spec) do |pkg|
|
||||||
|
pkg.need_zip = false
|
||||||
|
pkg.need_tar = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "build all platform gems at once"
|
||||||
|
task :gems => [:rmgems, "ruby:gem"]
|
||||||
|
|
||||||
|
desc "remove all platform gems"
|
||||||
|
task :rmgems => ["ruby:clobber_package"]
|
||||||
|
|
||||||
|
desc "build and push latest gems"
|
||||||
|
task :pushgems => :gems do
|
||||||
|
chdir("#{direc}/pkg") do
|
||||||
|
Dir["*.gem"].each do |gemfile|
|
||||||
|
sh "gem push #{gemfile}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
127
lib/pry.rb
127
lib/pry.rb
|
@ -3,66 +3,85 @@ require 'readline'
|
||||||
require 'ruby_parser'
|
require 'ruby_parser'
|
||||||
|
|
||||||
module Pry
|
module Pry
|
||||||
module RubyParserExtension
|
DEFAULT_PROMPT = proc { |v| "pry(#{v})> " }
|
||||||
def valid?(code)
|
DEFAULT_WAIT_PROMPT = proc { |v| "pry(#{v})* " }
|
||||||
new.parse(code)
|
|
||||||
rescue Racc::ParseError
|
# loop
|
||||||
false
|
def self.repl(target=TOPLEVEL_BINDING)
|
||||||
else
|
if !target.is_a?(Binding)
|
||||||
true
|
target = target.instance_eval { binding }
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
loop do
|
||||||
def self.repl_loop(target=TOPLEVEL_BINDING)
|
if catch(:pop) { rep(target) } == :return
|
||||||
repl(target, :loop => true)
|
return target.eval('self')
|
||||||
end
|
|
||||||
|
|
||||||
def self.repl(target=TOPLEVEL_BINDING, options={:loop => false})
|
|
||||||
prompt = ""
|
|
||||||
code = proc do
|
|
||||||
eval_string = ""
|
|
||||||
while true
|
|
||||||
if eval_string.empty?
|
|
||||||
prompt = "> "
|
|
||||||
else
|
|
||||||
prompt = "* "
|
|
||||||
end
|
|
||||||
|
|
||||||
val = Readline.readline(prompt, true)
|
|
||||||
eval_string += "#{val}\n"
|
|
||||||
|
|
||||||
if val == "#"
|
|
||||||
elsif val == "#pop"
|
|
||||||
puts "Poppping back"
|
|
||||||
return
|
|
||||||
elsif (_, new_target = val.split(/#target\s*\=\s*/)).size > 1
|
|
||||||
target = target.eval(new_target)
|
|
||||||
eval_string = ""
|
|
||||||
puts "Context changed to #{target}"
|
|
||||||
break
|
|
||||||
end
|
|
||||||
|
|
||||||
abort if val == "abort"
|
|
||||||
exit if val == "exit"
|
|
||||||
exit if val == "quit"
|
|
||||||
|
|
||||||
break if RubyParser.valid?(eval_string)
|
|
||||||
end
|
|
||||||
begin
|
|
||||||
puts "=> #{target.eval(eval_string).inspect}"
|
|
||||||
rescue StandardError => e
|
|
||||||
puts "#{e.message}"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if options[:loop]
|
# print
|
||||||
loop(&code)
|
def self.rep(target=TOP_LEVEL_BINDING)
|
||||||
|
if !target.is_a?(Binding)
|
||||||
|
target = target.instance_eval { binding }
|
||||||
|
end
|
||||||
|
|
||||||
|
value = re(target)
|
||||||
|
case value
|
||||||
|
when Exception
|
||||||
|
puts "#{value.class}: #{value.message}"
|
||||||
else
|
else
|
||||||
code.call
|
puts "=> #{value.inspect}"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
# eval
|
||||||
|
def self.re(target=TOPLEVEL_BINDING)
|
||||||
|
target.eval r(target)
|
||||||
|
rescue StandardError => e
|
||||||
|
e
|
||||||
|
end
|
||||||
|
|
||||||
|
# read
|
||||||
|
def self.r(target=TOPLEVEL_BINDING)
|
||||||
|
eval_string = ""
|
||||||
|
loop do
|
||||||
|
val = Readline.readline(prompt(eval_string, target), true)
|
||||||
|
eval_string += "#{val}\n"
|
||||||
|
process_commands(val, eval_string)
|
||||||
|
|
||||||
|
break eval_string if valid_expression?(eval_string)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.process_commands(val, eval_string)
|
||||||
|
case val
|
||||||
|
when "exit", "quit"
|
||||||
|
exit
|
||||||
|
when "!"
|
||||||
|
eval_string.replace("")
|
||||||
|
puts "Refreshed REPL."
|
||||||
|
when "#pop"
|
||||||
|
puts "Popping up a context."
|
||||||
|
throw(:pop, :return)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
class RubyParser
|
def self.prompt(eval_string, target)
|
||||||
extend Pry::RubyParserExtension
|
context = target.eval('self')
|
||||||
|
|
||||||
|
if eval_string.empty?
|
||||||
|
DEFAULT_PROMPT.call(context)
|
||||||
|
else
|
||||||
|
DEFAULT_WAIT_PROMPT.call(context)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.valid_expression?(code)
|
||||||
|
RubyParser.new.parse(code)
|
||||||
|
rescue Racc::ParseError
|
||||||
|
false
|
||||||
|
else
|
||||||
|
true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
3
lib/pry/version.rb
Normal file
3
lib/pry/version.rb
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
module Pry
|
||||||
|
VERSION = "0.1.0"
|
||||||
|
end
|
|
@ -1,16 +0,0 @@
|
||||||
require './pry'
|
|
||||||
|
|
||||||
o = Object.new
|
|
||||||
class << o
|
|
||||||
def pig;
|
|
||||||
puts "pig!!!"
|
|
||||||
end
|
|
||||||
|
|
||||||
def horse?
|
|
||||||
puts "HORSEY LOL"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
5.times {
|
|
||||||
pry(o)
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue