pry 0.9.7.4-i386-mswin32 → 0.9.8-i386-mswin32
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -3
- data/CHANGELOG +43 -0
- data/README.markdown +3 -1
- data/Rakefile +51 -32
- data/bin/pry +2 -80
- data/lib/pry.rb +33 -26
- data/lib/pry/cli.rb +152 -0
- data/lib/pry/code.rb +351 -0
- data/lib/pry/command.rb +422 -0
- data/lib/pry/command_set.rb +259 -129
- data/lib/pry/commands.rb +0 -1
- data/lib/pry/config.rb +43 -9
- data/lib/pry/default_commands/context.rb +109 -92
- data/lib/pry/default_commands/documentation.rb +174 -63
- data/lib/pry/default_commands/easter_eggs.rb +26 -2
- data/lib/pry/default_commands/gems.rb +65 -37
- data/lib/pry/default_commands/input.rb +175 -243
- data/lib/pry/default_commands/introspection.rb +173 -112
- data/lib/pry/default_commands/ls.rb +96 -114
- data/lib/pry/default_commands/shell.rb +175 -70
- data/lib/pry/helpers/base_helpers.rb +7 -2
- data/lib/pry/helpers/command_helpers.rb +71 -77
- data/lib/pry/helpers/options_helpers.rb +10 -41
- data/lib/pry/helpers/text.rb +24 -4
- data/lib/pry/history.rb +55 -17
- data/lib/pry/history_array.rb +2 -0
- data/lib/pry/hooks.rb +252 -0
- data/lib/pry/indent.rb +9 -5
- data/lib/pry/method.rb +149 -50
- data/lib/pry/plugins.rb +12 -4
- data/lib/pry/pry_class.rb +69 -26
- data/lib/pry/pry_instance.rb +187 -115
- data/lib/pry/version.rb +1 -1
- data/lib/pry/wrapped_module.rb +73 -0
- data/man/pry.1 +195 -0
- data/man/pry.1.html +204 -0
- data/man/pry.1.ronn +141 -0
- data/pry.gemspec +29 -32
- data/test/helper.rb +32 -36
- data/test/test_cli.rb +78 -0
- data/test/test_code.rb +201 -0
- data/test/test_command.rb +327 -0
- data/test/test_command_integration.rb +512 -0
- data/test/test_command_set.rb +338 -12
- data/test/test_completion.rb +1 -1
- data/test/test_default_commands.rb +1 -2
- data/test/test_default_commands/test_context.rb +27 -5
- data/test/test_default_commands/test_documentation.rb +20 -8
- data/test/test_default_commands/test_input.rb +84 -45
- data/test/test_default_commands/test_introspection.rb +74 -17
- data/test/test_default_commands/test_ls.rb +9 -36
- data/test/test_default_commands/test_shell.rb +240 -13
- data/test/test_hooks.rb +490 -0
- data/test/test_indent.rb +2 -0
- data/test/test_method.rb +60 -0
- data/test/test_pry.rb +29 -904
- data/test/test_pry_defaults.rb +380 -0
- data/test/test_pry_history.rb +24 -24
- data/test/test_syntax_checking.rb +63 -0
- data/test/test_wrapped_module.rb +71 -0
- metadata +50 -39
- data/lib/pry/command_context.rb +0 -53
- data/lib/pry/command_processor.rb +0 -181
- data/lib/pry/extended_commands/user_command_api.rb +0 -65
- data/test/test_command_processor.rb +0 -176
@@ -5,40 +5,58 @@ class Pry
|
|
5
5
|
|
6
6
|
Introspection = Pry::CommandSet.new do
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
8
|
+
create_command "show-method" do
|
9
|
+
description "Show the source for METH. Type `show-method --help` for more info. Aliases: $, show-source"
|
10
|
+
|
11
|
+
banner <<-BANNER
|
12
|
+
Usage: show-method [OPTIONS] [METH]
|
13
|
+
Aliases: $, show-source
|
14
|
+
|
15
|
+
Show the source for method METH. Tries instance methods first and then methods by default.
|
15
16
|
|
17
|
+
e.g: `show-method hello_method`
|
18
|
+
e.g: `show-method -m hello_method`
|
19
|
+
e.g: `show-method Pry#rep`
|
20
|
+
|
21
|
+
https://github.com/pry/pry/wiki/Source-browsing#wiki-Show_method
|
22
|
+
BANNER
|
23
|
+
|
24
|
+
command_options(
|
25
|
+
:shellwords => false
|
26
|
+
)
|
27
|
+
|
28
|
+
def options(opt)
|
29
|
+
method_options(opt)
|
16
30
|
opt.on :l, "line-numbers", "Show line numbers."
|
17
31
|
opt.on :b, "base-one", "Show line numbers but start numbering at 1 (useful for `amend-line` and `play` commands)."
|
18
32
|
opt.on :f, :flood, "Do not use a pager to view text longer than one screen."
|
19
33
|
end
|
20
34
|
|
21
|
-
|
35
|
+
def process
|
36
|
+
raise CommandError, "Could not find method source" unless method_object.source
|
37
|
+
|
38
|
+
output.puts make_header(method_object)
|
39
|
+
output.puts "#{text.bold("Owner:")} #{method_object.owner || "N/A"}"
|
40
|
+
output.puts "#{text.bold("Visibility:")} #{method_object.visibility}"
|
41
|
+
output.puts
|
22
42
|
|
23
|
-
|
24
|
-
|
25
|
-
output.puts "#{text.bold("Visibility:")} #{meth.visibility}"
|
26
|
-
output.puts
|
43
|
+
code = Code.from_method(method_object, start_line).
|
44
|
+
with_line_numbers(use_line_numbers?)
|
27
45
|
|
28
|
-
|
29
|
-
code = CodeRay.scan(meth.source, meth.source_type).term
|
30
|
-
else
|
31
|
-
code = meth.source
|
46
|
+
render_output(code, opts)
|
32
47
|
end
|
33
48
|
|
34
|
-
|
35
|
-
|
36
|
-
start_line = 1
|
37
|
-
elsif opts.l?
|
38
|
-
start_line = meth.source_line || 1
|
49
|
+
def use_line_numbers?
|
50
|
+
opts.present?(:b) || opts.present?(:l)
|
39
51
|
end
|
40
52
|
|
41
|
-
|
53
|
+
def start_line
|
54
|
+
if opts.present?(:'base-one')
|
55
|
+
1
|
56
|
+
else
|
57
|
+
method_object.source_line || 1
|
58
|
+
end
|
59
|
+
end
|
42
60
|
end
|
43
61
|
|
44
62
|
alias_command "show-source", "show-method"
|
@@ -57,11 +75,11 @@ class Pry
|
|
57
75
|
opt.on :l, "line-numbers", "Show line numbers."
|
58
76
|
opt.on :f, :flood, "Do not use a pager to view text longer than one screen."
|
59
77
|
opt.on :h, :help, "This message." do
|
60
|
-
output.puts opt
|
78
|
+
output.puts opt.help
|
61
79
|
end
|
62
80
|
end
|
63
81
|
|
64
|
-
next if opts.help
|
82
|
+
next if opts.present?(:help)
|
65
83
|
|
66
84
|
command_name = args.shift
|
67
85
|
if !command_name
|
@@ -77,68 +95,75 @@ class Pry
|
|
77
95
|
output.puts make_header(block)
|
78
96
|
output.puts
|
79
97
|
|
80
|
-
|
81
|
-
code = CodeRay.scan(block.source, :ruby).term
|
82
|
-
else
|
83
|
-
code = block.source
|
84
|
-
end
|
85
|
-
|
86
|
-
start_line = false
|
87
|
-
if opts.l?
|
88
|
-
start_line = block.source_line || 1
|
89
|
-
end
|
98
|
+
code = Code.from_method(block).with_line_numbers(opts.present?(:'line-numbers'))
|
90
99
|
|
91
|
-
render_output(
|
92
|
-
code
|
100
|
+
render_output(code, opts)
|
93
101
|
else
|
94
102
|
raise CommandError, "No such command: #{command_name}."
|
95
103
|
end
|
96
104
|
end
|
97
105
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
+
create_command "edit" do
|
107
|
+
description "Invoke the default editor on a file. Type `edit --help` for more info"
|
108
|
+
|
109
|
+
banner <<-BANNER
|
110
|
+
Usage: edit [--no-reload|--reload] [--line LINE] [--temp|--ex|FILE[:LINE]|--in N]
|
111
|
+
|
112
|
+
Open a text editor. When no FILE is given, edits the pry input buffer.
|
113
|
+
Ensure Pry.config.editor is set to your editor of choice.
|
114
|
+
|
115
|
+
e.g: `edit sample.rb`
|
116
|
+
e.g: `edit sample.rb --line 105`
|
117
|
+
e.g: `edit --ex`
|
118
|
+
|
119
|
+
https://github.com/pry/pry/wiki/Editor-integration#wiki-Edit_command
|
120
|
+
BANNER
|
106
121
|
|
122
|
+
def options(opt)
|
107
123
|
opt.on :e, :ex, "Open the file that raised the most recent exception (_ex_.file)", :optional => true, :as => Integer
|
108
124
|
opt.on :i, :in, "Open a temporary file containing the Nth line of _in_. N may be a range.", :optional => true, :as => Range, :default => -1..-1
|
109
125
|
opt.on :t, :temp, "Open an empty temporary file"
|
110
126
|
opt.on :l, :line, "Jump to this line in the opened file", true, :as => Integer
|
111
127
|
opt.on :n, :"no-reload", "Don't automatically reload the edited code"
|
112
128
|
opt.on :r, :reload, "Reload the edited code immediately (default for ruby files)"
|
113
|
-
|
114
|
-
|
129
|
+
end
|
130
|
+
|
131
|
+
def process
|
132
|
+
if [opts.present?(:ex), opts.present?(:temp), opts.present?(:in), !args.empty?].count(true) > 1
|
133
|
+
raise CommandError, "Only one of --ex, --temp, --in and FILE may be specified."
|
134
|
+
end
|
135
|
+
|
136
|
+
if !opts.present?(:ex) && args.empty?
|
137
|
+
# edit of local code, eval'd within pry.
|
138
|
+
process_local_edit
|
139
|
+
else
|
140
|
+
# edit of remote code, eval'd at top-level
|
141
|
+
process_remote_edit
|
115
142
|
end
|
116
143
|
end
|
117
|
-
next if opts.h?
|
118
144
|
|
119
|
-
|
120
|
-
|
145
|
+
def process_i
|
146
|
+
case opts[:i]
|
147
|
+
when Range
|
148
|
+
(_pry_.input_array[opts[:i]] || []).join
|
149
|
+
when Fixnum
|
150
|
+
_pry_.input_array[opts[:i]] || ""
|
151
|
+
else
|
152
|
+
return output.puts "Not a valid range: #{opts[:i]}"
|
153
|
+
end
|
121
154
|
end
|
122
155
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
else
|
135
|
-
next output.puts "Not a valid range: #{opts[:i]}"
|
136
|
-
end
|
137
|
-
elsif eval_string.strip != ""
|
138
|
-
eval_string
|
139
|
-
else
|
140
|
-
_pry_.input_array.reverse_each.find{ |x| x && x.strip != "" } || ""
|
141
|
-
end
|
156
|
+
def process_local_edit
|
157
|
+
content = case
|
158
|
+
when opts.present?(:temp)
|
159
|
+
""
|
160
|
+
when opts.present?(:in)
|
161
|
+
process_i
|
162
|
+
when eval_string.strip != ""
|
163
|
+
eval_string
|
164
|
+
else
|
165
|
+
_pry_.input_array.reverse_each.find{ |x| x && x.strip != "" } || ""
|
166
|
+
end
|
142
167
|
|
143
168
|
line = content.lines.count
|
144
169
|
|
@@ -146,16 +171,16 @@ class Pry
|
|
146
171
|
f.puts(content)
|
147
172
|
f.flush
|
148
173
|
invoke_editor(f.path, line)
|
149
|
-
if !opts.
|
174
|
+
if !opts.present?(:'no-reload')
|
150
175
|
silence_warnings do
|
151
176
|
eval_string.replace(File.read(f.path))
|
152
177
|
end
|
153
178
|
end
|
154
179
|
end
|
180
|
+
end
|
155
181
|
|
156
|
-
|
157
|
-
|
158
|
-
if opts.ex?
|
182
|
+
def process_remote_edit
|
183
|
+
if opts.present?(:ex)
|
159
184
|
if _pry_.last_exception.nil?
|
160
185
|
raise CommandError, "No exception found."
|
161
186
|
end
|
@@ -186,12 +211,12 @@ class Pry
|
|
186
211
|
line = file_name.sub!(/:(\d+)$/, "") ? $1.to_i : 1
|
187
212
|
end
|
188
213
|
|
189
|
-
line = opts[:l].to_i if opts.
|
214
|
+
line = opts[:l].to_i if opts.present?(:line)
|
190
215
|
|
191
216
|
invoke_editor(file_name, line)
|
192
217
|
set_file_and_dir_locals(file_name)
|
193
218
|
|
194
|
-
if opts.
|
219
|
+
if opts.present?(:reload) || ((opts.present?(:ex) || file_name.end_with?(".rb")) && !opts.present?(:'no-reload'))
|
195
220
|
silence_warnings do
|
196
221
|
TOPLEVEL_BINDING.eval(File.read(file_name), file_name)
|
197
222
|
end
|
@@ -199,33 +224,60 @@ class Pry
|
|
199
224
|
end
|
200
225
|
end
|
201
226
|
|
202
|
-
|
203
|
-
|
227
|
+
create_command "edit-method" do
|
228
|
+
description "Edit a method. Type `edit-method --help` for more info."
|
204
229
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
e.g: edit-method hello_method
|
211
|
-
USAGE
|
230
|
+
banner <<-BANNER
|
231
|
+
Usage: edit-method [OPTIONS] [METH]
|
232
|
+
|
233
|
+
Edit the method METH in an editor.
|
234
|
+
Ensure Pry.config.editor is set to your editor of choice.
|
212
235
|
|
236
|
+
e.g: `edit-method hello_method`
|
237
|
+
e.g: `edit-method Pry#rep`
|
238
|
+
e.g: `edit-method`
|
239
|
+
|
240
|
+
https://github.com/pry/pry/wiki/Editor-integration#wiki-Edit_method
|
241
|
+
BANNER
|
242
|
+
|
243
|
+
command_options :shellwords => false
|
244
|
+
|
245
|
+
def options(opt)
|
246
|
+
method_options(opt)
|
213
247
|
opt.on :n, "no-reload", "Do not automatically reload the method's file after editing."
|
214
248
|
opt.on "no-jump", "Do not fast forward editor to first line of method."
|
215
249
|
opt.on :p, :patch, "Instead of editing the method's file, try to edit in a tempfile and apply as a monkey patch."
|
216
|
-
opt.on :h, :help, "This message." do
|
217
|
-
output.puts opt
|
218
|
-
end
|
219
250
|
end
|
220
251
|
|
221
|
-
|
222
|
-
|
252
|
+
def process
|
253
|
+
if !Pry.config.editor
|
254
|
+
raise CommandError, "No editor set!\nEnsure that #{text.bold("Pry.config.editor")} is set to your editor of choice."
|
255
|
+
end
|
256
|
+
|
257
|
+
begin
|
258
|
+
@method = method_object
|
259
|
+
rescue NonMethodContextError => err
|
260
|
+
end
|
261
|
+
|
262
|
+
if opts.present?(:patch) || (@method && @method.dynamically_defined?)
|
263
|
+
if err
|
264
|
+
raise err # can't patch a non-method
|
265
|
+
end
|
266
|
+
|
267
|
+
process_patch
|
268
|
+
else
|
269
|
+
if err && !File.exist?(target.eval('__FILE__'))
|
270
|
+
raise err # can't edit a non-file
|
271
|
+
end
|
272
|
+
|
273
|
+
process_file
|
274
|
+
end
|
223
275
|
end
|
224
276
|
|
225
|
-
|
226
|
-
lines =
|
277
|
+
def process_patch
|
278
|
+
lines = @method.source.lines.to_a
|
227
279
|
|
228
|
-
if ((original_name =
|
280
|
+
if ((original_name = @method.original_name) &&
|
229
281
|
lines[0] =~ /^def (?:.*?\.)?#{original_name}(?=[\(\s;]|$)/)
|
230
282
|
lines[0] = "def #{original_name}#{$'}"
|
231
283
|
else
|
@@ -237,40 +289,49 @@ class Pry
|
|
237
289
|
f.flush
|
238
290
|
invoke_editor(f.path, 0)
|
239
291
|
|
240
|
-
if
|
241
|
-
with_method_transaction(original_name,
|
242
|
-
Pry.new(:input => StringIO.new(File.read(f.path))).rep(
|
243
|
-
Pry.binding_for(
|
292
|
+
if @method.alias?
|
293
|
+
with_method_transaction(original_name, @method.owner) do
|
294
|
+
Pry.new(:input => StringIO.new(File.read(f.path))).rep(@method.owner)
|
295
|
+
Pry.binding_for(@method.owner).eval("alias #{@method.name} #{original_name}")
|
244
296
|
end
|
245
297
|
else
|
246
|
-
Pry.new(:input => StringIO.new(File.read(f.path))).rep(
|
298
|
+
Pry.new(:input => StringIO.new(File.read(f.path))).rep(@method.owner)
|
247
299
|
end
|
248
300
|
end
|
249
|
-
next
|
250
301
|
end
|
251
302
|
|
252
|
-
|
253
|
-
|
254
|
-
else
|
255
|
-
file, line = meth.source_file, meth.source_line
|
303
|
+
def process_file
|
304
|
+
file, line = extract_file_and_line
|
256
305
|
|
257
306
|
invoke_editor(file, opts["no-jump"] ? 0 : line)
|
258
307
|
silence_warnings do
|
259
|
-
load file
|
308
|
+
load file unless opts.present?(:'no-jump') || Pry.config.disable_auto_reload
|
260
309
|
end
|
261
310
|
end
|
262
|
-
end
|
263
311
|
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
312
|
+
protected
|
313
|
+
def extract_file_and_line
|
314
|
+
if @method
|
315
|
+
if @method.source_type == :c
|
316
|
+
raise CommandError, "Can't edit a C method."
|
317
|
+
else
|
318
|
+
[@method.source_file, @method.source_line]
|
319
|
+
end
|
320
|
+
else
|
321
|
+
[target.eval('__FILE__'), target.eval('__LINE__')]
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
def with_method_transaction(meth_name, target=TOPLEVEL_BINDING)
|
326
|
+
target = Pry.binding_for(target)
|
327
|
+
temp_name = "__pry_#{meth_name}__"
|
268
328
|
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
329
|
+
target.eval("alias #{temp_name} #{meth_name}")
|
330
|
+
yield
|
331
|
+
target.eval("alias #{meth_name} #{temp_name}")
|
332
|
+
ensure
|
333
|
+
target.eval("undef #{temp_name}") rescue nil
|
334
|
+
end
|
274
335
|
end
|
275
336
|
end
|
276
337
|
end
|
@@ -3,7 +3,94 @@ class Pry
|
|
3
3
|
|
4
4
|
Ls = Pry::CommandSet.new do
|
5
5
|
|
6
|
-
|
6
|
+
create_command "ls","Show the list of vars and methods in the current scope. Type `ls --help` for more info.",
|
7
|
+
:shellwords => false, :interpolate => false do
|
8
|
+
|
9
|
+
def options(opt)
|
10
|
+
opt.banner unindent <<-USAGE
|
11
|
+
Usage: ls [-m|-M|-p|-pM] [-q|-v] [-c|-i] [Object]
|
12
|
+
ls [-g] [-l]
|
13
|
+
|
14
|
+
ls shows you which methods, constants and variables are accessible to Pry. By default it shows you the local variables defined in the current shell, and any public methods or instance variables defined on the current object.
|
15
|
+
|
16
|
+
The colours used are configurable using Pry.config.ls.*_color, and the separator is Pry.config.ls.separator.
|
17
|
+
|
18
|
+
Pry.config.ls.ceiling is used to hide methods defined higher up in the inheritance chain, this is by default set to [Object, Module, Class] so that methods defined on all Objects are omitted. The -v flag can be used to ignore this setting and show all methods, while the -q can be used to set the ceiling much lower and show only methods defined on the object or its direct class.
|
19
|
+
USAGE
|
20
|
+
|
21
|
+
opt.on :m, "methods", "Show public methods defined on the Object (default)"
|
22
|
+
opt.on :M, "instance-methods", "Show methods defined in a Module or Class"
|
23
|
+
|
24
|
+
opt.on :p, "ppp", "Show public, protected (in yellow) and private (in green) methods"
|
25
|
+
opt.on :q, "quiet", "Show only methods defined on object.singleton_class and object.class"
|
26
|
+
opt.on :v, "verbose", "Show methods and constants on all super-classes (ignores Pry.config.ls.ceiling)"
|
27
|
+
|
28
|
+
opt.on :g, "globals", "Show global variables, including those builtin to Ruby (in cyan)"
|
29
|
+
opt.on :l, "locals", "Show locals, including those provided by Pry (in red)"
|
30
|
+
|
31
|
+
opt.on :c, "constants", "Show constants, highlighting classes (in blue), and exceptions (in purple)"
|
32
|
+
|
33
|
+
opt.on :i, "ivars", "Show instance variables (in blue) and class variables (in bright blue)"
|
34
|
+
|
35
|
+
opt.on :G, "grep", "Filter output by regular expression", :optional => false
|
36
|
+
end
|
37
|
+
|
38
|
+
def process
|
39
|
+
obj = args.empty? ? target_self : target.eval(args.join(" "))
|
40
|
+
|
41
|
+
# exclude -q, -v and --grep because they don't specify what the user wants to see.
|
42
|
+
has_opts = (opts.present?(:methods) || opts.present?(:'instance-methods') || opts.present?(:ppp) ||
|
43
|
+
opts.present?(:globals) || opts.present?(:locals) || opts.present?(:constants) ||
|
44
|
+
opts.present?(:ivars))
|
45
|
+
|
46
|
+
show_methods = opts.present?(:methods) || opts.present?(:'instance-methods') || opts.present?(:ppp) || !has_opts
|
47
|
+
show_constants = opts.present?(:constants) || (!has_opts && Module === obj)
|
48
|
+
show_ivars = opts.present?(:ivars) || !has_opts
|
49
|
+
show_locals = opts.present?(:locals) || (!has_opts && args.empty?)
|
50
|
+
|
51
|
+
grep_regex, grep = [Regexp.new(opts[:G] || "."), lambda{ |x| x.grep(grep_regex) }]
|
52
|
+
|
53
|
+
raise Pry::CommandError, "-l does not make sense with a specified Object" if opts.present?(:locals) && !args.empty?
|
54
|
+
raise Pry::CommandError, "-g does not make sense with a specified Object" if opts.present?(:globals) && !args.empty?
|
55
|
+
raise Pry::CommandError, "-q does not make sense with -v" if opts.present?(:quiet) && opts.present?(:verbose)
|
56
|
+
raise Pry::CommandError, "-M only makes sense with a Module or a Class" if opts.present?(:'instance-methods') && !(Module === obj)
|
57
|
+
raise Pry::CommandError, "-c only makes sense with a Module or a Class" if opts.present?(:constants) && !args.empty? && !(Module === obj)
|
58
|
+
|
59
|
+
|
60
|
+
if opts.present?(:globals)
|
61
|
+
output_section("global variables", grep[format_globals(target.eval("global_variables"))])
|
62
|
+
end
|
63
|
+
|
64
|
+
if show_constants
|
65
|
+
mod = Module === obj ? obj : Object
|
66
|
+
constants = mod.constants
|
67
|
+
constants -= (mod.ancestors - [mod]).map(&:constants).flatten unless opts.present?(:verbose)
|
68
|
+
output_section("constants", grep[format_constants(mod, constants)])
|
69
|
+
end
|
70
|
+
|
71
|
+
if show_methods
|
72
|
+
# methods is a hash {Module/Class => [Pry::Methods]}
|
73
|
+
methods = all_methods(obj).select{ |method| opts.present?(:ppp) || method.visibility == :public }.group_by(&:owner)
|
74
|
+
|
75
|
+
# reverse the resolution order so that the most useful information appears right by the prompt
|
76
|
+
resolution_order(obj).take_while(&below_ceiling(obj)).reverse.each do |klass|
|
77
|
+
methods_here = format_methods((methods[klass] || []).select{ |m| m.name =~ grep_regex })
|
78
|
+
output_section "#{Pry::WrappedModule.new(klass).method_prefix}methods", methods_here
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
if show_ivars
|
83
|
+
klass = (Module === obj ? obj : obj.class)
|
84
|
+
output_section("instance variables", format_variables(:instance_var, grep[obj.__send__(:instance_variables)]))
|
85
|
+
output_section("class variables", format_variables(:class_var, grep[klass.__send__(:class_variables)]))
|
86
|
+
end
|
87
|
+
|
88
|
+
if show_locals
|
89
|
+
output_section("locals", format_locals(grep[target.eval("local_variables")]))
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
7
94
|
|
8
95
|
# http://ruby.runpaint.org/globals, and running "puts global_variables.inspect".
|
9
96
|
BUILTIN_GLOBALS = %w($" $$ $* $, $-0 $-F $-I $-K $-W $-a $-d $-i $-l $-p $-v $-w $. $/ $\\
|
@@ -20,37 +107,20 @@ class Pry
|
|
20
107
|
$LAST_PAREN_MATCH $LAST_READ_LINE $MATCH $POSTMATCH $PREMATCH)
|
21
108
|
|
22
109
|
# Get all the methods that we'll want to output
|
23
|
-
def all_methods(obj
|
24
|
-
opts.
|
110
|
+
def all_methods(obj)
|
111
|
+
opts.present?(:'instance-methods') ? Pry::Method.all_from_class(obj) : Pry::Method.all_from_obj(obj)
|
25
112
|
end
|
26
113
|
|
27
|
-
def resolution_order(obj
|
28
|
-
opts.
|
29
|
-
end
|
30
|
-
|
31
|
-
# Get the name of the klass for pretty display in the title column of ls -m
|
32
|
-
# as there can only ever be one singleton class of a non-class, we just call
|
33
|
-
# that "self".
|
34
|
-
def class_name(klass)
|
35
|
-
if klass == klass.ancestors.first
|
36
|
-
(klass.name || "") == "" ? klass.to_s : klass.name
|
37
|
-
elsif klass.ancestors.include?(Module)
|
38
|
-
begin
|
39
|
-
"#{class_name(ObjectSpace.each_object(klass).detect{ |x| class << x; self; end == klass })}.self"
|
40
|
-
rescue # ObjectSpace is not enabled by default in jruby
|
41
|
-
klass.to_s.sub(/#<Class:(.*)>/, '\1.self')
|
42
|
-
end
|
43
|
-
else
|
44
|
-
"self"
|
45
|
-
end
|
114
|
+
def resolution_order(obj)
|
115
|
+
opts.present?(:'instance-methods') ? Pry::Method.instance_resolution_order(obj) : Pry::Method.resolution_order(obj)
|
46
116
|
end
|
47
117
|
|
48
118
|
# Get a lambda that can be used with .take_while to prevent over-eager
|
49
119
|
# traversal of the Object's ancestry graph.
|
50
|
-
def below_ceiling(obj
|
51
|
-
ceiling = if opts.
|
52
|
-
[opts.
|
53
|
-
elsif opts.
|
120
|
+
def below_ceiling(obj)
|
121
|
+
ceiling = if opts.present?(:quiet)
|
122
|
+
[opts.present?(:'instance-methods') ? obj.ancestors[1] : obj.class.ancestors[1]] + Pry.config.ls.ceiling
|
123
|
+
elsif opts.present?(:verbose)
|
54
124
|
[]
|
55
125
|
else
|
56
126
|
Pry.config.ls.ceiling.dup
|
@@ -125,94 +195,6 @@ class Pry
|
|
125
195
|
text.send(Pry.config.ls.send(:"#{type}_color"), str)
|
126
196
|
end
|
127
197
|
end
|
128
|
-
|
129
|
-
command "ls", "Show the list of vars and methods in the current scope. Type `ls --help` for more info.",
|
130
|
-
:shellwords => false, :interpolate => false do |*args|
|
131
|
-
|
132
|
-
opts = Slop.parse!(args, :strict => true) do |opt|
|
133
|
-
opt.banner unindent <<-USAGE
|
134
|
-
Usage: ls [-m|-M|-p|-pM] [-q|-v] [-c|-i] [Object]
|
135
|
-
ls [-g] [-l]
|
136
|
-
|
137
|
-
ls shows you which methods, constants and variables are accessible to Pry. By default it shows you the local variables defined in the current shell, and any public methods or instance variables defined on the current object.
|
138
|
-
|
139
|
-
The colours used are configurable using Pry.config.ls.*_color, and the separator is Pry.config.ls.separator.
|
140
|
-
|
141
|
-
Pry.config.ls.ceiling is used to hide methods defined higher up in the inheritance chain, this is by default set to [Object, Module, Class] so that methods defined on all Objects are omitted. The -v flag can be used to ignore this setting and show all methods, while the -q can be used to set the ceiling much lower and show only methods defined on the object or its direct class.
|
142
|
-
USAGE
|
143
|
-
|
144
|
-
opt.on :m, "methods", "Show public methods defined on the Object (default)"
|
145
|
-
opt.on :M, "module", "Show methods defined in a Module or Class"
|
146
|
-
|
147
|
-
opt.on :p, "ppp", "Show public, protected (in yellow) and private (in green) methods"
|
148
|
-
opt.on :q, "quiet", "Show only methods defined on object.singleton_class and object.class"
|
149
|
-
opt.on :v, "verbose", "Show methods and constants on all super-classes (ignores Pry.config.ls.ceiling)"
|
150
|
-
|
151
|
-
opt.on :g, "globals", "Show global variables, including those builtin to Ruby (in cyan)"
|
152
|
-
opt.on :l, "locals", "Show locals, including those provided by Pry (in red)"
|
153
|
-
|
154
|
-
opt.on :c, "constants", "Show constants, highlighting classes (in blue), and exceptions (in purple)"
|
155
|
-
|
156
|
-
opt.on :i, "ivars", "Show instance variables (in blue) and class variables (in bright blue)"
|
157
|
-
|
158
|
-
opt.on :G, "grep", "Filter output by regular expression", :optional => false
|
159
|
-
|
160
|
-
opt.on :h, "help", "Show help"
|
161
|
-
end
|
162
|
-
|
163
|
-
next output.puts(opts) if opts.h?
|
164
|
-
|
165
|
-
obj = args.empty? ? target_self : target.eval(args.join(" "))
|
166
|
-
|
167
|
-
# exclude -q, -v and --grep because they don't specify what the user wants to see.
|
168
|
-
has_opts = (opts.m? || opts.M? || opts.p? || opts.g? || opts.l? || opts.c? || opts.i?)
|
169
|
-
|
170
|
-
show_methods = opts.m? || opts.M? || opts.p? || !has_opts
|
171
|
-
show_constants = opts.c? || (!has_opts && Module === obj)
|
172
|
-
show_ivars = opts.i? || !has_opts
|
173
|
-
show_locals = opts.l? || (!has_opts && args.empty?)
|
174
|
-
|
175
|
-
grep_regex, grep = [Regexp.new(opts[:G] || "."), lambda{ |x| x.grep(grep_regex) }]
|
176
|
-
|
177
|
-
raise Pry::CommandError, "-l does not make sense with a specified Object" if opts.l? && !args.empty?
|
178
|
-
raise Pry::CommandError, "-g does not make sense with a specified Object" if opts.g? && !args.empty?
|
179
|
-
raise Pry::CommandError, "-q does not make sense with -v" if opts.q? && opts.v?
|
180
|
-
raise Pry::CommandError, "-M only makes sense with a Module or a Class" if opts.M? && !(Module === obj)
|
181
|
-
raise Pry::CommandError, "-c only makes sense with a Module or a Class" if opts.c? && !args.empty? && !(Module === obj)
|
182
|
-
|
183
|
-
|
184
|
-
if opts.g?
|
185
|
-
output_section("global variables", grep[format_globals(target.eval("global_variables"))])
|
186
|
-
end
|
187
|
-
|
188
|
-
if show_constants
|
189
|
-
mod = Module === obj ? obj : Object
|
190
|
-
constants = mod.constants
|
191
|
-
constants -= (mod.ancestors - [mod]).map(&:constants).flatten unless opts.v?
|
192
|
-
output_section("constants", grep[format_constants(mod, constants)])
|
193
|
-
end
|
194
|
-
|
195
|
-
if show_methods
|
196
|
-
# methods is a hash {Module/Class => [Pry::Methods]}
|
197
|
-
methods = all_methods(obj, opts).select{ |method| opts.p? || method.visibility == :public }.group_by(&:owner)
|
198
|
-
|
199
|
-
# reverse the resolution order so that the most useful information appears right by the prompt
|
200
|
-
resolution_order(obj, opts).take_while(&below_ceiling(obj, opts)).reverse.each do |klass|
|
201
|
-
methods_here = format_methods((methods[klass] || []).select{ |m| m.name =~ grep_regex })
|
202
|
-
output_section "#{class_name(klass)} methods", methods_here
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
if show_ivars
|
207
|
-
klass = (Module === obj ? obj : obj.class)
|
208
|
-
output_section("instance variables", format_variables(:instance_var, grep[obj.__send__(:instance_variables)]))
|
209
|
-
output_section("class variables", format_variables(:class_var, grep[klass.__send__(:class_variables)]))
|
210
|
-
end
|
211
|
-
|
212
|
-
if show_locals
|
213
|
-
output_section("locals", format_locals(grep[target.eval("local_variables")]))
|
214
|
-
end
|
215
|
-
end
|
216
198
|
end
|
217
199
|
end
|
218
200
|
end
|