Permalink
Browse files

first commit

  • Loading branch information...
0 parents commit 3601caa6203917f2a8df0d683f35a451310eccbe @banister banister committed Nov 11, 2011
Showing with 307 additions and 0 deletions.
  1. 0 .gemtest
  2. +7 −0 .gitignore
  3. +1 −0 .yardopts
  4. 0 CHANGELOG
  5. +25 −0 LICENSE
  6. +56 −0 README.md
  7. +68 −0 Rakefile
  8. +121 −0 lib/pry-stack_explorer.rb
  9. +3 −0 lib/pry-stack_explorer/version.rb
  10. +12 −0 test/test.rb
  11. +14 −0 tester.rb
No changes.
@@ -0,0 +1,7 @@
+Makefile
+*.so
+*.o
+*.def
+doc/
+pkg/
+.yardoc/
@@ -0,0 +1 @@
+--markup markdown
No changes.
25 LICENSE
@@ -0,0 +1,25 @@
+License
+-------
+
+(The MIT License)
+
+Copyright (c) 2011 John Mair (banisterfiend)
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,56 @@
+pry-stack_explore
+===========
+
+(C) John Mair (banisterfiend) 2011
+
+FIXME: _tagline_
+
+FIXME: _description goes here_
+
+* Install the [gem](https://rubygems.org/gems/pry-stack_explore): `gem install pry-stack_explore`
+* Read the [documentation](http://rdoc.info/github/banister/pry-stack_explore/master/file/README.md)
+* See the [source code](http://github.com/banister/pry-stack_explore)
+
+Example: Example description
+--------
+
+Example preamble
+
+ puts "example code"
+
+Features and limitations
+-------------------------
+
+Feature List Preamble
+
+Contact
+-------
+
+Problems or questions contact me at [github](http://github.com/banister)
+
+
+License
+-------
+
+(The MIT License)
+
+Copyright (c) 2011 John Mair (banisterfiend)
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,68 @@
+$:.unshift 'lib'
+
+dlext = Config::CONFIG['DLEXT']
+direc = File.dirname(__FILE__)
+
+PROJECT_NAME = "pry-stack_explorer"
+
+require 'rake/clean'
+require 'rake/gempackagetask'
+require "#{PROJECT_NAME}/version"
+
+CLOBBER.include("**/*~", "**/*#*", "**/*.log")
+CLEAN.include("**/*#*", "**/*#*.*", "**/*_flymake*.*", "**/*_flymake",
+ "**/*.rbc", "**/.#*.*")
+
+def apply_spec_defaults(s)
+ s.name = PROJECT_NAME
+ s.summary = "Walk the stack in a Pry session"
+ s.version = PryStackExplorer::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("binding_of_caller","~>0.5.0")
+ s.add_development_dependency("bacon","~>1.1.0")
+ s.homepage = "https://github.com/banister"
+ s.files = Dir["lib/**/*.rb", "test/*.rb", "CHANGELOG", "README.md", "Rakefile"]
+end
+
+desc "run pry with plugin enabled"
+task :pry do
+ exec("pry -I#{direc}/lib/ -r #{direc}/lib/#{PROJECT_NAME}")
+end
+
+desc "run tests"
+task :test do
+ sh "bacon -Itest -rubygems -a"
+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 => [:clean, :rmgems, "ruby:gem"]
+
+desc "remove all platform gems"
+task :rmgems => ["ruby:clobber_package"]
+
+desc "build and push latest gems"
+task :pushgems => :gems do
+ chdir("#{File.dirname(__FILE__)}/pkg") do
+ Dir["*.gem"].each do |gemfile|
+ sh "gem push #{gemfile}"
+ end
+ end
+end
+
+
@@ -0,0 +1,121 @@
+# pry-stack_explorer.rb
+# (C) John Mair (banisterfiend); MIT license
+
+require "pry-stack_explorer/version"
+require "pry"
+require "binding_of_caller"
+
+module PryStackExplorer
+
+ def self.bindings_equal?(b1, b2)
+ (b1.eval('self') == b2.eval('self')) &&
+ (b1.eval('local_variables').map { |v| b1.eval("#{v}") } ==
+ b2.eval('local_variables').map { |v| b2.eval("#{v}") }) &&
+ (b1.eval('__method__') == b2.eval('__method__'))
+ end
+
+ def self.frame_manager
+ Thread.current[:__pry_frame_manager__]
+ end
+
+ def self.frame_manager=(obj)
+ Thread.current[:__pry_frame_manager__] = obj
+ end
+
+ class FrameManager
+ attr_reader :pry_instance
+ attr_reader :binding_index
+ attr_accessor :bindings
+
+ def initialize(bindings)
+ @bindings = bindings
+ @binding_index = 0
+ end
+
+ def change_binding_to(index, pry_instance)
+ if index > bindings.size - 1
+ pry_instance.output.puts "Warning: At top of stack, cannot go further!"
+ elsif index < 0
+ pry_instance.output.puts "Warning: At bottom of stack, cannot go further!"
+ else
+ @binding_index = index
+ pry_instance.binding_stack[-1] = bindings[binding_index]
+
+ pry_instance.run_command "whereami"
+ end
+ end
+ end
+
+ StackCommands = Pry::CommandSet.new do
+ command "up", "Go up to the caller's context" do |inc_str|
+ inc = inc_str.nil? ? 1 : inc_str.to_i
+
+ binding_index = PryStackExplorer.frame_manager.binding_index
+ PryStackExplorer.frame_manager.change_binding_to binding_index + inc, _pry_
+ end
+
+ command "down", "Go down to the callee's context." do |inc_str|
+ inc = inc_str.nil? ? 1 : inc_str.to_i
+
+ binding_index = PryStackExplorer.frame_manager.binding_index
+ PryStackExplorer.frame_manager.change_binding_to binding_index - inc, _pry_
+ end
+
+ command "frame", "Switch to a particular frame." do |frame_num|
+ PryStackExplorer.frame_manager.change_binding_to frame_num.to_i, _pry_
+ end
+
+ command "frame-type", "Display current frame type." do
+ bindex = PryStackExplorer.frame_manager.binding_index
+ output.puts PryStackExplorer.frame_manager.bindings[bindex].frame_type
+ end
+ end
+end
+
+class << Pry
+ alias_method :PSE_old_start, :start
+ def start(target, *args, &block)
+ target = Pry.binding_for(target)
+
+ # we need to know how many frames to skip depending on whether we
+ # were invoked with Pry.start or Object#pry
+ if binding.of_caller(1).eval('__method__') == :pry
+ drop_number = 2
+ else
+ drop_number = 1
+ end
+
+ bindings = binding.callers.drop(drop_number)
+
+ # Use the binding returned by #of_caller if possible (as we get
+ # access to frame_type).
+ # Otherwise stick to the given binding (target).
+ if !PryStackExplorer.bindings_equal?(target, bindings.first)
+ bindings.shift
+ bindings.unshift(target)
+ end
+
+ PryStackExplorer.frame_manager = PryStackExplorer::FrameManager.new(bindings)
+
+ PSE_old_start(bindings.first)
+ end
+end
+
+Pry.config.commands.import PryStackExplorer::StackCommands
+
+Pry.config.commands.alias_command "__old_whereami__", "whereami", ""
+
+# monkey-patch the whereami command to show some frame information,
+# useful for navigating stack.
+Pry.config.commands.command "whereami", "Show the code context for the session. (whereami <n> shows <n> extra lines of code around the invocation line. Default: 5)" do |num|
+ if PryStackExplorer.frame_manager
+ bindings = PryStackExplorer.frame_manager.bindings
+ binding_index = PryStackExplorer.frame_manager.binding_index
+
+ output.puts "\n"
+ output.puts "#{Pry::Helpers::Text.bold('Frame number:')} #{binding_index}/#{bindings.size - 1}"
+ output.puts "#{Pry::Helpers::Text.bold('Frame type:')} #{bindings[binding_index].frame_type}" rescue nil
+ end
+
+ run "__old_whereami__", num
+end
@@ -0,0 +1,3 @@
+module PryStackExplorer
+ VERSION = "0.1.0pre1"
+end
@@ -0,0 +1,12 @@
+direc = File.dirname(__FILE__)
+
+require 'rubygems'
+require "#{direc}/../lib/pry-stack_explorer"
+require 'bacon'
+
+puts "Testing pry-stack_explorer version #{PryStackExplorer::VERSION}..."
+puts "Ruby version: #{RUBY_VERSION}"
+
+describe PryStackExplorer do
+end
+
@@ -0,0 +1,14 @@
+def a
+ x = 20
+ b
+end
+
+def b
+ x = 30
+ c
+end
+
+def c
+ u = 50
+ binding.pry
+end

0 comments on commit 3601caa

Please sign in to comment.