pry 0.9.10 → 0.9.11
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +3 -1
- data/CHANGELOG +60 -1
- 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 +27 -16
- 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 +6 -121
- 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 +236 -112
- 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
|