pry 0.9.10pre1-i386-mswin32 → 0.9.11-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.
- data/.travis.yml +3 -1
- data/CHANGELOG +63 -2
- data/CONTRIBUTORS +43 -25
- data/Gemfile +7 -0
- data/Guardfile +62 -0
- data/README.markdown +4 -4
- data/Rakefile +34 -35
- data/lib/pry.rb +107 -54
- data/lib/pry/cli.rb +34 -11
- data/lib/pry/code.rb +165 -182
- data/lib/pry/code/code_range.rb +70 -0
- data/lib/pry/code/loc.rb +92 -0
- data/lib/pry/code_object.rb +153 -0
- data/lib/pry/command.rb +160 -22
- data/lib/pry/command_set.rb +37 -26
- data/lib/pry/commands.rb +4 -27
- data/lib/pry/commands/amend_line.rb +99 -0
- data/lib/pry/commands/bang.rb +20 -0
- data/lib/pry/commands/bang_pry.rb +17 -0
- data/lib/pry/commands/cat.rb +53 -0
- data/lib/pry/commands/cat/abstract_formatter.rb +27 -0
- data/lib/pry/commands/cat/exception_formatter.rb +78 -0
- data/lib/pry/commands/cat/file_formatter.rb +84 -0
- data/lib/pry/commands/cat/input_expression_formatter.rb +43 -0
- data/lib/pry/commands/cd.rb +30 -0
- data/lib/pry/commands/code_collector.rb +165 -0
- data/lib/pry/commands/deprecated_commands.rb +2 -0
- data/lib/pry/commands/disable_pry.rb +27 -0
- data/lib/pry/commands/easter_eggs.rb +112 -0
- data/lib/pry/commands/edit.rb +206 -0
- data/lib/pry/commands/edit/exception_patcher.rb +25 -0
- data/lib/pry/commands/edit/file_and_line_locator.rb +38 -0
- data/lib/pry/commands/edit/method_patcher.rb +122 -0
- data/lib/pry/commands/exit.rb +42 -0
- data/lib/pry/commands/exit_all.rb +29 -0
- data/lib/pry/commands/exit_program.rb +24 -0
- data/lib/pry/commands/find_method.rb +199 -0
- data/lib/pry/commands/fix_indent.rb +19 -0
- data/lib/pry/commands/gem_cd.rb +26 -0
- data/lib/pry/commands/gem_install.rb +29 -0
- data/lib/pry/commands/gem_list.rb +33 -0
- data/lib/pry/commands/gem_open.rb +29 -0
- data/lib/pry/commands/gist.rb +95 -0
- data/lib/pry/commands/help.rb +164 -0
- data/lib/pry/commands/hist.rb +161 -0
- data/lib/pry/commands/import_set.rb +22 -0
- data/lib/pry/commands/install_command.rb +51 -0
- data/lib/pry/commands/jump_to.rb +29 -0
- data/lib/pry/commands/ls.rb +339 -0
- data/lib/pry/commands/nesting.rb +25 -0
- data/lib/pry/commands/play.rb +69 -0
- data/lib/pry/commands/pry_backtrace.rb +26 -0
- data/lib/pry/commands/pry_version.rb +17 -0
- data/lib/pry/commands/raise_up.rb +32 -0
- data/lib/pry/commands/reload_code.rb +39 -0
- data/lib/pry/commands/reset.rb +18 -0
- data/lib/pry/commands/ri.rb +56 -0
- data/lib/pry/commands/save_file.rb +61 -0
- data/lib/pry/commands/shell_command.rb +43 -0
- data/lib/pry/commands/shell_mode.rb +27 -0
- data/lib/pry/commands/show_doc.rb +78 -0
- data/lib/pry/commands/show_info.rb +139 -0
- data/lib/pry/commands/show_input.rb +17 -0
- data/lib/pry/commands/show_source.rb +37 -0
- data/lib/pry/commands/simple_prompt.rb +22 -0
- data/lib/pry/commands/stat.rb +40 -0
- data/lib/pry/commands/switch_to.rb +23 -0
- data/lib/pry/commands/toggle_color.rb +20 -0
- data/lib/pry/commands/whereami.rb +114 -0
- data/lib/pry/commands/wtf.rb +57 -0
- data/lib/pry/completion.rb +120 -46
- data/lib/pry/config.rb +11 -0
- data/lib/pry/core_extensions.rb +30 -19
- data/lib/pry/editor.rb +129 -0
- data/lib/pry/helpers.rb +1 -0
- data/lib/pry/helpers/base_helpers.rb +89 -119
- data/lib/pry/helpers/command_helpers.rb +7 -122
- data/lib/pry/helpers/table.rb +100 -0
- data/lib/pry/helpers/text.rb +4 -4
- data/lib/pry/history_array.rb +5 -0
- data/lib/pry/hooks.rb +1 -3
- data/lib/pry/indent.rb +104 -30
- data/lib/pry/method.rb +66 -22
- data/lib/pry/module_candidate.rb +26 -15
- data/lib/pry/pager.rb +70 -0
- data/lib/pry/plugins.rb +1 -2
- data/lib/pry/pry_class.rb +63 -22
- data/lib/pry/pry_instance.rb +58 -37
- data/lib/pry/rubygem.rb +74 -0
- data/lib/pry/terminal_info.rb +43 -0
- data/lib/pry/test/helper.rb +185 -0
- data/lib/pry/version.rb +1 -1
- data/lib/pry/wrapped_module.rb +58 -24
- data/pry.gemspec +21 -37
- data/{test/test_cli.rb → spec/cli_spec.rb} +0 -0
- data/spec/code_object_spec.rb +277 -0
- data/{test/test_code.rb → spec/code_spec.rb} +19 -1
- data/{test/test_command_helpers.rb → spec/command_helpers_spec.rb} +0 -0
- data/{test/test_command_integration.rb → spec/command_integration_spec.rb} +38 -46
- data/{test/test_command_set.rb → spec/command_set_spec.rb} +18 -1
- data/{test/test_command.rb → spec/command_spec.rb} +250 -149
- data/spec/commands/amend_line_spec.rb +247 -0
- data/spec/commands/bang_spec.rb +19 -0
- data/spec/commands/cat_spec.rb +164 -0
- data/spec/commands/cd_spec.rb +250 -0
- data/spec/commands/disable_pry_spec.rb +25 -0
- data/spec/commands/edit_spec.rb +727 -0
- data/spec/commands/exit_all_spec.rb +34 -0
- data/spec/commands/exit_program_spec.rb +19 -0
- data/spec/commands/exit_spec.rb +34 -0
- data/{test/test_default_commands/test_find_method.rb → spec/commands/find_method_spec.rb} +27 -7
- data/spec/commands/gem_list_spec.rb +26 -0
- data/spec/commands/gist_spec.rb +75 -0
- data/{test/test_default_commands/test_help.rb → spec/commands/help_spec.rb} +8 -9
- data/spec/commands/hist_spec.rb +181 -0
- data/spec/commands/jump_to_spec.rb +15 -0
- data/spec/commands/ls_spec.rb +177 -0
- data/spec/commands/play_spec.rb +140 -0
- data/spec/commands/raise_up_spec.rb +56 -0
- data/spec/commands/save_file_spec.rb +177 -0
- data/spec/commands/show_doc_spec.rb +378 -0
- data/spec/commands/show_input_spec.rb +17 -0
- data/spec/commands/show_source_spec.rb +597 -0
- data/spec/commands/whereami_spec.rb +154 -0
- data/spec/completion_spec.rb +233 -0
- data/spec/control_d_handler_spec.rb +58 -0
- data/spec/editor_spec.rb +79 -0
- data/{test/test_exception_whitelist.rb → spec/exception_whitelist_spec.rb} +0 -0
- data/{test → spec/fixtures}/candidate_helper1.rb +0 -0
- data/{test → spec/fixtures}/candidate_helper2.rb +0 -0
- data/{test/test_default_commands → spec/fixtures}/example.erb +0 -0
- data/spec/fixtures/example_nesting.rb +33 -0
- data/spec/fixtures/show_source_doc_examples.rb +15 -0
- data/{test → spec/fixtures}/testrc +0 -0
- data/{test → spec/fixtures}/testrcbad +0 -0
- data/spec/helper.rb +34 -0
- data/spec/helpers/bacon.rb +86 -0
- data/spec/helpers/mock_pry.rb +43 -0
- data/spec/helpers/table_spec.rb +83 -0
- data/{test/test_history_array.rb → spec/history_array_spec.rb} +21 -19
- data/{test/test_hooks.rb → spec/hooks_spec.rb} +0 -0
- data/{test/test_indent.rb → spec/indent_spec.rb} +24 -0
- data/{test/test_input_stack.rb → spec/input_stack_spec.rb} +4 -0
- data/{test/test_method.rb → spec/method_spec.rb} +65 -1
- data/{test/test_prompt.rb → spec/prompt_spec.rb} +0 -0
- data/{test/test_pry_defaults.rb → spec/pry_defaults_spec.rb} +14 -14
- data/{test/test_pry_history.rb → spec/pry_history_spec.rb} +15 -0
- data/spec/pry_output_spec.rb +95 -0
- data/{test/test_pry.rb → spec/pry_spec.rb} +74 -32
- data/{test/test_sticky_locals.rb → spec/sticky_locals_spec.rb} +27 -25
- data/{test/test_syntax_checking.rb → spec/syntax_checking_spec.rb} +17 -1
- data/{test/test_wrapped_module.rb → spec/wrapped_module_spec.rb} +92 -5
- metadata +239 -115
- data/examples/example_basic.rb +0 -15
- data/examples/example_command_override.rb +0 -32
- data/examples/example_commands.rb +0 -36
- data/examples/example_hooks.rb +0 -9
- data/examples/example_image_edit.rb +0 -67
- data/examples/example_input.rb +0 -7
- data/examples/example_input2.rb +0 -29
- data/examples/example_output.rb +0 -11
- data/examples/example_print.rb +0 -6
- data/examples/example_prompt.rb +0 -9
- data/examples/helper.rb +0 -6
- data/lib/pry/default_commands/cd.rb +0 -81
- data/lib/pry/default_commands/commands.rb +0 -62
- data/lib/pry/default_commands/context.rb +0 -98
- data/lib/pry/default_commands/easter_eggs.rb +0 -95
- data/lib/pry/default_commands/editing.rb +0 -420
- data/lib/pry/default_commands/find_method.rb +0 -169
- data/lib/pry/default_commands/gems.rb +0 -84
- data/lib/pry/default_commands/gist.rb +0 -187
- data/lib/pry/default_commands/help.rb +0 -127
- data/lib/pry/default_commands/hist.rb +0 -120
- data/lib/pry/default_commands/input_and_output.rb +0 -306
- data/lib/pry/default_commands/introspection.rb +0 -410
- data/lib/pry/default_commands/ls.rb +0 -272
- data/lib/pry/default_commands/misc.rb +0 -38
- data/lib/pry/default_commands/navigating_pry.rb +0 -110
- data/lib/pry/default_commands/whereami.rb +0 -92
- data/lib/pry/extended_commands/experimental.rb +0 -7
- data/test/helper.rb +0 -223
- data/test/test_completion.rb +0 -62
- data/test/test_control_d_handler.rb +0 -45
- data/test/test_default_commands/test_cd.rb +0 -321
- data/test/test_default_commands/test_context.rb +0 -288
- data/test/test_default_commands/test_documentation.rb +0 -315
- data/test/test_default_commands/test_gems.rb +0 -18
- data/test/test_default_commands/test_input.rb +0 -428
- data/test/test_default_commands/test_introspection.rb +0 -511
- data/test/test_default_commands/test_ls.rb +0 -151
- data/test/test_default_commands/test_shell.rb +0 -343
- data/test/test_default_commands/test_show_source.rb +0 -432
- data/test/test_pry_output.rb +0 -41
data/lib/pry/helpers/text.rb
CHANGED
@@ -33,7 +33,7 @@ class Pry
|
|
33
33
|
#
|
34
34
|
# @param [String, #to_s] text
|
35
35
|
# @return [String] _text_ stripped of any color codes.
|
36
|
-
def strip_color
|
36
|
+
def strip_color(text)
|
37
37
|
text.to_s.gsub(/\e\[.*?(\d)+m/ , '')
|
38
38
|
end
|
39
39
|
|
@@ -42,7 +42,7 @@ class Pry
|
|
42
42
|
#
|
43
43
|
# @param [String, #to_s] text
|
44
44
|
# @return [String] _text_
|
45
|
-
def bold
|
45
|
+
def bold(text)
|
46
46
|
Pry.color ? "\e[1m#{text}\e[0m" : text.to_s
|
47
47
|
end
|
48
48
|
|
@@ -59,7 +59,7 @@ class Pry
|
|
59
59
|
# Executes the block with `Pry.color` set to false.
|
60
60
|
# @yield
|
61
61
|
# @return [void]
|
62
|
-
def no_color
|
62
|
+
def no_color(&block)
|
63
63
|
boolean = Pry.config.color
|
64
64
|
Pry.config.color = false
|
65
65
|
yield
|
@@ -70,7 +70,7 @@ class Pry
|
|
70
70
|
# Executes the block with `Pry.config.pager` set to false.
|
71
71
|
# @yield
|
72
72
|
# @return [void]
|
73
|
-
def no_pager
|
73
|
+
def no_pager(&block)
|
74
74
|
boolean = Pry.config.pager
|
75
75
|
Pry.config.pager = false
|
76
76
|
yield
|
data/lib/pry/history_array.rb
CHANGED
data/lib/pry/hooks.rb
CHANGED
@@ -244,9 +244,7 @@ class Pry
|
|
244
244
|
# @param [Symbol] hook_name Name of the hook.
|
245
245
|
# @return [Boolean] Whether the hook by the name `hook_name`
|
246
246
|
def hook_exists?(event_name, hook_name)
|
247
|
-
|
247
|
+
!!(@hooks[event_name] && @hooks[event_name].find { |name, _| name == hook_name })
|
248
248
|
end
|
249
|
-
private :hook_exists?
|
250
|
-
|
251
249
|
end
|
252
250
|
end
|
data/lib/pry/indent.rb
CHANGED
@@ -17,9 +17,12 @@ class Pry
|
|
17
17
|
class Indent
|
18
18
|
include Helpers::BaseHelpers
|
19
19
|
|
20
|
+
# Raised if {#module_nesting} would not work.
|
21
|
+
class UnparseableNestingError < StandardError; end
|
22
|
+
|
20
23
|
# @return [String] String containing the spaces to be inserted before the next line.
|
21
24
|
attr_reader :indent_level
|
22
|
-
|
25
|
+
|
23
26
|
# @return [Array<String>] The stack of open tokens.
|
24
27
|
attr_reader :stack
|
25
28
|
|
@@ -51,6 +54,9 @@ class Pry
|
|
51
54
|
# a single-line.
|
52
55
|
SINGLELINE_TOKENS = %w(if while until unless rescue)
|
53
56
|
|
57
|
+
# Which tokens can be followed by an optional "do" keyword.
|
58
|
+
OPTIONAL_DO_TOKENS = %w(for while until)
|
59
|
+
|
54
60
|
# Collection of token types that should be ignored. Without this list
|
55
61
|
# keywords such as "class" inside strings would cause the code to be
|
56
62
|
# indented incorrectly.
|
@@ -73,6 +79,32 @@ class Pry
|
|
73
79
|
# don't affect the surrounding code.
|
74
80
|
MIDWAY_TOKENS = %w(when else elsif ensure rescue)
|
75
81
|
|
82
|
+
# Clean the indentation of a fragment of ruby.
|
83
|
+
#
|
84
|
+
# @param [String] str
|
85
|
+
# @return [String]
|
86
|
+
def self.indent(str)
|
87
|
+
new.indent(str)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Get the module nesting at the given point in the given string.
|
91
|
+
#
|
92
|
+
# NOTE If the line specified contains a method definition, then the nesting
|
93
|
+
# at the start of the method definition is used. Otherwise the nesting from
|
94
|
+
# the end of the line is used.
|
95
|
+
#
|
96
|
+
# @param [String] str The ruby code to analyze
|
97
|
+
# @param [Fixnum] line_number The line number (starting from 1)
|
98
|
+
# @return [Array<String>]
|
99
|
+
def self.nesting_at(str, line_number)
|
100
|
+
indent = new
|
101
|
+
lines = str.split("\n")
|
102
|
+
n = line_number - 1
|
103
|
+
to_indent = lines[0...n] + (lines[n] || "").split("def").first(1)
|
104
|
+
indent.indent(to_indent.join("\n") + "\n")
|
105
|
+
indent.module_nesting
|
106
|
+
end
|
107
|
+
|
76
108
|
def initialize
|
77
109
|
reset
|
78
110
|
end
|
@@ -84,6 +116,8 @@ class Pry
|
|
84
116
|
@heredoc_queue = []
|
85
117
|
@close_heredocs = {}
|
86
118
|
@string_start = nil
|
119
|
+
@awaiting_class = false
|
120
|
+
@module_nesting = []
|
87
121
|
self
|
88
122
|
end
|
89
123
|
|
@@ -129,7 +163,6 @@ class Pry
|
|
129
163
|
new_prefix = prefix + SPACES * after
|
130
164
|
|
131
165
|
line = prefix + line.lstrip unless previously_in_string
|
132
|
-
line = line.rstrip + "\n" unless in_string?
|
133
166
|
|
134
167
|
output += line
|
135
168
|
|
@@ -138,7 +171,7 @@ class Pry
|
|
138
171
|
|
139
172
|
@indent_level = prefix
|
140
173
|
|
141
|
-
return output
|
174
|
+
return output
|
142
175
|
end
|
143
176
|
|
144
177
|
# Get the indentation for the start of the next line.
|
@@ -192,7 +225,9 @@ class Pry
|
|
192
225
|
last_token, last_kind = token, kind unless kind == :space
|
193
226
|
next if IGNORE_TOKENS.include?(kind)
|
194
227
|
|
195
|
-
|
228
|
+
track_module_nesting(token, kind)
|
229
|
+
|
230
|
+
seen_for_at << add_after if OPTIONAL_DO_TOKENS.include?(token)
|
196
231
|
|
197
232
|
if kind == :delimiter
|
198
233
|
track_delimiter(token)
|
@@ -200,7 +235,8 @@ class Pry
|
|
200
235
|
@stack << token
|
201
236
|
add_after += 1
|
202
237
|
elsif token == OPEN_TOKENS[@stack.last]
|
203
|
-
@stack.pop
|
238
|
+
popped = @stack.pop
|
239
|
+
track_module_nesting_end(popped)
|
204
240
|
if add_after == 0
|
205
241
|
remove_before += 1
|
206
242
|
else
|
@@ -282,6 +318,68 @@ class Pry
|
|
282
318
|
"puts #{open_delimiters.join(", ")}"
|
283
319
|
end
|
284
320
|
|
321
|
+
# Update the internal state relating to module nesting.
|
322
|
+
#
|
323
|
+
# It's responsible for adding to the @module_nesting array, which looks
|
324
|
+
# something like:
|
325
|
+
#
|
326
|
+
# [ ["class", "Foo"], ["module", "Bar::Baz"], ["class <<", "self"] ]
|
327
|
+
#
|
328
|
+
# A nil value in the @module_nesting array happens in two places: either
|
329
|
+
# when @awaiting_token is true and we're still waiting for the string to
|
330
|
+
# fill that space, or when a parse was rejected.
|
331
|
+
#
|
332
|
+
# At the moment this function is quite restricted about what formats it will
|
333
|
+
# parse, for example we disallow expressions after the class keyword. This
|
334
|
+
# could maybe be improved in the future.
|
335
|
+
#
|
336
|
+
# @param [String] token a token from Coderay
|
337
|
+
# @param [Symbol] kind the kind of that token
|
338
|
+
def track_module_nesting(token, kind)
|
339
|
+
if kind == :keyword && (token == "class" || token == "module")
|
340
|
+
@module_nesting << [token, nil]
|
341
|
+
@awaiting_class = true
|
342
|
+
elsif @awaiting_class
|
343
|
+
if kind == :operator && token == "<<" && @module_nesting.last[0] == "class"
|
344
|
+
@module_nesting.last[0] = "class <<"
|
345
|
+
@awaiting_class = true
|
346
|
+
elsif kind == :class && token =~ /\A(self|[A-Z:][A-Za-z0-9_:]*)\z/
|
347
|
+
@module_nesting.last[1] = token if kind == :class
|
348
|
+
@awaiting_class = false
|
349
|
+
else
|
350
|
+
# leave @nesting[-1][
|
351
|
+
@awaiting_class = false
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
# Update the internal state relating to module nesting on 'end'.
|
357
|
+
#
|
358
|
+
# If the current 'end' pairs up with a class or a module then we should
|
359
|
+
# pop an array off of @module_nesting
|
360
|
+
#
|
361
|
+
# @param [String] token a token from Coderay
|
362
|
+
# @param [Symbol] kind the kind of that token
|
363
|
+
def track_module_nesting_end(token, kind=:keyword)
|
364
|
+
if kind == :keyword && (token == "class" || token == "module")
|
365
|
+
@module_nesting.pop
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
# Return a list of strings which can be used to re-construct the Module.nesting at
|
370
|
+
# the current point in the file.
|
371
|
+
#
|
372
|
+
# Returns nil if the syntax of the file was not recognizable.
|
373
|
+
#
|
374
|
+
# @return [Array<String>]
|
375
|
+
def module_nesting
|
376
|
+
@module_nesting.map do |(kind, token)|
|
377
|
+
raise UnparseableNestingError, @module_nesting.inspect if token.nil?
|
378
|
+
|
379
|
+
"#{kind} #{token}"
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
285
383
|
# Return a string which, when printed, will rewrite the previous line with
|
286
384
|
# the correct indentation. Mostly useful for fixing 'end'.
|
287
385
|
#
|
@@ -294,7 +392,7 @@ class Pry
|
|
294
392
|
full_line = prompt + code
|
295
393
|
whitespace = ' ' * overhang
|
296
394
|
|
297
|
-
_, cols = screen_size
|
395
|
+
_, cols = TerminalInfo.screen_size
|
298
396
|
|
299
397
|
cols = cols.to_i
|
300
398
|
lines = cols != 0 ? (full_line.length / cols + 1) : 1
|
@@ -309,29 +407,5 @@ class Pry
|
|
309
407
|
|
310
408
|
"#{move_up}#{prompt}#{colorize_code(code)}#{whitespace}#{move_down}"
|
311
409
|
end
|
312
|
-
|
313
|
-
# Return a pair of [rows, columns] which gives the size of the window.
|
314
|
-
#
|
315
|
-
# If the window size cannot be determined, return nil.
|
316
|
-
def screen_size
|
317
|
-
[
|
318
|
-
# io/console adds a winsize method to IO streams.
|
319
|
-
$stdout.tty? && $stdout.respond_to?(:winsize) && $stdout.winsize,
|
320
|
-
|
321
|
-
# Some readlines also provides get_screen_size.
|
322
|
-
Readline.respond_to?(:get_screen_size) && Readline.get_screen_size,
|
323
|
-
|
324
|
-
# Otherwise try to use the environment (this may be out of date due
|
325
|
-
# to window resizing, but it's better than nothing).
|
326
|
-
[ENV["ROWS"], ENV["COLUMNS"],
|
327
|
-
|
328
|
-
# If the user is running within ansicon, then use the screen size
|
329
|
-
# that it reports (same caveats apply as with ROWS and COLUMNS)
|
330
|
-
ENV['ANSICON'] =~ /\((.*)x(.*)\)/ && [$2, $1]
|
331
|
-
]
|
332
|
-
].detect do |(_, cols)|
|
333
|
-
cols.to_i > 0
|
334
|
-
end
|
335
|
-
end
|
336
410
|
end
|
337
411
|
end
|
data/lib/pry/method.rb
CHANGED
@@ -17,8 +17,11 @@ class Pry
|
|
17
17
|
# This class wraps the normal `Method` and `UnboundMethod` classes
|
18
18
|
# to provide extra functionality useful to Pry.
|
19
19
|
class Method
|
20
|
+
extend Helpers::BaseHelpers
|
21
|
+
include Helpers::BaseHelpers
|
20
22
|
include RbxMethod if Helpers::BaseHelpers.rbx?
|
21
23
|
include Helpers::DocumentationHelpers
|
24
|
+
include CodeObject::Helpers
|
22
25
|
|
23
26
|
class << self
|
24
27
|
# Given a string representing a method name and optionally a binding to
|
@@ -40,18 +43,21 @@ class Pry
|
|
40
43
|
from_binding(target)
|
41
44
|
elsif name.to_s =~ /(.+)\#(\S+)\Z/
|
42
45
|
context, meth_name = $1, $2
|
43
|
-
from_module(target.eval(context), meth_name)
|
44
|
-
elsif name.to_s =~ /(.+)
|
45
|
-
context, meth_name = $1, $
|
46
|
-
from_obj(target.eval(context), meth_name)
|
46
|
+
from_module(target.eval(context), meth_name, target)
|
47
|
+
elsif name.to_s =~ /(.+)(\.|::)(\S+)\Z/
|
48
|
+
context, meth_name = $1, $3
|
49
|
+
from_obj(target.eval(context), meth_name, target)
|
47
50
|
elsif options[:instance]
|
48
|
-
from_module(target.eval("self"), name)
|
51
|
+
from_module(target.eval("self"), name, target)
|
49
52
|
elsif options[:methods]
|
50
|
-
from_obj(target.eval("self"), name)
|
53
|
+
from_obj(target.eval("self"), name, target)
|
51
54
|
else
|
52
55
|
from_str(name, target, :instance => true) or
|
53
56
|
from_str(name, target, :methods => true)
|
54
57
|
end
|
58
|
+
|
59
|
+
rescue Pry::RescuableException
|
60
|
+
nil
|
55
61
|
end
|
56
62
|
|
57
63
|
# Given a `Binding`, try to extract the `::Method` it originated from and
|
@@ -62,12 +68,16 @@ class Pry
|
|
62
68
|
# @return [Pry::Method, nil]
|
63
69
|
#
|
64
70
|
def from_binding(b)
|
65
|
-
meth_name = b.eval('__method__')
|
71
|
+
meth_name = b.eval('::Kernel.__method__')
|
66
72
|
if [:__script__, nil].include?(meth_name)
|
67
73
|
nil
|
68
74
|
else
|
69
75
|
method = begin
|
70
|
-
|
76
|
+
if Object === b.eval('self')
|
77
|
+
new(Kernel.instance_method(:method).bind(b.eval("self")).call(meth_name))
|
78
|
+
else
|
79
|
+
new(b.eval('class << self; self; end.instance_method(::Kernel.__method__).bind(self)'))
|
80
|
+
end
|
71
81
|
rescue NameError, NoMethodError
|
72
82
|
Disowned.new(b.eval('self'), meth_name.to_s)
|
73
83
|
end
|
@@ -106,15 +116,32 @@ class Pry
|
|
106
116
|
end
|
107
117
|
end
|
108
118
|
|
119
|
+
# In order to support 2.0 Refinements we need to look up methods
|
120
|
+
# inside the relevant Binding.
|
121
|
+
# @param [Object] obj The owner/receiver of the method.
|
122
|
+
# @param [Symbol] method_name The name of the method.
|
123
|
+
# @param [Symbol] method_type The type of method: :method or :instance_method
|
124
|
+
# @param [Binding] target The binding where the method is looked up.
|
125
|
+
# @return [Method, UnboundMethod] The 'refined' method object.
|
126
|
+
def lookup_method_via_binding(obj, method_name, method_type, target=TOPLEVEL_BINDING)
|
127
|
+
Pry.current[:obj] = obj
|
128
|
+
Pry.current[:name] = method_name
|
129
|
+
receiver = obj.is_a?(Module) ? "Module" : "Kernel"
|
130
|
+
target.eval("::#{receiver}.instance_method(:#{method_type}).bind(Pry.current[:obj]).call(Pry.current[:name])")
|
131
|
+
ensure
|
132
|
+
Pry.current[:obj] = Pry.current[:name] = nil
|
133
|
+
end
|
134
|
+
|
109
135
|
# Given a `Class` or `Module` and the name of a method, try to
|
110
136
|
# instantiate a `Pry::Method` containing the instance method of
|
111
137
|
# that name. Return `nil` if no such method exists.
|
112
138
|
#
|
113
139
|
# @param [Class, Module] klass
|
114
140
|
# @param [String] name
|
141
|
+
# @param [Binding] target The binding where the method is looked up.
|
115
142
|
# @return [Pry::Method, nil]
|
116
|
-
def from_class(klass, name)
|
117
|
-
new(
|
143
|
+
def from_class(klass, name, target=TOPLEVEL_BINDING)
|
144
|
+
new(lookup_method_via_binding(klass, name, :instance_method, target)) rescue nil
|
118
145
|
end
|
119
146
|
alias from_module from_class
|
120
147
|
|
@@ -124,9 +151,10 @@ class Pry
|
|
124
151
|
#
|
125
152
|
# @param [Object] obj
|
126
153
|
# @param [String] name
|
154
|
+
# @param [Binding] target The binding where the method is looked up.
|
127
155
|
# @return [Pry::Method, nil]
|
128
|
-
def from_obj(obj, name)
|
129
|
-
new(
|
156
|
+
def from_obj(obj, name, target=TOPLEVEL_BINDING)
|
157
|
+
new(lookup_method_via_binding(obj, name, :method, target)) rescue nil
|
130
158
|
end
|
131
159
|
|
132
160
|
# Get all of the instance methods of a `Class` or `Module`
|
@@ -183,15 +211,6 @@ class Pry
|
|
183
211
|
end.flatten(1)
|
184
212
|
end
|
185
213
|
|
186
|
-
# Acts like send but ignores any methods defined below Object or Class in the
|
187
|
-
# inheritance hierarchy.
|
188
|
-
# This is required to introspect methods on objects like Net::HTTP::Get that
|
189
|
-
# have overridden the `method` method.
|
190
|
-
def safe_send(obj, method, *args, &block)
|
191
|
-
(Module === obj ? Module : Object).instance_method(method).bind(obj).call(*args, &block)
|
192
|
-
end
|
193
|
-
public :safe_send
|
194
|
-
|
195
214
|
# Get the singleton classes of superclasses that could define methods on
|
196
215
|
# the given class object, and any modules they include.
|
197
216
|
# If a module is included at multiple points in the ancestry, only
|
@@ -229,6 +248,12 @@ class Pry
|
|
229
248
|
@wrapped_owner ||= Pry::WrappedModule.new(owner)
|
230
249
|
end
|
231
250
|
|
251
|
+
# Get underlying object wrapped by this Pry::Method instance
|
252
|
+
# @return [Method, UnboundMethod, Proc]
|
253
|
+
def wrapped
|
254
|
+
@method
|
255
|
+
end
|
256
|
+
|
232
257
|
# Is the method undefined? (aka `Disowned`)
|
233
258
|
# @return [Boolean] false
|
234
259
|
def undefined?
|
@@ -403,6 +428,24 @@ class Pry
|
|
403
428
|
source_file == Pry.eval_path
|
404
429
|
end
|
405
430
|
|
431
|
+
# @return [Array<String>] All known aliases for the method.
|
432
|
+
# @note On Ruby 1.8 this method always returns an empty Array for methods
|
433
|
+
# implemented in C.
|
434
|
+
def aliases
|
435
|
+
owner = @method.owner
|
436
|
+
# Avoid using `to_sym` on {Method#name}, which returns a `String`, because
|
437
|
+
# it won't be garbage collected.
|
438
|
+
name = @method.name
|
439
|
+
|
440
|
+
alias_list = owner.instance_methods.combination(2).select do |pair|
|
441
|
+
pair.include?(name) &&
|
442
|
+
owner.instance_method(pair.first) == owner.instance_method(pair.last)
|
443
|
+
end.flatten
|
444
|
+
alias_list.delete(name)
|
445
|
+
|
446
|
+
alias_list.map(&:to_s)
|
447
|
+
end
|
448
|
+
|
406
449
|
# @return [Boolean] Is the method definitely an alias?
|
407
450
|
def alias?
|
408
451
|
name != original_name
|
@@ -475,7 +518,8 @@ class Pry
|
|
475
518
|
end
|
476
519
|
next_owner = ancestors[i] or return nil
|
477
520
|
end
|
478
|
-
|
521
|
+
|
522
|
+
safe_send(next_owner, :instance_method, name) rescue nil
|
479
523
|
end
|
480
524
|
|
481
525
|
# @param [String] first_ln The first line of a method definition.
|
data/lib/pry/module_candidate.rb
CHANGED
@@ -8,18 +8,21 @@ class Pry
|
|
8
8
|
# It provides access to the source, documentation, line and file
|
9
9
|
# for a monkeypatch (reopening) of a class/module.
|
10
10
|
class Candidate
|
11
|
+
include Pry::Helpers::DocumentationHelpers
|
12
|
+
include Pry::CodeObject::Helpers
|
11
13
|
extend Forwardable
|
12
14
|
|
13
15
|
# @return [String] The file where the module definition is located.
|
14
16
|
attr_reader :file
|
17
|
+
alias_method :source_file, :file
|
15
18
|
|
16
19
|
# @return [Fixnum] The line where the module definition is located.
|
17
20
|
attr_reader :line
|
21
|
+
alias_method :source_line, :line
|
18
22
|
|
19
23
|
# Methods to delegate to associated `Pry::WrappedModule instance`.
|
20
24
|
to_delegate = [:lines_for_file, :method_candidates, :name, :wrapped,
|
21
|
-
:yard_docs?, :number_of_candidates
|
22
|
-
:strip_leading_whitespace]
|
25
|
+
:yard_docs?, :number_of_candidates]
|
23
26
|
|
24
27
|
def_delegators :@wrapper, *to_delegate
|
25
28
|
private(*to_delegate)
|
@@ -61,7 +64,7 @@ class Pry
|
|
61
64
|
return @doc if @doc
|
62
65
|
raise CommandError, "Could not locate doc for #{wrapped}!" if file.nil?
|
63
66
|
|
64
|
-
@doc =
|
67
|
+
@doc = strip_leading_hash_and_whitespace_from_ruby_comments(Pry::Code.from_file(file).comment_describing(line))
|
65
68
|
end
|
66
69
|
|
67
70
|
# @return [Array, nil] A `[String, Fixnum]` pair representing the
|
@@ -70,27 +73,35 @@ class Pry
|
|
70
73
|
def source_location
|
71
74
|
return @source_location if @source_location
|
72
75
|
|
73
|
-
mod_type_string = wrapped.class.to_s.downcase
|
74
76
|
file, line = first_method_source_location
|
75
|
-
|
76
77
|
return nil if !file.is_a?(String)
|
77
78
|
|
78
|
-
|
79
|
-
/^\s*(::)?#{wrapped.name.split(/::/).last}\s*?=\s*?#{wrapped.class}/,
|
80
|
-
/^\s*(::)?#{wrapped.name.split(/::/).last}\.(class|instance)_eval/]
|
81
|
-
|
82
|
-
host_file_lines = lines_for_file(file)
|
83
|
-
|
84
|
-
search_lines = host_file_lines[0..(line - 2)]
|
85
|
-
idx = search_lines.rindex { |v| class_regexes.any? { |r| r =~ v } }
|
86
|
-
|
87
|
-
@source_location = [file, idx + 1]
|
79
|
+
@source_location = [file, first_line_of_module_definition(file, line)]
|
88
80
|
rescue Pry::RescuableException
|
89
81
|
nil
|
90
82
|
end
|
91
83
|
|
92
84
|
private
|
93
85
|
|
86
|
+
# Locate the first line of the module definition.
|
87
|
+
# @param [String] file The file that contains the module
|
88
|
+
# definition (somewhere).
|
89
|
+
# @param [Fixnum] line The module definition should appear
|
90
|
+
# before this line (if it exists).
|
91
|
+
# @return [Fixnum] The line where the module is defined. This
|
92
|
+
# line number is one-indexed.
|
93
|
+
def first_line_of_module_definition(file, line)
|
94
|
+
searchable_lines = lines_for_file(file)[0..(line - 2)]
|
95
|
+
searchable_lines.rindex { |v| class_regexes.any? { |r| r =~ v } } + 1
|
96
|
+
end
|
97
|
+
|
98
|
+
def class_regexes
|
99
|
+
mod_type_string = wrapped.class.to_s.downcase
|
100
|
+
[/^\s*#{mod_type_string}\s+(?:(?:\w*)::)*?#{wrapped.name.split(/::/).last}/,
|
101
|
+
/^\s*(::)?#{wrapped.name.split(/::/).last}\s*?=\s*?#{wrapped.class}/,
|
102
|
+
/^\s*(::)?#{wrapped.name.split(/::/).last}\.(class|instance)_eval/]
|
103
|
+
end
|
104
|
+
|
94
105
|
# This method is used by `Candidate#source_location` as a
|
95
106
|
# starting point for the search for the candidate's definition.
|
96
107
|
# @return [Array] The source location of the base method used to
|