pry 0.10.pre.1-java → 0.10.0.pre2-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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +702 -0
- data/LICENSE +2 -2
- data/{README.markdown → README.md} +41 -35
- data/lib/pry.rb +82 -139
- data/lib/pry/cli.rb +77 -30
- data/lib/pry/code.rb +126 -182
- data/lib/pry/code/code_file.rb +103 -0
- data/lib/pry/code/code_range.rb +71 -0
- data/lib/pry/code/loc.rb +92 -0
- data/lib/pry/code_object.rb +172 -0
- data/lib/pry/color_printer.rb +55 -0
- data/lib/pry/command.rb +184 -28
- data/lib/pry/command_set.rb +113 -59
- 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 +62 -0
- data/lib/pry/commands/cat/abstract_formatter.rb +27 -0
- data/lib/pry/commands/cat/exception_formatter.rb +77 -0
- data/lib/pry/commands/cat/file_formatter.rb +67 -0
- data/lib/pry/commands/cat/input_expression_formatter.rb +43 -0
- data/lib/pry/commands/cd.rb +41 -0
- data/lib/pry/commands/change_inspector.rb +27 -0
- data/lib/pry/commands/change_prompt.rb +26 -0
- data/lib/pry/commands/code_collector.rb +165 -0
- data/lib/pry/commands/disable_pry.rb +27 -0
- data/lib/pry/commands/disabled_commands.rb +2 -0
- data/lib/pry/commands/easter_eggs.rb +112 -0
- data/lib/pry/commands/edit.rb +195 -0
- data/lib/pry/commands/edit/exception_patcher.rb +25 -0
- data/lib/pry/commands/edit/file_and_line_locator.rb +36 -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 +23 -0
- data/lib/pry/commands/find_method.rb +193 -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 +32 -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 +101 -0
- data/lib/pry/commands/help.rb +164 -0
- data/lib/pry/commands/hist.rb +180 -0
- data/lib/pry/commands/import_set.rb +22 -0
- data/lib/pry/commands/install_command.rb +53 -0
- data/lib/pry/commands/jump_to.rb +29 -0
- data/lib/pry/commands/list_inspectors.rb +35 -0
- data/lib/pry/commands/list_prompts.rb +35 -0
- data/lib/pry/commands/ls.rb +114 -0
- data/lib/pry/commands/ls/constants.rb +47 -0
- data/lib/pry/commands/ls/formatter.rb +49 -0
- data/lib/pry/commands/ls/globals.rb +48 -0
- data/lib/pry/commands/ls/grep.rb +21 -0
- data/lib/pry/commands/ls/instance_vars.rb +39 -0
- data/lib/pry/commands/ls/interrogatable.rb +18 -0
- data/lib/pry/commands/ls/jruby_hacks.rb +49 -0
- data/lib/pry/commands/ls/local_names.rb +35 -0
- data/lib/pry/commands/ls/local_vars.rb +39 -0
- data/lib/pry/commands/ls/ls_entity.rb +70 -0
- data/lib/pry/commands/ls/methods.rb +57 -0
- data/lib/pry/commands/ls/methods_helper.rb +46 -0
- data/lib/pry/commands/ls/self_methods.rb +32 -0
- data/lib/pry/commands/nesting.rb +25 -0
- data/lib/pry/commands/play.rb +103 -0
- data/lib/pry/commands/pry_backtrace.rb +25 -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 +62 -0
- data/lib/pry/commands/reset.rb +18 -0
- data/lib/pry/commands/ri.rb +60 -0
- data/lib/pry/commands/save_file.rb +61 -0
- data/lib/pry/commands/shell_command.rb +48 -0
- data/lib/pry/commands/shell_mode.rb +25 -0
- data/lib/pry/commands/show_doc.rb +83 -0
- data/lib/pry/commands/show_info.rb +195 -0
- data/lib/pry/commands/show_input.rb +17 -0
- data/lib/pry/commands/show_source.rb +50 -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 +24 -0
- data/lib/pry/commands/watch_expression.rb +105 -0
- data/lib/pry/commands/watch_expression/expression.rb +38 -0
- data/lib/pry/commands/whereami.rb +190 -0
- data/lib/pry/commands/wtf.rb +57 -0
- data/lib/pry/config.rb +20 -229
- data/lib/pry/config/behavior.rb +139 -0
- data/lib/pry/config/convenience.rb +26 -0
- data/lib/pry/config/default.rb +165 -0
- data/lib/pry/core_extensions.rb +59 -38
- data/lib/pry/editor.rb +133 -0
- data/lib/pry/exceptions.rb +77 -0
- data/lib/pry/helpers.rb +1 -0
- data/lib/pry/helpers/base_helpers.rb +40 -154
- data/lib/pry/helpers/command_helpers.rb +19 -130
- data/lib/pry/helpers/documentation_helpers.rb +21 -11
- data/lib/pry/helpers/table.rb +109 -0
- data/lib/pry/helpers/text.rb +8 -9
- data/lib/pry/history.rb +61 -45
- data/lib/pry/history_array.rb +11 -1
- data/lib/pry/hooks.rb +10 -32
- data/lib/pry/indent.rb +110 -38
- data/lib/pry/input_completer.rb +242 -0
- data/lib/pry/input_lock.rb +132 -0
- data/lib/pry/inspector.rb +27 -0
- data/lib/pry/last_exception.rb +61 -0
- data/lib/pry/method.rb +199 -200
- data/lib/pry/method/disowned.rb +53 -0
- data/lib/pry/method/patcher.rb +125 -0
- data/lib/pry/method/weird_method_locator.rb +186 -0
- data/lib/pry/module_candidate.rb +39 -33
- data/lib/pry/object_path.rb +82 -0
- data/lib/pry/output.rb +50 -0
- data/lib/pry/pager.rb +234 -0
- data/lib/pry/plugins.rb +4 -3
- data/lib/pry/prompt.rb +26 -0
- data/lib/pry/pry_class.rb +199 -227
- data/lib/pry/pry_instance.rb +344 -403
- data/lib/pry/rbx_path.rb +1 -1
- data/lib/pry/repl.rb +202 -0
- data/lib/pry/repl_file_loader.rb +20 -26
- data/lib/pry/rubygem.rb +82 -0
- data/lib/pry/terminal.rb +79 -0
- data/lib/pry/test/helper.rb +170 -0
- data/lib/pry/version.rb +1 -1
- data/lib/pry/wrapped_module.rb +133 -48
- metadata +132 -197
- data/.document +0 -2
- data/.gemtest +0 -0
- data/.gitignore +0 -16
- data/.travis.yml +0 -17
- data/.yardopts +0 -1
- data/CHANGELOG +0 -387
- data/CONTRIBUTORS +0 -36
- data/Gemfile +0 -2
- data/Rakefile +0 -137
- data/TODO +0 -117
- 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/completion.rb +0 -221
- data/lib/pry/custom_completions.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/lib/pry/rbx_method.rb +0 -13
- data/man/pry.1 +0 -195
- data/man/pry.1.html +0 -204
- data/man/pry.1.ronn +0 -141
- data/pry.gemspec +0 -46
- data/test/candidate_helper1.rb +0 -11
- data/test/candidate_helper2.rb +0 -8
- data/test/helper.rb +0 -223
- data/test/test_cli.rb +0 -78
- data/test/test_code.rb +0 -201
- data/test/test_command.rb +0 -712
- data/test/test_command_helpers.rb +0 -9
- data/test/test_command_integration.rb +0 -668
- data/test/test_command_set.rb +0 -610
- data/test/test_completion.rb +0 -62
- data/test/test_control_d_handler.rb +0 -45
- data/test/test_default_commands/example.erb +0 -5
- data/test/test_default_commands/test_cd.rb +0 -318
- data/test/test_default_commands/test_context.rb +0 -280
- data/test/test_default_commands/test_documentation.rb +0 -314
- data/test/test_default_commands/test_find_method.rb +0 -50
- data/test/test_default_commands/test_gems.rb +0 -18
- data/test/test_default_commands/test_help.rb +0 -57
- 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_exception_whitelist.rb +0 -21
- data/test/test_history_array.rb +0 -65
- data/test/test_hooks.rb +0 -521
- data/test/test_indent.rb +0 -277
- data/test/test_input_stack.rb +0 -86
- data/test/test_method.rb +0 -401
- data/test/test_pry.rb +0 -463
- data/test/test_pry_defaults.rb +0 -419
- data/test/test_pry_history.rb +0 -84
- data/test/test_pry_output.rb +0 -41
- data/test/test_sticky_locals.rb +0 -155
- data/test/test_syntax_checking.rb +0 -65
- data/test/test_wrapped_module.rb +0 -174
- data/test/testrc +0 -2
- data/test/testrcbad +0 -2
- data/wiki/Customizing-pry.md +0 -397
- data/wiki/Home.md +0 -4
data/lib/pry/indent.rb
CHANGED
@@ -1,12 +1,6 @@
|
|
1
1
|
require 'coderay'
|
2
2
|
|
3
3
|
class Pry
|
4
|
-
# Load io-console if possible, so that we can use $stdout.winsize.
|
5
|
-
begin
|
6
|
-
require 'io/console'
|
7
|
-
rescue LoadError
|
8
|
-
end
|
9
|
-
|
10
4
|
##
|
11
5
|
# Pry::Indent is a class that can be used to indent a number of lines
|
12
6
|
# containing Ruby code similar as to how IRB does it (but better). The class
|
@@ -17,9 +11,15 @@ class Pry
|
|
17
11
|
class Indent
|
18
12
|
include Helpers::BaseHelpers
|
19
13
|
|
20
|
-
#
|
14
|
+
# Raised if {#module_nesting} would not work.
|
15
|
+
class UnparseableNestingError < StandardError; end
|
16
|
+
|
17
|
+
# @return [String] String containing the spaces to be inserted before the next line.
|
21
18
|
attr_reader :indent_level
|
22
19
|
|
20
|
+
# @return [Array<String>] The stack of open tokens.
|
21
|
+
attr_reader :stack
|
22
|
+
|
23
23
|
# The amount of spaces to insert for each indent level.
|
24
24
|
SPACES = ' '
|
25
25
|
|
@@ -48,6 +48,9 @@ class Pry
|
|
48
48
|
# a single-line.
|
49
49
|
SINGLELINE_TOKENS = %w(if while until unless rescue)
|
50
50
|
|
51
|
+
# Which tokens can be followed by an optional "do" keyword.
|
52
|
+
OPTIONAL_DO_TOKENS = %w(for while until)
|
53
|
+
|
51
54
|
# Collection of token types that should be ignored. Without this list
|
52
55
|
# keywords such as "class" inside strings would cause the code to be
|
53
56
|
# indented incorrectly.
|
@@ -70,6 +73,32 @@ class Pry
|
|
70
73
|
# don't affect the surrounding code.
|
71
74
|
MIDWAY_TOKENS = %w(when else elsif ensure rescue)
|
72
75
|
|
76
|
+
# Clean the indentation of a fragment of ruby.
|
77
|
+
#
|
78
|
+
# @param [String] str
|
79
|
+
# @return [String]
|
80
|
+
def self.indent(str)
|
81
|
+
new.indent(str)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Get the module nesting at the given point in the given string.
|
85
|
+
#
|
86
|
+
# NOTE If the line specified contains a method definition, then the nesting
|
87
|
+
# at the start of the method definition is used. Otherwise the nesting from
|
88
|
+
# the end of the line is used.
|
89
|
+
#
|
90
|
+
# @param [String] str The ruby code to analyze
|
91
|
+
# @param [Fixnum] line_number The line number (starting from 1)
|
92
|
+
# @return [Array<String>]
|
93
|
+
def self.nesting_at(str, line_number)
|
94
|
+
indent = new
|
95
|
+
lines = str.split("\n")
|
96
|
+
n = line_number - 1
|
97
|
+
to_indent = lines[0...n] << (lines[n] || "").split("def").first(1)
|
98
|
+
indent.indent(to_indent.join("\n") << "\n")
|
99
|
+
indent.module_nesting
|
100
|
+
end
|
101
|
+
|
73
102
|
def initialize
|
74
103
|
reset
|
75
104
|
end
|
@@ -81,6 +110,8 @@ class Pry
|
|
81
110
|
@heredoc_queue = []
|
82
111
|
@close_heredocs = {}
|
83
112
|
@string_start = nil
|
113
|
+
@awaiting_class = false
|
114
|
+
@module_nesting = []
|
84
115
|
self
|
85
116
|
end
|
86
117
|
|
@@ -126,7 +157,6 @@ class Pry
|
|
126
157
|
new_prefix = prefix + SPACES * after
|
127
158
|
|
128
159
|
line = prefix + line.lstrip unless previously_in_string
|
129
|
-
line = line.rstrip + "\n" unless in_string?
|
130
160
|
|
131
161
|
output += line
|
132
162
|
|
@@ -135,7 +165,7 @@ class Pry
|
|
135
165
|
|
136
166
|
@indent_level = prefix
|
137
167
|
|
138
|
-
return output
|
168
|
+
return output
|
139
169
|
end
|
140
170
|
|
141
171
|
# Get the indentation for the start of the next line.
|
@@ -189,7 +219,9 @@ class Pry
|
|
189
219
|
last_token, last_kind = token, kind unless kind == :space
|
190
220
|
next if IGNORE_TOKENS.include?(kind)
|
191
221
|
|
192
|
-
|
222
|
+
track_module_nesting(token, kind)
|
223
|
+
|
224
|
+
seen_for_at << add_after if OPTIONAL_DO_TOKENS.include?(token)
|
193
225
|
|
194
226
|
if kind == :delimiter
|
195
227
|
track_delimiter(token)
|
@@ -197,7 +229,8 @@ class Pry
|
|
197
229
|
@stack << token
|
198
230
|
add_after += 1
|
199
231
|
elsif token == OPEN_TOKENS[@stack.last]
|
200
|
-
@stack.pop
|
232
|
+
popped = @stack.pop
|
233
|
+
track_module_nesting_end(popped)
|
201
234
|
if add_after == 0
|
202
235
|
remove_before += 1
|
203
236
|
else
|
@@ -279,6 +312,68 @@ class Pry
|
|
279
312
|
"puts #{open_delimiters.join(", ")}"
|
280
313
|
end
|
281
314
|
|
315
|
+
# Update the internal state relating to module nesting.
|
316
|
+
#
|
317
|
+
# It's responsible for adding to the @module_nesting array, which looks
|
318
|
+
# something like:
|
319
|
+
#
|
320
|
+
# [ ["class", "Foo"], ["module", "Bar::Baz"], ["class <<", "self"] ]
|
321
|
+
#
|
322
|
+
# A nil value in the @module_nesting array happens in two places: either
|
323
|
+
# when @awaiting_class is true and we're still waiting for the string to
|
324
|
+
# fill that space, or when a parse was rejected.
|
325
|
+
#
|
326
|
+
# At the moment this function is quite restricted about what formats it will
|
327
|
+
# parse, for example we disallow expressions after the class keyword. This
|
328
|
+
# could maybe be improved in the future.
|
329
|
+
#
|
330
|
+
# @param [String] token a token from Coderay
|
331
|
+
# @param [Symbol] kind the kind of that token
|
332
|
+
def track_module_nesting(token, kind)
|
333
|
+
if kind == :keyword && (token == "class" || token == "module")
|
334
|
+
@module_nesting << [token, nil]
|
335
|
+
@awaiting_class = true
|
336
|
+
elsif @awaiting_class
|
337
|
+
if kind == :operator && token == "<<" && @module_nesting.last[0] == "class"
|
338
|
+
@module_nesting.last[0] = "class <<"
|
339
|
+
@awaiting_class = true
|
340
|
+
elsif kind == :class && token =~ /\A(self|[A-Z:][A-Za-z0-9_:]*)\z/
|
341
|
+
@module_nesting.last[1] = token if kind == :class
|
342
|
+
@awaiting_class = false
|
343
|
+
else
|
344
|
+
# leave @module_nesting[-1]
|
345
|
+
@awaiting_class = false
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
# Update the internal state relating to module nesting on 'end'.
|
351
|
+
#
|
352
|
+
# If the current 'end' pairs up with a class or a module then we should
|
353
|
+
# pop an array off of @module_nesting
|
354
|
+
#
|
355
|
+
# @param [String] token a token from Coderay
|
356
|
+
# @param [Symbol] kind the kind of that token
|
357
|
+
def track_module_nesting_end(token, kind=:keyword)
|
358
|
+
if kind == :keyword && (token == "class" || token == "module")
|
359
|
+
@module_nesting.pop
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
# Return a list of strings which can be used to re-construct the Module.nesting at
|
364
|
+
# the current point in the file.
|
365
|
+
#
|
366
|
+
# Returns nil if the syntax of the file was not recognizable.
|
367
|
+
#
|
368
|
+
# @return [Array<String>]
|
369
|
+
def module_nesting
|
370
|
+
@module_nesting.map do |(kind, token)|
|
371
|
+
raise UnparseableNestingError, @module_nesting.inspect if token.nil?
|
372
|
+
|
373
|
+
"#{kind} #{token}"
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
282
377
|
# Return a string which, when printed, will rewrite the previous line with
|
283
378
|
# the correct indentation. Mostly useful for fixing 'end'.
|
284
379
|
#
|
@@ -288,13 +383,14 @@ class Pry
|
|
288
383
|
# the difference in length between the old line and the new one).
|
289
384
|
# @return [String]
|
290
385
|
def correct_indentation(prompt, code, overhang=0)
|
291
|
-
|
386
|
+
prompt = prompt.delete("\001\002")
|
387
|
+
line_to_measure = Pry::Helpers::Text.strip_color(prompt) << code
|
292
388
|
whitespace = ' ' * overhang
|
293
389
|
|
294
|
-
_, cols = screen_size
|
390
|
+
_, cols = Terminal.screen_size
|
295
391
|
|
296
392
|
cols = cols.to_i
|
297
|
-
lines = cols != 0 ? (
|
393
|
+
lines = (cols != 0 ? (line_to_measure.length / cols + 1) : 1).to_i
|
298
394
|
|
299
395
|
if Pry::Helpers::BaseHelpers.windows_ansi?
|
300
396
|
move_up = "\e[#{lines}F"
|
@@ -306,29 +402,5 @@ class Pry
|
|
306
402
|
|
307
403
|
"#{move_up}#{prompt}#{colorize_code(code)}#{whitespace}#{move_down}"
|
308
404
|
end
|
309
|
-
|
310
|
-
# Return a pair of [rows, columns] which gives the size of the window.
|
311
|
-
#
|
312
|
-
# If the window size cannot be determined, return nil.
|
313
|
-
def screen_size
|
314
|
-
[
|
315
|
-
# io/console adds a winsize method to IO streams.
|
316
|
-
$stdout.tty? && $stdout.respond_to?(:winsize) && $stdout.winsize,
|
317
|
-
|
318
|
-
# Some readlines also provides get_screen_size.
|
319
|
-
Readline.respond_to?(:get_screen_size) && Readline.get_screen_size,
|
320
|
-
|
321
|
-
# Otherwise try to use the environment (this may be out of date due
|
322
|
-
# to window resizing, but it's better than nothing).
|
323
|
-
[ENV["ROWS"], ENV["COLUMNS"],
|
324
|
-
|
325
|
-
# If the user is running within ansicon, then use the screen size
|
326
|
-
# that it reports (same caveats apply as with ROWS and COLUMNS)
|
327
|
-
ENV['ANSICON'] =~ /\((.*)x(.*)\)/ && [$2, $1]
|
328
|
-
]
|
329
|
-
].detect do |(_, cols)|
|
330
|
-
cols.to_i > 0
|
331
|
-
end
|
332
|
-
end
|
333
405
|
end
|
334
406
|
end
|
@@ -0,0 +1,242 @@
|
|
1
|
+
# taken from irb
|
2
|
+
# Implements tab completion for Readline in Pry
|
3
|
+
class Pry::InputCompleter
|
4
|
+
NUMERIC_REGEXP = /^(-?(0[dbo])?[0-9_]+(\.[0-9_]+)?([eE]-?[0-9]+)?)\.([^.]*)$/
|
5
|
+
ARRAY_REGEXP = /^([^\]]*\])\.([^.]*)$/
|
6
|
+
SYMBOL_REGEXP = /^(:[^:.]*)$/
|
7
|
+
SYMBOL_METHOD_CALL_REGEXP = /^(:[^:.]+)\.([^.]*)$/
|
8
|
+
REGEX_REGEXP = /^(\/[^\/]*\/)\.([^.]*)$/
|
9
|
+
PROC_OR_HASH_REGEXP = /^([^\}]*\})\.([^.]*)$/
|
10
|
+
TOPLEVEL_LOOKUP_REGEXP = /^::([A-Z][^:\.\(]*)$/
|
11
|
+
CONSTANT_REGEXP = /^([A-Z][A-Za-z0-9]*)$/
|
12
|
+
CONSTANT_OR_METHOD_REGEXP = /^([A-Z].*)::([^:.]*)$/
|
13
|
+
HEX_REGEXP = /^(-?0x[0-9a-fA-F_]+)\.([^.]*)$/
|
14
|
+
GLOBALVARIABLE_REGEXP = /^(\$[^.]*)$/
|
15
|
+
VARIABLE_REGEXP = /^([^."].*)\.([^.]*)$/
|
16
|
+
|
17
|
+
ReservedWords = [
|
18
|
+
"BEGIN", "END",
|
19
|
+
"alias", "and",
|
20
|
+
"begin", "break",
|
21
|
+
"case", "class",
|
22
|
+
"def", "defined", "do",
|
23
|
+
"else", "elsif", "end", "ensure",
|
24
|
+
"false", "for",
|
25
|
+
"if", "in",
|
26
|
+
"module",
|
27
|
+
"next", "nil", "not",
|
28
|
+
"or",
|
29
|
+
"redo", "rescue", "retry", "return",
|
30
|
+
"self", "super",
|
31
|
+
"then", "true",
|
32
|
+
"undef", "unless", "until",
|
33
|
+
"when", "while",
|
34
|
+
"yield" ]
|
35
|
+
|
36
|
+
Operators = [
|
37
|
+
"%", "&", "*", "**", "+", "-", "/",
|
38
|
+
"<", "<<", "<=", "<=>", "==", "===", "=~", ">", ">=", ">>",
|
39
|
+
"[]", "[]=", "^", "!", "!=", "!~"
|
40
|
+
]
|
41
|
+
|
42
|
+
WORD_ESCAPE_STR = " \t\n\"\\'`><=;|&{("
|
43
|
+
|
44
|
+
def initialize(input, pry = nil)
|
45
|
+
@pry = pry
|
46
|
+
@input = input
|
47
|
+
@input.basic_word_break_characters = WORD_ESCAPE_STR if @input.respond_to?(:basic_word_break_characters=)
|
48
|
+
@input.completion_append_character = nil if @input.respond_to?(:completion_append_character=)
|
49
|
+
end
|
50
|
+
|
51
|
+
#
|
52
|
+
# Return a new completion proc for use by Readline.
|
53
|
+
#
|
54
|
+
def call(str, options = {})
|
55
|
+
custom_completions = options[:custom_completions] || []
|
56
|
+
# if there are multiple contexts e.g. cd 1/2/3
|
57
|
+
# get new target for 1/2 and find candidates for 3
|
58
|
+
path, input = build_path(str)
|
59
|
+
|
60
|
+
if path.call.empty?
|
61
|
+
target = options[:target]
|
62
|
+
else
|
63
|
+
# Assume the user is tab-completing the 'cd' command
|
64
|
+
begin
|
65
|
+
target = Pry::ObjectPath.new(path.call, @pry.binding_stack).resolve.last
|
66
|
+
# but if that doesn't work, assume they're doing division with no spaces
|
67
|
+
rescue Pry::CommandError
|
68
|
+
target = options[:target]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
begin
|
73
|
+
bind = target
|
74
|
+
# Complete stdlib symbols
|
75
|
+
case input
|
76
|
+
when REGEX_REGEXP # Regexp
|
77
|
+
receiver = $1
|
78
|
+
message = Regexp.quote($2)
|
79
|
+
candidates = Regexp.instance_methods.collect(&:to_s)
|
80
|
+
select_message(path, receiver, message, candidates)
|
81
|
+
when ARRAY_REGEXP # Array
|
82
|
+
receiver = $1
|
83
|
+
message = Regexp.quote($2)
|
84
|
+
candidates = Array.instance_methods.collect(&:to_s)
|
85
|
+
select_message(path, receiver, message, candidates)
|
86
|
+
when PROC_OR_HASH_REGEXP # Proc or Hash
|
87
|
+
receiver = $1
|
88
|
+
message = Regexp.quote($2)
|
89
|
+
candidates = Proc.instance_methods.collect(&:to_s)
|
90
|
+
candidates |= Hash.instance_methods.collect(&:to_s)
|
91
|
+
select_message(path, receiver, message, candidates)
|
92
|
+
when SYMBOL_REGEXP # Symbol
|
93
|
+
if Symbol.respond_to?(:all_symbols)
|
94
|
+
sym = Regexp.quote($1)
|
95
|
+
candidates = Symbol.all_symbols.collect{|s| ":" << s.id2name}
|
96
|
+
candidates.grep(/^#{sym}/)
|
97
|
+
else
|
98
|
+
[]
|
99
|
+
end
|
100
|
+
when TOPLEVEL_LOOKUP_REGEXP # Absolute Constant or class methods
|
101
|
+
receiver = $1
|
102
|
+
candidates = Object.constants.collect(&:to_s)
|
103
|
+
candidates.grep(/^#{receiver}/).collect{|e| "::" << e}
|
104
|
+
when CONSTANT_REGEXP # Constant
|
105
|
+
message = $1
|
106
|
+
begin
|
107
|
+
context = target.eval("self")
|
108
|
+
context = context.class unless context.respond_to? :constants
|
109
|
+
candidates = context.constants.collect(&:to_s)
|
110
|
+
rescue
|
111
|
+
candidates = []
|
112
|
+
end
|
113
|
+
candidates = candidates.grep(/^#{message}/).collect(&path)
|
114
|
+
when CONSTANT_OR_METHOD_REGEXP # Constant or class methods
|
115
|
+
receiver = $1
|
116
|
+
message = Regexp.quote($2)
|
117
|
+
begin
|
118
|
+
candidates = eval("#{receiver}.constants.collect(&:to_s)", bind)
|
119
|
+
candidates |= eval("#{receiver}.methods.collect(&:to_s)", bind)
|
120
|
+
rescue Pry::RescuableException
|
121
|
+
candidates = []
|
122
|
+
end
|
123
|
+
candidates.grep(/^#{message}/).collect{|e| receiver << "::" << e}
|
124
|
+
when SYMBOL_METHOD_CALL_REGEXP # method call on a Symbol
|
125
|
+
receiver = $1
|
126
|
+
message = Regexp.quote($2)
|
127
|
+
candidates = Symbol.instance_methods.collect(&:to_s)
|
128
|
+
select_message(path, receiver, message, candidates)
|
129
|
+
when NUMERIC_REGEXP
|
130
|
+
# Numeric
|
131
|
+
receiver = $1
|
132
|
+
message = Regexp.quote($5)
|
133
|
+
begin
|
134
|
+
candidates = eval(receiver, bind).methods.collect(&:to_s)
|
135
|
+
rescue Pry::RescuableException
|
136
|
+
candidates = []
|
137
|
+
end
|
138
|
+
select_message(path, receiver, message, candidates)
|
139
|
+
when HEX_REGEXP
|
140
|
+
# Numeric(0xFFFF)
|
141
|
+
receiver = $1
|
142
|
+
message = Regexp.quote($2)
|
143
|
+
begin
|
144
|
+
candidates = eval(receiver, bind).methods.collect(&:to_s)
|
145
|
+
rescue Pry::RescuableException
|
146
|
+
candidates = []
|
147
|
+
end
|
148
|
+
select_message(path, receiver, message, candidates)
|
149
|
+
when GLOBALVARIABLE_REGEXP # global
|
150
|
+
regmessage = Regexp.new(Regexp.quote($1))
|
151
|
+
candidates = global_variables.collect(&:to_s).grep(regmessage)
|
152
|
+
when VARIABLE_REGEXP # variable
|
153
|
+
receiver = $1
|
154
|
+
message = Regexp.quote($2)
|
155
|
+
|
156
|
+
gv = eval("global_variables", bind).collect(&:to_s)
|
157
|
+
lv = eval("local_variables", bind).collect(&:to_s)
|
158
|
+
cv = eval("self.class.constants", bind).collect(&:to_s)
|
159
|
+
|
160
|
+
if (gv | lv | cv).include?(receiver) or /^[A-Z]/ =~ receiver && /\./ !~ receiver
|
161
|
+
# foo.func and foo is local var. OR
|
162
|
+
# Foo::Bar.func
|
163
|
+
begin
|
164
|
+
candidates = eval("#{receiver}.methods", bind).collect(&:to_s)
|
165
|
+
rescue Pry::RescuableException
|
166
|
+
candidates = []
|
167
|
+
end
|
168
|
+
else
|
169
|
+
# func1.func2
|
170
|
+
candidates = []
|
171
|
+
ObjectSpace.each_object(Module){|m|
|
172
|
+
begin
|
173
|
+
name = m.name.to_s
|
174
|
+
rescue Pry::RescuableException
|
175
|
+
name = ""
|
176
|
+
end
|
177
|
+
next if name != "IRB::Context" and
|
178
|
+
/^(IRB|SLex|RubyLex|RubyToken)/ =~ name
|
179
|
+
|
180
|
+
# jruby doesn't always provide #instance_methods() on each
|
181
|
+
# object.
|
182
|
+
if m.respond_to?(:instance_methods)
|
183
|
+
candidates.concat m.instance_methods(false).collect(&:to_s)
|
184
|
+
end
|
185
|
+
}
|
186
|
+
candidates.sort!
|
187
|
+
candidates.uniq!
|
188
|
+
end
|
189
|
+
select_message(path, receiver, message, candidates)
|
190
|
+
when /^\.([^.]*)$/
|
191
|
+
# Unknown(maybe String)
|
192
|
+
receiver = ""
|
193
|
+
message = Regexp.quote($1)
|
194
|
+
candidates = String.instance_methods(true).collect(&:to_s)
|
195
|
+
select_message(path, receiver, message, candidates)
|
196
|
+
else
|
197
|
+
candidates = eval(
|
198
|
+
"methods | private_methods | local_variables | " \
|
199
|
+
"self.class.constants | instance_variables",
|
200
|
+
bind
|
201
|
+
).collect(&:to_s)
|
202
|
+
|
203
|
+
if eval("respond_to?(:class_variables)", bind)
|
204
|
+
candidates += eval("class_variables", bind).collect(&:to_s)
|
205
|
+
end
|
206
|
+
candidates = (candidates|ReservedWords|custom_completions).grep(/^#{Regexp.quote(input)}/)
|
207
|
+
candidates.collect(&path)
|
208
|
+
end
|
209
|
+
rescue Pry::RescuableException
|
210
|
+
[]
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def select_message(path, receiver, message, candidates)
|
215
|
+
candidates.grep(/^#{message}/).collect { |e|
|
216
|
+
case e
|
217
|
+
when /^[a-zA-Z_]/
|
218
|
+
path.call(receiver + "." << e)
|
219
|
+
when /^[0-9]/
|
220
|
+
when *Operators
|
221
|
+
#receiver + " " << e
|
222
|
+
end
|
223
|
+
}.compact
|
224
|
+
end
|
225
|
+
|
226
|
+
# build_path seperates the input into two parts: path and input.
|
227
|
+
# input is the partial string that should be completed
|
228
|
+
# path is a proc that takes an input and builds a full path.
|
229
|
+
def build_path(input)
|
230
|
+
# check to see if the input is a regex
|
231
|
+
return proc {|i| i.to_s }, input if input[/\/\./]
|
232
|
+
trailing_slash = input.end_with?('/')
|
233
|
+
contexts = input.chomp('/').split(/\//)
|
234
|
+
input = contexts[-1]
|
235
|
+
path = proc do |i|
|
236
|
+
p = contexts[0..-2].push(i).join('/')
|
237
|
+
p += '/' if trailing_slash && !i.nil?
|
238
|
+
p
|
239
|
+
end
|
240
|
+
return path, input
|
241
|
+
end
|
242
|
+
end
|