1
0
Fork 0
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:
John Mair 2010-12-08 20:30:38 +13:00
parent a3399b96ed
commit 2dc06b23c8
6 changed files with 242 additions and 70 deletions

3
CHANGELOG Normal file
View file

@ -0,0 +1,3 @@
8/12/2010 version 0.1.0
* release!

105
README.markdown Normal file
View 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
View 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

View file

@ -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
View file

@ -0,0 +1,3 @@
module Pry
VERSION = "0.1.0"
end

View file

@ -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)
}