pry 0.9.8.4-i386-mswin32 → 0.9.9-i386-mswin32

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 (46) hide show
  1. data/.gitignore +1 -0
  2. data/CHANGELOG +26 -0
  3. data/README.markdown +3 -3
  4. data/lib/pry.rb +9 -1
  5. data/lib/pry/code.rb +93 -0
  6. data/lib/pry/command.rb +35 -22
  7. data/lib/pry/command_set.rb +97 -67
  8. data/lib/pry/config.rb +63 -10
  9. data/lib/pry/core_extensions.rb +24 -18
  10. data/lib/pry/default_commands/context.rb +72 -12
  11. data/lib/pry/default_commands/easter_eggs.rb +4 -0
  12. data/lib/pry/default_commands/editing.rb +43 -15
  13. data/lib/pry/default_commands/find_method.rb +171 -0
  14. data/lib/pry/default_commands/hist.rb +10 -6
  15. data/lib/pry/default_commands/introspection.rb +183 -30
  16. data/lib/pry/default_commands/ls.rb +77 -7
  17. data/lib/pry/default_commands/misc.rb +1 -0
  18. data/lib/pry/default_commands/navigating_pry.rb +1 -8
  19. data/lib/pry/helpers/base_helpers.rb +10 -2
  20. data/lib/pry/helpers/command_helpers.rb +23 -40
  21. data/lib/pry/helpers/documentation_helpers.rb +65 -0
  22. data/lib/pry/indent.rb +17 -4
  23. data/lib/pry/method.rb +61 -45
  24. data/lib/pry/pry_class.rb +9 -3
  25. data/lib/pry/pry_instance.rb +99 -65
  26. data/lib/pry/rbx_method.rb +2 -9
  27. data/lib/pry/version.rb +1 -1
  28. data/lib/pry/wrapped_module.rb +236 -1
  29. data/pry.gemspec +5 -5
  30. data/test/helper.rb +22 -0
  31. data/test/test_command.rb +29 -0
  32. data/test/test_command_integration.rb +193 -10
  33. data/test/test_command_set.rb +82 -17
  34. data/test/test_default_commands/test_cd.rb +16 -0
  35. data/test/test_default_commands/test_context.rb +61 -0
  36. data/test/test_default_commands/test_documentation.rb +163 -43
  37. data/test/test_default_commands/test_find_method.rb +42 -0
  38. data/test/test_default_commands/test_input.rb +32 -0
  39. data/test/test_default_commands/test_introspection.rb +50 -197
  40. data/test/test_default_commands/test_ls.rb +22 -0
  41. data/test/test_default_commands/test_show_source.rb +306 -0
  42. data/test/test_pry.rb +3 -3
  43. data/test/test_pry_defaults.rb +21 -0
  44. data/test/test_sticky_locals.rb +81 -1
  45. data/test/test_syntax_checking.rb +7 -6
  46. metadata +24 -16
@@ -32,21 +32,25 @@ class Pry
32
32
  def process
33
33
  @history = Pry::Code(Pry.history.to_a)
34
34
 
35
+ if opts.present?(:show)
36
+ @history = @history.between(opts[:show])
37
+ end
38
+
39
+ if opts.present?(:grep)
40
+ @history = @history.grep(opts[:grep])
41
+ end
42
+
35
43
  @history = case
36
44
  when opts.present?(:head)
37
- @history.between(1, opts[:head] || 10)
45
+ @history.take_lines(1, opts[:head] || 10)
38
46
  when opts.present?(:tail)
39
- @history.between(-(opts[:tail] || 10), -1)
47
+ @history.take_lines(-(opts[:tail] || 10), opts[:tail] || 10)
40
48
  when opts.present?(:show)
41
49
  @history.between(opts[:show])
42
50
  else
43
51
  @history
44
52
  end
45
53
 
46
- if opts.present?(:grep)
47
- @history = @history.grep(opts[:grep])
48
- end
49
-
50
54
  if opts.present?(:'exclude-pry')
51
55
  @history = @history.select { |l, ln| !command_set.valid_command?(l) }
52
56
  end
@@ -3,23 +3,127 @@ require 'tempfile'
3
3
  class Pry
4
4
  module DefaultCommands
5
5
 
6
+ # For show-doc and show-source
7
+ module ModuleIntrospectionHelpers
8
+ attr_accessor :module_object
9
+
10
+ def module?(name)
11
+ self.module_object = Pry::WrappedModule.from_str(name, target)
12
+ end
13
+
14
+ def method?
15
+ !!method_object
16
+ rescue CommandError
17
+ false
18
+ end
19
+
20
+ def process(name)
21
+ if module?(name)
22
+ code_or_doc = process_module
23
+ else method?
24
+ code_or_doc = process_method
25
+ end
26
+
27
+ render_output(code_or_doc, opts)
28
+ end
29
+
30
+ def module_start_line(mod, candidate=0)
31
+ if opts.present?(:'base-one')
32
+ 1
33
+ else
34
+ mod.source_line_for_candidate(candidate)
35
+ end
36
+ end
37
+
38
+ def use_line_numbers?
39
+ opts.present?(:b) || opts.present?(:l)
40
+ end
41
+ end
42
+
6
43
  Introspection = Pry::CommandSet.new do
7
44
 
8
- create_command "show-doc", "Show the comments above METH. Aliases: \?", :shellwords => false do |*args|
45
+ create_command "show-doc", "Show the comments above METH. Aliases: \?", :shellwords => false do
46
+ include ModuleIntrospectionHelpers
47
+ include Helpers::DocumentationHelpers
48
+ extend Helpers::BaseHelpers
49
+
9
50
  banner <<-BANNER
10
51
  Usage: show-doc [OPTIONS] [METH]
52
+ Aliases: ?
53
+
11
54
  Show the comments above method METH. Tries instance methods first and then methods by default.
12
- e.g show-doc hello_method
55
+ e.g show-doc hello_method # docs for hello_method
56
+ e.g show-doc Pry # docs for Pry class
57
+ e.g show-doc Pry -a # docs for all definitions of Pry class (all monkey patches)
13
58
  BANNER
14
59
 
60
+ options :requires_gem => "ruby18_source_location" if mri_18?
61
+
62
+ def setup
63
+ require 'ruby18_source_location' if mri_18?
64
+ end
65
+
15
66
  def options(opt)
16
67
  method_options(opt)
17
68
  opt.on :l, "line-numbers", "Show line numbers."
18
69
  opt.on :b, "base-one", "Show line numbers but start numbering at 1 (useful for `amend-line` and `play` commands)."
19
70
  opt.on :f, :flood, "Do not use a pager to view text longer than one screen."
71
+ opt.on :a, :all, "Show docs for all definitions and monkeypatches of the module (modules only)"
20
72
  end
21
73
 
22
- def process
74
+ def process_module
75
+ if opts.present?(:all)
76
+ all_modules
77
+ else
78
+ normal_module
79
+ end
80
+ end
81
+
82
+ 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
90
+ else
91
+ file_name, line = mod.source_location
92
+ end
93
+
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
101
+
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
107
+ end
108
+
109
+ def all_modules
110
+ mod = module_object
111
+
112
+ doc = ""
113
+ doc << "Found #{mod.number_of_candidates} candidates for `#{mod.name}` definition:\n"
114
+ mod.number_of_candidates.times do |v|
115
+ 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)
119
+ rescue Pry::RescuableException
120
+ next
121
+ end
122
+ end
123
+ doc
124
+ end
125
+
126
+ def process_method
23
127
  meth = method_object
24
128
  raise Pry::CommandError, "No documentation found." if meth.doc.nil? || meth.doc.empty?
25
129
 
@@ -30,12 +134,20 @@ class Pry
30
134
  output.puts "#{text.bold("Signature:")} #{meth.signature}"
31
135
  output.puts
32
136
 
33
- if opts.present?(:b) || opts.present?(:l)
137
+ if use_line_numbers?
34
138
  doc = Code.new(doc, start_line, :text).
35
- with_line_numbers(true)
139
+ with_line_numbers(true).to_s
36
140
  end
37
141
 
38
- render_output(doc, opts)
142
+ doc
143
+ end
144
+
145
+ def module_start_line(mod, candidate=0)
146
+ if opts.present?(:'base-one')
147
+ 1
148
+ else
149
+ mod.source_line_for_candidate(candidate) - mod.doc_for_candidate(candidate).lines.count
150
+ end
39
151
  end
40
152
 
41
153
  def start_line
@@ -45,12 +157,11 @@ class Pry
45
157
  (method_object.source_line - method_object.doc.lines.count) || 1
46
158
  end
47
159
  end
48
-
49
160
  end
50
161
 
51
162
  alias_command "?", "show-doc"
52
163
 
53
- create_command "stat", "View method information and set _file_ and _dir_ locals.", :shellwords => false do |*args|
164
+ create_command "stat", "View method information and set _file_ and _dir_ locals.", :shellwords => false do
54
165
  banner <<-BANNER
55
166
  Usage: stat [OPTIONS] [METH]
56
167
  Show method information for method METH and set _file_ and _dir_ locals.
@@ -77,45 +188,87 @@ class Pry
77
188
  end
78
189
  end
79
190
 
80
- create_command "show-method" do
81
- description "Show the source for METH. Aliases: $, show-source"
191
+ create_command "show-source" do
192
+ include ModuleIntrospectionHelpers
193
+ extend Helpers::BaseHelpers
194
+
195
+ description "Show the source for METH or CLASS. Aliases: $, show-method"
82
196
 
83
197
  banner <<-BANNER
84
- Usage: show-method [OPTIONS] [METH]
85
- Aliases: $, show-source
198
+ Usage: show-source [OPTIONS] [METH|CLASS]
199
+ Aliases: $, show-method
86
200
 
87
- Show the source for method METH. Tries instance methods first and then methods by default.
201
+ Show the source for method METH or CLASS. Tries instance methods first and then methods by default.
88
202
 
89
- e.g: `show-method hello_method`
90
- e.g: `show-method -m hello_method`
91
- e.g: `show-method Pry#rep`
203
+ e.g: `show-source hello_method`
204
+ e.g: `show-source -m hello_method`
205
+ e.g: `show-source Pry#rep` # source for Pry#rep method
206
+ e.g: `show-source Pry` # source for Pry class
207
+ e.g: `show-source Pry -a` # source for all Pry class definitions (all monkey patches)
92
208
 
93
209
  https://github.com/pry/pry/wiki/Source-browsing#wiki-Show_method
94
210
  BANNER
95
211
 
96
- command_options(
97
- :shellwords => false
98
- )
212
+ options :shellwords => false
213
+ options :requires_gem => "ruby18_source_location" if mri_18?
214
+
215
+ def setup
216
+ require 'ruby18_source_location' if mri_18?
217
+ end
99
218
 
100
219
  def options(opt)
101
220
  method_options(opt)
102
221
  opt.on :l, "line-numbers", "Show line numbers."
103
222
  opt.on :b, "base-one", "Show line numbers but start numbering at 1 (useful for `amend-line` and `play` commands)."
104
223
  opt.on :f, :flood, "Do not use a pager to view text longer than one screen."
224
+ opt.on :a, :all, "Show source for all definitions and monkeypatches of the module (modules only)"
105
225
  end
106
226
 
107
- def process
227
+ def process_method
108
228
  raise CommandError, "Could not find method source" unless method_object.source
109
229
 
110
- output.puts make_header(method_object)
111
- output.puts "#{text.bold("Owner:")} #{method_object.owner || "N/A"}"
112
- output.puts "#{text.bold("Visibility:")} #{method_object.visibility}"
113
- output.puts
230
+ code = ""
231
+ code << make_header(method_object)
232
+ code << "#{text.bold("Owner:")} #{method_object.owner || "N/A"}\n"
233
+ code << "#{text.bold("Visibility:")} #{method_object.visibility}\n"
234
+ code << "\n"
114
235
 
115
- code = Code.from_method(method_object, start_line).
116
- with_line_numbers(use_line_numbers?)
236
+ code << Code.from_method(method_object, start_line).
237
+ with_line_numbers(use_line_numbers?).to_s
238
+ end
117
239
 
118
- render_output(code, opts)
240
+ def process_module
241
+ if opts.present?(:all)
242
+ all_modules
243
+ else
244
+ normal_module
245
+ end
246
+ end
247
+
248
+ def normal_module
249
+ mod = module_object
250
+
251
+ file_name, line = mod.source_location
252
+ set_file_and_dir_locals(file_name)
253
+ code = ""
254
+ code << "\n#{Pry::Helpers::Text.bold('From:')} #{file_name} @ line #{line}:\n\n"
255
+ code << Code.from_module(mod, module_start_line(mod)).with_line_numbers(use_line_numbers?).to_s
256
+ end
257
+
258
+ def all_modules
259
+ mod = module_object
260
+
261
+ code = ""
262
+ code << "Found #{mod.number_of_candidates} candidates for `#{mod.name}` definition:\n"
263
+ mod.number_of_candidates.times do |v|
264
+ begin
265
+ code << "\nCandidate #{v+1}/#{mod.number_of_candidates}: #{mod.source_file_for_candidate(v)} @ line #{mod.source_line_for_candidate(v)}:\n\n"
266
+ code << Code.new(mod.source_for_candidate(v), module_start_line(mod, v)).with_line_numbers(use_line_numbers?).to_s
267
+ rescue Pry::RescuableException
268
+ next
269
+ end
270
+ end
271
+ code
119
272
  end
120
273
 
121
274
  def use_line_numbers?
@@ -131,8 +284,8 @@ class Pry
131
284
  end
132
285
  end
133
286
 
134
- alias_command "show-source", "show-method"
135
- alias_command "$", "show-method"
287
+ alias_command "show-method", "show-source"
288
+ alias_command "$", "show-source"
136
289
 
137
290
  command "show-command", "Show the source for CMD." do |*args|
138
291
  target = target()
@@ -167,7 +320,7 @@ class Pry
167
320
  output.puts make_header(block)
168
321
  output.puts
169
322
 
170
- code = Code.from_method(block).with_line_numbers(opts.present?(:'line-numbers'))
323
+ code = Code.from_method(block).with_line_numbers(opts.present?(:'line-numbers')).to_s
171
324
 
172
325
  render_output(code, opts)
173
326
  else
@@ -30,11 +30,15 @@ class Pry
30
30
  opt.on :g, "globals", "Show global variables, including those builtin to Ruby (in cyan)"
31
31
  opt.on :l, "locals", "Show locals, including those provided by Pry (in red)"
32
32
 
33
- opt.on :c, "constants", "Show constants, highlighting classes (in blue), and exceptions (in purple)"
33
+ opt.on :c, "constants", "Show constants, highlighting classes (in blue), and exceptions (in purple).\n" +
34
+ " " * 32 + "Constants that are pending autoload? are also shown (in yellow)."
34
35
 
35
36
  opt.on :i, "ivars", "Show instance variables (in blue) and class variables (in bright blue)"
36
37
 
37
38
  opt.on :G, "grep", "Filter output by regular expression", :optional => false
39
+ if jruby?
40
+ opt.on :J, "all-java", "Show all the aliases for methods from java (default is to show only prettiest)"
41
+ end
38
42
  end
39
43
 
40
44
  def process
@@ -46,6 +50,7 @@ class Pry
46
50
  opts.present?(:ivars))
47
51
 
48
52
  show_methods = opts.present?(:methods) || opts.present?(:'instance-methods') || opts.present?(:ppp) || !has_opts
53
+ show_self_methods = (!has_opts && Module === obj)
49
54
  show_constants = opts.present?(:constants) || (!has_opts && Module === obj)
50
55
  show_ivars = opts.present?(:ivars) || !has_opts
51
56
  show_locals = opts.present?(:locals) || (!has_opts && args.empty?)
@@ -72,7 +77,7 @@ class Pry
72
77
 
73
78
  if show_methods
74
79
  # methods is a hash {Module/Class => [Pry::Methods]}
75
- methods = all_methods(obj).select{ |method| opts.present?(:ppp) || method.visibility == :public }.group_by(&:owner)
80
+ methods = all_methods(obj).group_by(&:owner)
76
81
 
77
82
  # reverse the resolution order so that the most useful information appears right by the prompt
78
83
  resolution_order(obj).take_while(&below_ceiling(obj)).reverse.each do |klass|
@@ -81,10 +86,17 @@ class Pry
81
86
  end
82
87
  end
83
88
 
89
+ if show_self_methods
90
+ methods = all_methods(obj, true).select{ |m| m.owner == obj && m.name =~ grep_regex }
91
+ output_section "#{Pry::WrappedModule.new(obj).method_prefix}methods", format_methods(methods)
92
+ end
93
+
84
94
  if show_ivars
85
95
  klass = (Module === obj ? obj : obj.class)
86
- output_section("instance variables", format_variables(:instance_var, grep[obj.__send__(:instance_variables)]))
87
- output_section("class variables", format_variables(:class_var, grep[klass.__send__(:class_variables)]))
96
+ ivars = Pry::Method.safe_send(obj, :instance_variables)
97
+ kvars = Pry::Method.safe_send(klass, :class_variables)
98
+ output_section("instance variables", format_variables(:instance_var, ivars))
99
+ output_section("class variables", format_variables(:class_var, kvars))
88
100
  end
89
101
 
90
102
  if show_locals
@@ -109,8 +121,64 @@ class Pry
109
121
  $LAST_PAREN_MATCH $LAST_READ_LINE $MATCH $POSTMATCH $PREMATCH)
110
122
 
111
123
  # Get all the methods that we'll want to output
112
- def all_methods(obj)
113
- opts.present?(:'instance-methods') ? Pry::Method.all_from_class(obj) : Pry::Method.all_from_obj(obj)
124
+ def all_methods(obj, instance_methods=false)
125
+ methods = if instance_methods || opts.present?(:'instance-methods')
126
+ Pry::Method.all_from_class(obj)
127
+ else
128
+ Pry::Method.all_from_obj(obj)
129
+ end
130
+
131
+ if jruby? && !opts.present?(:J)
132
+ methods = trim_jruby_aliases(methods)
133
+ end
134
+
135
+ methods.select{ |method| opts.present?(:ppp) || method.visibility == :public }
136
+ end
137
+
138
+ # JRuby creates lots of aliases for methods imported from java in an attempt to
139
+ # make life easier for ruby programmers.
140
+ # (e.g. getFooBar becomes get_foo_bar and foo_bar, and maybe foo_bar? if it
141
+ # returns a Boolean).
142
+ # The full transformations are in the assignAliases method of:
143
+ # https://github.com/jruby/jruby/blob/master/src/org/jruby/javasupport/JavaClass.java
144
+ #
145
+ # This has the unfortunate side-effect of making the output of ls even more
146
+ # incredibly verbose than it normally would be for these objects; and so we filter
147
+ # out all but the nicest of these aliases here.
148
+ #
149
+ # TODO: This is a little bit vague, better heuristics could be used.
150
+ # JRuby also has a lot of scala-specific logic, which we don't copy.
151
+ #
152
+ def trim_jruby_aliases(methods)
153
+ grouped = methods.group_by do |m|
154
+ m.name.sub(/\A(is|get|set)(?=[A-Z_])/, '').gsub(/[_?=]/, '').downcase
155
+ end
156
+
157
+ grouped.map do |key, values|
158
+ values = values.sort_by do |m|
159
+ rubbishness(m.name)
160
+ end
161
+
162
+ found = []
163
+ values.select do |x|
164
+ (!found.any?{ |y| x == y }) && found << x
165
+ end
166
+ end.flatten(1)
167
+ end
168
+
169
+ # When removing jruby aliases, we want to keep the alias that is "least rubbish"
170
+ # according to this metric.
171
+ def rubbishness(name)
172
+ name.each_char.map{ |x|
173
+ case x
174
+ when /[A-Z]/
175
+ 1
176
+ when '?', '=', '!'
177
+ -2
178
+ else
179
+ 0
180
+ end
181
+ }.inject(&:+) + (name.size / 100.0)
114
182
  end
115
183
 
116
184
  def resolution_order(obj)
@@ -152,7 +220,7 @@ class Pry
152
220
 
153
221
  def format_constants(mod, constants)
154
222
  constants.sort_by(&:downcase).map do |name|
155
- if const = (!mod.autoload?(name) && mod.const_get(name) rescue nil)
223
+ if const = (!mod.autoload?(name) && (mod.const_get(name) || true) rescue nil)
156
224
  if (const < Exception rescue false)
157
225
  color(:exception_constant, name)
158
226
  elsif (Module === mod.const_get(name) rescue false)
@@ -160,6 +228,8 @@ class Pry
160
228
  else
161
229
  color(:constant, name)
162
230
  end
231
+ else
232
+ color(:unloaded_constant, name)
163
233
  end
164
234
  end
165
235
  end