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
|
125
lib/pry.rb
125
lib/pry.rb
|
@ -3,66 +3,85 @@ require 'readline'
|
|||
require 'ruby_parser'
|
||||
|
||||
module Pry
|
||||
module RubyParserExtension
|
||||
def valid?(code)
|
||||
new.parse(code)
|
||||
rescue Racc::ParseError
|
||||
false
|
||||
else
|
||||
true
|
||||
DEFAULT_PROMPT = proc { |v| "pry(#{v})> " }
|
||||
DEFAULT_WAIT_PROMPT = proc { |v| "pry(#{v})* " }
|
||||
|
||||
# loop
|
||||
def self.repl(target=TOPLEVEL_BINDING)
|
||||
if !target.is_a?(Binding)
|
||||
target = target.instance_eval { binding }
|
||||
end
|
||||
end
|
||||
|
||||
def self.repl_loop(target=TOPLEVEL_BINDING)
|
||||
repl(target, :loop => true)
|
||||
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}"
|
||||
loop do
|
||||
if catch(:pop) { rep(target) } == :return
|
||||
return target.eval('self')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if options[:loop]
|
||||
loop(&code)
|
||||
# print
|
||||
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
|
||||
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
|
||||
end
|
||||
|
||||
class RubyParser
|
||||
extend Pry::RubyParserExtension
|
||||
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
|
||||
|
||||
def self.prompt(eval_string, target)
|
||||
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
|
||||
|
|
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…
Reference in a new issue