mirror of
https://github.com/pry/pry.git
synced 2022-11-09 12:35:05 -05:00
Merge branch 'master' into refactor/command-set
Conflicts: lib/pry/command_helpers.rb
This commit is contained in:
commit
cac7ca89d3
9 changed files with 161 additions and 65 deletions
|
@ -11,6 +11,7 @@ these include:
|
|||
* Source code browsing (including core C source with the pry-doc gem)
|
||||
* Documentation browsing
|
||||
* Live help system
|
||||
* Open methods in editors (`edit-method Class#method`)
|
||||
* Syntax highlighting
|
||||
* Command shell integration (start editors, run git, and rake from within Pry)
|
||||
* Gist integration
|
||||
|
@ -126,16 +127,16 @@ code:
|
|||
|
||||
# test.rb
|
||||
require 'pry'
|
||||
|
||||
|
||||
class A
|
||||
def hello() puts "hello world!" end
|
||||
end
|
||||
|
||||
|
||||
a = A.new
|
||||
|
||||
|
||||
# start a REPL session
|
||||
binding.pry
|
||||
|
||||
|
||||
# program resumes here (after pry session)
|
||||
puts "program resumes here."
|
||||
|
||||
|
@ -169,8 +170,8 @@ using the normal `#{}` string interpolation syntax.
|
|||
In the code below we're going to switch to `shell-mode` and edit the
|
||||
`.pryrc` file in the home directory. We'll then cat its contents and
|
||||
reload the file.
|
||||
|
||||
pry(main)> shell-mode
|
||||
|
||||
pry(main)> shell-mode
|
||||
pry main:/home/john/ruby/projects/pry $ .cd ~
|
||||
pry main:/home/john $ .emacsclient .pryrc
|
||||
pry main:/home/john $ .cat .pryrc
|
||||
|
@ -179,7 +180,7 @@ reload the file.
|
|||
end
|
||||
pry main:/home/john $ load ".pryrc"
|
||||
=> true
|
||||
pry main:/home/john $ hello_world
|
||||
pry main:/home/john $ hello_world
|
||||
hello world!
|
||||
|
||||
We can also interpolate Ruby code into the shell. In the
|
||||
|
@ -189,7 +190,7 @@ current directory and count the number of lines in that file with
|
|||
|
||||
pry main:/home/john $ .cat #{Dir['*.*'].sample} | wc -l
|
||||
44
|
||||
|
||||
|
||||
### Code Browsing
|
||||
|
||||
#### show-method
|
||||
|
@ -206,37 +207,37 @@ include line numbers in the output.
|
|||
|
||||
In the following example we will enter the `Pry` class, list the
|
||||
instance methods beginning with 're' and display the source code for the `rep` method:
|
||||
|
||||
|
||||
pry(main)> cd Pry
|
||||
pry(Pry):1> ls -M --grep ^re
|
||||
[:re, :readline, :rep, :repl, :repl_epilogue, :repl_prologue, :retrieve_line]
|
||||
pry(Pry):1> show-method rep -l
|
||||
|
||||
|
||||
From: /home/john/ruby/projects/pry/lib/pry/pry_instance.rb @ line 143:
|
||||
Number of lines: 6
|
||||
|
||||
|
||||
143: def rep(target=TOPLEVEL_BINDING)
|
||||
144: target = Pry.binding_for(target)
|
||||
145: result = re(target)
|
||||
146:
|
||||
146:
|
||||
147: show_result(result) if should_print?
|
||||
148: end
|
||||
|
||||
Note that we can also view C methods (from Ruby Core) using the
|
||||
`pry-doc` gem; we also show off the alternate syntax for
|
||||
`show-method`:
|
||||
|
||||
|
||||
pry(main)> show-method Array#select
|
||||
|
||||
|
||||
From: array.c in Ruby Core (C Method):
|
||||
Number of lines: 15
|
||||
|
||||
|
||||
static VALUE
|
||||
rb_ary_select(VALUE ary)
|
||||
{
|
||||
VALUE result;
|
||||
long i;
|
||||
|
||||
|
||||
RETURN_ENUMERATOR(ary, 0, 0);
|
||||
result = rb_ary_new2(RARRAY_LEN(ary));
|
||||
for (i = 0; i < RARRAY_LEN(ary); i++) {
|
||||
|
@ -259,14 +260,14 @@ commands to do such things as change directory into the directory
|
|||
containing the file, open the file in an editor, display the file using `cat`, and so on.
|
||||
|
||||
In the following example we wil use Pry to fix a bug in a method:
|
||||
|
||||
|
||||
pry(main)> greet "john"
|
||||
hello johnhow are you?=> nil
|
||||
pry(main)> show-method greet
|
||||
|
||||
|
||||
From: /Users/john/ruby/play/bug.rb @ line 2:
|
||||
Number of lines: 4
|
||||
|
||||
|
||||
def greet(name)
|
||||
print "hello #{name}"
|
||||
print "how are you?"
|
||||
|
@ -278,10 +279,10 @@ In the following example we wil use Pry to fix a bug in a method:
|
|||
how are you?
|
||||
=> nil
|
||||
pry(main)> show-method greet
|
||||
|
||||
|
||||
From: /Users/john/ruby/play/bug.rb @ line 2:
|
||||
Number of lines: 4
|
||||
|
||||
|
||||
def greet(name)
|
||||
puts "hello #{name}"
|
||||
puts "how are you?"
|
||||
|
@ -317,10 +318,10 @@ documentation for the `try_activate` method:
|
|||
|
||||
pry(main)> cd Gem
|
||||
pry(Gem):1> show-doc try_activate
|
||||
|
||||
|
||||
From: /Users/john/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/site_ruby/1.9.1/rubygems.rb @ line 201:
|
||||
Number of lines: 3
|
||||
|
||||
|
||||
Try to activate a gem containing path. Returns true if
|
||||
activation succeeded or wasn't needed because it was already
|
||||
activated. Returns false if it can't find the path in a gem.
|
||||
|
@ -334,14 +335,14 @@ We can also use `ri` in the normal way:
|
|||
------------------------------------------------------------------------
|
||||
Calls _block_ once for each element in _self_, passing that element
|
||||
as a parameter.
|
||||
|
||||
|
||||
a = [ "a", "b", "c" ]
|
||||
a.each {|x| print x, " -- " }
|
||||
|
||||
|
||||
produces:
|
||||
|
||||
|
||||
a -- b -- c --
|
||||
|
||||
|
||||
|
||||
### History
|
||||
|
||||
|
@ -353,7 +354,7 @@ history can be replayed.
|
|||
|
||||
In the example below we will enter a few lines in a Pry session and
|
||||
then view history; we will then replay one of those lines:
|
||||
|
||||
|
||||
pry(main)> hist
|
||||
0: hist -h
|
||||
1: ls
|
||||
|
@ -362,10 +363,10 @@ then view history; we will then replay one of those lines:
|
|||
4: x = rand
|
||||
5: hist
|
||||
pry(main)> hist --replay 3
|
||||
|
||||
|
||||
From: io.c in Ruby Core (C Method):
|
||||
Number of lines: 8
|
||||
|
||||
|
||||
static VALUE
|
||||
rb_f_puts(int argc, VALUE *argv, VALUE recv)
|
||||
{
|
||||
|
@ -374,7 +375,7 @@ then view history; we will then replay one of those lines:
|
|||
}
|
||||
return rb_funcall2(rb_stdout, rb_intern("puts"), argc, argv);
|
||||
}
|
||||
|
||||
|
||||
In the next example we will replay a range of lines in history. Note
|
||||
that we replay to a point where a class definition is still open and so
|
||||
we can continue to add instance methods to the class:
|
||||
|
@ -397,7 +398,7 @@ we can continue to add instance methods to the class:
|
|||
pry(main)>
|
||||
|
||||
Also note that in the above the line `Hello.new.goodbye_world;` ends
|
||||
with a semi-colon which causes expression evaluation output to be suppressed.
|
||||
with a semi-colon which causes expression evaluation output to be suppressed.
|
||||
|
||||
### Gist integration
|
||||
|
||||
|
@ -405,13 +406,31 @@ If the `gist` gem is installed then method source or documentation can be gisted
|
|||
`gist-method` command. The `gist-method` command accepts the same two
|
||||
syntaxes as `show-method`. In the example below we will gist the C source
|
||||
code for the `Symbol#to_proc` method to github:
|
||||
|
||||
|
||||
pry(main)> gist-method Symbol#to_proc
|
||||
https://gist.github.com/5332c38afc46d902ce46
|
||||
pry(main)>
|
||||
|
||||
You can see the actual gist generated here: https://gist.github.com/5332c38afc46d902ce46
|
||||
pry(main)>
|
||||
|
||||
You can see the actual gist generated here: [https://gist.github.com/5332c38afc46d902ce46](https://gist.github.com/5332c38afc46d902ce46)
|
||||
|
||||
### Edit methods
|
||||
|
||||
You can use `edit-method Class#method` or `edit-method my_method`
|
||||
(if the method is in scope) to open a method for editing directly in
|
||||
your favorite editor. Pry has knowledge of a few different editors and
|
||||
will attempt to open the file at the line the method is defined.
|
||||
|
||||
You can set the editor to use by assigning to the `Pry.editor`
|
||||
accessor. `Pry.editor` will default to `$EDITOR` or failing that will
|
||||
use `nano` as the backup default. The file that is edited will be
|
||||
automatically reloaded after exiting the editor - reloading can be
|
||||
suppressed by passing the `--no-reload` option to `edit-method`
|
||||
|
||||
In the example below we will set our default editor to "emacsclient"
|
||||
and open the `Pry#repl` method for editing:
|
||||
|
||||
pry(main)> Pry.editor = "emacsclient"
|
||||
pry(main)> edit-method Pry#repl
|
||||
|
||||
### Live Help System
|
||||
|
||||
|
@ -471,7 +490,7 @@ invoke any of these methods directly depending on exactly what aspect of the fun
|
|||
limitation in JRuby's regex).
|
||||
* Tab completion is currently a bit broken/limited this will have a
|
||||
major overhaul in a future version.
|
||||
|
||||
|
||||
### Syntax Highlighting
|
||||
|
||||
Syntax highlighting is on by default in Pry. You can toggle it on and
|
||||
|
@ -497,7 +516,7 @@ features, see the `examples/` directory.
|
|||
|
||||
### Customizing Pry
|
||||
|
||||
Pry allows a large degree of customization.
|
||||
Pry allows a large degree of customization.
|
||||
|
||||
[Read how to customize Pry here.](http://rdoc.info/github/banister/pry/master/file/wiki/Customizing-pry.md)
|
||||
|
||||
|
|
4
Rakefile
4
Rakefile
|
@ -21,7 +21,7 @@ def apply_spec_defaults(s)
|
|||
s.require_path = 'lib'
|
||||
s.add_dependency("ruby_parser",">=2.0.5")
|
||||
s.add_dependency("coderay",">=0.9.7")
|
||||
s.add_dependency("slop",">=1.5.2")
|
||||
s.add_dependency("slop",">=1.5.3")
|
||||
s.add_development_dependency("bacon",">=1.1.0")
|
||||
s.homepage = "http://banisterfiend.wordpress.com"
|
||||
s.has_rdoc = 'yard'
|
||||
|
@ -90,7 +90,7 @@ end
|
|||
|
||||
|
||||
desc "build all platform gems at once"
|
||||
task :gems => [:rmgems, "ruby:gem", "jruby:gem", "mswin32:gem", "mingw32:gem"]
|
||||
task :gems => [:clean, :rmgems, "ruby:gem", "jruby:gem", "mswin32:gem", "mingw32:gem"]
|
||||
|
||||
desc "remove all platform gems"
|
||||
task :rmgems => ["ruby:clobber_package"]
|
||||
|
|
7
bin/pry
7
bin/pry
|
@ -10,7 +10,7 @@ rescue LoadError
|
|||
require 'pry'
|
||||
end
|
||||
|
||||
opts = Slop.parse do
|
||||
opts = Slop.parse(:help => true) do
|
||||
banner %{Usage: pry [OPTIONS]
|
||||
Start a Pry session.
|
||||
See: `https://github.com/banister` for more information.
|
||||
|
@ -43,11 +43,6 @@ See: `https://github.com/banister` for more information.
|
|||
true,
|
||||
:default => "TOPLEVEL_BINDING"
|
||||
)
|
||||
|
||||
on :h, :help, "This message" do
|
||||
puts help
|
||||
exit
|
||||
end
|
||||
end
|
||||
|
||||
# invoked via cli
|
||||
|
|
|
@ -46,12 +46,38 @@ class Pry
|
|||
def render_output(should_flood, start_line, doc)
|
||||
if start_line
|
||||
doc = add_line_numbers(doc, start_line)
|
||||
end
|
||||
|
||||
if should_flood
|
||||
output.puts doc
|
||||
if should_flood
|
||||
output.puts doc
|
||||
else
|
||||
stagger_output(doc)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def editor_with_start_line(line_number)
|
||||
case Pry.editor
|
||||
when /^[gm]?vi/, /^emacs/, /^nano/, /^pico/, /^gedit/, /^kate/
|
||||
"#{Pry.editor} +#{line_number}"
|
||||
when /^mate/
|
||||
"#{Pry.editor} -l#{line_number}"
|
||||
else
|
||||
stagger_output(doc)
|
||||
if RUBY_PLATFORM =~ /mswin|mingw/
|
||||
Pry.editor
|
||||
else
|
||||
"#{Pry.editor} +#{line_number}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def is_a_dynamically_defined_method?(meth)
|
||||
file, _ = meth.source_location
|
||||
!!(file =~ /(\(.*\))|<.*>/)
|
||||
end
|
||||
|
||||
def check_for_dynamically_defined_method(meth)
|
||||
if is_a_dynamically_defined_method?(meth)
|
||||
raise "Cannot retrieve source for dynamically defined method."
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -49,6 +49,57 @@ class Pry
|
|||
Pry.active_instance.input = StringIO.new(actions)
|
||||
end
|
||||
|
||||
command "edit-method", "Edit a method. Type `edit-method --help` for more info." do |*args|
|
||||
target = target()
|
||||
|
||||
opts = Slop.parse!(args) do |opts|
|
||||
opts.banner %{Usage: edit-method [OPTIONS] [METH]
|
||||
Edit the method METH in an editor.
|
||||
Ensure #{bold("Pry.editor")} is set to your editor of choice.
|
||||
e.g: edit-method hello_method
|
||||
--
|
||||
}
|
||||
opts.on :M, "instance-methods", "Operate on instance methods."
|
||||
opts.on :m, :methods, "Operate on methods."
|
||||
opts.on "no-reload", "Do not automatically reload the method's file after editting."
|
||||
opts.on :c, :context, "Select object context to run under.", true do |context|
|
||||
target = Pry.binding_for(target.eval(context))
|
||||
end
|
||||
opts.on :h, :help, "This message." do
|
||||
output.puts opts
|
||||
end
|
||||
end
|
||||
|
||||
next if opts.help?
|
||||
|
||||
meth_name = args.shift
|
||||
if meth_name
|
||||
if meth_name =~ /\A([^\.\#]+)[\.\#](.+)\z/ && !opts.context?
|
||||
context, meth_name = $1, $2
|
||||
target = Pry.binding_for(target.eval(context))
|
||||
end
|
||||
else
|
||||
meth_name = meth_name_from_binding(target)
|
||||
end
|
||||
|
||||
if (meth = get_method_object(meth_name, target, opts.to_hash(true))).nil?
|
||||
output.puts "Invalid method name: #{meth_name}."
|
||||
next
|
||||
end
|
||||
|
||||
next output.puts "Error: No editor set!\nEnsure that #{bold("Pry.editor")} is set to your editor of choice." if !Pry.editor
|
||||
|
||||
if is_a_c_method?(meth)
|
||||
output.puts "Error: Can't edit a C method."
|
||||
elsif is_a_dynamically_defined_method?(meth)
|
||||
output.puts "Error: Can't edit an eval method."
|
||||
else
|
||||
file, line = meth.source_location
|
||||
run ".#{editor_with_start_line(line)}", file
|
||||
load file if !opts["no-reload"]
|
||||
end
|
||||
end
|
||||
|
||||
command "exit-program", "End the current program. Aliases: quit-program, !!!" do
|
||||
exit
|
||||
end
|
||||
|
|
|
@ -98,6 +98,11 @@ class Pry
|
|||
# Set to true if the pry-doc extension is loaded.
|
||||
# @return [Boolean]
|
||||
attr_accessor :has_pry_doc
|
||||
|
||||
# The default editor to use. Defaults to $EDITOR or nano if
|
||||
# $EDITOR is not defined.
|
||||
# @return [String]
|
||||
attr_accessor :editor
|
||||
end
|
||||
|
||||
# Load the rc files given in the `Pry::RC_FILES` array.
|
||||
|
@ -198,6 +203,14 @@ class Pry
|
|||
commands.run_command(context, name, *Shellwords.shellwords(arg_string))
|
||||
end
|
||||
|
||||
def self.default_editor_for_platform
|
||||
if RUBY_PLATFORM =~ /mswin|mingw/
|
||||
ENV['EDITOR'] ? ENV['EDITOR'] : "notepad"
|
||||
else
|
||||
ENV['EDITOR'] ? ENV['EDITOR'] : "nano"
|
||||
end
|
||||
end
|
||||
|
||||
# Set all the configurable options back to their default values
|
||||
def self.reset_defaults
|
||||
@input = Readline
|
||||
|
@ -213,6 +226,7 @@ class Pry
|
|||
@should_load_rc = true
|
||||
@rc_loaded = false
|
||||
@cli = false
|
||||
@editor = default_editor_for_platform
|
||||
end
|
||||
|
||||
self.reset_defaults
|
||||
|
|
|
@ -54,12 +54,7 @@ class Pry
|
|||
# @return [Pry] The parent of the current Pry session.
|
||||
def parent
|
||||
idx = Pry.sessions.index(self)
|
||||
|
||||
if idx > 0
|
||||
Pry.sessions[idx - 1]
|
||||
else
|
||||
nil
|
||||
end
|
||||
Pry.sessions[idx - 1] if idx > 0
|
||||
end
|
||||
|
||||
# Execute the hook `hook_name`, if it is defined.
|
||||
|
@ -125,12 +120,7 @@ class Pry
|
|||
end
|
||||
|
||||
return_value = repl_epilogue(target, nesting_level, break_data)
|
||||
|
||||
# if one was provided, return the return value
|
||||
return return_value if return_value
|
||||
|
||||
# otherwise return the target_self
|
||||
target_self
|
||||
return_value || target_self
|
||||
end
|
||||
|
||||
# Perform a read-eval-print.
|
||||
|
@ -356,10 +346,9 @@ class Pry
|
|||
# valid_expression?("class Hello; end") #=> true
|
||||
def valid_expression?(code)
|
||||
RubyParser.new.parse(code)
|
||||
true
|
||||
rescue Racc::ParseError, SyntaxError
|
||||
false
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
class Pry
|
||||
VERSION = "0.8.2"
|
||||
VERSION = "0.8.3"
|
||||
end
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
direc = File.dirname(__FILE__)
|
||||
$LOAD_PATH.unshift "#{direc}/../lib"
|
||||
|
||||
$LOAD_PATH.unshift "#{direc}/../lib"
|
||||
|
||||
require 'rubygems'
|
||||
require 'bacon'
|
||||
require "pry"
|
||||
|
|
Loading…
Reference in a new issue