pry 0.8.3 → 0.8.4pre1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +2 -0
- data/.gitignore +8 -0
- data/.yardopts +1 -0
- data/README.markdown +10 -6
- data/Rakefile +15 -23
- data/TODO +62 -0
- data/bin/pry +3 -1
- data/lib/pry.rb +6 -7
- data/lib/pry/command_context.rb +29 -0
- data/lib/pry/command_processor.rb +15 -28
- data/lib/pry/command_set.rb +234 -0
- data/lib/pry/commands.rb +15 -861
- data/lib/pry/core_extensions.rb +40 -48
- data/lib/pry/default_commands/context.rb +127 -0
- data/lib/pry/default_commands/documentation.rb +145 -0
- data/lib/pry/default_commands/easter_eggs.rb +71 -0
- data/lib/pry/default_commands/gems.rb +59 -0
- data/lib/pry/default_commands/input.rb +38 -0
- data/lib/pry/default_commands/introspection.rb +190 -0
- data/lib/pry/default_commands/ls.rb +199 -0
- data/lib/pry/default_commands/shell.rb +90 -0
- data/lib/pry/helpers.rb +2 -0
- data/lib/pry/{command_base_helpers.rb → helpers/base_helpers.rb} +46 -21
- data/lib/pry/{command_helpers.rb → helpers/command_helpers.rb} +34 -36
- data/lib/pry/pry_class.rb +17 -11
- data/lib/pry/pry_instance.rb +59 -2
- data/lib/pry/version.rb +1 -1
- data/test/{test_helper.rb → helper.rb} +8 -2
- data/test/test_command_helpers.rb +77 -0
- data/test/test_commandset.rb +184 -0
- data/test/{test.rb → test_pry.rb} +164 -132
- data/wiki/Customizing-pry.md +397 -0
- data/wiki/Home.md +4 -0
- metadata +61 -41
- data/lib/pry/command_base.rb +0 -202
data/lib/pry/helpers.rb
ADDED
@@ -1,10 +1,29 @@
|
|
1
1
|
class Pry
|
2
|
-
|
3
|
-
|
2
|
+
module Helpers
|
3
|
+
|
4
|
+
module BaseHelpers
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def silence_warnings
|
8
|
+
old_verbose = $VERBOSE
|
9
|
+
$VERBOSE = nil
|
10
|
+
begin
|
11
|
+
yield
|
12
|
+
ensure
|
13
|
+
$VERBOSE = old_verbose
|
14
|
+
end
|
15
|
+
end
|
4
16
|
|
5
|
-
|
17
|
+
# turn off color for duration of block
|
18
|
+
def no_color(&block)
|
19
|
+
old_color_state = Pry.color
|
20
|
+
Pry.color = false
|
21
|
+
yield
|
22
|
+
ensure
|
23
|
+
Pry.color = old_color_state
|
24
|
+
end
|
6
25
|
|
7
|
-
|
26
|
+
def gem_installed?(gem_name)
|
8
27
|
require 'rubygems'
|
9
28
|
!!Gem.source_index.find_name(gem_name).first
|
10
29
|
end
|
@@ -16,6 +35,14 @@ class Pry
|
|
16
35
|
end
|
17
36
|
end
|
18
37
|
|
38
|
+
def set_file_and_dir_locals(file_name)
|
39
|
+
return if !target
|
40
|
+
$_file_temp = File.expand_path(file_name)
|
41
|
+
$_dir_temp = File.dirname($_file_temp)
|
42
|
+
target.eval("_file_ = $_file_temp")
|
43
|
+
target.eval("_dir_ = $_dir_temp")
|
44
|
+
end
|
45
|
+
|
19
46
|
def stub_proc(name, options)
|
20
47
|
gems_needed = Array(options[:requires_gem])
|
21
48
|
gems_not_installed = gems_needed.select { |g| !gem_installed?(g) }
|
@@ -49,15 +76,15 @@ class Pry
|
|
49
76
|
#
|
50
77
|
|
51
78
|
COLORS = {
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
79
|
+
"black" => 0,
|
80
|
+
"red" => 1,
|
81
|
+
"green" => 2,
|
82
|
+
"yellow" => 3,
|
83
|
+
"blue" => 4,
|
84
|
+
"purple" => 5,
|
85
|
+
"magenta" => 5,
|
86
|
+
"cyan" => 6,
|
87
|
+
"white" => 7
|
61
88
|
}
|
62
89
|
|
63
90
|
COLORS.each do |color, i|
|
@@ -75,10 +102,10 @@ class Pry
|
|
75
102
|
|
76
103
|
require 'set'
|
77
104
|
VALID_COLORS = Set.new(
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
105
|
+
COLORS.keys +
|
106
|
+
COLORS.keys.map{|k| "bright_#{k}" } +
|
107
|
+
["grey", "gray"]
|
108
|
+
)
|
82
109
|
|
83
110
|
def bold(text)
|
84
111
|
Pry.color ? "\e[1m#{text}\e[0m" : text
|
@@ -106,7 +133,7 @@ class Pry
|
|
106
133
|
if /<([\w\d_]+)>/ =~ token and VALID_COLORS.include?($1) #valid_tag?($1)
|
107
134
|
stack.push $1
|
108
135
|
|
109
|
-
|
136
|
+
# token is a closing tag!
|
110
137
|
|
111
138
|
elsif /<\/([\w\d_]+)>/ =~ token and VALID_COLORS.include?($1) # valid_tag?($1)
|
112
139
|
|
@@ -118,7 +145,7 @@ class Pry
|
|
118
145
|
raise "Error: tried to close an unopened color tag -- #{token}"
|
119
146
|
end
|
120
147
|
|
121
|
-
|
148
|
+
# token is a literal string!
|
122
149
|
|
123
150
|
else
|
124
151
|
|
@@ -237,5 +264,3 @@ class Pry
|
|
237
264
|
end
|
238
265
|
end
|
239
266
|
end
|
240
|
-
|
241
|
-
|
@@ -1,8 +1,9 @@
|
|
1
1
|
class Pry
|
2
|
-
|
2
|
+
module Helpers
|
3
|
+
|
3
4
|
module CommandHelpers
|
4
5
|
|
5
|
-
|
6
|
+
module_function
|
6
7
|
|
7
8
|
def try_to_load_pry_doc
|
8
9
|
|
@@ -22,14 +23,6 @@ class Pry
|
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
25
|
-
def set_file_and_dir_locals(file_name)
|
26
|
-
return if !target
|
27
|
-
$_file_temp = File.expand_path(file_name)
|
28
|
-
$_dir_temp = File.dirname($_file_temp)
|
29
|
-
target.eval("_file_ = $_file_temp")
|
30
|
-
target.eval("_dir_ = $_dir_temp")
|
31
|
-
end
|
32
|
-
|
33
26
|
def add_line_numbers(lines, start_line)
|
34
27
|
line_array = lines.each_line.to_a
|
35
28
|
line_array.each_with_index.map do |line, idx|
|
@@ -56,21 +49,6 @@ class Pry
|
|
56
49
|
end
|
57
50
|
end
|
58
51
|
|
59
|
-
def editor_with_start_line(line_number)
|
60
|
-
case Pry.editor
|
61
|
-
when /^[gm]?vi/, /^emacs/, /^nano/, /^pico/, /^gedit/, /^kate/
|
62
|
-
"#{Pry.editor} +#{line_number}"
|
63
|
-
when /^mate/
|
64
|
-
"#{Pry.editor} -l#{line_number}"
|
65
|
-
else
|
66
|
-
if RUBY_PLATFORM =~ /mswin|mingw/
|
67
|
-
Pry.editor
|
68
|
-
else
|
69
|
-
"#{Pry.editor} +#{line_number}"
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
52
|
def is_a_dynamically_defined_method?(meth)
|
75
53
|
file, _ = meth.source_location
|
76
54
|
!!(file =~ /(\(.*\))|<.*>/)
|
@@ -82,6 +60,13 @@ class Pry
|
|
82
60
|
end
|
83
61
|
end
|
84
62
|
|
63
|
+
def check_for_dynamically_defined_method(meth)
|
64
|
+
file, _ = meth.source_location
|
65
|
+
if file =~ /(\(.*\))|<.*>/
|
66
|
+
raise "Cannot retrieve source for dynamically defined method."
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
85
70
|
def remove_first_word(text)
|
86
71
|
text.split.drop(1).join(' ')
|
87
72
|
end
|
@@ -91,8 +76,8 @@ class Pry
|
|
91
76
|
old_color_state = Pry.color
|
92
77
|
Pry.color = false
|
93
78
|
yield
|
94
|
-
|
95
|
-
|
79
|
+
ensure
|
80
|
+
Pry.color = old_color_state
|
96
81
|
end
|
97
82
|
|
98
83
|
def code_and_code_type_for(meth)
|
@@ -126,23 +111,35 @@ class Pry
|
|
126
111
|
end
|
127
112
|
|
128
113
|
def get_method_object(meth_name, target, options)
|
114
|
+
if meth_name
|
115
|
+
if meth_name =~ /(\S+)\#(\S+)\Z/
|
116
|
+
context, meth_name = $1, $2
|
117
|
+
target = Pry.binding_for(target.eval(context))
|
118
|
+
options["instance-methods"] = true
|
119
|
+
options[:methods] = false
|
120
|
+
elsif meth_name =~ /(\S+)\.(\S+)\Z/
|
121
|
+
context, meth_name = $1, $2
|
122
|
+
target = Pry.binding_for(target.eval(context))
|
123
|
+
options["instance-methods"] = false
|
124
|
+
options[:methods] = true
|
125
|
+
end
|
126
|
+
else
|
127
|
+
meth_name = meth_name_from_binding(target)
|
128
|
+
end
|
129
|
+
|
129
130
|
if !meth_name
|
130
131
|
return nil
|
131
132
|
end
|
132
133
|
|
133
|
-
if options[
|
134
|
-
target.eval("instance_method(:#{meth_name})")
|
135
|
-
elsif options[:
|
136
|
-
target.eval("method(:#{meth_name})")
|
134
|
+
if options["instance-methods"]
|
135
|
+
target.eval("instance_method(:#{meth_name})") rescue nil
|
136
|
+
elsif options[:methods]
|
137
|
+
target.eval("method(:#{meth_name})") rescue nil
|
137
138
|
else
|
138
139
|
begin
|
139
140
|
target.eval("instance_method(:#{meth_name})")
|
140
141
|
rescue
|
141
|
-
|
142
|
-
target.eval("method(:#{meth_name})")
|
143
|
-
rescue
|
144
|
-
return nil
|
145
|
-
end
|
142
|
+
target.eval("method(:#{meth_name})") rescue nil
|
146
143
|
end
|
147
144
|
end
|
148
145
|
end
|
@@ -318,5 +315,6 @@ class Pry
|
|
318
315
|
end
|
319
316
|
|
320
317
|
end
|
318
|
+
|
321
319
|
end
|
322
320
|
end
|
data/lib/pry/pry_class.rb
CHANGED
@@ -101,7 +101,16 @@ class Pry
|
|
101
101
|
|
102
102
|
# The default editor to use. Defaults to $EDITOR or nano if
|
103
103
|
# $EDITOR is not defined.
|
104
|
-
#
|
104
|
+
# If `editor` is a String then that string is used as the shell
|
105
|
+
# command to invoke the editor. If `editor` is callable (e.g a
|
106
|
+
# Proc) then `file` and `line` are passed in as parameters and the
|
107
|
+
# return value of that callable invocation is used as the exact
|
108
|
+
# shell command to invoke the editor.
|
109
|
+
# @example String
|
110
|
+
# Pry.editor = "emacsclient"
|
111
|
+
# @example Callable
|
112
|
+
# Pry.editor = proc { |file, line| "emacsclient #{file} +#{line}" }
|
113
|
+
# @return [String, #call]
|
105
114
|
attr_accessor :editor
|
106
115
|
end
|
107
116
|
|
@@ -190,20 +199,17 @@ class Pry
|
|
190
199
|
:commands => Pry.commands
|
191
200
|
}.merge!(options)
|
192
201
|
|
193
|
-
null_output =
|
202
|
+
null_output = StringIO.new
|
194
203
|
|
204
|
+
context = CommandContext.new
|
195
205
|
commands = options[:commands]
|
196
206
|
|
197
|
-
|
198
|
-
|
207
|
+
context.opts = {}
|
208
|
+
context.output = options[:show_output] ? options[:output] : null_output
|
209
|
+
context.target = Pry.binding_for(options[:context])
|
210
|
+
context.command_set = commands
|
199
211
|
|
200
|
-
|
201
|
-
if cmd
|
202
|
-
action = cmd[:action]
|
203
|
-
commands.instance_exec(*Shellwords.shellwords(arg_string), &action)
|
204
|
-
else
|
205
|
-
raise "No such Pry command: #{name}"
|
206
|
-
end
|
212
|
+
commands.run_command(context, name, *Shellwords.shellwords(arg_string))
|
207
213
|
end
|
208
214
|
|
209
215
|
def self.default_editor_for_platform
|
data/lib/pry/pry_instance.rb
CHANGED
@@ -30,7 +30,7 @@ class Pry
|
|
30
30
|
default_options.merge!(options)
|
31
31
|
|
32
32
|
CONFIG_OPTIONS.each do |key|
|
33
|
-
|
33
|
+
send "#{key}=", default_options[key]
|
34
34
|
end
|
35
35
|
|
36
36
|
@command_processor = CommandProcessor.new(self)
|
@@ -54,7 +54,7 @@ class Pry
|
|
54
54
|
# @return [Pry] The parent of the current Pry session.
|
55
55
|
def parent
|
56
56
|
idx = Pry.sessions.index(self)
|
57
|
-
Pry.sessions[idx - 1] if idx > 0
|
57
|
+
Pry.sessions[idx - 1] if idx && idx > 0
|
58
58
|
end
|
59
59
|
|
60
60
|
# Execute the hook `hook_name`, if it is defined.
|
@@ -320,6 +320,63 @@ class Pry
|
|
320
320
|
end
|
321
321
|
end
|
322
322
|
|
323
|
+
# the array that the prompt stack is stored in
|
324
|
+
def prompt_stack
|
325
|
+
@prompt_stack ||= Array.new
|
326
|
+
end
|
327
|
+
private :prompt_stack
|
328
|
+
|
329
|
+
# The current prompt, this is the prompt at the top of the prompt stack.
|
330
|
+
# @return [Array<Proc>] Current prompt.
|
331
|
+
# @example
|
332
|
+
# push_prompt(Pry::SIMPLE_PROMPT)
|
333
|
+
# prompt # => Pry::SIMPLE_PROMPT
|
334
|
+
def prompt
|
335
|
+
prompt_stack.last
|
336
|
+
end
|
337
|
+
|
338
|
+
# Replaces the current prompt with the new prompt.
|
339
|
+
# Does not change the rest of the prompt stack.
|
340
|
+
# @param [Array<Proc>] new_prompt
|
341
|
+
# @return [Array<Proc>] new_prompt
|
342
|
+
# @example
|
343
|
+
# pry.prompt = Pry::SIMPLE_PROMPT # => Pry::SIMPLE_PROMPT
|
344
|
+
# pry.prompt # => Pry::SIMPLE_PROMPT
|
345
|
+
def prompt=(new_prompt)
|
346
|
+
if prompt_stack.empty?
|
347
|
+
push_prompt new_prompt
|
348
|
+
else
|
349
|
+
prompt_stack[-1] = new_prompt
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
# Pushes the current prompt onto a stack that it can be restored from later.
|
354
|
+
# Use this if you wish to temporarily change the prompt.
|
355
|
+
# @param [Array<Proc>] new_prompt
|
356
|
+
# @return [Array<Proc>] new_prompt
|
357
|
+
# @example
|
358
|
+
# new_prompt = [ proc { '>' }, proc { '>>' } ]
|
359
|
+
# push_prompt(new_prompt) # => new_prompt
|
360
|
+
def push_prompt(new_prompt)
|
361
|
+
prompt_stack.push new_prompt
|
362
|
+
end
|
363
|
+
|
364
|
+
# Pops the current prompt off of the prompt stack.
|
365
|
+
# If the prompt you are popping is the last prompt, it will not be popped.
|
366
|
+
# Use this to restore the previous prompt.
|
367
|
+
# @return [Array<Proc>] Prompt being popped.
|
368
|
+
# @example
|
369
|
+
# prompt1 = [ proc { '>' }, proc { '>>' } ]
|
370
|
+
# prompt2 = [ proc { '$' }, proc { '>' } ]
|
371
|
+
# pry = Pry.new :prompt => prompt1
|
372
|
+
# pry.push_prompt(prompt2)
|
373
|
+
# pry.pop_prompt # => prompt2
|
374
|
+
# pry.pop_prompt # => prompt1
|
375
|
+
# pry.pop_prompt # => prompt1
|
376
|
+
def pop_prompt
|
377
|
+
if prompt_stack.size > 1 then prompt_stack.pop else prompt end
|
378
|
+
end
|
379
|
+
|
323
380
|
if RUBY_VERSION =~ /1.9/ && RUBY_ENGINE == "ruby"
|
324
381
|
require 'ripper'
|
325
382
|
|
data/lib/pry/version.rb
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
unless Object.const_defined? 'Pry'
|
2
|
+
$:.unshift File.expand_path '../../lib', __FILE__
|
3
|
+
require 'pry'
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'bacon'
|
7
|
+
|
1
8
|
# Ensure we do not execute any rc files
|
2
9
|
Pry::RC_FILES.clear
|
3
10
|
Pry.color = false
|
@@ -40,8 +47,7 @@ class Pry
|
|
40
47
|
end
|
41
48
|
|
42
49
|
|
43
|
-
|
44
|
-
|
50
|
+
CommandTester = Pry::CommandSet.new :test do
|
45
51
|
command "command1", "command 1 test" do
|
46
52
|
output.puts "command1"
|
47
53
|
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Pry::Helpers::CommandHelpers do
|
4
|
+
before do
|
5
|
+
@helper = Pry::Helpers::CommandHelpers
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "get_method_object" do
|
9
|
+
it 'should look up instance methods if no methods available and no options provided' do
|
10
|
+
klass = Class.new { def hello; end }
|
11
|
+
meth = @helper.get_method_object(:hello, Pry.binding_for(klass), {})
|
12
|
+
meth.should == klass.instance_method(:hello)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should look up methods if no instance methods available and no options provided' do
|
16
|
+
klass = Class.new { def self.hello; end }
|
17
|
+
meth = @helper.get_method_object(:hello, Pry.binding_for(klass), {})
|
18
|
+
meth.should == klass.method(:hello)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should look up instance methods first even if methods available and no options provided' do
|
22
|
+
klass = Class.new { def hello; end; def self.hello; end }
|
23
|
+
meth = @helper.get_method_object(:hello, Pry.binding_for(klass), {})
|
24
|
+
meth.should == klass.instance_method(:hello)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should look up instance methods if "instance-methods" option provided' do
|
28
|
+
klass = Class.new { def hello; end; def self.hello; end }
|
29
|
+
meth = @helper.get_method_object(:hello, Pry.binding_for(klass), {"instance-methods" => true})
|
30
|
+
meth.should == klass.instance_method(:hello)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should look up methods if :methods option provided' do
|
34
|
+
klass = Class.new { def hello; end; def self.hello; end }
|
35
|
+
meth = @helper.get_method_object(:hello, Pry.binding_for(klass), {:methods => true})
|
36
|
+
meth.should == klass.method(:hello)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should look up instance methods using the Class#method syntax' do
|
40
|
+
klass = Class.new { def hello; end; def self.hello; end }
|
41
|
+
meth = @helper.get_method_object("klass#hello", Pry.binding_for(binding), {})
|
42
|
+
meth.should == klass.instance_method(:hello)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should look up methods using the object.method syntax' do
|
46
|
+
klass = Class.new { def hello; end; def self.hello; end }
|
47
|
+
meth = @helper.get_method_object("klass.hello", Pry.binding_for(binding), {})
|
48
|
+
meth.should == klass.method(:hello)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should NOT look up instance methods using the Class#method syntax if no instance methods defined' do
|
52
|
+
klass = Class.new { def self.hello; end }
|
53
|
+
meth = @helper.get_method_object("klass#hello", Pry.binding_for(binding), {})
|
54
|
+
meth.should == nil
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should NOT look up methods using the object.method syntax if no methods defined' do
|
58
|
+
klass = Class.new { def hello; end }
|
59
|
+
meth = @helper.get_method_object("klass.hello", Pry.binding_for(binding), {})
|
60
|
+
meth.should == nil
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should look up methods using klass.new.method syntax' do
|
64
|
+
klass = Class.new { def hello; :hello; end }
|
65
|
+
meth = @helper.get_method_object("klass.new.hello", Pry.binding_for(binding), {})
|
66
|
+
meth.name.to_sym.should == :hello
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should look up instance methods using klass.meth#method syntax' do
|
70
|
+
klass = Class.new { def self.meth; Class.new; end }
|
71
|
+
meth = @helper.get_method_object("klass.meth#initialize", Pry.binding_for(binding), {})
|
72
|
+
meth.name.to_sym.should == :initialize
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
|