irb 1.14.3 → 1.15.3
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 +4 -0
- 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 +275 -0
- data/doc/EXTEND_IRB.md +122 -0
- data/doc/Index.md +705 -0
- data/lib/irb/color.rb +1 -0
- data/lib/irb/color_printer.rb +10 -9
- data/lib/irb/command/copy.rb +73 -0
- data/lib/irb/command/history.rb +1 -1
- data/lib/irb/completion.rb +31 -36
- data/lib/irb/context.rb +95 -60
- data/lib/irb/debug.rb +2 -2
- data/lib/irb/default_commands.rb +4 -1
- data/lib/irb/easter-egg.rb +3 -1
- data/lib/irb/history.rb +4 -0
- data/lib/irb/init.rb +3 -1
- data/lib/irb/input-method.rb +17 -11
- data/lib/irb/inspector.rb +12 -7
- data/lib/irb/pager.rb +119 -6
- data/lib/irb/ruby-lex.rb +25 -0
- data/lib/irb/source_finder.rb +1 -1
- data/lib/irb/statement.rb +21 -0
- data/lib/irb/version.rb +2 -2
- data/lib/irb.rb +73 -910
- data/man/irb.1 +2 -0
- metadata +27 -12
- data/.document +0 -8
- data/Rakefile +0 -52
- data/bin/console +0 -6
- data/bin/setup +0 -6
- data/irb.gemspec +0 -46
data/lib/irb/color_printer.rb
CHANGED
|
@@ -4,12 +4,9 @@ require_relative 'color'
|
|
|
4
4
|
|
|
5
5
|
module IRB
|
|
6
6
|
class ColorPrinter < ::PP
|
|
7
|
-
METHOD_RESPOND_TO = Object.instance_method(:respond_to?)
|
|
8
|
-
METHOD_INSPECT = Object.instance_method(:inspect)
|
|
9
|
-
|
|
10
7
|
class << self
|
|
11
|
-
def pp(obj, out = $>, width = screen_width)
|
|
12
|
-
q = ColorPrinter.new(out, width)
|
|
8
|
+
def pp(obj, out = $>, width = screen_width, colorize: true)
|
|
9
|
+
q = ColorPrinter.new(out, width, colorize: colorize)
|
|
13
10
|
q.guard_inspect_key {q.pp obj}
|
|
14
11
|
q.flush
|
|
15
12
|
out << "\n"
|
|
@@ -24,12 +21,16 @@ module IRB
|
|
|
24
21
|
end
|
|
25
22
|
end
|
|
26
23
|
|
|
24
|
+
def initialize(out, width, colorize: true)
|
|
25
|
+
@colorize = colorize
|
|
26
|
+
|
|
27
|
+
super(out, width)
|
|
28
|
+
end
|
|
29
|
+
|
|
27
30
|
def pp(obj)
|
|
28
31
|
if String === obj
|
|
29
32
|
# Avoid calling Ruby 2.4+ String#pretty_print that splits a string by "\n"
|
|
30
33
|
text(obj.inspect)
|
|
31
|
-
elsif !METHOD_RESPOND_TO.bind(obj).call(:inspect)
|
|
32
|
-
text(METHOD_INSPECT.bind(obj).call)
|
|
33
34
|
else
|
|
34
35
|
super
|
|
35
36
|
end
|
|
@@ -46,9 +47,9 @@ module IRB
|
|
|
46
47
|
when ',', '=>', '[', ']', '{', '}', '..', '...', /\A@\w+\z/
|
|
47
48
|
super(str, width)
|
|
48
49
|
when /\A#</, '=', '>'
|
|
49
|
-
super(Color.colorize(str, [:GREEN]), width)
|
|
50
|
+
super(@colorize ? Color.colorize(str, [:GREEN]) : str, width)
|
|
50
51
|
else
|
|
51
|
-
super(Color.colorize_code(str, ignore_error: true), width)
|
|
52
|
+
super(@colorize ? Color.colorize_code(str, ignore_error: true) : str, width)
|
|
52
53
|
end
|
|
53
54
|
end
|
|
54
55
|
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module IRB
|
|
4
|
+
module Command
|
|
5
|
+
class Copy < Base
|
|
6
|
+
category "Misc"
|
|
7
|
+
description "Copy expression output to clipboard"
|
|
8
|
+
|
|
9
|
+
help_message(<<~HELP)
|
|
10
|
+
Usage: copy ([expression])
|
|
11
|
+
|
|
12
|
+
When given:
|
|
13
|
+
- an expression, copy the inspect result of the expression to the clipboard.
|
|
14
|
+
- no arguments, copy the last evaluated result (`_`) to the clipboard.
|
|
15
|
+
|
|
16
|
+
Examples:
|
|
17
|
+
|
|
18
|
+
copy Foo.new
|
|
19
|
+
copy User.all.to_a
|
|
20
|
+
copy
|
|
21
|
+
HELP
|
|
22
|
+
|
|
23
|
+
def execute(arg)
|
|
24
|
+
# Copy last value if no expression was supplied
|
|
25
|
+
arg = '_' if arg.to_s.strip.empty?
|
|
26
|
+
|
|
27
|
+
value = irb_context.workspace.binding.eval(arg)
|
|
28
|
+
output = irb_context.inspect_method.inspect_value(value, +'', colorize: false).chomp
|
|
29
|
+
|
|
30
|
+
if clipboard_available?
|
|
31
|
+
copy_to_clipboard(output)
|
|
32
|
+
else
|
|
33
|
+
warn "System clipboard not found"
|
|
34
|
+
end
|
|
35
|
+
rescue StandardError => e
|
|
36
|
+
warn "Error: #{e}"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def copy_to_clipboard(text)
|
|
42
|
+
IO.popen(clipboard_program, 'w') do |io|
|
|
43
|
+
io.write(text)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
raise IOError.new("Copying to clipboard failed") unless $? == 0
|
|
47
|
+
|
|
48
|
+
puts "Copied to system clipboard"
|
|
49
|
+
rescue Errno::ENOENT => e
|
|
50
|
+
warn e.message
|
|
51
|
+
warn "Is IRB.conf[:COPY_COMMAND] set to a bad value?"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def clipboard_program
|
|
55
|
+
@clipboard_program ||= if IRB.conf[:COPY_COMMAND]
|
|
56
|
+
IRB.conf[:COPY_COMMAND]
|
|
57
|
+
elsif executable?("pbcopy")
|
|
58
|
+
"pbcopy"
|
|
59
|
+
elsif executable?("xclip")
|
|
60
|
+
"xclip -selection clipboard"
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def executable?(command)
|
|
65
|
+
system("which #{command} > /dev/null 2>&1")
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def clipboard_available?
|
|
69
|
+
!!clipboard_program
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
data/lib/irb/command/history.rb
CHANGED
data/lib/irb/completion.rb
CHANGED
|
@@ -12,26 +12,6 @@ module IRB
|
|
|
12
12
|
|
|
13
13
|
# Set of reserved words used by Ruby, you should not use these for
|
|
14
14
|
# 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
15
|
|
|
36
16
|
HELP_COMMAND_PREPOSING = /\Ahelp\s+/
|
|
37
17
|
|
|
@@ -60,13 +40,13 @@ module IRB
|
|
|
60
40
|
|
|
61
41
|
def retrieve_gem_and_system_load_path
|
|
62
42
|
candidates = (GEM_PATHS | $LOAD_PATH)
|
|
63
|
-
candidates.
|
|
43
|
+
candidates.filter_map do |p|
|
|
64
44
|
if p.respond_to?(:to_path)
|
|
65
45
|
p.to_path
|
|
66
46
|
else
|
|
67
47
|
String(p) rescue nil
|
|
68
48
|
end
|
|
69
|
-
end.
|
|
49
|
+
end.sort
|
|
70
50
|
end
|
|
71
51
|
|
|
72
52
|
def retrieve_files_to_require_from_load_path
|
|
@@ -127,7 +107,14 @@ module IRB
|
|
|
127
107
|
|
|
128
108
|
return commands unless result
|
|
129
109
|
|
|
130
|
-
|
|
110
|
+
encoded_candidates = result.completion_candidates.filter_map do |i|
|
|
111
|
+
encoded = i.encode(Encoding.default_external)
|
|
112
|
+
target + encoded
|
|
113
|
+
rescue Encoding::UndefinedConversionError
|
|
114
|
+
# If the string cannot be converted, we just ignore it
|
|
115
|
+
nil
|
|
116
|
+
end
|
|
117
|
+
commands | encoded_candidates
|
|
131
118
|
end
|
|
132
119
|
|
|
133
120
|
def doc_namespace(preposing, matched, _postposing, bind:)
|
|
@@ -179,7 +166,7 @@ module IRB
|
|
|
179
166
|
else
|
|
180
167
|
return nil # It's not String literal
|
|
181
168
|
end
|
|
182
|
-
tokens = RubyLex.ripper_lex_without_warning(preposing.
|
|
169
|
+
tokens = RubyLex.ripper_lex_without_warning(preposing.rstrip)
|
|
183
170
|
tok = nil
|
|
184
171
|
tokens.reverse_each do |t|
|
|
185
172
|
unless [:on_lparen, :on_sp, :on_ignored_sp, :on_nl, :on_ignored_nl, :on_comment].include?(t.event)
|
|
@@ -191,16 +178,12 @@ module IRB
|
|
|
191
178
|
|
|
192
179
|
case tok.tok
|
|
193
180
|
when 'require'
|
|
194
|
-
retrieve_files_to_require_from_load_path.
|
|
195
|
-
path.start_with?(actual_target)
|
|
196
|
-
}.map { |path|
|
|
197
|
-
quote + path
|
|
181
|
+
retrieve_files_to_require_from_load_path.filter_map { |path|
|
|
182
|
+
quote + path if path.start_with?(actual_target)
|
|
198
183
|
}
|
|
199
184
|
when 'require_relative'
|
|
200
|
-
retrieve_files_to_require_relative_from_current_dir.
|
|
201
|
-
path.start_with?(actual_target)
|
|
202
|
-
}.map { |path|
|
|
203
|
-
quote + path
|
|
185
|
+
retrieve_files_to_require_relative_from_current_dir.filter_map { |path|
|
|
186
|
+
quote + path if path.start_with?(actual_target)
|
|
204
187
|
}
|
|
205
188
|
end
|
|
206
189
|
end
|
|
@@ -218,7 +201,12 @@ module IRB
|
|
|
218
201
|
# It doesn't make sense to propose commands with other preposing
|
|
219
202
|
commands = [] unless preposing.empty?
|
|
220
203
|
|
|
221
|
-
completion_data = retrieve_completion_data(target, bind: bind, doc_namespace: false).compact.
|
|
204
|
+
completion_data = retrieve_completion_data(target, bind: bind, doc_namespace: false).compact.filter_map do |i|
|
|
205
|
+
i.encode(Encoding.default_external)
|
|
206
|
+
rescue Encoding::UndefinedConversionError
|
|
207
|
+
# If the string cannot be converted, we just ignore it
|
|
208
|
+
nil
|
|
209
|
+
end
|
|
222
210
|
commands | completion_data
|
|
223
211
|
end
|
|
224
212
|
|
|
@@ -287,7 +275,7 @@ module IRB
|
|
|
287
275
|
nil
|
|
288
276
|
else
|
|
289
277
|
sym = $1
|
|
290
|
-
candidates = Symbol.all_symbols.
|
|
278
|
+
candidates = Symbol.all_symbols.filter_map do |s|
|
|
291
279
|
s.inspect
|
|
292
280
|
rescue EncodingError
|
|
293
281
|
# ignore
|
|
@@ -459,12 +447,19 @@ module IRB
|
|
|
459
447
|
eval("#{perfect_match_var}.class.name", bind) rescue nil
|
|
460
448
|
else
|
|
461
449
|
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 |=
|
|
450
|
+
candidates |= RubyLex::RESERVED_WORDS.map(&:to_s)
|
|
463
451
|
candidates.find{ |i| i == input }
|
|
464
452
|
end
|
|
465
453
|
else
|
|
466
454
|
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 |=
|
|
455
|
+
candidates |= RubyLex::RESERVED_WORDS.map(&:to_s)
|
|
456
|
+
|
|
457
|
+
target_encoding = Encoding.default_external
|
|
458
|
+
candidates = candidates.compact.filter_map do |candidate|
|
|
459
|
+
candidate.encoding == target_encoding ? candidate : candidate.encode(target_encoding)
|
|
460
|
+
rescue EncodingError
|
|
461
|
+
nil
|
|
462
|
+
end
|
|
468
463
|
candidates.grep(/^#{Regexp.quote(input)}/).sort
|
|
469
464
|
end
|
|
470
465
|
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,35 +593,60 @@ 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
635
|
# Check visibility
|
|
654
636
|
public_method = !!KERNEL_PUBLIC_METHOD.bind_call(main, command) rescue false
|
|
655
637
|
private_method = !public_method && !!KERNEL_METHOD.bind_call(main, command) rescue false
|
|
656
|
-
if Command.execute_as_command?(command, public_method: public_method, private_method: private_method)
|
|
657
|
-
|
|
638
|
+
if command_class && Command.execute_as_command?(command, public_method: public_method, private_method: private_method)
|
|
639
|
+
Statement::Command.new(code, command_class, arg)
|
|
640
|
+
else
|
|
641
|
+
Statement::Expression.new(code, is_assignment_expression)
|
|
658
642
|
end
|
|
659
643
|
end
|
|
660
644
|
|
|
661
645
|
def colorize_input(input, complete:)
|
|
662
646
|
if IRB.conf[:USE_COLORIZE] && IRB::Color.colorable?
|
|
663
647
|
lvars = local_variables || []
|
|
664
|
-
|
|
648
|
+
parsed_input = parse_input(input, false)
|
|
649
|
+
if parsed_input.is_a?(Statement::Command)
|
|
665
650
|
name, sep, arg = input.split(/(\s+)/, 2)
|
|
666
651
|
arg = IRB::Color.colorize_code(arg, complete: complete, local_variables: lvars)
|
|
667
652
|
"#{IRB::Color.colorize(name, [:BOLD])}\e[m#{sep}#{arg}"
|
|
@@ -673,8 +658,12 @@ module IRB
|
|
|
673
658
|
end
|
|
674
659
|
end
|
|
675
660
|
|
|
676
|
-
def inspect_last_value # :nodoc:
|
|
677
|
-
@inspect_method.inspect_value(@last_value)
|
|
661
|
+
def inspect_last_value(output = +'') # :nodoc:
|
|
662
|
+
@inspect_method.inspect_value(@last_value, output)
|
|
663
|
+
end
|
|
664
|
+
|
|
665
|
+
def inspector_support_stream_output?
|
|
666
|
+
@inspect_method.support_stream_output?
|
|
678
667
|
end
|
|
679
668
|
|
|
680
669
|
NOPRINTING_IVARS = ["@last_value"] # :nodoc:
|
|
@@ -712,5 +701,51 @@ module IRB
|
|
|
712
701
|
main_object = main
|
|
713
702
|
Object === main_object ? main_object.__send__(method_name) : Object.instance_method(method_name).bind_call(main_object)
|
|
714
703
|
end
|
|
704
|
+
|
|
705
|
+
private
|
|
706
|
+
|
|
707
|
+
def term_interactive?
|
|
708
|
+
return true if ENV['TEST_IRB_FORCE_INTERACTIVE']
|
|
709
|
+
STDIN.tty? && ENV['TERM'] != 'dumb'
|
|
710
|
+
end
|
|
711
|
+
|
|
712
|
+
def build_completor
|
|
713
|
+
completor_type = IRB.conf[:COMPLETOR]
|
|
714
|
+
|
|
715
|
+
# Gem repl_type_completor is added to bundled gems in Ruby 3.4.
|
|
716
|
+
# Use :type as default completor only in Ruby 3.4 or later.
|
|
717
|
+
verbose = !!completor_type
|
|
718
|
+
completor_type ||= RUBY_VERSION >= '3.4' ? :type : :regexp
|
|
719
|
+
|
|
720
|
+
case completor_type
|
|
721
|
+
when :regexp
|
|
722
|
+
return RegexpCompletor.new
|
|
723
|
+
when :type
|
|
724
|
+
completor = build_type_completor(verbose: verbose)
|
|
725
|
+
return completor if completor
|
|
726
|
+
else
|
|
727
|
+
warn "Invalid value for IRB.conf[:COMPLETOR]: #{completor_type}"
|
|
728
|
+
end
|
|
729
|
+
# Fallback to RegexpCompletor
|
|
730
|
+
RegexpCompletor.new
|
|
731
|
+
end
|
|
732
|
+
|
|
733
|
+
def build_type_completor(verbose:)
|
|
734
|
+
if RUBY_ENGINE == 'truffleruby'
|
|
735
|
+
# Avoid SyntaxError. truffleruby does not support endless method definition yet.
|
|
736
|
+
warn 'TypeCompletor is not supported on TruffleRuby yet' if verbose
|
|
737
|
+
return
|
|
738
|
+
end
|
|
739
|
+
|
|
740
|
+
begin
|
|
741
|
+
require 'repl_type_completor'
|
|
742
|
+
rescue LoadError => e
|
|
743
|
+
warn "TypeCompletor requires `gem repl_type_completor`: #{e.message}" if verbose
|
|
744
|
+
return
|
|
745
|
+
end
|
|
746
|
+
|
|
747
|
+
ReplTypeCompletor.preload_rbs
|
|
748
|
+
TypeCompletor.new(self)
|
|
749
|
+
end
|
|
715
750
|
end
|
|
716
751
|
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")
|
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/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
|
@@ -93,7 +93,7 @@ module IRB # :nodoc:
|
|
|
93
93
|
@CONF[:VERBOSE] = nil
|
|
94
94
|
|
|
95
95
|
@CONF[:EVAL_HISTORY] = nil
|
|
96
|
-
@CONF[:SAVE_HISTORY] =
|
|
96
|
+
@CONF[:SAVE_HISTORY] = History::DEFAULT_ENTRY_LIMIT
|
|
97
97
|
|
|
98
98
|
@CONF[:BACK_TRACE_LIMIT] = 16
|
|
99
99
|
|
|
@@ -194,6 +194,8 @@ module IRB # :nodoc:
|
|
|
194
194
|
:'$' => :show_source,
|
|
195
195
|
:'@' => :whereami,
|
|
196
196
|
}
|
|
197
|
+
|
|
198
|
+
@CONF[:COPY_COMMAND] = ENV.fetch("IRB_COPY_COMMAND", nil)
|
|
197
199
|
end
|
|
198
200
|
|
|
199
201
|
def IRB.set_measure_callback(type = nil, arg = nil, &block)
|
data/lib/irb/input-method.rb
CHANGED
|
@@ -26,10 +26,11 @@ module IRB
|
|
|
26
26
|
|
|
27
27
|
def winsize
|
|
28
28
|
if instance_variable_defined?(:@stdout) && @stdout.tty?
|
|
29
|
-
@stdout.winsize
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
winsize = @stdout.winsize
|
|
30
|
+
# If width or height is 0, something is wrong.
|
|
31
|
+
return winsize unless winsize.include? 0
|
|
32
32
|
end
|
|
33
|
+
[24, 80]
|
|
33
34
|
end
|
|
34
35
|
|
|
35
36
|
# Whether this input method is still readable when there is no more data to
|
|
@@ -175,10 +176,15 @@ module IRB
|
|
|
175
176
|
class ReadlineInputMethod < StdioInputMethod
|
|
176
177
|
class << self
|
|
177
178
|
def initialize_readline
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
179
|
+
return if defined?(self::Readline)
|
|
180
|
+
|
|
181
|
+
begin
|
|
182
|
+
require 'readline'
|
|
183
|
+
const_set(:Readline, ::Readline)
|
|
184
|
+
rescue LoadError
|
|
185
|
+
const_set(:Readline, ::Reline)
|
|
186
|
+
end
|
|
187
|
+
const_set(:HISTORY, self::Readline::HISTORY)
|
|
182
188
|
end
|
|
183
189
|
end
|
|
184
190
|
|
|
@@ -216,8 +222,8 @@ module IRB
|
|
|
216
222
|
def gets
|
|
217
223
|
Readline.input = @stdin
|
|
218
224
|
Readline.output = @stdout
|
|
219
|
-
if l = readline(@prompt, false)
|
|
220
|
-
HISTORY.push(l) if !l.empty?
|
|
225
|
+
if l = Readline.readline(@prompt, false)
|
|
226
|
+
Readline::HISTORY.push(l) if !l.empty? && l != Readline::HISTORY.to_a.last
|
|
221
227
|
@line[@line_no += 1] = l + "\n"
|
|
222
228
|
else
|
|
223
229
|
@eof = true
|
|
@@ -239,7 +245,7 @@ module IRB
|
|
|
239
245
|
|
|
240
246
|
# For debug message
|
|
241
247
|
def inspect
|
|
242
|
-
readline_impl =
|
|
248
|
+
readline_impl = Readline == ::Reline ? 'Reline' : 'ext/readline'
|
|
243
249
|
str = "ReadlineInputMethod with #{readline_impl} #{Readline::VERSION}"
|
|
244
250
|
inputrc_path = File.expand_path(ENV['INPUTRC'] || '~/.inputrc')
|
|
245
251
|
str += " and #{inputrc_path}" if File.exist?(inputrc_path)
|
|
@@ -474,7 +480,7 @@ module IRB
|
|
|
474
480
|
Reline.prompt_proc = @prompt_proc
|
|
475
481
|
Reline.auto_indent_proc = @auto_indent_proc if @auto_indent_proc
|
|
476
482
|
if l = Reline.readmultiline(@prompt, false, &@check_termination_proc)
|
|
477
|
-
Reline::HISTORY.push(l) if !l.empty?
|
|
483
|
+
Reline::HISTORY.push(l) if !l.empty? && l != Reline::HISTORY.to_a.last
|
|
478
484
|
@line[@line_no += 1] = l + "\n"
|
|
479
485
|
else
|
|
480
486
|
@eof = true
|
data/lib/irb/inspector.rb
CHANGED
|
@@ -46,7 +46,7 @@ module IRB # :nodoc:
|
|
|
46
46
|
# Determines the inspector to use where +inspector+ is one of the keys passed
|
|
47
47
|
# during inspector definition.
|
|
48
48
|
def keys_with_inspector(inspector)
|
|
49
|
-
INSPECTORS.
|
|
49
|
+
INSPECTORS.filter_map {|k, v| k if v == inspector}
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
# Example
|
|
@@ -92,9 +92,14 @@ module IRB # :nodoc:
|
|
|
92
92
|
@init.call if @init
|
|
93
93
|
end
|
|
94
94
|
|
|
95
|
+
def support_stream_output?
|
|
96
|
+
second_parameter_type = @inspect.parameters[1]&.first
|
|
97
|
+
second_parameter_type == :req || second_parameter_type == :opt
|
|
98
|
+
end
|
|
99
|
+
|
|
95
100
|
# Proc to call when the input is evaluated and output in irb.
|
|
96
|
-
def inspect_value(v)
|
|
97
|
-
@inspect.call(v)
|
|
101
|
+
def inspect_value(v, output, colorize: true)
|
|
102
|
+
support_stream_output? ? @inspect.call(v, output, colorize: colorize) : output << @inspect.call(v, colorize: colorize)
|
|
98
103
|
rescue => e
|
|
99
104
|
puts "An error occurred when inspecting the object: #{e.inspect}"
|
|
100
105
|
|
|
@@ -110,11 +115,11 @@ module IRB # :nodoc:
|
|
|
110
115
|
end
|
|
111
116
|
|
|
112
117
|
Inspector.def_inspector([false, :to_s, :raw]){|v| v.to_s}
|
|
113
|
-
Inspector.def_inspector([:p, :inspect]){|v|
|
|
114
|
-
Color.colorize_code(v.inspect, colorable: Color.colorable? && Color.inspect_colorable?(v))
|
|
118
|
+
Inspector.def_inspector([:p, :inspect]){|v, colorize: true|
|
|
119
|
+
Color.colorize_code(v.inspect, colorable: colorize && Color.colorable? && Color.inspect_colorable?(v))
|
|
115
120
|
}
|
|
116
|
-
Inspector.def_inspector([true, :pp, :pretty_inspect], proc{require_relative "color_printer"}){|v|
|
|
117
|
-
IRB::ColorPrinter.pp(v,
|
|
121
|
+
Inspector.def_inspector([true, :pp, :pretty_inspect], proc{require_relative "color_printer"}){|v, output, colorize: true|
|
|
122
|
+
IRB::ColorPrinter.pp(v, output, colorize: colorize)
|
|
118
123
|
}
|
|
119
124
|
Inspector.def_inspector([:yaml, :YAML], proc{require "yaml"}){|v|
|
|
120
125
|
begin
|