irb 1.14.3 → 1.18.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/.rdoc_options +5 -0
- data/CONTRIBUTING.md +52 -0
- data/EXTEND_IRB.md +3 -0
- data/Gemfile +11 -1
- data/README.md +13 -310
- data/doc/COMMAND_LINE_OPTIONS.md +69 -0
- data/doc/COMPARED_WITH_PRY.md +22 -0
- data/doc/Configurations.md +274 -0
- data/doc/EXTEND_IRB.md +122 -0
- data/doc/Index.md +705 -0
- data/doc/irb/irb.rd.ja +1 -1
- data/lib/irb/color.rb +251 -162
- data/lib/irb/color_printer.rb +10 -9
- data/lib/irb/command/base.rb +35 -0
- data/lib/irb/command/copy.rb +83 -0
- data/lib/irb/command/history.rb +1 -1
- data/lib/irb/command/internal_helpers.rb +6 -3
- data/lib/irb/command/ls.rb +6 -4
- data/lib/irb/completion.rb +69 -52
- data/lib/irb/context.rb +100 -64
- data/lib/irb/debug.rb +3 -3
- data/lib/irb/default_commands.rb +4 -1
- data/lib/irb/easter-egg.rb +3 -1
- data/lib/irb/ext/multi-irb.rb +2 -0
- data/lib/irb/history.rb +4 -0
- data/lib/irb/init.rb +6 -1
- data/lib/irb/input-method.rb +158 -122
- data/lib/irb/inspector.rb +12 -7
- data/lib/irb/lc/help-message +2 -2
- data/lib/irb/lc/ja/help-message +1 -1
- data/lib/irb/nesting_parser.rb +362 -213
- data/lib/irb/pager.rb +127 -6
- data/lib/irb/ruby-lex.rb +225 -299
- data/lib/irb/ruby_logo.aa +4 -0
- data/lib/irb/source_finder.rb +12 -18
- data/lib/irb/startup_message.rb +83 -0
- data/lib/irb/statement.rb +21 -0
- data/lib/irb/version.rb +2 -2
- data/lib/irb/workspace.rb +9 -0
- data/lib/irb.rb +112 -927
- data/man/irb.1 +2 -0
- metadata +42 -12
- data/.document +0 -8
- data/Rakefile +0 -52
- data/bin/console +0 -6
- data/bin/setup +0 -6
- data/irb.gemspec +0 -46
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'prism'
|
|
4
|
+
|
|
3
5
|
module IRB
|
|
4
6
|
module Command
|
|
5
7
|
# Internal use only, for default command's backward compatibility.
|
|
@@ -7,9 +9,10 @@ module IRB
|
|
|
7
9
|
def unwrap_string_literal(str)
|
|
8
10
|
return if str.empty?
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
result = Prism.parse(str)
|
|
13
|
+
body = result.value.statements.body
|
|
14
|
+
if result.success? && body.size == 1 && body.first.is_a?(Prism::StringNode)
|
|
15
|
+
body.first.unescaped
|
|
13
16
|
else
|
|
14
17
|
str
|
|
15
18
|
end
|
data/lib/irb/command/ls.rb
CHANGED
|
@@ -55,11 +55,13 @@ module IRB
|
|
|
55
55
|
|
|
56
56
|
o = Output.new(grep: grep)
|
|
57
57
|
|
|
58
|
-
klass
|
|
58
|
+
klass = Kernel.instance_method(:class).bind(obj).call
|
|
59
|
+
obj_is_class_or_module = Module === obj
|
|
60
|
+
klass = obj_is_class_or_module ? obj : klass
|
|
59
61
|
|
|
60
|
-
o.dump("constants", obj.constants) if
|
|
62
|
+
o.dump("constants", obj.constants) if obj_is_class_or_module
|
|
61
63
|
dump_methods(o, klass, obj)
|
|
62
|
-
o.dump("instance variables",
|
|
64
|
+
o.dump("instance variables", Kernel.instance_method(:instance_variables).bind(obj).call)
|
|
63
65
|
o.dump("class variables", klass.class_variables)
|
|
64
66
|
o.dump("locals", locals) if locals
|
|
65
67
|
o.print_result
|
|
@@ -67,7 +69,7 @@ module IRB
|
|
|
67
69
|
end
|
|
68
70
|
|
|
69
71
|
def dump_methods(o, klass, obj)
|
|
70
|
-
singleton_class = begin obj.
|
|
72
|
+
singleton_class = begin Kernel.instance_method(:singleton_class).bind(obj).call; rescue TypeError; nil end
|
|
71
73
|
dumped_mods = Array.new
|
|
72
74
|
ancestors = klass.ancestors
|
|
73
75
|
ancestors = ancestors.reject { |c| c >= Object } if klass < Object
|
data/lib/irb/completion.rb
CHANGED
|
@@ -8,30 +8,33 @@
|
|
|
8
8
|
require_relative 'ruby-lex'
|
|
9
9
|
|
|
10
10
|
module IRB
|
|
11
|
+
class DocumentTarget # :nodoc:
|
|
12
|
+
attr_reader :name
|
|
13
|
+
|
|
14
|
+
def initialize(name)
|
|
15
|
+
@name = name
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class CommandDocument < DocumentTarget # :nodoc:
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Represents a method/class documentation target. May hold multiple names
|
|
23
|
+
# when the receiver is ambiguous (e.g. `{}.any?` could be Hash#any? or Proc#any?).
|
|
24
|
+
# The dialog popup uses only the first name; the full-screen display renders all.
|
|
25
|
+
class MethodDocument < DocumentTarget # :nodoc:
|
|
26
|
+
attr_reader :names
|
|
27
|
+
|
|
28
|
+
def initialize(*names)
|
|
29
|
+
super(names.first)
|
|
30
|
+
@names = names
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
11
34
|
class BaseCompletor # :nodoc:
|
|
12
35
|
|
|
13
36
|
# Set of reserved words used by Ruby, you should not use these for
|
|
14
37
|
# constants or variables
|
|
15
|
-
ReservedWords = %w[
|
|
16
|
-
__ENCODING__ __LINE__ __FILE__
|
|
17
|
-
BEGIN END
|
|
18
|
-
alias and
|
|
19
|
-
begin break
|
|
20
|
-
case class
|
|
21
|
-
def defined? do
|
|
22
|
-
else elsif end ensure
|
|
23
|
-
false for
|
|
24
|
-
if in
|
|
25
|
-
module
|
|
26
|
-
next nil not
|
|
27
|
-
or
|
|
28
|
-
redo rescue retry return
|
|
29
|
-
self super
|
|
30
|
-
then true
|
|
31
|
-
undef unless until
|
|
32
|
-
when while
|
|
33
|
-
yield
|
|
34
|
-
]
|
|
35
38
|
|
|
36
39
|
HELP_COMMAND_PREPOSING = /\Ahelp\s+/
|
|
37
40
|
|
|
@@ -60,13 +63,13 @@ module IRB
|
|
|
60
63
|
|
|
61
64
|
def retrieve_gem_and_system_load_path
|
|
62
65
|
candidates = (GEM_PATHS | $LOAD_PATH)
|
|
63
|
-
candidates.
|
|
66
|
+
candidates.filter_map do |p|
|
|
64
67
|
if p.respond_to?(:to_path)
|
|
65
68
|
p.to_path
|
|
66
69
|
else
|
|
67
70
|
String(p) rescue nil
|
|
68
71
|
end
|
|
69
|
-
end.
|
|
72
|
+
end.sort
|
|
70
73
|
end
|
|
71
74
|
|
|
72
75
|
def retrieve_files_to_require_from_load_path
|
|
@@ -96,6 +99,12 @@ module IRB
|
|
|
96
99
|
end
|
|
97
100
|
end
|
|
98
101
|
|
|
102
|
+
def command_document_target(preposing, matched)
|
|
103
|
+
if preposing.empty? && IRB::Command.command_names.include?(matched)
|
|
104
|
+
CommandDocument.new(matched)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
99
108
|
def retrieve_files_to_require_relative_from_current_dir
|
|
100
109
|
@files_from_current_dir ||= Dir.glob("**/*.{rb,#{RbConfig::CONFIG['DLEXT']}}", base: '.').map { |path|
|
|
101
110
|
path.sub(/\.(rb|#{RbConfig::CONFIG['DLEXT']})\z/, '')
|
|
@@ -127,12 +136,21 @@ module IRB
|
|
|
127
136
|
|
|
128
137
|
return commands unless result
|
|
129
138
|
|
|
130
|
-
|
|
139
|
+
encoded_candidates = result.completion_candidates.filter_map do |i|
|
|
140
|
+
encoded = i.encode(Encoding.default_external)
|
|
141
|
+
target + encoded
|
|
142
|
+
rescue Encoding::UndefinedConversionError
|
|
143
|
+
# If the string cannot be converted, we just ignore it
|
|
144
|
+
nil
|
|
145
|
+
end
|
|
146
|
+
commands | encoded_candidates
|
|
131
147
|
end
|
|
132
148
|
|
|
133
149
|
def doc_namespace(preposing, matched, _postposing, bind:)
|
|
134
|
-
|
|
135
|
-
|
|
150
|
+
command_document_target(preposing, matched) || begin
|
|
151
|
+
result = ReplTypeCompletor.analyze(preposing + matched, binding: bind, filename: @context.irb_path)
|
|
152
|
+
result&.doc_namespace('')
|
|
153
|
+
end
|
|
136
154
|
end
|
|
137
155
|
end
|
|
138
156
|
|
|
@@ -179,28 +197,15 @@ module IRB
|
|
|
179
197
|
else
|
|
180
198
|
return nil # It's not String literal
|
|
181
199
|
end
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
break
|
|
188
|
-
end
|
|
189
|
-
end
|
|
190
|
-
return unless tok&.event == :on_ident && tok.state == Ripper::EXPR_CMDARG
|
|
191
|
-
|
|
192
|
-
case tok.tok
|
|
193
|
-
when 'require'
|
|
194
|
-
retrieve_files_to_require_from_load_path.select { |path|
|
|
195
|
-
path.start_with?(actual_target)
|
|
196
|
-
}.map { |path|
|
|
197
|
-
quote + path
|
|
200
|
+
|
|
201
|
+
case preposing
|
|
202
|
+
when /(^|[^\w])require\(? *\z/
|
|
203
|
+
retrieve_files_to_require_from_load_path.filter_map { |path|
|
|
204
|
+
quote + path if path.start_with?(actual_target)
|
|
198
205
|
}
|
|
199
|
-
when
|
|
200
|
-
retrieve_files_to_require_relative_from_current_dir.
|
|
201
|
-
path.start_with?(actual_target)
|
|
202
|
-
}.map { |path|
|
|
203
|
-
quote + path
|
|
206
|
+
when /(^|[^\w])require_relative\(? *\z/
|
|
207
|
+
retrieve_files_to_require_relative_from_current_dir.filter_map { |path|
|
|
208
|
+
quote + path if path.start_with?(actual_target)
|
|
204
209
|
}
|
|
205
210
|
end
|
|
206
211
|
end
|
|
@@ -218,12 +223,17 @@ module IRB
|
|
|
218
223
|
# It doesn't make sense to propose commands with other preposing
|
|
219
224
|
commands = [] unless preposing.empty?
|
|
220
225
|
|
|
221
|
-
completion_data = retrieve_completion_data(target, bind: bind, doc_namespace: false).compact.
|
|
226
|
+
completion_data = retrieve_completion_data(target, bind: bind, doc_namespace: false).compact.filter_map do |i|
|
|
227
|
+
i.encode(Encoding.default_external)
|
|
228
|
+
rescue Encoding::UndefinedConversionError
|
|
229
|
+
# If the string cannot be converted, we just ignore it
|
|
230
|
+
nil
|
|
231
|
+
end
|
|
222
232
|
commands | completion_data
|
|
223
233
|
end
|
|
224
234
|
|
|
225
|
-
def doc_namespace(
|
|
226
|
-
retrieve_completion_data(matched, bind: bind, doc_namespace: true)
|
|
235
|
+
def doc_namespace(preposing, matched, _postposing, bind:)
|
|
236
|
+
command_document_target(preposing, matched) || retrieve_completion_data(matched, bind: bind, doc_namespace: true)
|
|
227
237
|
end
|
|
228
238
|
|
|
229
239
|
def retrieve_completion_data(input, bind:, doc_namespace:)
|
|
@@ -287,7 +297,7 @@ module IRB
|
|
|
287
297
|
nil
|
|
288
298
|
else
|
|
289
299
|
sym = $1
|
|
290
|
-
candidates = Symbol.all_symbols.
|
|
300
|
+
candidates = Symbol.all_symbols.filter_map do |s|
|
|
291
301
|
s.inspect
|
|
292
302
|
rescue EncodingError
|
|
293
303
|
# ignore
|
|
@@ -459,12 +469,19 @@ module IRB
|
|
|
459
469
|
eval("#{perfect_match_var}.class.name", bind) rescue nil
|
|
460
470
|
else
|
|
461
471
|
candidates = (bind.eval_methods | bind.eval_private_methods | bind.local_variables | bind.eval_instance_variables | bind.eval_class_constants).collect{|m| m.to_s}
|
|
462
|
-
candidates |=
|
|
472
|
+
candidates |= RubyLex::RESERVED_WORDS.map(&:to_s)
|
|
463
473
|
candidates.find{ |i| i == input }
|
|
464
474
|
end
|
|
465
475
|
else
|
|
466
476
|
candidates = (bind.eval_methods | bind.eval_private_methods | bind.local_variables | bind.eval_instance_variables | bind.eval_class_constants).collect{|m| m.to_s}
|
|
467
|
-
candidates |=
|
|
477
|
+
candidates |= RubyLex::RESERVED_WORDS.map(&:to_s)
|
|
478
|
+
|
|
479
|
+
target_encoding = Encoding.default_external
|
|
480
|
+
candidates = candidates.compact.filter_map do |candidate|
|
|
481
|
+
candidate.encoding == target_encoding ? candidate : candidate.encode(target_encoding)
|
|
482
|
+
rescue EncodingError
|
|
483
|
+
nil
|
|
484
|
+
end
|
|
468
485
|
candidates.grep(/^#{Regexp.quote(input)}/).sort
|
|
469
486
|
end
|
|
470
487
|
end
|
data/lib/irb/context.rb
CHANGED
|
@@ -155,11 +155,6 @@ module IRB
|
|
|
155
155
|
@command_aliases = IRB.conf[:COMMAND_ALIASES].dup
|
|
156
156
|
end
|
|
157
157
|
|
|
158
|
-
private def term_interactive?
|
|
159
|
-
return true if ENV['TEST_IRB_FORCE_INTERACTIVE']
|
|
160
|
-
STDIN.tty? && ENV['TERM'] != 'dumb'
|
|
161
|
-
end
|
|
162
|
-
|
|
163
158
|
def use_tracer=(val)
|
|
164
159
|
require_relative "ext/tracer" if val
|
|
165
160
|
IRB.conf[:USE_TRACER] = val
|
|
@@ -177,45 +172,6 @@ module IRB
|
|
|
177
172
|
__send__(__method__, val)
|
|
178
173
|
end
|
|
179
174
|
|
|
180
|
-
private def build_completor
|
|
181
|
-
completor_type = IRB.conf[:COMPLETOR]
|
|
182
|
-
|
|
183
|
-
# Gem repl_type_completor is added to bundled gems in Ruby 3.4.
|
|
184
|
-
# Use :type as default completor only in Ruby 3.4 or later.
|
|
185
|
-
verbose = !!completor_type
|
|
186
|
-
completor_type ||= RUBY_VERSION >= '3.4' ? :type : :regexp
|
|
187
|
-
|
|
188
|
-
case completor_type
|
|
189
|
-
when :regexp
|
|
190
|
-
return RegexpCompletor.new
|
|
191
|
-
when :type
|
|
192
|
-
completor = build_type_completor(verbose: verbose)
|
|
193
|
-
return completor if completor
|
|
194
|
-
else
|
|
195
|
-
warn "Invalid value for IRB.conf[:COMPLETOR]: #{completor_type}"
|
|
196
|
-
end
|
|
197
|
-
# Fallback to RegexpCompletor
|
|
198
|
-
RegexpCompletor.new
|
|
199
|
-
end
|
|
200
|
-
|
|
201
|
-
private def build_type_completor(verbose:)
|
|
202
|
-
if RUBY_ENGINE == 'truffleruby'
|
|
203
|
-
# Avoid SyntaxError. truffleruby does not support endless method definition yet.
|
|
204
|
-
warn 'TypeCompletor is not supported on TruffleRuby yet' if verbose
|
|
205
|
-
return
|
|
206
|
-
end
|
|
207
|
-
|
|
208
|
-
begin
|
|
209
|
-
require 'repl_type_completor'
|
|
210
|
-
rescue LoadError => e
|
|
211
|
-
warn "TypeCompletor requires `gem repl_type_completor`: #{e.message}" if verbose
|
|
212
|
-
return
|
|
213
|
-
end
|
|
214
|
-
|
|
215
|
-
ReplTypeCompletor.preload_rbs
|
|
216
|
-
TypeCompletor.new(self)
|
|
217
|
-
end
|
|
218
|
-
|
|
219
175
|
def save_history=(val)
|
|
220
176
|
IRB.conf[:SAVE_HISTORY] = val
|
|
221
177
|
end
|
|
@@ -308,6 +264,8 @@ module IRB
|
|
|
308
264
|
attr_reader :use_autocomplete
|
|
309
265
|
# A copy of the default <code>IRB.conf[:INSPECT_MODE]</code>
|
|
310
266
|
attr_reader :inspect_mode
|
|
267
|
+
# Inspector for the current context
|
|
268
|
+
attr_reader :inspect_method
|
|
311
269
|
|
|
312
270
|
# A copy of the default <code>IRB.conf[:PROMPT_MODE]</code>
|
|
313
271
|
attr_reader :prompt_mode
|
|
@@ -600,6 +558,8 @@ module IRB
|
|
|
600
558
|
set_last_value(result)
|
|
601
559
|
when Statement::Command
|
|
602
560
|
statement.command_class.execute(self, statement.arg)
|
|
561
|
+
when Statement::IncorrectAlias
|
|
562
|
+
warn statement.message
|
|
603
563
|
end
|
|
604
564
|
|
|
605
565
|
nil
|
|
@@ -633,37 +593,63 @@ module IRB
|
|
|
633
593
|
result
|
|
634
594
|
end
|
|
635
595
|
|
|
636
|
-
def
|
|
596
|
+
def parse_input(code, is_assignment_expression)
|
|
637
597
|
command_name, arg = code.strip.split(/\s+/, 2)
|
|
638
|
-
return unless code.lines.size == 1 && command_name
|
|
639
|
-
|
|
640
598
|
arg ||= ''
|
|
641
|
-
|
|
642
|
-
#
|
|
643
|
-
if
|
|
644
|
-
|
|
599
|
+
|
|
600
|
+
# command can only be 1 line
|
|
601
|
+
if code.lines.size != 1 ||
|
|
602
|
+
# command name is required
|
|
603
|
+
command_name.nil? ||
|
|
604
|
+
# local variable have precedence over command
|
|
605
|
+
local_variables.include?(command_name.to_sym) ||
|
|
606
|
+
# assignment expression is not a command
|
|
607
|
+
(is_assignment_expression ||
|
|
608
|
+
(arg.start_with?(ASSIGN_OPERATORS_REGEXP) && !arg.start_with?(/==|=~/)))
|
|
609
|
+
return Statement::Expression.new(code, is_assignment_expression)
|
|
645
610
|
end
|
|
646
611
|
|
|
647
|
-
|
|
648
|
-
return if arg.start_with?(ASSIGN_OPERATORS_REGEXP) && !arg.start_with?(/==|=~/)
|
|
612
|
+
command = command_name.to_sym
|
|
649
613
|
|
|
650
|
-
#
|
|
651
|
-
|
|
614
|
+
# Check command aliases
|
|
615
|
+
if aliased_name = command_aliases[command]
|
|
616
|
+
if command_class = Command.load_command(aliased_name)
|
|
617
|
+
command = aliased_name
|
|
618
|
+
elsif HelperMethod.helper_methods[aliased_name]
|
|
619
|
+
message = <<~MESSAGE
|
|
620
|
+
Using command alias `#{command}` for helper method `#{aliased_name}` is not supported.
|
|
621
|
+
Please check the value of `IRB.conf[:COMMAND_ALIASES]`.
|
|
622
|
+
MESSAGE
|
|
623
|
+
return Statement::IncorrectAlias.new(message)
|
|
624
|
+
else
|
|
625
|
+
message = <<~MESSAGE
|
|
626
|
+
You're trying to use command alias `#{command}` for command `#{aliased_name}`, but `#{aliased_name}` does not exist.
|
|
627
|
+
Please check the value of `IRB.conf[:COMMAND_ALIASES]`.
|
|
628
|
+
MESSAGE
|
|
629
|
+
return Statement::IncorrectAlias.new(message)
|
|
630
|
+
end
|
|
631
|
+
else
|
|
632
|
+
command_class = Command.load_command(command)
|
|
633
|
+
end
|
|
652
634
|
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
635
|
+
if command_class
|
|
636
|
+
# Check whether the command conflicts with existing methods
|
|
637
|
+
public_method = !!KERNEL_PUBLIC_METHOD.bind_call(main, command) rescue false
|
|
638
|
+
private_method = !public_method && !!KERNEL_METHOD.bind_call(main, command) rescue false
|
|
639
|
+
if Command.execute_as_command?(command, public_method: public_method, private_method: private_method)
|
|
640
|
+
return Statement::Command.new(code, command_class, arg)
|
|
641
|
+
end
|
|
658
642
|
end
|
|
643
|
+
Statement::Expression.new(code, is_assignment_expression)
|
|
659
644
|
end
|
|
660
645
|
|
|
661
646
|
def colorize_input(input, complete:)
|
|
662
647
|
if IRB.conf[:USE_COLORIZE] && IRB::Color.colorable?
|
|
663
648
|
lvars = local_variables || []
|
|
664
|
-
|
|
649
|
+
parsed_input = parse_input(input, false)
|
|
650
|
+
if parsed_input.is_a?(Statement::Command)
|
|
665
651
|
name, sep, arg = input.split(/(\s+)/, 2)
|
|
666
|
-
arg = IRB::Color.colorize_code(arg, complete: complete, local_variables: lvars)
|
|
652
|
+
arg = IRB::Color.colorize_code(arg, complete: complete, local_variables: lvars) if arg
|
|
667
653
|
"#{IRB::Color.colorize(name, [:BOLD])}\e[m#{sep}#{arg}"
|
|
668
654
|
else
|
|
669
655
|
IRB::Color.colorize_code(input, complete: complete, local_variables: lvars)
|
|
@@ -673,8 +659,12 @@ module IRB
|
|
|
673
659
|
end
|
|
674
660
|
end
|
|
675
661
|
|
|
676
|
-
def inspect_last_value # :nodoc:
|
|
677
|
-
@inspect_method.inspect_value(@last_value)
|
|
662
|
+
def inspect_last_value(output = +'') # :nodoc:
|
|
663
|
+
@inspect_method.inspect_value(@last_value, output)
|
|
664
|
+
end
|
|
665
|
+
|
|
666
|
+
def inspector_support_stream_output?
|
|
667
|
+
@inspect_method.support_stream_output?
|
|
678
668
|
end
|
|
679
669
|
|
|
680
670
|
NOPRINTING_IVARS = ["@last_value"] # :nodoc:
|
|
@@ -712,5 +702,51 @@ module IRB
|
|
|
712
702
|
main_object = main
|
|
713
703
|
Object === main_object ? main_object.__send__(method_name) : Object.instance_method(method_name).bind_call(main_object)
|
|
714
704
|
end
|
|
705
|
+
|
|
706
|
+
private
|
|
707
|
+
|
|
708
|
+
def term_interactive?
|
|
709
|
+
return true if ENV['TEST_IRB_FORCE_INTERACTIVE']
|
|
710
|
+
STDIN.tty? && ENV['TERM'] != 'dumb'
|
|
711
|
+
end
|
|
712
|
+
|
|
713
|
+
def build_completor
|
|
714
|
+
completor_type = IRB.conf[:COMPLETOR]
|
|
715
|
+
|
|
716
|
+
# Gem repl_type_completor is added to bundled gems in Ruby 3.4.
|
|
717
|
+
# Use :type as default completor only in Ruby 3.4 or later.
|
|
718
|
+
verbose = !!completor_type
|
|
719
|
+
completor_type ||= RUBY_VERSION >= '3.4' ? :type : :regexp
|
|
720
|
+
|
|
721
|
+
case completor_type
|
|
722
|
+
when :regexp
|
|
723
|
+
return RegexpCompletor.new
|
|
724
|
+
when :type
|
|
725
|
+
completor = build_type_completor(verbose: verbose)
|
|
726
|
+
return completor if completor
|
|
727
|
+
else
|
|
728
|
+
warn "Invalid value for IRB.conf[:COMPLETOR]: #{completor_type}"
|
|
729
|
+
end
|
|
730
|
+
# Fallback to RegexpCompletor
|
|
731
|
+
RegexpCompletor.new
|
|
732
|
+
end
|
|
733
|
+
|
|
734
|
+
def build_type_completor(verbose:)
|
|
735
|
+
if RUBY_ENGINE == 'truffleruby'
|
|
736
|
+
# Avoid SyntaxError. truffleruby does not support endless method definition yet.
|
|
737
|
+
warn 'TypeCompletor is not supported on TruffleRuby yet' if verbose
|
|
738
|
+
return
|
|
739
|
+
end
|
|
740
|
+
|
|
741
|
+
begin
|
|
742
|
+
require 'repl_type_completor'
|
|
743
|
+
rescue LoadError => e
|
|
744
|
+
warn "TypeCompletor requires `gem repl_type_completor`: #{e.message}" if verbose
|
|
745
|
+
return
|
|
746
|
+
end
|
|
747
|
+
|
|
748
|
+
ReplTypeCompletor.preload_rbs
|
|
749
|
+
TypeCompletor.new(self)
|
|
750
|
+
end
|
|
715
751
|
end
|
|
716
752
|
end
|
data/lib/irb/debug.rb
CHANGED
|
@@ -49,7 +49,7 @@ module IRB
|
|
|
49
49
|
def DEBUGGER__.capture_frames(*args)
|
|
50
50
|
frames = capture_frames_without_irb(*args)
|
|
51
51
|
frames.reject! do |frame|
|
|
52
|
-
frame.realpath&.start_with?(IRB_DIR) || frame.path
|
|
52
|
+
frame.realpath&.start_with?(IRB_DIR) || frame.path&.start_with?("<internal:")
|
|
53
53
|
end
|
|
54
54
|
frames
|
|
55
55
|
end
|
|
@@ -60,7 +60,7 @@ module IRB
|
|
|
60
60
|
if !DEBUGGER__::CONFIG[:no_hint] && irb.context.io.is_a?(RelineInputMethod)
|
|
61
61
|
Reline.output_modifier_proc = proc do |input, complete:|
|
|
62
62
|
unless input.strip.empty?
|
|
63
|
-
cmd = input
|
|
63
|
+
cmd = input[/\S+/]
|
|
64
64
|
|
|
65
65
|
if !complete && DEBUGGER__.commands.key?(cmd)
|
|
66
66
|
input = input.sub(/\n$/, " # debug command\n")
|
|
@@ -87,7 +87,7 @@ module IRB
|
|
|
87
87
|
module SkipPathHelperForIRB
|
|
88
88
|
def skip_internal_path?(path)
|
|
89
89
|
# The latter can be removed once https://github.com/ruby/debug/issues/866 is resolved
|
|
90
|
-
super || path
|
|
90
|
+
super || path&.match?(IRB_DIR) || path&.match?('<internal:prelude>')
|
|
91
91
|
end
|
|
92
92
|
end
|
|
93
93
|
|
data/lib/irb/default_commands.rb
CHANGED
|
@@ -9,6 +9,7 @@ require_relative "command/cd"
|
|
|
9
9
|
require_relative "command/chws"
|
|
10
10
|
require_relative "command/context"
|
|
11
11
|
require_relative "command/continue"
|
|
12
|
+
require_relative "command/copy"
|
|
12
13
|
require_relative "command/debug"
|
|
13
14
|
require_relative "command/delete"
|
|
14
15
|
require_relative "command/disable_irb"
|
|
@@ -218,7 +219,8 @@ module IRB
|
|
|
218
219
|
)
|
|
219
220
|
|
|
220
221
|
_register_with_aliases(:irb_show_doc, Command::ShowDoc,
|
|
221
|
-
[:show_doc, NO_OVERRIDE]
|
|
222
|
+
[:show_doc, NO_OVERRIDE],
|
|
223
|
+
[:ri, NO_OVERRIDE]
|
|
222
224
|
)
|
|
223
225
|
|
|
224
226
|
_register_with_aliases(:irb_info, Command::IrbInfo)
|
|
@@ -249,6 +251,7 @@ module IRB
|
|
|
249
251
|
)
|
|
250
252
|
|
|
251
253
|
register(:cd, Command::CD)
|
|
254
|
+
register(:copy, Command::Copy)
|
|
252
255
|
end
|
|
253
256
|
|
|
254
257
|
ExtendCommand = Command
|
data/lib/irb/easter-egg.rb
CHANGED
|
@@ -121,12 +121,13 @@ module IRB
|
|
|
121
121
|
interrupted = false
|
|
122
122
|
prev_trap = trap("SIGINT") { interrupted = true }
|
|
123
123
|
canvas = Canvas.new(Reline.get_screen_size)
|
|
124
|
+
otio = Reline::IOGate.prep
|
|
124
125
|
Reline::IOGate.set_winch_handler do
|
|
125
126
|
canvas = Canvas.new(Reline.get_screen_size)
|
|
126
127
|
end
|
|
127
128
|
ruby_model = RubyModel.new
|
|
128
129
|
print "\e[?25l" # hide cursor
|
|
129
|
-
0.
|
|
130
|
+
(0..).each do |i|
|
|
130
131
|
buff = canvas.draw do
|
|
131
132
|
ruby_model.render_frame(i) do |p1, p2|
|
|
132
133
|
canvas.line(p1, p2)
|
|
@@ -139,6 +140,7 @@ module IRB
|
|
|
139
140
|
end
|
|
140
141
|
rescue Interrupt
|
|
141
142
|
ensure
|
|
143
|
+
Reline::IOGate.deprep(otio)
|
|
142
144
|
print "\e[?25h" # show cursor
|
|
143
145
|
trap("SIGINT", prev_trap)
|
|
144
146
|
end
|
data/lib/irb/ext/multi-irb.rb
CHANGED
|
@@ -65,6 +65,7 @@ module IRB
|
|
|
65
65
|
@current_job = irb
|
|
66
66
|
th.run
|
|
67
67
|
Thread.stop
|
|
68
|
+
Thread.pass
|
|
68
69
|
@current_job = irb(Thread.current)
|
|
69
70
|
end
|
|
70
71
|
|
|
@@ -220,6 +221,7 @@ module IRB
|
|
|
220
221
|
end
|
|
221
222
|
end
|
|
222
223
|
Thread.stop
|
|
224
|
+
Thread.pass
|
|
223
225
|
@JobManager.current_job = @JobManager.irb(Thread.current)
|
|
224
226
|
end
|
|
225
227
|
|
data/lib/irb/history.rb
CHANGED
|
@@ -2,9 +2,13 @@ require "pathname"
|
|
|
2
2
|
|
|
3
3
|
module IRB
|
|
4
4
|
module History
|
|
5
|
+
DEFAULT_ENTRY_LIMIT = 1000
|
|
6
|
+
|
|
5
7
|
class << self
|
|
6
8
|
# Integer representation of <code>IRB.conf[:HISTORY_FILE]</code>.
|
|
7
9
|
def save_history
|
|
10
|
+
return 0 if IRB.conf[:SAVE_HISTORY] == false
|
|
11
|
+
return DEFAULT_ENTRY_LIMIT if IRB.conf[:SAVE_HISTORY] == true
|
|
8
12
|
IRB.conf[:SAVE_HISTORY].to_i
|
|
9
13
|
end
|
|
10
14
|
|
data/lib/irb/init.rb
CHANGED
|
@@ -87,13 +87,14 @@ module IRB # :nodoc:
|
|
|
87
87
|
@CONF[:IGNORE_SIGINT] = true
|
|
88
88
|
@CONF[:IGNORE_EOF] = false
|
|
89
89
|
@CONF[:USE_PAGER] = true
|
|
90
|
+
@CONF[:SHOW_BANNER] = true
|
|
90
91
|
@CONF[:EXTRA_DOC_DIRS] = []
|
|
91
92
|
@CONF[:ECHO] = nil
|
|
92
93
|
@CONF[:ECHO_ON_ASSIGNMENT] = nil
|
|
93
94
|
@CONF[:VERBOSE] = nil
|
|
94
95
|
|
|
95
96
|
@CONF[:EVAL_HISTORY] = nil
|
|
96
|
-
@CONF[:SAVE_HISTORY] =
|
|
97
|
+
@CONF[:SAVE_HISTORY] = History::DEFAULT_ENTRY_LIMIT
|
|
97
98
|
|
|
98
99
|
@CONF[:BACK_TRACE_LIMIT] = 16
|
|
99
100
|
|
|
@@ -194,6 +195,8 @@ module IRB # :nodoc:
|
|
|
194
195
|
:'$' => :show_source,
|
|
195
196
|
:'@' => :whereami,
|
|
196
197
|
}
|
|
198
|
+
|
|
199
|
+
@CONF[:COPY_COMMAND] = ENV.fetch("IRB_COPY_COMMAND", nil)
|
|
197
200
|
end
|
|
198
201
|
|
|
199
202
|
def IRB.set_measure_callback(type = nil, arg = nil, &block)
|
|
@@ -343,6 +346,8 @@ module IRB # :nodoc:
|
|
|
343
346
|
opt = $1 || argv.shift
|
|
344
347
|
prompt_mode = opt.upcase.tr("-", "_").intern
|
|
345
348
|
@CONF[:PROMPT_MODE] = prompt_mode
|
|
349
|
+
when "--nobanner"
|
|
350
|
+
@CONF[:SHOW_BANNER] = false
|
|
346
351
|
when "--noprompt"
|
|
347
352
|
@CONF[:PROMPT_MODE] = :NULL
|
|
348
353
|
when "--script"
|