pry 0.9.9.6pre2-java → 0.9.10-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. data/CHANGELOG +41 -0
  2. data/CONTRIBUTORS +27 -26
  3. data/README.markdown +4 -4
  4. data/Rakefile +2 -2
  5. data/lib/pry.rb +25 -19
  6. data/lib/pry/cli.rb +31 -10
  7. data/lib/pry/code.rb +41 -83
  8. data/lib/pry/command.rb +87 -76
  9. data/lib/pry/command_set.rb +13 -20
  10. data/lib/pry/completion.rb +139 -121
  11. data/lib/pry/config.rb +4 -0
  12. data/lib/pry/core_extensions.rb +88 -31
  13. data/lib/pry/default_commands/cd.rb +31 -8
  14. data/lib/pry/default_commands/context.rb +4 -58
  15. data/lib/pry/default_commands/easter_eggs.rb +1 -1
  16. data/lib/pry/default_commands/editing.rb +21 -14
  17. data/lib/pry/default_commands/find_method.rb +5 -7
  18. data/lib/pry/default_commands/gist.rb +187 -0
  19. data/lib/pry/default_commands/hist.rb +6 -6
  20. data/lib/pry/default_commands/input_and_output.rb +73 -129
  21. data/lib/pry/default_commands/introspection.rb +107 -52
  22. data/lib/pry/default_commands/ls.rb +1 -1
  23. data/lib/pry/default_commands/misc.rb +0 -5
  24. data/lib/pry/default_commands/whereami.rb +92 -0
  25. data/lib/pry/helpers/base_helpers.rb +6 -1
  26. data/lib/pry/helpers/command_helpers.rb +30 -9
  27. data/lib/pry/helpers/documentation_helpers.rb +7 -7
  28. data/lib/pry/helpers/options_helpers.rb +1 -1
  29. data/lib/pry/helpers/text.rb +7 -9
  30. data/lib/pry/history.rb +15 -2
  31. data/lib/pry/hooks.rb +1 -1
  32. data/lib/pry/indent.rb +17 -10
  33. data/lib/pry/method.rb +35 -19
  34. data/lib/pry/module_candidate.rb +130 -0
  35. data/lib/pry/pry_class.rb +54 -22
  36. data/lib/pry/pry_instance.rb +71 -14
  37. data/lib/pry/repl_file_loader.rb +80 -0
  38. data/lib/pry/version.rb +1 -1
  39. data/lib/pry/wrapped_module.rb +121 -142
  40. data/pry.gemspec +13 -13
  41. data/test/candidate_helper1.rb +11 -0
  42. data/test/candidate_helper2.rb +8 -0
  43. data/test/helper.rb +16 -0
  44. data/test/test_code.rb +1 -1
  45. data/test/test_command.rb +364 -270
  46. data/test/test_command_integration.rb +235 -267
  47. data/test/test_completion.rb +36 -0
  48. data/test/test_control_d_handler.rb +45 -0
  49. data/test/test_default_commands/example.erb +5 -0
  50. data/test/test_default_commands/test_cd.rb +316 -11
  51. data/test/test_default_commands/test_context.rb +143 -192
  52. data/test/test_default_commands/test_documentation.rb +81 -14
  53. data/test/test_default_commands/test_find_method.rb +10 -2
  54. data/test/test_default_commands/test_input.rb +102 -111
  55. data/test/test_default_commands/test_introspection.rb +17 -12
  56. data/test/test_default_commands/test_ls.rb +8 -6
  57. data/test/test_default_commands/test_shell.rb +18 -15
  58. data/test/test_default_commands/test_show_source.rb +170 -44
  59. data/test/test_exception_whitelist.rb +6 -2
  60. data/test/test_hooks.rb +32 -0
  61. data/test/test_input_stack.rb +19 -16
  62. data/test/test_method.rb +0 -4
  63. data/test/test_prompt.rb +60 -0
  64. data/test/test_pry.rb +23 -31
  65. data/test/test_pry_defaults.rb +75 -57
  66. data/test/test_syntax_checking.rb +12 -11
  67. data/test/test_wrapped_module.rb +103 -0
  68. metadata +72 -26
@@ -20,29 +20,53 @@ class Pry
20
20
  def process(name)
21
21
  if module?(name)
22
22
  code_or_doc = process_module
23
- else method?
23
+ elsif method?
24
24
  code_or_doc = process_method
25
+ else
26
+ code_or_doc = process_alternatives
25
27
  end
26
28
 
27
29
  render_output(code_or_doc, opts)
28
30
  end
29
31
 
30
- def module_start_line(mod, candidate=0)
32
+ def process_alternatives
33
+ if args.empty? && internal_binding?(target)
34
+ mod = target_self.is_a?(Module) ? target_self : target_self.class
35
+ self.module_object = Pry::WrappedModule(mod)
36
+
37
+ process_module
38
+ else
39
+ process_method
40
+ end
41
+ end
42
+
43
+ def module_start_line(mod, candidate_rank=0)
31
44
  if opts.present?(:'base-one')
32
45
  1
33
46
  else
34
- mod.source_line_for_candidate(candidate)
47
+ mod.candidate(candidate_rank).line
35
48
  end
36
49
  end
37
50
 
38
51
  def use_line_numbers?
39
52
  opts.present?(:b) || opts.present?(:l)
40
53
  end
54
+
55
+ def attempt
56
+ rank = 0
57
+ begin
58
+ yield(rank)
59
+ rescue Pry::CommandError
60
+ raise if rank > (module_object.number_of_candidates - 1)
61
+ rank += 1
62
+ retry
63
+ end
64
+ end
41
65
  end
42
66
 
43
67
  Introspection = Pry::CommandSet.new do
44
68
 
45
- create_command "show-doc", "Show the comments above METH. Aliases: \?", :shellwords => false do
69
+ create_command "show-doc", "Show the documentation for a method or class. Aliases: \?", :shellwords => false do
46
70
  include ModuleIntrospectionHelpers
47
71
  include Helpers::DocumentationHelpers
48
72
  extend Helpers::BaseHelpers
@@ -51,7 +75,7 @@ class Pry
51
75
  Usage: show-doc [OPTIONS] [METH]
52
76
  Aliases: ?
53
77
 
54
- Show the comments above method METH. Tries instance methods first and then methods by default.
78
+ Show the documentation for a method or class. Tries instance methods first and then methods by default.
55
79
  e.g show-doc hello_method # docs for hello_method
56
80
  e.g show-doc Pry # docs for Pry class
57
81
  e.g show-doc Pry -a # docs for all definitions of Pry class (all monkey patches)
@@ -80,43 +104,36 @@ class Pry
80
104
  end
81
105
 
82
106
  def normal_module
83
- mod = module_object
84
-
85
- # source_file reveals the underlying .c file in case of core
86
- # classes on MRI. This is different to source_location, which
87
- # will return nil.
88
- if mod.yard_docs?
89
- file_name, line = mod.source_file, nil
107
+ doc = ""
108
+ if module_object.yard_docs?
109
+ file_name, line = module_object.yard_file, module_object.yard_line
110
+ doc << module_object.yard_doc
111
+ start_line = 1
90
112
  else
91
- file_name, line = mod.source_location
113
+ attempt do |rank|
114
+ file_name, line = module_object.candidate(rank).source_location
115
+ set_file_and_dir_locals(file_name)
116
+ doc << module_object.candidate(rank).doc
117
+ start_line = module_start_line(module_object, rank)
118
+ end
92
119
  end
93
120
 
94
- if mod.doc.empty?
95
- output.puts "No documentation found."
96
- ""
97
- else
98
- set_file_and_dir_locals(file_name) if !mod.yard_docs?
99
- doc = ""
100
- doc << mod.doc
121
+ doc = Code.new(doc, start_line, :text).
122
+ with_line_numbers(use_line_numbers?).to_s
101
123
 
102
- doc = Code.new(doc, module_start_line(mod), :text).
103
- with_line_numbers(use_line_numbers?).to_s
104
-
105
- doc.insert(0, "\n#{Pry::Helpers::Text.bold('From:')} #{file_name} @ line #{line ? line : "N/A"}:\n\n")
106
- end
124
+ doc.insert(0, "\n#{Pry::Helpers::Text.bold('From:')} #{file_name} @ line #{line ? line : "N/A"}:\n\n")
107
125
  end
108
126
 
109
127
  def all_modules
110
- mod = module_object
111
-
112
128
  doc = ""
113
- doc << "Found #{mod.number_of_candidates} candidates for `#{mod.name}` definition:\n"
114
- mod.number_of_candidates.times do |v|
129
+ doc << "Found #{module_object.number_of_candidates} candidates for `#{module_object.name}` definition:\n"
130
+ module_object.number_of_candidates.times do |v|
131
+ candidate = module_object.candidate(v)
115
132
  begin
116
- doc << "\nCandidate #{v+1}/#{mod.number_of_candidates}: #{mod.source_file_for_candidate(v)} @ #{mod.source_line_for_candidate(v)}:\n\n"
117
- dc = mod.doc_for_candidate(v)
118
- doc << (dc.empty? ? "No documentation found.\n" : dc)
133
+ doc << "\nCandidate #{v+1}/#{module_object.number_of_candidates}: #{candidate.file} @ #{candidate.line}:\n\n"
134
+ doc << candidate.doc
119
135
  rescue Pry::RescuableException
136
+ doc << "No documentation found.\n"
120
137
  next
121
138
  end
122
139
  end
@@ -124,14 +141,13 @@ class Pry
124
141
  end
125
142
 
126
143
  def process_method
127
- meth = method_object
128
- raise Pry::CommandError, "No documentation found." if meth.doc.nil? || meth.doc.empty?
144
+ raise Pry::CommandError, "No documentation found." if method_object.doc.nil? || method_object.doc.empty?
129
145
 
130
- doc = process_comment_markup(meth.doc, meth.source_type)
131
- output.puts make_header(meth, doc)
132
- output.puts "#{text.bold("Owner:")} #{meth.owner || "N/A"}"
133
- output.puts "#{text.bold("Visibility:")} #{meth.visibility}"
134
- output.puts "#{text.bold("Signature:")} #{meth.signature}"
146
+ doc = process_comment_markup(method_object.doc)
147
+ output.puts make_header(method_object, doc)
148
+ output.puts "#{text.bold("Owner:")} #{method_object.owner || "N/A"}"
149
+ output.puts "#{text.bold("Visibility:")} #{method_object.visibility}"
150
+ output.puts "#{text.bold("Signature:")} #{method_object.signature}"
135
151
  output.puts
136
152
 
137
153
  if use_line_numbers?
@@ -146,8 +162,8 @@ class Pry
146
162
  if opts.present?(:'base-one')
147
163
  1
148
164
  else
149
- if mod.source_line_for_candidate(candidate)
150
- mod.source_line_for_candidate(candidate) - mod.doc_for_candidate(candidate).lines.count
165
+ if mod.candidate(candidate).line
166
+ mod.candidate(candidate).line - mod.candidate(candidate).doc.lines.count
151
167
  else
152
168
  1
153
169
  end
@@ -196,13 +212,13 @@ class Pry
196
212
  include ModuleIntrospectionHelpers
197
213
  extend Helpers::BaseHelpers
198
214
 
199
- description "Show the source for METH or CLASS. Aliases: $, show-method"
215
+ description "Show the source for a method or class. Aliases: $, show-method"
200
216
 
201
217
  banner <<-BANNER
202
218
  Usage: show-source [OPTIONS] [METH|CLASS]
203
219
  Aliases: $, show-method
204
220
 
205
- Show the source for method METH or CLASS. Tries instance methods first and then methods by default.
221
+ Show the source for a method or class. Tries instance methods first and then methods by default.
206
222
 
207
223
  e.g: `show-source hello_method`
208
224
  e.g: `show-source -m hello_method`
@@ -250,11 +266,14 @@ class Pry
250
266
  end
251
267
 
252
268
  def normal_module
253
- mod = module_object
269
+ file_name = line = code = nil
270
+ attempt do |rank|
271
+ file_name, line = module_object.candidate(rank).source_location
272
+ set_file_and_dir_locals(file_name)
273
+ code = Code.from_module(module_object, module_start_line(module_object, rank), rank).
274
+ with_line_numbers(use_line_numbers?).to_s
275
+ end
254
276
 
255
- file_name, line = mod.source_location
256
- set_file_and_dir_locals(file_name)
257
- code = Code.from_module(mod, module_start_line(mod)).with_line_numbers(use_line_numbers?).to_s
258
277
  result = ""
259
278
  result << "\n#{Pry::Helpers::Text.bold('From:')} #{file_name} @ line #{line}:\n"
260
279
  result << "#{Pry::Helpers::Text.bold('Number of lines:')} #{code.lines.count}\n\n"
@@ -267,12 +286,15 @@ class Pry
267
286
  result = ""
268
287
  result << "Found #{mod.number_of_candidates} candidates for `#{mod.name}` definition:\n"
269
288
  mod.number_of_candidates.times do |v|
289
+ candidate = mod.candidate(v)
270
290
  begin
271
- code = Code.new(mod.source_for_candidate(v), module_start_line(mod, v)).with_line_numbers(use_line_numbers?).to_s
272
- result << "\nCandidate #{v+1}/#{mod.number_of_candidates}: #{mod.source_file_for_candidate(v)} @ line #{mod.source_line_for_candidate(v)}:\n"
291
+ result << "\nCandidate #{v+1}/#{mod.number_of_candidates}: #{candidate.file} @ line #{candidate.line}:\n"
292
+ code = Code.from_module(mod, module_start_line(mod, v), v).
293
+ with_line_numbers(use_line_numbers?).to_s
273
294
  result << "Number of lines: #{code.lines.count}\n\n"
274
295
  result << code
275
296
  rescue Pry::RescuableException
297
+ result << "\nNo code found.\n"
276
298
  next
277
299
  end
278
300
  end
@@ -341,12 +363,45 @@ class Pry
341
363
  Usage: ri [spec]
342
364
  e.g. ri Array#each
343
365
 
344
- Relies on the ri executable being available. See also: show-doc.
366
+ Relies on the rdoc gem being installed. See also: show-doc.
345
367
  BANNER
346
368
 
347
- def process
348
- run ".ri", *args
369
+ def process(spec)
370
+ # Lazily load RI
371
+ require 'rdoc/ri/driver'
372
+
373
+ unless defined? RDoc::RI::PryDriver
374
+
375
+ # Subclass RI so that it formats its output nicely, and uses `lesspipe`.
376
+ subclass = Class.new(RDoc::RI::Driver) # the hard way.
377
+
378
+ subclass.class_eval do
379
+ def page
380
+ Pry::Helpers::BaseHelpers.lesspipe {|less| yield less}
381
+ end
382
+
383
+ def formatter(io)
384
+ if @formatter_klass then
385
+ @formatter_klass.new
386
+ else
387
+ RDoc::Markup::ToAnsi.new
388
+ end
389
+ end
390
+ end
391
+
392
+ RDoc::RI.const_set :PryDriver, subclass # hook it up!
393
+ end
394
+
395
+ # Spin-up an RI insance.
396
+ ri = RDoc::RI::PryDriver.new :use_stdout => true, :interactive => false
397
+
398
+ begin
399
+ ri.display_names [spec] # Get the documentation (finally!)
400
+ rescue RDoc::RI::Driver::NotFoundError => e
401
+ output.puts "error: '#{e.name}' not found"
402
+ end
349
403
  end
404
+
350
405
  end
351
406
 
352
407
  end
@@ -35,7 +35,7 @@ class Pry
35
35
 
36
36
  opt.on :i, "ivars", "Show instance variables (in blue) and class variables (in bright blue)"
37
37
 
38
- opt.on :G, "grep", "Filter output by regular expression", :optional => false
38
+ opt.on :G, "grep", "Filter output by regular expression", :argument => true
39
39
  if jruby?
40
40
  opt.on :J, "all-java", "Show all the aliases for methods from java (default is to show only prettiest)"
41
41
  end
@@ -33,11 +33,6 @@ class Pry
33
33
  output.puts "Reloaded #{file_name}."
34
34
  end
35
35
  end
36
-
37
- command "req", "Require file(s) and expand their paths." do |*args|
38
- args.each { |file_name| load File.expand_path(file_name) }
39
- end
40
-
41
36
  end
42
37
  end
43
38
  end
@@ -0,0 +1,92 @@
1
+
2
+ class Pry
3
+ module DefaultCommands
4
+ Whereami = Pry::CommandSet.new do
5
+ create_command "whereami" do
6
+ description "Show code surrounding the current context."
7
+ group 'Context'
8
+ banner <<-BANNER
9
+ Usage: whereami [-q] [N]
10
+
11
+ Describe the current location. If you use `binding.pry` inside a
12
+ method then whereami will print out the source for that method.
13
+
14
+ If a number is passed, then N lines before and after the current line
15
+ will be shown instead of the method itself.
16
+
17
+ The `-q` flag can be used to suppress error messages in the case that
18
+ there's no code to show. This is used by pry in the default
19
+ before_session hook to show you when you arrive at a `binding.pry`.
20
+
21
+ When pry was started on an Object and there is no associated method,
22
+ whereami will instead output a brief description of the current
23
+ object.
24
+ BANNER
25
+
26
+ def setup
27
+ @method = Pry::Method.from_binding(target)
28
+ @file = target.eval('__FILE__')
29
+ @line = target.eval('__LINE__')
30
+ end
31
+
32
+ def options(opt)
33
+ opt.on :q, :quiet, "Don't display anything in case of an error"
34
+ end
35
+
36
+ def code
37
+ @code ||= if show_method?
38
+ Pry::Code.from_method(@method)
39
+ else
40
+ Pry::Code.from_file(@file).around(@line, window_size)
41
+ end
42
+ end
43
+
44
+ def location
45
+ "#{@file} @ line #{show_method? ? @method.source_line : @line} #{@method && @method.name_with_owner}"
46
+ end
47
+
48
+ def process
49
+ if opts.quiet? && (internal_binding?(target) || !code?)
50
+ return
51
+ elsif internal_binding?(target)
52
+ if target_self == TOPLEVEL_BINDING.eval("self")
53
+ output.puts "At the top level."
54
+ else
55
+ output.puts "Inside #{Pry.view_clip(target_self)}."
56
+ end
57
+ return
58
+ end
59
+
60
+ set_file_and_dir_locals(@file)
61
+
62
+ output.puts "\n#{text.bold('From:')} #{location}:\n\n"
63
+ output.puts code.with_line_numbers.with_marker(@line)
64
+ output.puts
65
+ end
66
+
67
+ private
68
+
69
+ def show_method?
70
+ args.empty? && @method && @method.source? && @method.source_range.count < 20 &&
71
+ # These checks are needed in case of an eval with a binding and file/line
72
+ # numbers set to outside the function. As in rails' use of ERB.
73
+ @method.source_file == @file && @method.source_range.include?(@line)
74
+ end
75
+
76
+ def code?
77
+ !!code
78
+ rescue MethodSource::SourceNotFoundError
79
+ false
80
+ end
81
+
82
+ def window_size
83
+ if args.empty?
84
+ Pry.config.default_window_size
85
+ else
86
+ args.first.to_i
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -70,7 +70,7 @@ class Pry
70
70
  end
71
71
 
72
72
  def use_ansi_codes?
73
- defined?(Win32::Console) || ENV['TERM'] && ENV['TERM'] != "dumb"
73
+ windows_ansi? || ENV['TERM'] && ENV['TERM'] != "dumb"
74
74
  end
75
75
 
76
76
  def colorize_code(code)
@@ -100,6 +100,11 @@ class Pry
100
100
  RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
101
101
  end
102
102
 
103
+ # are we able to use ansi on windows?
104
+ def windows_ansi?
105
+ defined?(Win32::Console) || ENV['ANSICON']
106
+ end
107
+
103
108
  # are we on Jruby platform?
104
109
  def jruby?
105
110
  RbConfig::CONFIG['ruby_install_name'] == 'jruby'
@@ -39,13 +39,17 @@ class Pry
39
39
  [file, line_num]
40
40
  end
41
41
 
42
+ def internal_binding?(target)
43
+ m = target.eval("__method__").to_s
44
+ # class_eval is here because of http://jira.codehaus.org/browse/JRUBY-6753
45
+ ["__binding__", "__pry__", "class_eval"].include?(m)
46
+ end
47
+
42
48
  def get_method_or_raise(name, target, opts={}, omit_help=false)
43
49
  meth = Pry::Method.from_str(name, target, opts)
44
50
 
45
51
  if name && !meth
46
52
  command_error("The method '#{name}' could not be found.", omit_help)
47
- elsif !meth
48
- command_error("No method name given, and context is not a method.", omit_help, NonMethodContextError)
49
53
  end
50
54
 
51
55
  (opts[:super] || 0).times do
@@ -56,6 +60,10 @@ class Pry
56
60
  end
57
61
  end
58
62
 
63
+ if !meth || (!name && internal_binding?(target))
64
+ command_error("No method name given, and context is not a method.", omit_help, NonMethodContextError)
65
+ end
66
+
59
67
  set_file_and_dir_locals(meth.source_file)
60
68
  meth
61
69
  end
@@ -69,7 +77,7 @@ class Pry
69
77
  header = "\n#{Pry::Helpers::Text.bold('From:')} #{meth.source_file} "
70
78
 
71
79
  if meth.source_type == :c
72
- header << "in Ruby Core (C Method):\n"
80
+ header << "(C Method):\n"
73
81
  else
74
82
  header << "@ line #{meth.source_line}:\n"
75
83
  end
@@ -107,7 +115,7 @@ class Pry
107
115
  # not to block the process from which they were launched (in this case, Pry).
108
116
  # For those editors, return the flag that produces the desired behavior.
109
117
  def blocking_flag_for_editor(block)
110
- case Pry.config.editor
118
+ case editor_name
111
119
  when /^emacsclient/
112
120
  '--no-wait' unless block
113
121
  when /^[gm]vim/
@@ -129,7 +137,7 @@ class Pry
129
137
  # special case for 1st line
130
138
  return file_name if line_number <= 1
131
139
 
132
- case Pry.config.editor
140
+ case editor_name
133
141
  when /^[gm]?vi/, /^emacs/, /^nano/, /^pico/, /^gedit/, /^kate/
134
142
  "+#{line_number} #{file_name}"
135
143
  when /^mate/, /^geany/
@@ -149,6 +157,20 @@ class Pry
149
157
  end
150
158
  end
151
159
 
160
+ # Get the name of the binary that Pry.config.editor points to.
161
+ #
162
+ # This is useful for deciding which flags we pass to the editor as
163
+ # we can just use the program's name and ignore any absolute paths.
164
+ #
165
+ # @example
166
+ # Pry.config.editor="/home/conrad/bin/textmate -w"
167
+ # editor_name
168
+ # # => textmate
169
+ #
170
+ def editor_name
171
+ File.basename(Pry.config.editor).split(" ").first
172
+ end
173
+
152
174
  # Remove any common leading whitespace from every line in `text`.
153
175
  #
154
176
  # This can be used to make a HEREDOC line up with the left margin, without
@@ -161,10 +183,7 @@ class Pry
161
183
  # "Ut enim ad minim veniam."
162
184
  # USAGE
163
185
  #
164
- # @param [String] The text from which to remove indentation
165
- # @return [String], The text with indentation stripped.
166
- #
167
- # @copyright Heavily based on textwrap.dedent from Python, which is:
186
+ # Heavily based on textwrap.dedent from Python, which is:
168
187
  # Copyright (C) 1999-2001 Gregory P. Ward.
169
188
  # Copyright (C) 2002, 2003 Python Software Foundation.
170
189
  # Written by Greg Ward <gward@python.net>
@@ -172,6 +191,8 @@ class Pry
172
191
  # Licensed under <http://docs.python.org/license.html>
173
192
  # From <http://hg.python.org/cpython/file/6b9f0a6efaeb/Lib/textwrap.py>
174
193
  #
194
+ # @param [String] text The text from which to remove indentation
195
+ # @return [String] The text with indentation stripped.
175
196
  def unindent(text)
176
197
  # Empty blank lines
177
198
  text = text.sub(/^[ \t]+$/, '')