pry 0.9.0pre3-java → 0.9.4pre2-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/.gitignore +1 -0
  2. data/CHANGELOG +84 -6
  3. data/CONTRIBUTORS +13 -0
  4. data/README.markdown +23 -183
  5. data/Rakefile +22 -19
  6. data/TODO +36 -6
  7. data/bin/pry +12 -1
  8. data/lib/pry.rb +60 -12
  9. data/lib/pry/command_context.rb +21 -0
  10. data/lib/pry/command_processor.rb +62 -16
  11. data/lib/pry/command_set.rb +25 -11
  12. data/lib/pry/commands.rb +0 -3
  13. data/lib/pry/completion.rb +6 -6
  14. data/lib/pry/config.rb +25 -5
  15. data/lib/pry/default_commands/basic.rb +27 -6
  16. data/lib/pry/default_commands/context.rb +84 -35
  17. data/lib/pry/default_commands/documentation.rb +69 -31
  18. data/lib/pry/default_commands/easter_eggs.rb +5 -0
  19. data/lib/pry/default_commands/input.rb +193 -56
  20. data/lib/pry/default_commands/introspection.rb +98 -50
  21. data/lib/pry/default_commands/ls.rb +51 -21
  22. data/lib/pry/default_commands/shell.rb +57 -13
  23. data/lib/pry/extended_commands/experimental.rb +0 -32
  24. data/lib/pry/extended_commands/user_command_api.rb +33 -2
  25. data/lib/pry/helpers/base_helpers.rb +30 -10
  26. data/lib/pry/helpers/command_helpers.rb +75 -16
  27. data/lib/pry/helpers/text.rb +12 -11
  28. data/lib/pry/history.rb +61 -0
  29. data/lib/pry/plugins.rb +23 -12
  30. data/lib/pry/pry_class.rb +51 -50
  31. data/lib/pry/pry_instance.rb +129 -119
  32. data/lib/pry/version.rb +1 -1
  33. data/pry.gemspec +46 -0
  34. data/test/helper.rb +37 -3
  35. data/test/test_command_processor.rb +62 -19
  36. data/test/test_command_set.rb +40 -2
  37. data/test/test_completion.rb +27 -0
  38. data/test/test_default_commands/test_context.rb +185 -1
  39. data/test/test_default_commands/test_documentation.rb +10 -0
  40. data/test/test_default_commands/test_input.rb +207 -11
  41. data/test/test_default_commands/test_introspection.rb +20 -1
  42. data/test/test_default_commands/test_shell.rb +18 -0
  43. data/test/test_pry.rb +261 -45
  44. data/test/test_pry_history.rb +82 -0
  45. data/test/test_pry_output.rb +44 -0
  46. data/test/test_special_locals.rb +35 -0
  47. metadata +185 -159
data/lib/pry/commands.rb CHANGED
@@ -22,8 +22,5 @@ class Pry
22
22
  import DefaultCommands::Shell
23
23
  import DefaultCommands::Introspection
24
24
  import DefaultCommands::EasterEggs
25
-
26
- # Helpers::CommandHelpers.try_to_load_pry_doc
27
-
28
25
  end
29
26
  end
@@ -94,7 +94,7 @@ class Pry
94
94
  begin
95
95
  candidates = eval("#{receiver}.constants.collect{|m| m.to_s}", bind)
96
96
  candidates |= eval("#{receiver}.methods.collect{|m| m.to_s}", bind)
97
- rescue Exception
97
+ rescue RescuableException
98
98
  candidates = []
99
99
  end
100
100
  candidates.grep(/^#{message}/).collect{|e| receiver + "::" + e}
@@ -114,7 +114,7 @@ class Pry
114
114
 
115
115
  begin
116
116
  candidates = eval(receiver, bind).methods.collect{|m| m.to_s}
117
- rescue Exception
117
+ rescue RescuableException
118
118
  candidates = []
119
119
  end
120
120
  select_message(receiver, message, candidates)
@@ -126,7 +126,7 @@ class Pry
126
126
 
127
127
  begin
128
128
  candidates = eval(receiver, bind).methods.collect{|m| m.to_s}
129
- rescue Exception
129
+ rescue RescuableException
130
130
  candidates = []
131
131
  end
132
132
  select_message(receiver, message, candidates)
@@ -149,7 +149,7 @@ class Pry
149
149
  # Foo::Bar.func
150
150
  begin
151
151
  candidates = eval("#{receiver}.methods", bind).collect{|m| m.to_s}
152
- rescue Exception
152
+ rescue RescuableException
153
153
  candidates = []
154
154
  end
155
155
  else
@@ -157,8 +157,8 @@ class Pry
157
157
  candidates = []
158
158
  ObjectSpace.each_object(Module){|m|
159
159
  begin
160
- name = m.name
161
- rescue Exception
160
+ name = m.name.to_s
161
+ rescue RescuableException
162
162
  name = ""
163
163
  end
164
164
  next if name != "IRB::Context" and
data/lib/pry/config.rb CHANGED
@@ -51,12 +51,17 @@ class Pry
51
51
  # return value of that callable invocation is used as the exact
52
52
  # shell command to invoke the editor.
53
53
  # @example String
54
- # Pry.editor = "emacsclient"
54
+ # Pry.config.editor = "emacsclient"
55
55
  # @example Callable
56
- # Pry.editor = proc { |file, line| "emacsclient #{file} +#{line}" }
56
+ # Pry.config.editor = proc { |file, line| "emacsclient #{file} +#{line}" }
57
57
  # @return [String, #call]
58
58
  attr_accessor :editor
59
59
 
60
+ # A string that must precede all Pry commands (e.g., if command_prefix is
61
+ # set to "%", the "cd" command must be invoked as "%cd").
62
+ # @return [String]
63
+ attr_accessor :command_prefix
64
+
60
65
  # @return [Boolean] Toggle Pry color on and off.
61
66
  attr_accessor :color
62
67
 
@@ -71,13 +76,21 @@ class Pry
71
76
  # @return [Boolean]
72
77
  attr_accessor :should_load_plugins
73
78
 
79
+ # Determines whether to load files specified with the -r flag.
80
+ # @return [Boolean]
81
+ attr_accessor :should_load_requires
82
+
83
+ # Determines whether to disable edit-method's auto-reloading behavior.
84
+ # @return [Boolean]
85
+ attr_accessor :disable_auto_reload
86
+
74
87
  # Config option for history.
75
88
  # sub-options include hist.file, hist.load, and hist.save
76
89
  # hist.file is the file to save/load history too, e.g
77
90
  # Pry.config.history.file = "~/.pry_history".
78
- # hist.load is a boolean that determines whether history will be
91
+ # hist.should_load is a boolean that determines whether history will be
79
92
  # loaded from hist.file at session start.
80
- # hist.save is a boolean that determines whether history will be
93
+ # hist.should_save is a boolean that determines whether history will be
81
94
  # saved to hist.file at session end.
82
95
  # @return [OpenStruct]
83
96
  attr_accessor :history
@@ -89,8 +102,15 @@ class Pry
89
102
  # @return [OpenStruct]
90
103
  attr_accessor :plugins
91
104
 
92
- # @return [Integer] Amount of results that will be stored into _out_
105
+ # @return [Array<String>] Ruby files to be required after loading any plugins.
106
+ attr_accessor :requires
107
+
108
+ # @return [Integer] Amount of results that will be stored into out
93
109
  attr_accessor :memory_size
110
+
111
+ # @return [Proc] The proc that manages ^D presses in the REPL.
112
+ # The proc is passed the current eval_string and the current pry instance.
113
+ attr_accessor :control_d_handler
94
114
  end
95
115
  end
96
116
 
@@ -8,23 +8,44 @@ class Pry
8
8
  end
9
9
 
10
10
  command "simple-prompt", "Toggle the simple prompt." do
11
- case Pry.active_instance.prompt
11
+ case _pry_.prompt
12
12
  when Pry::SIMPLE_PROMPT
13
- Pry.active_instance.pop_prompt
13
+ _pry_.pop_prompt
14
14
  else
15
- Pry.active_instance.push_prompt Pry::SIMPLE_PROMPT
15
+ _pry_.push_prompt Pry::SIMPLE_PROMPT
16
16
  end
17
17
  end
18
18
 
19
- command "version", "Show Pry version." do
19
+ command "pry-version", "Show Pry version." do
20
20
  output.puts "Pry version: #{Pry::VERSION} on Ruby #{RUBY_VERSION}."
21
21
  end
22
22
 
23
- command "import", "Import a command set" do |command_set_name|
23
+ command "import-set", "Import a command set" do |command_set_name|
24
24
  next output.puts "Provide a command set name" if command_set.nil?
25
25
 
26
26
  set = target.eval(arg_string)
27
- Pry.active_instance.commands.import set
27
+ _pry_.commands.import set
28
+ end
29
+
30
+ command "reload-method", "Reload the source file that contains the specified method" do |meth_name|
31
+ if (meth = get_method_object(meth_name, target, {})).nil?
32
+ output.puts "Invalid method name: #{meth_name}."
33
+ next
34
+ end
35
+
36
+ if is_a_c_method?(meth)
37
+ output.puts "Error: Can't reload a C method."
38
+ elsif is_a_dynamically_defined_method?(meth)
39
+ output.puts "Error: Can't reload an eval method."
40
+ else
41
+ file_name = meth.source_location.first
42
+ load file_name
43
+ output.puts "Reloaded #{file_name}."
44
+ end
45
+ end
46
+
47
+ command "req", "Require file(s) and expand their paths." do |*args|
48
+ args.each { |file_name| load File.expand_path(file_name) }
28
49
  end
29
50
 
30
51
  command "reset", "Reset the REPL to a clean state." do
@@ -6,74 +6,122 @@ class Pry
6
6
  Context = Pry::CommandSet.new do
7
7
  import Ls
8
8
 
9
- command "cd", "Start a Pry session on VAR (use `cd ..` to go back and `cd /` to return to Pry top-level)", :keep_retval => true do |obj|
10
- case obj
11
- when nil
12
- output.puts "Must provide an object."
13
- next
14
- when ".."
15
- throw(:breakout, opts[:nesting].level)
16
- when "/"
17
- throw(:breakout, 1) if opts[:nesting].level > 0
18
- next
19
- when "::"
20
- TOPLEVEL_BINDING.pry
21
- next
9
+ command "cd", "Move into a new context (use `cd ..` to go back and `cd /` to return to Pry top-level). Complex syntax (e.g cd ../@x/y) also supported." do |obj|
10
+ path = arg_string.split(/\//)
11
+ stack = _pry_.binding_stack.dup
12
+
13
+ # special case when we only get a single "/", return to root
14
+ stack = [stack.first] if path.empty?
15
+
16
+ resolve_failure = false
17
+ path.each do |context|
18
+ begin
19
+ case context.chomp
20
+ when ""
21
+ stack = [stack.first]
22
+ when "::"
23
+ stack.push(TOPLEVEL_BINDING)
24
+ when "."
25
+ next
26
+ when ".."
27
+ if stack.one?
28
+ _pry_.binding_stack.clear
29
+ throw(:breakout)
30
+ else
31
+ stack.pop
32
+ end
33
+ else
34
+ stack.push(Pry.binding_for(stack.last.eval(context)))
35
+ end
36
+
37
+ rescue RescuableException
38
+ output.puts "Bad object path: #{arg_string}. Failed trying to resolve: #{context}"
39
+ resolve_failure = true
40
+ end
41
+ end
42
+
43
+ next if resolve_failure
44
+
45
+ _pry_.binding_stack = stack
46
+ end
47
+
48
+ command "switch-to", "Start a new sub-session on a binding in the current stack (numbered by nesting)." do |selection|
49
+ selection = selection.to_i
50
+
51
+ if selection < 0 || selection > _pry_.binding_stack.size - 1
52
+ output.puts "Invalid binding index #{selection} - use `nesting` command to view valid indices."
22
53
  else
23
- Pry.start target.eval(arg_string)
54
+ Pry.start(_pry_.binding_stack[selection])
24
55
  end
25
56
  end
26
57
 
27
58
  command "nesting", "Show nesting information." do
28
- nesting = opts[:nesting]
29
-
30
59
  output.puts "Nesting status:"
31
60
  output.puts "--"
32
- nesting.each do |level, obj|
61
+ _pry_.binding_stack.each_with_index do |obj, level|
33
62
  if level == 0
34
- output.puts "#{level}. #{Pry.view_clip(obj)} (Pry top level)"
63
+ output.puts "#{level}. #{Pry.view_clip(obj.eval('self'))} (Pry top level)"
35
64
  else
36
- output.puts "#{level}. #{Pry.view_clip(obj)}"
65
+ output.puts "#{level}. #{Pry.view_clip(obj.eval('self'))}"
37
66
  end
38
67
  end
39
68
  end
40
69
 
41
- command "jump-to", "Jump to a Pry session further up the stack, exiting all sessions below." do |break_level|
70
+ command "jump-to", "Jump to a binding further up the stack, popping all bindings below." do |break_level|
42
71
  break_level = break_level.to_i
43
- nesting = opts[:nesting]
72
+ nesting_level = _pry_.binding_stack.size - 1
44
73
 
45
74
  case break_level
46
- when nesting.level
47
- output.puts "Already at nesting level #{nesting.level}"
48
- when (0...nesting.level)
49
- throw(:breakout, break_level + 1)
75
+ when nesting_level
76
+ output.puts "Already at nesting level #{nesting_level}"
77
+ when (0...nesting_level)
78
+ _pry_.binding_stack.slice!(break_level + 1, _pry_.binding_stack.size)
79
+
50
80
  else
51
- max_nest_level = nesting.level - 1
81
+ max_nest_level = nesting_level - 1
52
82
  output.puts "Invalid nest level. Must be between 0 and #{max_nest_level}. Got #{break_level}."
53
83
  end
54
84
  end
55
85
 
56
- command "exit", "End the current Pry session. Accepts optional return value. Aliases: quit, back" do
57
- throw(:breakout, [opts[:nesting].level, target.eval(arg_string)])
86
+ command "exit-all", "End the current Pry session (popping all bindings) and returning to caller. Accepts optional return value. Aliases: !!@" do
87
+ # clear the binding stack
88
+ _pry_.binding_stack.clear
89
+
90
+ # break out of the repl loop
91
+ throw(:breakout, target.eval(arg_string))
58
92
  end
59
93
 
60
- alias_command "quit", "exit", ""
61
- alias_command "back", "exit", ""
94
+ alias_command "!!@", "exit-all", ""
95
+
96
+ command "exit", "Pop the current binding and return to the one immediately prior. Note this does NOT exit the program. Aliases: quit", :keep_retval => true do
97
+ if _pry_.binding_stack.one?
98
+ # when breaking out of top-level then behave like `exit-all`
99
+ _pry_.binding_stack.clear
100
+ throw(:breakout, target.eval(arg_string))
101
+ else
102
+ # otherwise just pop a binding
103
+ popped_object = _pry_.binding_stack.pop.eval('self')
62
104
 
63
- command "exit-all", "End all nested Pry sessions. Accepts optional return value. Aliases: !!@" do
64
- throw(:breakout, [0, target.eval(arg_string)])
105
+ # return a user-specified value if given
106
+ if !arg_string.empty?
107
+ target.eval(arg_string)
108
+ else
109
+ popped_object
110
+ end
111
+ end
65
112
  end
66
113
 
67
- alias_command "!!@", "exit-all", ""
114
+ alias_command "quit", "exit", ""
68
115
 
69
116
  command "exit-program", "End the current program. Aliases: quit-program, !!!" do
70
- exit
117
+ Pry.save_history if Pry.config.history.should_save
118
+ Kernel.exit target.eval(arg_string).to_i
71
119
  end
72
120
 
73
121
  alias_command "quit-program", "exit-program", ""
74
122
  alias_command "!!!", "exit-program", ""
75
123
 
76
- command "!pry", "Start a Pry session on current self; this even works mid-expression." do
124
+ command "!pry", "Start a Pry session on current self; this even works mid multi-line expression." do
77
125
  target.pry
78
126
  end
79
127
 
@@ -99,6 +147,7 @@ class Pry
99
147
  set_file_and_dir_locals(file)
100
148
  output.puts "\n#{text.bold('From:')} #{file} @ line #{line_num} in #{klass}##{meth_name}:\n\n"
101
149
 
150
+
102
151
  # This method inspired by http://rubygems.org/gems/ir_b
103
152
  File.open(file).each_with_index do |line, index|
104
153
  line_n = index + 1
@@ -11,7 +11,7 @@ class Pry
11
11
  target = target()
12
12
 
13
13
  opts = Slop.parse!(args) do |opt|
14
- opt.banner = "Usage: show-doc [OPTIONS] [METH]\n" \
14
+ opt.banner = "Usage: show-doc [OPTIONS] [METH 1] [METH 2] [METH N]\n" \
15
15
  "Show the comments above method METH. Tries instance methods first and then methods by default.\n" \
16
16
  "e.g show-doc hello_method"
17
17
 
@@ -28,25 +28,30 @@ class Pry
28
28
 
29
29
  next if opts.help?
30
30
 
31
- meth_name = args.shift
32
- if (meth = get_method_object(meth_name, target, opts.to_hash(true))).nil?
33
- output.puts "Invalid method name: #{meth_name}. Type `show-doc --help` for help"
34
- next
35
- end
36
-
37
- doc, code_type = doc_and_code_type_for(meth)
38
- next if !doc
31
+ args = [nil] if args.empty?
32
+ args.each do |method_name|
33
+ meth_name = method_name
34
+ if (meth = get_method_object(meth_name, target, opts.to_hash(true))).nil?
35
+ output.puts "Invalid method name: #{meth_name}. Type `show-doc --help` for help"
36
+ next
37
+ end
39
38
 
40
- next output.puts("No documentation found.") if doc.empty?
41
- doc = process_comment_markup(doc, code_type)
42
- output.puts make_header(meth, code_type, doc)
43
- render_output(opts.flood?, false, doc)
44
- doc
39
+ doc, code_type = doc_and_code_type_for(meth)
40
+ next if !doc
41
+
42
+ next output.puts("No documentation found.") if doc.empty?
43
+ doc = process_comment_markup(doc, code_type)
44
+ output.puts make_header(meth, code_type, doc)
45
+ output.puts "#{text.bold("visibility: ")} #{method_visibility(meth).to_s}"
46
+ output.puts "#{text.bold("signature: ")} #{signature_for(meth)}"
47
+ output.puts
48
+ render_output(opts.flood?, false, doc)
49
+ doc
50
+ end
45
51
  end
46
52
 
47
53
  alias_command "?", "show-doc", ""
48
54
 
49
-
50
55
  command "stat", "View method information and set _file_ and _dir_ locals. Type `stat --help` for more info." do |*args|
51
56
  target = target()
52
57
 
@@ -73,23 +78,20 @@ class Pry
73
78
  next
74
79
  end
75
80
 
76
- code, code_type = code_and_code_type_for(meth)
77
- next if !code
78
- doc, code_type = doc_and_code_type_for(meth)
79
-
80
- output.puts make_header(meth, code_type, code)
81
- output.puts text.bold("Method Name: ") + meth_name
82
- output.puts text.bold("Method Owner: ") + (meth.owner.to_s ? meth.owner.to_s : "Unknown")
83
- output.puts text.bold("Method Language: ") + code_type.to_s.capitalize
84
- output.puts text.bold("Method Type: ") + (meth.is_a?(Method) ? "Bound" : "Unbound")
85
- output.puts text.bold("Method Arity: ") + meth.arity.to_s
86
-
87
- name_map = { :req => "Required:", :opt => "Optional:", :rest => "Rest:" }
88
- if meth.respond_to?(:parameters)
89
- output.puts text.bold("Method Parameters: ") + meth.parameters.group_by(&:first).
90
- map { |k, v| "#{name_map[k]} #{v.map { |kk, vv| vv ? vv.to_s : "noname" }.join(", ")}" }.join(". ")
81
+ if !is_a_c_method?(meth) && !is_a_dynamically_defined_method?(meth)
82
+ set_file_and_dir_locals(path_line_for(meth).first)
91
83
  end
92
- output.puts text.bold("Comment length: ") + (doc.empty? ? 'No comment.' : (doc.lines.count.to_s + ' lines.'))
84
+
85
+ output.puts "Method Information:"
86
+ output.puts "--"
87
+ output.puts "Name: " + meth_name
88
+ output.puts "Owner: " + (meth.owner.to_s ? meth.owner.to_s : "Unknown")
89
+ output.puts "Visibility: " + method_visibility(meth).to_s
90
+ output.puts "Type: " + (meth.is_a?(Method) ? "Bound" : "Unbound")
91
+ output.puts "Arity: " + meth.arity.to_s
92
+ output.puts "Method Signature: " + signature_for(meth)
93
+
94
+ output.puts "Source location: " + (meth.source_location ? meth.source_location.join(":") : "Not found.")
93
95
  end
94
96
 
95
97
  command "gist-method", "Gist a method to github. Type `gist-method --help` for more info.", :requires_gem => "gist" do |*args|
@@ -140,6 +142,42 @@ class Pry
140
142
  output.puts "Gist created at #{link}"
141
143
  end
142
144
 
145
+ helpers do
146
+
147
+ # paraphrased from awesome_print gem
148
+ def signature_for(method)
149
+ if method.respond_to?(:parameters)
150
+
151
+ args = method.parameters.inject([]) do |arr, (type, name)|
152
+ name ||= (type == :block ? 'block' : "arg#{arr.size + 1}")
153
+ arr << case type
154
+ when :req then name.to_s
155
+ when :opt, :rest then "*#{name}"
156
+ when :block then "&#{name}"
157
+ else '?'
158
+ end
159
+ end
160
+ else
161
+ args = (1..method.arity.abs).map { |i| "arg#{i}" }
162
+ args[-1] = "*#{args[-1]}" if method.arity < 0
163
+ end
164
+
165
+ "#{method.name}(#{args.join(', ')})"
166
+ end
167
+
168
+ def method_visibility(meth)
169
+ if meth.owner.public_instance_methods.include? meth.name
170
+ :public
171
+ elsif meth.owner.protected_instance_methods.include? meth.name
172
+ :protected
173
+ elsif meth.owner.private_instance_methods.include? meth.name
174
+ :private
175
+ else
176
+ :none
177
+ end
178
+ end
179
+ end
180
+
143
181
  end
144
182
 
145
183
  end