irb 1.9.0 → 1.10.0
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 +4 -4
- data/Gemfile +3 -5
- data/README.md +11 -9
- data/Rakefile +2 -2
- data/lib/irb/cmd/history.rb +47 -0
- data/lib/irb/cmd/show_cmds.rb +6 -0
- data/lib/irb/cmd/show_source.rb +9 -2
- data/lib/irb/completion.rb +25 -4
- data/lib/irb/context.rb +22 -14
- data/lib/irb/debug.rb +18 -0
- data/lib/irb/extend-command.rb +6 -0
- data/lib/irb/history.rb +1 -1
- data/lib/irb/init.rb +4 -5
- data/lib/irb/input-method.rb +3 -0
- data/lib/irb/lc/help-message +1 -0
- data/lib/irb/pager.rb +12 -11
- data/lib/irb/source_finder.rb +26 -6
- data/lib/irb/version.rb +2 -2
- data/lib/irb.rb +48 -40
- metadata +4 -8
- data/lib/irb/type_completion/completor.rb +0 -235
- data/lib/irb/type_completion/methods.rb +0 -13
- data/lib/irb/type_completion/scope.rb +0 -412
- data/lib/irb/type_completion/type_analyzer.rb +0 -1169
- data/lib/irb/type_completion/types.rb +0 -426
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c0e7153fbd64c519a7af411d95779821c279a63b786c16df0e5cff4b577a258f
|
4
|
+
data.tar.gz: 86c81569fa9788676c575f64b1010191690b4b3c056330e5f21fb798d724924f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e78e35a1a46ac5b4e62e93f7cac0e1b3657b16cd108851624b3cfd2b6c81662ca6dfa7aff9737d743a625eaa96a47179c95e9af28833dcb9d761ee150923497d
|
7
|
+
data.tar.gz: 562c5e88c5c09adbe4f882d30a34b496599af4f7a45f41d60609ef91148d7271cd97bbfd629ca75da4f3845d7815e51bca3b1969e9bff1c723c18b3c0840517d
|
data/Gemfile
CHANGED
@@ -16,11 +16,9 @@ gem "reline", github: "ruby/reline" if ENV["WITH_LATEST_RELINE"] == "true"
|
|
16
16
|
gem "rake"
|
17
17
|
gem "test-unit"
|
18
18
|
gem "test-unit-ruby-core"
|
19
|
-
gem "debug", github: "ruby/debug"
|
20
19
|
|
21
|
-
gem "
|
20
|
+
gem "debug", github: "ruby/debug", platforms: [:mri, :mswin]
|
22
21
|
|
23
|
-
if RUBY_VERSION >= "3.0.0"
|
24
|
-
gem "
|
25
|
-
gem "prism", ">= 0.17.1"
|
22
|
+
if RUBY_VERSION >= "3.0.0" && !is_truffleruby
|
23
|
+
gem "repl_type_completor"
|
26
24
|
end
|
data/README.md
CHANGED
@@ -119,6 +119,7 @@ IRB
|
|
119
119
|
source Loads a given file in the current session.
|
120
120
|
irb_info Show information about IRB.
|
121
121
|
show_cmds List all available commands and their description.
|
122
|
+
history Shows the input history. `-g [query]` or `-G [query]` allows you to filter the output.
|
122
123
|
|
123
124
|
Multi-irb (DEPRECATED)
|
124
125
|
irb Start a child IRB.
|
@@ -237,11 +238,11 @@ However, there are also some limitations to be aware of:
|
|
237
238
|
|
238
239
|
## Type Based Completion
|
239
240
|
|
240
|
-
IRB's default completion `IRB::RegexpCompletor` uses Regexp. IRB has another experimental completion `IRB::
|
241
|
+
IRB's default completion `IRB::RegexpCompletor` uses Regexp. IRB has another experimental completion `IRB::TypeCompletor` that uses type analysis.
|
241
242
|
|
242
|
-
### How to Enable IRB::
|
243
|
+
### How to Enable IRB::TypeCompletor
|
243
244
|
|
244
|
-
To enable IRB::
|
245
|
+
To enable IRB::TypeCompletor, run IRB with `--type-completor` option
|
245
246
|
```
|
246
247
|
$ irb --type-completor
|
247
248
|
```
|
@@ -249,14 +250,14 @@ Or write the code below to IRB's rc-file.
|
|
249
250
|
```ruby
|
250
251
|
IRB.conf[:COMPLETOR] = :type # default is :regexp
|
251
252
|
```
|
252
|
-
You also need `gem
|
253
|
+
You also need `gem repl_type_completor` to use this feature.
|
253
254
|
|
254
255
|
To check if it's enabled, type `irb_info` into IRB and see the `Completion` section.
|
255
256
|
```
|
256
257
|
irb(main):001> irb_info
|
257
258
|
...
|
258
259
|
# Enabled
|
259
|
-
Completion: Autocomplete,
|
260
|
+
Completion: Autocomplete, ReplTypeCompletor: 0.1.0, Prism: 0.18.0, RBS: 3.3.0
|
260
261
|
# Not enabled
|
261
262
|
Completion: Autocomplete, RegexpCompletor
|
262
263
|
...
|
@@ -265,7 +266,7 @@ If you have `sig/` directory or `rbs_collection.lock.yaml` in current directory,
|
|
265
266
|
|
266
267
|
### Advantage over Default IRB::RegexpCompletor
|
267
268
|
|
268
|
-
IRB::
|
269
|
+
IRB::TypeCompletor can autocomplete chained methods, block parameters and more if type information is available.
|
269
270
|
These are some examples IRB::RegexpCompletor cannot complete.
|
270
271
|
|
271
272
|
```ruby
|
@@ -287,11 +288,11 @@ As a trade-off, completion calculation takes more time than IRB::RegexpCompletor
|
|
287
288
|
|
288
289
|
### Difference between Steep's Completion
|
289
290
|
|
290
|
-
Compared with Steep, IRB::
|
291
|
+
Compared with Steep, IRB::TypeCompletor has some difference and limitations.
|
291
292
|
```ruby
|
292
293
|
[0, 'a'].sample.
|
293
294
|
# Steep completes intersection of Integer methods and String methods
|
294
|
-
# IRB::
|
295
|
+
# IRB::TypeCompletor completes both Integer and String methods
|
295
296
|
```
|
296
297
|
|
297
298
|
Some features like type narrowing is not implemented.
|
@@ -301,7 +302,7 @@ def f(arg = [0, 'a'].sample)
|
|
301
302
|
arg. # Completes both Integer and String methods
|
302
303
|
```
|
303
304
|
|
304
|
-
Unlike other static type checker, IRB::
|
305
|
+
Unlike other static type checker, IRB::TypeCompletor uses runtime information to provide better completion.
|
305
306
|
```ruby
|
306
307
|
irb(main):001> a = [1]
|
307
308
|
=> [1]
|
@@ -314,6 +315,7 @@ irb(main):002> a.first. # Completes Integer methods
|
|
314
315
|
|
315
316
|
- `NO_COLOR`: Assigning a value to it disables IRB's colorization.
|
316
317
|
- `IRB_USE_AUTOCOMPLETE`: Setting it to `false` disables IRB's autocompletion.
|
318
|
+
- `IRB_COMPLETOR`: Configures IRB's auto-completion behavior, allowing settings for either `regexp` or `type`.
|
317
319
|
- `VISUAL`: Its value would be used to open files by the `edit` command.
|
318
320
|
- `EDITOR`: Its value would be used to open files by the `edit` command if `VISUAL` is unset.
|
319
321
|
- `IRBRC`: The file specified would be evaluated as IRB's rc-file.
|
data/Rakefile
CHANGED
@@ -5,7 +5,7 @@ Rake::TestTask.new(:test) do |t|
|
|
5
5
|
t.libs << "test" << "test/lib"
|
6
6
|
t.libs << "lib"
|
7
7
|
t.ruby_opts << "-rhelper"
|
8
|
-
t.test_files = FileList["test/irb
|
8
|
+
t.test_files = FileList["test/irb/**/test_*.rb"]
|
9
9
|
end
|
10
10
|
|
11
11
|
# To make sure they have been correctly setup for Ruby CI.
|
@@ -13,7 +13,7 @@ desc "Run each irb test file in isolation."
|
|
13
13
|
task :test_in_isolation do
|
14
14
|
failed = false
|
15
15
|
|
16
|
-
FileList["test/irb
|
16
|
+
FileList["test/irb/**/test_*.rb"].each do |test_file|
|
17
17
|
ENV["TEST"] = test_file
|
18
18
|
begin
|
19
19
|
Rake::Task["test"].execute
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "stringio"
|
4
|
+
require_relative "nop"
|
5
|
+
require_relative "../pager"
|
6
|
+
|
7
|
+
module IRB
|
8
|
+
# :stopdoc:
|
9
|
+
|
10
|
+
module ExtendCommand
|
11
|
+
class History < Nop
|
12
|
+
category "IRB"
|
13
|
+
description "Shows the input history. `-g [query]` or `-G [query]` allows you to filter the output."
|
14
|
+
|
15
|
+
def self.transform_args(args)
|
16
|
+
match = args&.match(/(-g|-G)\s+(?<grep>.+)\s*\n\z/)
|
17
|
+
return unless match
|
18
|
+
|
19
|
+
"grep: #{Regexp.new(match[:grep]).inspect}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def execute(grep: nil)
|
23
|
+
formatted_inputs = irb_context.io.class::HISTORY.each_with_index.reverse_each.filter_map do |input, index|
|
24
|
+
next if grep && !input.match?(grep)
|
25
|
+
|
26
|
+
header = "#{index}: "
|
27
|
+
|
28
|
+
first_line, *other_lines = input.split("\n")
|
29
|
+
first_line = "#{header}#{first_line}"
|
30
|
+
|
31
|
+
truncated_lines = other_lines.slice!(1..) # Show 1 additional line (2 total)
|
32
|
+
other_lines << "..." if truncated_lines&.any?
|
33
|
+
|
34
|
+
other_lines.map! do |line|
|
35
|
+
" " * header.length + line
|
36
|
+
end
|
37
|
+
|
38
|
+
[first_line, *other_lines].join("\n") + "\n"
|
39
|
+
end
|
40
|
+
|
41
|
+
Pager.page_content(formatted_inputs.join)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# :startdoc:
|
47
|
+
end
|
data/lib/irb/cmd/show_cmds.rb
CHANGED
@@ -16,6 +16,12 @@ module IRB
|
|
16
16
|
commands_info = IRB::ExtendCommandBundle.all_commands_info
|
17
17
|
commands_grouped_by_categories = commands_info.group_by { |cmd| cmd[:category] }
|
18
18
|
|
19
|
+
user_aliases = irb_context.instance_variable_get(:@user_aliases)
|
20
|
+
|
21
|
+
commands_grouped_by_categories["Aliases"] = user_aliases.map do |alias_name, target|
|
22
|
+
{ display_name: alias_name, description: "Alias for `#{target}`" }
|
23
|
+
end
|
24
|
+
|
19
25
|
if irb_context.with_debugger
|
20
26
|
# Remove the original "Debugging" category
|
21
27
|
commands_grouped_by_categories.delete("Debugging")
|
data/lib/irb/cmd/show_source.rb
CHANGED
@@ -27,11 +27,18 @@ module IRB
|
|
27
27
|
puts "Error: Expected a string but got #{str.inspect}"
|
28
28
|
return
|
29
29
|
end
|
30
|
-
|
31
|
-
|
30
|
+
if str.include? " -s"
|
31
|
+
str, esses = str.split(" -")
|
32
|
+
s_count = esses.count("^s").zero? ? esses.size : 1
|
33
|
+
source = SourceFinder.new(@irb_context).find_source(str, s_count)
|
34
|
+
else
|
35
|
+
source = SourceFinder.new(@irb_context).find_source(str)
|
36
|
+
end
|
32
37
|
|
33
38
|
if source
|
34
39
|
show_source(source)
|
40
|
+
elsif s_count
|
41
|
+
puts "Error: Couldn't locate a super definition for #{str}"
|
35
42
|
else
|
36
43
|
puts "Error: Couldn't locate a definition for #{str}"
|
37
44
|
end
|
data/lib/irb/completion.rb
CHANGED
@@ -93,6 +93,27 @@ module IRB
|
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
|
+
class TypeCompletor < BaseCompletor # :nodoc:
|
97
|
+
def initialize(context)
|
98
|
+
@context = context
|
99
|
+
end
|
100
|
+
|
101
|
+
def inspect
|
102
|
+
ReplTypeCompletor.info
|
103
|
+
end
|
104
|
+
|
105
|
+
def completion_candidates(preposing, target, _postposing, bind:)
|
106
|
+
result = ReplTypeCompletor.analyze(preposing + target, binding: bind, filename: @context.irb_path)
|
107
|
+
return [] unless result
|
108
|
+
result.completion_candidates.map { target + _1 }
|
109
|
+
end
|
110
|
+
|
111
|
+
def doc_namespace(preposing, matched, _postposing, bind:)
|
112
|
+
result = ReplTypeCompletor.analyze(preposing + matched, binding: bind, filename: @context.irb_path)
|
113
|
+
result&.doc_namespace('')
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
96
117
|
class RegexpCompletor < BaseCompletor # :nodoc:
|
97
118
|
using Module.new {
|
98
119
|
refine ::Binding do
|
@@ -210,16 +231,16 @@ module IRB
|
|
210
231
|
end
|
211
232
|
|
212
233
|
when /^([^\}]*\})\.([^.]*)$/
|
213
|
-
#
|
234
|
+
# Hash or Proc
|
214
235
|
receiver = $1
|
215
236
|
message = $2
|
216
237
|
|
217
238
|
if doc_namespace
|
218
|
-
["
|
239
|
+
["Hash.#{message}", "Proc.#{message}"]
|
219
240
|
else
|
220
|
-
proc_candidates = Proc.instance_methods.collect{|m| m.to_s}
|
221
241
|
hash_candidates = Hash.instance_methods.collect{|m| m.to_s}
|
222
|
-
|
242
|
+
proc_candidates = Proc.instance_methods.collect{|m| m.to_s}
|
243
|
+
select_message(receiver, message, hash_candidates | proc_candidates)
|
223
244
|
end
|
224
245
|
|
225
246
|
when /^(:[^:.]+)$/
|
data/lib/irb/context.rb
CHANGED
@@ -146,9 +146,21 @@ module IRB
|
|
146
146
|
@newline_before_multiline_output = true
|
147
147
|
end
|
148
148
|
|
149
|
-
@
|
149
|
+
@user_aliases = IRB.conf[:COMMAND_ALIASES].dup
|
150
|
+
@command_aliases = @user_aliases.merge(KEYWORD_ALIASES)
|
150
151
|
end
|
151
152
|
|
153
|
+
# because all input will eventually be evaluated as Ruby code,
|
154
|
+
# command names that conflict with Ruby keywords need special workaround
|
155
|
+
# we can remove them once we implemented a better command system for IRB
|
156
|
+
KEYWORD_ALIASES = {
|
157
|
+
:break => :irb_break,
|
158
|
+
:catch => :irb_catch,
|
159
|
+
:next => :irb_next,
|
160
|
+
}.freeze
|
161
|
+
|
162
|
+
private_constant :KEYWORD_ALIASES
|
163
|
+
|
152
164
|
private def build_completor
|
153
165
|
completor_type = IRB.conf[:COMPLETOR]
|
154
166
|
case completor_type
|
@@ -164,26 +176,22 @@ module IRB
|
|
164
176
|
RegexpCompletor.new
|
165
177
|
end
|
166
178
|
|
167
|
-
TYPE_COMPLETION_REQUIRED_PRISM_VERSION = '0.17.1'
|
168
|
-
|
169
179
|
private def build_type_completor
|
170
|
-
|
171
|
-
|
180
|
+
if RUBY_ENGINE == 'truffleruby'
|
181
|
+
# Avoid SynatxError. truffleruby does not support endless method definition yet.
|
182
|
+
warn 'TypeCompletor is not supported on TruffleRuby yet'
|
172
183
|
return
|
173
184
|
end
|
185
|
+
|
174
186
|
begin
|
175
|
-
require '
|
187
|
+
require 'repl_type_completor'
|
176
188
|
rescue LoadError => e
|
177
|
-
warn "
|
189
|
+
warn "TypeCompletor requires `gem repl_type_completor`: #{e.message}"
|
178
190
|
return
|
179
191
|
end
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
end
|
184
|
-
require 'irb/type_completion/completor'
|
185
|
-
TypeCompletion::Types.preload_in_thread
|
186
|
-
TypeCompletion::Completor.new
|
192
|
+
|
193
|
+
ReplTypeCompletor.preload_rbs
|
194
|
+
TypeCompletor.new(self)
|
187
195
|
end
|
188
196
|
|
189
197
|
def save_history=(val)
|
data/lib/irb/debug.rb
CHANGED
@@ -57,6 +57,24 @@ module IRB
|
|
57
57
|
DEBUGGER__::ThreadClient.prepend(SkipPathHelperForIRB)
|
58
58
|
end
|
59
59
|
|
60
|
+
if !@output_modifier_defined && !DEBUGGER__::CONFIG[:no_hint]
|
61
|
+
irb_output_modifier_proc = Reline.output_modifier_proc
|
62
|
+
|
63
|
+
Reline.output_modifier_proc = proc do |output, complete:|
|
64
|
+
unless output.strip.empty?
|
65
|
+
cmd = output.split(/\s/, 2).first
|
66
|
+
|
67
|
+
if !complete && DEBUGGER__.commands.key?(cmd)
|
68
|
+
output = output.sub(/\n$/, " # debug command\n")
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
irb_output_modifier_proc.call(output, complete: complete)
|
73
|
+
end
|
74
|
+
|
75
|
+
@output_modifier_defined = true
|
76
|
+
end
|
77
|
+
|
60
78
|
true
|
61
79
|
end
|
62
80
|
|
data/lib/irb/extend-command.rb
CHANGED
data/lib/irb/history.rb
CHANGED
@@ -60,7 +60,7 @@ module IRB
|
|
60
60
|
end
|
61
61
|
|
62
62
|
File.open(history_file, (append_history ? 'a' : 'w'), 0o600, encoding: IRB.conf[:LC_MESSAGES]&.encoding) do |f|
|
63
|
-
hist = history.map{ |l| l.split("\n").join("\\\n") }
|
63
|
+
hist = history.map{ |l| l.scrub.split("\n").join("\\\n") }
|
64
64
|
unless append_history
|
65
65
|
begin
|
66
66
|
hist = hist.last(num) if hist.size > num and num > 0
|
data/lib/irb/init.rb
CHANGED
@@ -76,12 +76,13 @@ module IRB # :nodoc:
|
|
76
76
|
@CONF[:USE_SINGLELINE] = false unless defined?(ReadlineInputMethod)
|
77
77
|
@CONF[:USE_COLORIZE] = (nc = ENV['NO_COLOR']).nil? || nc.empty?
|
78
78
|
@CONF[:USE_AUTOCOMPLETE] = ENV.fetch("IRB_USE_AUTOCOMPLETE", "true") != "false"
|
79
|
-
@CONF[:COMPLETOR] =
|
79
|
+
@CONF[:COMPLETOR] = ENV.fetch("IRB_COMPLETOR", "regexp").to_sym
|
80
80
|
@CONF[:INSPECT_MODE] = true
|
81
81
|
@CONF[:USE_TRACER] = false
|
82
82
|
@CONF[:USE_LOADER] = false
|
83
83
|
@CONF[:IGNORE_SIGINT] = true
|
84
84
|
@CONF[:IGNORE_EOF] = false
|
85
|
+
@CONF[:USE_PAGER] = true
|
85
86
|
@CONF[:EXTRA_DOC_DIRS] = []
|
86
87
|
@CONF[:ECHO] = nil
|
87
88
|
@CONF[:ECHO_ON_ASSIGNMENT] = nil
|
@@ -188,10 +189,6 @@ module IRB # :nodoc:
|
|
188
189
|
# Symbol aliases
|
189
190
|
:'$' => :show_source,
|
190
191
|
:'@' => :whereami,
|
191
|
-
# Keyword aliases
|
192
|
-
:break => :irb_break,
|
193
|
-
:catch => :irb_catch,
|
194
|
-
:next => :irb_next,
|
195
192
|
}
|
196
193
|
end
|
197
194
|
|
@@ -285,6 +282,8 @@ module IRB # :nodoc:
|
|
285
282
|
end
|
286
283
|
when "--noinspect"
|
287
284
|
@CONF[:INSPECT_MODE] = false
|
285
|
+
when "--no-pager"
|
286
|
+
@CONF[:USE_PAGER] = false
|
288
287
|
when "--singleline", "--readline", "--legacy"
|
289
288
|
@CONF[:USE_SINGLELINE] = true
|
290
289
|
when "--nosingleline", "--noreadline"
|
data/lib/irb/input-method.rb
CHANGED
@@ -312,6 +312,9 @@ module IRB
|
|
312
312
|
return nil if result.nil? or pointer.nil? or pointer < 0
|
313
313
|
|
314
314
|
name = doc_namespace.call(result[pointer])
|
315
|
+
# Use first one because document dialog does not support multiple namespaces.
|
316
|
+
name = name.first if name.is_a?(Array)
|
317
|
+
|
315
318
|
show_easter_egg = name&.match?(/\ARubyVM/) && !ENV['RUBY_YES_I_AM_NOT_A_NORMAL_USER']
|
316
319
|
|
317
320
|
options = {}
|
data/lib/irb/lc/help-message
CHANGED
@@ -22,6 +22,7 @@ Usage: irb.rb [options] [programfile] [arguments]
|
|
22
22
|
Show truncated result on assignment (default).
|
23
23
|
--inspect Use 'inspect' for output.
|
24
24
|
--noinspect Don't use 'inspect' for output.
|
25
|
+
--no-pager Don't use pager.
|
25
26
|
--multiline Use multiline editor module (default).
|
26
27
|
--nomultiline Don't use multiline editor module.
|
27
28
|
--singleline Use single line editor module.
|
data/lib/irb/pager.rb
CHANGED
@@ -7,9 +7,9 @@ module IRB
|
|
7
7
|
PAGE_COMMANDS = [ENV['RI_PAGER'], ENV['PAGER'], 'less', 'more'].compact.uniq
|
8
8
|
|
9
9
|
class << self
|
10
|
-
def page_content(content)
|
10
|
+
def page_content(content, **options)
|
11
11
|
if content_exceeds_screen_height?(content)
|
12
|
-
page do |io|
|
12
|
+
page(**options) do |io|
|
13
13
|
io.puts content
|
14
14
|
end
|
15
15
|
else
|
@@ -17,8 +17,8 @@ module IRB
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
def page
|
21
|
-
if STDIN.tty? && pager = setup_pager
|
20
|
+
def page(retain_content: false)
|
21
|
+
if IRB.conf[:USE_PAGER] && STDIN.tty? && pager = setup_pager(retain_content: retain_content)
|
22
22
|
begin
|
23
23
|
pid = pager.pid
|
24
24
|
yield pager
|
@@ -55,19 +55,20 @@ module IRB
|
|
55
55
|
pageable_height * screen_width < Reline::Unicode.calculate_width(content, true)
|
56
56
|
end
|
57
57
|
|
58
|
-
def setup_pager
|
58
|
+
def setup_pager(retain_content:)
|
59
59
|
require 'shellwords'
|
60
60
|
|
61
|
-
PAGE_COMMANDS.each do |
|
62
|
-
|
63
|
-
next if
|
61
|
+
PAGE_COMMANDS.each do |pager_cmd|
|
62
|
+
cmd = Shellwords.split(pager_cmd)
|
63
|
+
next if cmd.empty?
|
64
64
|
|
65
|
-
if
|
66
|
-
|
65
|
+
if cmd.first == 'less'
|
66
|
+
cmd << '-R' unless cmd.include?('-R')
|
67
|
+
cmd << '-X' if retain_content && !cmd.include?('-X')
|
67
68
|
end
|
68
69
|
|
69
70
|
begin
|
70
|
-
io = IO.popen(
|
71
|
+
io = IO.popen(cmd, 'w')
|
71
72
|
rescue
|
72
73
|
next
|
73
74
|
end
|
data/lib/irb/source_finder.rb
CHANGED
@@ -16,7 +16,7 @@ module IRB
|
|
16
16
|
@irb_context = irb_context
|
17
17
|
end
|
18
18
|
|
19
|
-
def find_source(signature)
|
19
|
+
def find_source(signature, s_count = nil)
|
20
20
|
context_binding = @irb_context.workspace.binding
|
21
21
|
case signature
|
22
22
|
when /\A[A-Z]\w*(::[A-Z]\w*)*\z/ # Const::Name
|
@@ -26,14 +26,13 @@ module IRB
|
|
26
26
|
when /\A(?<owner>[A-Z]\w*(::[A-Z]\w*)*)#(?<method>[^ :.]+)\z/ # Class#method
|
27
27
|
owner = eval(Regexp.last_match[:owner], context_binding)
|
28
28
|
method = Regexp.last_match[:method]
|
29
|
-
|
30
|
-
|
31
|
-
file, line = owner.instance_method(method).source_location if methods.include?(method.to_sym)
|
32
|
-
end
|
29
|
+
return unless owner.respond_to?(:instance_method)
|
30
|
+
file, line = method_target(owner, s_count, method, "owner")
|
33
31
|
when /\A((?<receiver>.+)(\.|::))?(?<method>[^ :.]+)\z/ # method, receiver.method, receiver::method
|
34
32
|
receiver = eval(Regexp.last_match[:receiver] || 'self', context_binding)
|
35
33
|
method = Regexp.last_match[:method]
|
36
|
-
|
34
|
+
return unless receiver.respond_to?(method, true)
|
35
|
+
file, line = method_target(receiver, s_count, method, "receiver")
|
37
36
|
end
|
38
37
|
if file && line && File.exist?(file)
|
39
38
|
Source.new(file: file, first_line: line, last_line: find_end(file, line))
|
@@ -60,5 +59,26 @@ module IRB
|
|
60
59
|
end
|
61
60
|
first_line
|
62
61
|
end
|
62
|
+
|
63
|
+
def method_target(owner_receiver, s_count, method, type)
|
64
|
+
case type
|
65
|
+
when "owner"
|
66
|
+
target_method = owner_receiver.instance_method(method)
|
67
|
+
return target_method.source_location unless s_count
|
68
|
+
when "receiver"
|
69
|
+
if s_count
|
70
|
+
target_method = owner_receiver.class.instance_method(method)
|
71
|
+
else
|
72
|
+
target_method = method
|
73
|
+
return owner_receiver.method(method).source_location
|
74
|
+
end
|
75
|
+
end
|
76
|
+
s_count.times do |s|
|
77
|
+
target_method = target_method.super_method if target_method
|
78
|
+
end
|
79
|
+
target_method.nil? ? nil : target_method.source_location
|
80
|
+
rescue NameError
|
81
|
+
nil
|
82
|
+
end
|
63
83
|
end
|
64
84
|
end
|