irb 1.2.6 → 1.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/irb.gemspec +2 -0
- data/lib/irb.rb +78 -43
- data/lib/irb/cmd/fork.rb +1 -1
- data/lib/irb/cmd/measure.rb +34 -0
- data/lib/irb/color.rb +15 -2
- data/lib/irb/color_printer.rb +28 -0
- data/lib/irb/completion.rb +12 -12
- data/lib/irb/context.rb +13 -22
- data/lib/irb/easter-egg.rb +2 -1
- data/lib/irb/extend-command.rb +13 -9
- data/lib/irb/init.rb +70 -8
- data/lib/irb/input-method.rb +9 -1
- data/lib/irb/inspector.rb +12 -14
- data/lib/irb/ruby-lex.rb +168 -70
- data/lib/irb/version.rb +2 -2
- data/lib/irb/workspace.rb +4 -2
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e147abaf69084b92f2f7accaf7d83014b6c0f7b3b6cbe0cc9b9878c52baee8af
|
4
|
+
data.tar.gz: 9a770f98f44f4bf498c91a3d8546d13a1db418daa034639646c0df0c3720d23e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f760ae68d08c7ae7f9f4ec07149935819f50df015a5f4a9453eca4a01574677ed5a29ae1c4eb8462b9cc92f5ad6b465b4e8b1c3f37748bd81ecde7159cf3a1c0
|
7
|
+
data.tar.gz: 3da91491f2e3928c8b619f120b6c6adcd020ed16760a4c176aee38bec5ca3964eb7cd0acc053a6a18dacec571b9a0b1e93d2a4c94a628a642b3b39bfd98b5284
|
data/irb.gemspec
CHANGED
@@ -33,10 +33,12 @@ Gem::Specification.new do |spec|
|
|
33
33
|
"lib/irb/cmd/fork.rb",
|
34
34
|
"lib/irb/cmd/help.rb",
|
35
35
|
"lib/irb/cmd/load.rb",
|
36
|
+
"lib/irb/cmd/measure.rb",
|
36
37
|
"lib/irb/cmd/nop.rb",
|
37
38
|
"lib/irb/cmd/pushws.rb",
|
38
39
|
"lib/irb/cmd/subirb.rb",
|
39
40
|
"lib/irb/color.rb",
|
41
|
+
"lib/irb/color_printer.rb",
|
40
42
|
"lib/irb/completion.rb",
|
41
43
|
"lib/irb/context.rb",
|
42
44
|
"lib/irb/easter-egg.rb",
|
data/lib/irb.rb
CHANGED
@@ -400,7 +400,7 @@ module IRB
|
|
400
400
|
irb.run(@CONF)
|
401
401
|
end
|
402
402
|
|
403
|
-
# Calls each event hook of <code>IRB.conf[:
|
403
|
+
# Calls each event hook of <code>IRB.conf[:AT_EXIT]</code> when the current session quits.
|
404
404
|
def IRB.irb_at_exit
|
405
405
|
@CONF[:AT_EXIT].each{|hook| hook.call}
|
406
406
|
end
|
@@ -538,11 +538,28 @@ module IRB
|
|
538
538
|
signal_status(:IN_EVAL) do
|
539
539
|
begin
|
540
540
|
line.untaint if RUBY_VERSION < '2.7'
|
541
|
-
|
541
|
+
if IRB.conf[:MEASURE] && IRB.conf[:MEASURE_CALLBACKS].empty?
|
542
|
+
IRB.set_measure_callback
|
543
|
+
end
|
544
|
+
if IRB.conf[:MEASURE] && !IRB.conf[:MEASURE_CALLBACKS].empty?
|
545
|
+
result = nil
|
546
|
+
last_proc = proc{ result = @context.evaluate(line, line_no, exception: exc) }
|
547
|
+
IRB.conf[:MEASURE_CALLBACKS].inject(last_proc) { |chain, item|
|
548
|
+
_name, callback, arg = item
|
549
|
+
proc {
|
550
|
+
callback.(@context, line, line_no, arg, exception: exc) do
|
551
|
+
chain.call
|
552
|
+
end
|
553
|
+
}
|
554
|
+
}.call
|
555
|
+
@context.set_last_value(result)
|
556
|
+
else
|
557
|
+
@context.evaluate(line, line_no, exception: exc)
|
558
|
+
end
|
542
559
|
if @context.echo?
|
543
560
|
if assignment_expression?(line)
|
544
561
|
if @context.echo_on_assignment?
|
545
|
-
output_value(@context.
|
562
|
+
output_value(@context.echo_on_assignment? == :truncate)
|
546
563
|
end
|
547
564
|
else
|
548
565
|
output_value
|
@@ -561,6 +578,29 @@ module IRB
|
|
561
578
|
end
|
562
579
|
end
|
563
580
|
|
581
|
+
def convert_invalid_byte_sequence(str)
|
582
|
+
str = str.force_encoding(Encoding::ASCII_8BIT)
|
583
|
+
conv = Encoding::Converter.new(Encoding::ASCII_8BIT, Encoding::UTF_8)
|
584
|
+
dst = String.new
|
585
|
+
begin
|
586
|
+
ret = conv.primitive_convert(str, dst)
|
587
|
+
case ret
|
588
|
+
when :invalid_byte_sequence
|
589
|
+
conv.insert_output(conf.primitive_errinfo[3].dump[1..-2])
|
590
|
+
redo
|
591
|
+
when :undefined_conversion
|
592
|
+
c = conv.primitive_errinfo[3].dup.force_encoding(conv.primitive_errinfo[1])
|
593
|
+
conv.insert_output(c.dump[1..-2])
|
594
|
+
redo
|
595
|
+
when :incomplete_input
|
596
|
+
conv.insert_output(conv.primitive_errinfo[3].dump[1..-2])
|
597
|
+
when :finished
|
598
|
+
end
|
599
|
+
break
|
600
|
+
end while nil
|
601
|
+
dst
|
602
|
+
end
|
603
|
+
|
564
604
|
def handle_exception(exc)
|
565
605
|
if exc.backtrace && exc.backtrace[0] =~ /\/irb(2)?(\/.*|-.*|\.rb)?:/ && exc.class.to_s !~ /^IRB/ &&
|
566
606
|
!(SyntaxError === exc) && !(EncodingError === exc)
|
@@ -570,49 +610,44 @@ module IRB
|
|
570
610
|
irb_bug = false
|
571
611
|
end
|
572
612
|
|
573
|
-
if STDOUT.tty?
|
574
|
-
attr = ATTR_TTY
|
575
|
-
print "#{attr[1]}Traceback#{attr[]} (most recent call last):\n"
|
576
|
-
else
|
577
|
-
attr = ATTR_PLAIN
|
578
|
-
end
|
579
|
-
messages = []
|
580
|
-
lasts = []
|
581
|
-
levels = 0
|
582
613
|
if exc.backtrace
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
614
|
+
order = nil
|
615
|
+
if '2.5.0' == RUBY_VERSION
|
616
|
+
# Exception#full_message doesn't have keyword arguments.
|
617
|
+
message = exc.full_message # the same of (highlight: true, order: bottom)
|
618
|
+
order = :bottom
|
619
|
+
elsif '2.5.1' <= RUBY_VERSION && RUBY_VERSION < '3.0.0'
|
620
|
+
if STDOUT.tty?
|
621
|
+
message = exc.full_message(order: :bottom)
|
622
|
+
order = :bottom
|
589
623
|
else
|
590
|
-
|
624
|
+
message = exc.full_message(order: :top)
|
625
|
+
order = :top
|
591
626
|
end
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
lasts.push(m).shift
|
596
|
-
levels += 1
|
597
|
-
end
|
598
|
-
end
|
599
|
-
end
|
600
|
-
if attr == ATTR_TTY
|
601
|
-
unless lasts.empty?
|
602
|
-
puts lasts.reverse
|
603
|
-
printf "... %d levels...\n", levels if levels > 0
|
604
|
-
end
|
605
|
-
puts messages.reverse
|
606
|
-
end
|
607
|
-
m = exc.to_s.split(/\n/)
|
608
|
-
print "#{attr[1]}#{exc.class} (#{attr[4]}#{m.shift}#{attr[0, 1]})#{attr[]}\n"
|
609
|
-
puts m.map {|s| "#{attr[1]}#{s}#{attr[]}\n"}
|
610
|
-
if attr == ATTR_PLAIN
|
611
|
-
puts messages
|
612
|
-
unless lasts.empty?
|
613
|
-
puts lasts
|
614
|
-
printf "... %d levels...\n", levels if levels > 0
|
627
|
+
else # '3.0.0' <= RUBY_VERSION
|
628
|
+
message = exc.full_message(order: :top)
|
629
|
+
order = :top
|
615
630
|
end
|
631
|
+
message = convert_invalid_byte_sequence(message)
|
632
|
+
message = message.gsub(/((?:^\t.+$\n)+)/) { |m|
|
633
|
+
case order
|
634
|
+
when :top
|
635
|
+
lines = m.split("\n")
|
636
|
+
when :bottom
|
637
|
+
lines = m.split("\n").reverse
|
638
|
+
end
|
639
|
+
unless irb_bug
|
640
|
+
lines = lines.map { |l| @context.workspace.filter_backtrace(l) }.compact
|
641
|
+
if lines.size > @context.back_trace_limit
|
642
|
+
omit = lines.size - @context.back_trace_limit
|
643
|
+
lines = lines[0..(@context.back_trace_limit - 1)]
|
644
|
+
lines << "\t... %d levels..." % omit
|
645
|
+
end
|
646
|
+
end
|
647
|
+
lines = lines.reverse if order == :bottom
|
648
|
+
lines.map{ |l| l + "\n" }.join
|
649
|
+
}
|
650
|
+
puts message
|
616
651
|
end
|
617
652
|
print "Maybe IRB bug!\n" if irb_bug
|
618
653
|
end
|
@@ -761,7 +796,7 @@ module IRB
|
|
761
796
|
str = "%s...\e[0m" % lines.first
|
762
797
|
multiline_p = false
|
763
798
|
else
|
764
|
-
str.gsub
|
799
|
+
str = str.gsub(/(\A.*?\n).*/m, "\\1...")
|
765
800
|
end
|
766
801
|
else
|
767
802
|
output_width = Reline::Unicode.calculate_width(@context.return_format % str, true)
|
data/lib/irb/cmd/fork.rb
CHANGED
@@ -16,7 +16,7 @@ module IRB
|
|
16
16
|
module ExtendCommand
|
17
17
|
class Fork < Nop
|
18
18
|
def execute
|
19
|
-
pid =
|
19
|
+
pid = __send__ ExtendCommand.irb_original_method_name("fork")
|
20
20
|
unless pid
|
21
21
|
class << self
|
22
22
|
alias_method :exit, ExtendCommand.irb_original_method_name('exit')
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require_relative "nop"
|
2
|
+
|
3
|
+
# :stopdoc:
|
4
|
+
module IRB
|
5
|
+
module ExtendCommand
|
6
|
+
class Measure < Nop
|
7
|
+
def initialize(*args)
|
8
|
+
super(*args)
|
9
|
+
end
|
10
|
+
|
11
|
+
def execute(type = nil, arg = nil)
|
12
|
+
case type
|
13
|
+
when :off
|
14
|
+
IRB.conf[:MEASURE] = nil
|
15
|
+
IRB.unset_measure_callback(arg)
|
16
|
+
when :list
|
17
|
+
IRB.conf[:MEASURE_CALLBACKS].each do |type_name, _, arg_val|
|
18
|
+
puts "- #{type_name}" + (arg_val ? "(#{arg_val.inspect})" : '')
|
19
|
+
end
|
20
|
+
when :on
|
21
|
+
IRB.conf[:MEASURE] = true
|
22
|
+
added = IRB.set_measure_callback(type, arg)
|
23
|
+
puts "#{added[0]} is added." if added
|
24
|
+
else
|
25
|
+
IRB.conf[:MEASURE] = true
|
26
|
+
added = IRB.set_measure_callback(type, arg)
|
27
|
+
puts "#{added[0]} is added." if added
|
28
|
+
end
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
# :startdoc:
|
data/lib/irb/color.rb
CHANGED
@@ -60,6 +60,10 @@ module IRB # :nodoc:
|
|
60
60
|
on_words_beg: [[RED, BOLD], ALL],
|
61
61
|
on_parse_error: [[RED, REVERSE], ALL],
|
62
62
|
compile_error: [[RED, REVERSE], ALL],
|
63
|
+
on_assign_error: [[RED, REVERSE], ALL],
|
64
|
+
on_alias_error: [[RED, REVERSE], ALL],
|
65
|
+
on_class_name_error:[[RED, REVERSE], ALL],
|
66
|
+
on_param_error: [[RED, REVERSE], ALL],
|
63
67
|
}
|
64
68
|
rescue NameError
|
65
69
|
# Give up highlighting Ripper-incompatible older Ruby
|
@@ -67,6 +71,9 @@ module IRB # :nodoc:
|
|
67
71
|
end
|
68
72
|
private_constant :TOKEN_SEQ_EXPRS
|
69
73
|
|
74
|
+
ERROR_TOKENS = TOKEN_SEQ_EXPRS.keys.select { |k| k.to_s.end_with?('error') }
|
75
|
+
private_constant :ERROR_TOKENS
|
76
|
+
|
70
77
|
class << self
|
71
78
|
def colorable?
|
72
79
|
$stdout.tty? && supported? && (/mswin|mingw/ =~ RUBY_PLATFORM || (ENV.key?('TERM') && ENV['TERM'] != 'dumb'))
|
@@ -107,7 +114,7 @@ module IRB # :nodoc:
|
|
107
114
|
# If `complete` is false (code is incomplete), this does not warn compile_error.
|
108
115
|
# This option is needed to avoid warning a user when the compile_error is happening
|
109
116
|
# because the input is not wrong but just incomplete.
|
110
|
-
def colorize_code(code, complete: true)
|
117
|
+
def colorize_code(code, complete: true, ignore_error: false)
|
111
118
|
return code unless colorable?
|
112
119
|
|
113
120
|
symbol_state = SymbolState.new
|
@@ -115,6 +122,11 @@ module IRB # :nodoc:
|
|
115
122
|
length = 0
|
116
123
|
|
117
124
|
scan(code, allow_last_error: !complete) do |token, str, expr|
|
125
|
+
# IRB::ColorPrinter skips colorizing fragments with any invalid token
|
126
|
+
if ignore_error && ERROR_TOKENS.include?(token)
|
127
|
+
return Reline::Unicode.escape_for_print(code)
|
128
|
+
end
|
129
|
+
|
118
130
|
in_symbol = symbol_state.scan_token(token)
|
119
131
|
str.each_line do |line|
|
120
132
|
line = Reline::Unicode.escape_for_print(line)
|
@@ -180,11 +192,12 @@ module IRB # :nodoc:
|
|
180
192
|
end
|
181
193
|
end
|
182
194
|
end
|
195
|
+
ensure
|
183
196
|
$VERBOSE = verbose
|
184
197
|
end
|
185
198
|
|
186
199
|
def dispatch_seq(token, expr, str, in_symbol:)
|
187
|
-
if token
|
200
|
+
if ERROR_TOKENS.include?(token)
|
188
201
|
TOKEN_SEQ_EXPRS[token][0]
|
189
202
|
elsif in_symbol
|
190
203
|
[YELLOW]
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'pp'
|
3
|
+
require 'irb/color'
|
4
|
+
|
5
|
+
module IRB
|
6
|
+
class ColorPrinter < ::PP
|
7
|
+
def self.pp(obj, out = $>, width = 79)
|
8
|
+
q = ColorPrinter.new(out, width)
|
9
|
+
q.guard_inspect_key {q.pp obj}
|
10
|
+
q.flush
|
11
|
+
out << "\n"
|
12
|
+
end
|
13
|
+
|
14
|
+
def text(str, width = nil)
|
15
|
+
unless str.is_a?(String)
|
16
|
+
str = str.inspect
|
17
|
+
end
|
18
|
+
width ||= str.length
|
19
|
+
|
20
|
+
case str
|
21
|
+
when /\A#</, '=', '>'
|
22
|
+
super(Color.colorize(str, [:GREEN]), width)
|
23
|
+
else
|
24
|
+
super(Color.colorize_code(str, ignore_error: true), width)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/irb/completion.rb
CHANGED
@@ -47,7 +47,7 @@ module IRB
|
|
47
47
|
when /^((["'`]).*\2)\.([^.]*)$/
|
48
48
|
# String
|
49
49
|
receiver = $1
|
50
|
-
message =
|
50
|
+
message = $3
|
51
51
|
|
52
52
|
candidates = String.instance_methods.collect{|m| m.to_s}
|
53
53
|
if doc_namespace
|
@@ -59,7 +59,7 @@ module IRB
|
|
59
59
|
when /^(\/[^\/]*\/)\.([^.]*)$/
|
60
60
|
# Regexp
|
61
61
|
receiver = $1
|
62
|
-
message =
|
62
|
+
message = $2
|
63
63
|
|
64
64
|
candidates = Regexp.instance_methods.collect{|m| m.to_s}
|
65
65
|
if doc_namespace
|
@@ -71,7 +71,7 @@ module IRB
|
|
71
71
|
when /^([^\]]*\])\.([^.]*)$/
|
72
72
|
# Array
|
73
73
|
receiver = $1
|
74
|
-
message =
|
74
|
+
message = $2
|
75
75
|
|
76
76
|
candidates = Array.instance_methods.collect{|m| m.to_s}
|
77
77
|
if doc_namespace
|
@@ -83,7 +83,7 @@ module IRB
|
|
83
83
|
when /^([^\}]*\})\.([^.]*)$/
|
84
84
|
# Proc or Hash
|
85
85
|
receiver = $1
|
86
|
-
message =
|
86
|
+
message = $2
|
87
87
|
|
88
88
|
proc_candidates = Proc.instance_methods.collect{|m| m.to_s}
|
89
89
|
hash_candidates = Hash.instance_methods.collect{|m| m.to_s}
|
@@ -117,7 +117,7 @@ module IRB
|
|
117
117
|
when /^([A-Z].*)::([^:.]*)$/
|
118
118
|
# Constant or class methods
|
119
119
|
receiver = $1
|
120
|
-
message =
|
120
|
+
message = $2
|
121
121
|
begin
|
122
122
|
candidates = eval("#{receiver}.constants.collect{|m| m.to_s}", bind)
|
123
123
|
candidates |= eval("#{receiver}.methods.collect{|m| m.to_s}", bind)
|
@@ -134,7 +134,7 @@ module IRB
|
|
134
134
|
# Symbol
|
135
135
|
receiver = $1
|
136
136
|
sep = $2
|
137
|
-
message =
|
137
|
+
message = $3
|
138
138
|
|
139
139
|
candidates = Symbol.instance_methods.collect{|m| m.to_s}
|
140
140
|
if doc_namespace
|
@@ -147,7 +147,7 @@ module IRB
|
|
147
147
|
# Numeric
|
148
148
|
receiver = $~[:num]
|
149
149
|
sep = $~[:sep]
|
150
|
-
message =
|
150
|
+
message = $~[:mes]
|
151
151
|
|
152
152
|
begin
|
153
153
|
instance = eval(receiver, bind)
|
@@ -169,7 +169,7 @@ module IRB
|
|
169
169
|
# Numeric(0xFFFF)
|
170
170
|
receiver = $1
|
171
171
|
sep = $2
|
172
|
-
message =
|
172
|
+
message = $3
|
173
173
|
|
174
174
|
begin
|
175
175
|
instance = eval(receiver, bind)
|
@@ -201,7 +201,7 @@ module IRB
|
|
201
201
|
# variable.func or func.func
|
202
202
|
receiver = $1
|
203
203
|
sep = $2
|
204
|
-
message =
|
204
|
+
message = $3
|
205
205
|
|
206
206
|
gv = eval("global_variables", bind).collect{|m| m.to_s}.push("true", "false", "nil")
|
207
207
|
lv = eval("local_variables", bind).collect{|m| m.to_s}
|
@@ -244,7 +244,7 @@ module IRB
|
|
244
244
|
# unknown(maybe String)
|
245
245
|
|
246
246
|
receiver = ""
|
247
|
-
message =
|
247
|
+
message = $1
|
248
248
|
|
249
249
|
candidates = String.instance_methods(true).collect{|m| m.to_s}
|
250
250
|
if doc_namespace
|
@@ -268,7 +268,7 @@ module IRB
|
|
268
268
|
PerfectMatchedProc = ->(matched, bind: IRB.conf[:MAIN_CONTEXT].workspace.binding) {
|
269
269
|
RDocRIDriver ||= RDoc::RI::Driver.new
|
270
270
|
if matched =~ /\A(?:::)?RubyVM/ and not ENV['RUBY_YES_I_AM_NOT_A_NORMAL_USER']
|
271
|
-
IRB.
|
271
|
+
IRB.__send__(:easter_egg)
|
272
272
|
return
|
273
273
|
end
|
274
274
|
namespace = retrieve_completion_data(matched, bind: bind, doc_namespace: true)
|
@@ -294,7 +294,7 @@ module IRB
|
|
294
294
|
Operators = %w[% & * ** + - / < << <= <=> == === =~ > >= >> [] []= ^ ! != !~]
|
295
295
|
|
296
296
|
def self.select_message(receiver, message, candidates, sep = ".")
|
297
|
-
candidates.grep(/^#{message}/).collect do |e|
|
297
|
+
candidates.grep(/^#{Regexp.quote(message)}/).collect do |e|
|
298
298
|
case e
|
299
299
|
when /^[a-zA-Z_]/
|
300
300
|
receiver + sep + e
|
data/lib/irb/context.rb
CHANGED
@@ -131,12 +131,7 @@ module IRB
|
|
131
131
|
|
132
132
|
@echo_on_assignment = IRB.conf[:ECHO_ON_ASSIGNMENT]
|
133
133
|
if @echo_on_assignment.nil?
|
134
|
-
@echo_on_assignment =
|
135
|
-
end
|
136
|
-
|
137
|
-
@omit_on_assignment = IRB.conf[:OMIT_ON_ASSIGNMENT]
|
138
|
-
if @omit_on_assignment.nil?
|
139
|
-
@omit_on_assignment = true
|
134
|
+
@echo_on_assignment = :truncate
|
140
135
|
end
|
141
136
|
|
142
137
|
@newline_before_multiline_output = IRB.conf[:NEWLINE_BEFORE_MULTILINE_OUTPUT]
|
@@ -256,27 +251,24 @@ module IRB
|
|
256
251
|
attr_accessor :echo
|
257
252
|
# Whether to echo for assignment expressions
|
258
253
|
#
|
259
|
-
#
|
254
|
+
# If set to +false+, the value of assignment will not be shown.
|
255
|
+
#
|
256
|
+
# If set to +true+, the value of assignment will be shown.
|
257
|
+
#
|
258
|
+
# If set to +:truncate+, the value of assignment will be shown and truncated.
|
259
|
+
#
|
260
|
+
# It defaults to +:truncate+.
|
260
261
|
#
|
261
262
|
# a = "omg"
|
262
263
|
# #=> omg
|
264
|
+
# a = "omg" * 10
|
265
|
+
# #=> omgomgomgomgomgomgomg...
|
263
266
|
# IRB.CurrentContext.echo_on_assignment = false
|
264
267
|
# a = "omg"
|
268
|
+
# IRB.CurrentContext.echo_on_assignment = true
|
269
|
+
# a = "omg"
|
270
|
+
# #=> omgomgomgomgomgomgomgomgomgomg
|
265
271
|
attr_accessor :echo_on_assignment
|
266
|
-
# Whether to omit echo for assignment expressions
|
267
|
-
#
|
268
|
-
# Uses <code>IRB.conf[:OMIT_ON_ASSIGNMENT]</code> if available, or defaults to +true+.
|
269
|
-
#
|
270
|
-
# a = [1] * 10
|
271
|
-
# #=> [1, 1, 1, 1, 1, 1, 1, 1, ...
|
272
|
-
# [1] * 10
|
273
|
-
# #=> [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
274
|
-
# IRB.CurrentContext.omit_on_assignment = false
|
275
|
-
# a = [1] * 10
|
276
|
-
# #=> [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
277
|
-
# [1] * 10
|
278
|
-
# #=> [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
279
|
-
attr_accessor :omit_on_assignment
|
280
272
|
# Whether a newline is put before multiline output.
|
281
273
|
#
|
282
274
|
# Uses <code>IRB.conf[:NEWLINE_BEFORE_MULTILINE_OUTPUT]</code> if available,
|
@@ -325,7 +317,6 @@ module IRB
|
|
325
317
|
alias ignore_eof? ignore_eof
|
326
318
|
alias echo? echo
|
327
319
|
alias echo_on_assignment? echo_on_assignment
|
328
|
-
alias omit_on_assignment? omit_on_assignment
|
329
320
|
alias newline_before_multiline_output? newline_before_multiline_output
|
330
321
|
|
331
322
|
# Returns whether messages are displayed or not.
|
data/lib/irb/easter-egg.rb
CHANGED
@@ -126,6 +126,7 @@ module IRB
|
|
126
126
|
print "\e[H" + buff
|
127
127
|
sleep 0.05
|
128
128
|
end
|
129
|
+
rescue Interrupt
|
129
130
|
ensure
|
130
131
|
print "\e[0m\e[?1049l"
|
131
132
|
end
|
@@ -134,4 +135,4 @@ module IRB
|
|
134
135
|
end
|
135
136
|
end
|
136
137
|
|
137
|
-
IRB.
|
138
|
+
IRB.__send__(:easter_egg, ARGV[0]&.to_sym) if $0 == __FILE__
|
data/lib/irb/extend-command.rb
CHANGED
@@ -125,6 +125,10 @@ module IRB # :nodoc:
|
|
125
125
|
:irb_info, :Info, "irb/cmd/info"
|
126
126
|
],
|
127
127
|
|
128
|
+
[
|
129
|
+
:measure, :Measure, "irb/cmd/measure"
|
130
|
+
],
|
131
|
+
|
128
132
|
]
|
129
133
|
|
130
134
|
# Installs the default irb commands:
|
@@ -173,14 +177,14 @@ module IRB # :nodoc:
|
|
173
177
|
args << "&block"
|
174
178
|
args = args.join(", ")
|
175
179
|
line = __LINE__; eval %[
|
176
|
-
unless
|
177
|
-
|
178
|
-
def
|
180
|
+
unless singleton_class.class_variable_defined?(:@@#{cmd_name}_)
|
181
|
+
singleton_class.class_variable_set(:@@#{cmd_name}_, true)
|
182
|
+
def self.#{cmd_name}_(\#{args})
|
179
183
|
ExtendCommand::#{cmd_class}.execute(irb_context, \#{args})
|
180
184
|
end
|
181
185
|
end
|
182
186
|
], nil, __FILE__, line
|
183
|
-
|
187
|
+
__send__ :#{cmd_name}_, *opts, &b
|
184
188
|
end
|
185
189
|
], nil, __FILE__, line
|
186
190
|
else
|
@@ -268,7 +272,7 @@ module IRB # :nodoc:
|
|
268
272
|
def #{cmd_name}(*opts, &b)
|
269
273
|
Context.module_eval {remove_method(:#{cmd_name})}
|
270
274
|
require "#{load_file}"
|
271
|
-
|
275
|
+
__send__ :#{cmd_name}, *opts, &b
|
272
276
|
end
|
273
277
|
for ali in aliases
|
274
278
|
alias_method ali, cmd_name
|
@@ -291,8 +295,8 @@ module IRB # :nodoc:
|
|
291
295
|
module_eval %[
|
292
296
|
alias_method alias_name, base_method
|
293
297
|
def #{base_method}(*opts)
|
294
|
-
|
295
|
-
|
298
|
+
__send__ :#{extend_method}, *opts
|
299
|
+
__send__ :#{alias_name}, *opts
|
296
300
|
end
|
297
301
|
]
|
298
302
|
end
|
@@ -307,8 +311,8 @@ module IRB # :nodoc:
|
|
307
311
|
module_eval %[
|
308
312
|
alias_method alias_name, base_method
|
309
313
|
def #{base_method}(*opts)
|
310
|
-
|
311
|
-
|
314
|
+
__send__ :#{alias_name}, *opts
|
315
|
+
__send__ :#{extend_method}, *opts
|
312
316
|
end
|
313
317
|
]
|
314
318
|
end
|
data/lib/irb/init.rb
CHANGED
@@ -52,7 +52,6 @@ module IRB # :nodoc:
|
|
52
52
|
@CONF[:IGNORE_EOF] = false
|
53
53
|
@CONF[:ECHO] = nil
|
54
54
|
@CONF[:ECHO_ON_ASSIGNMENT] = nil
|
55
|
-
@CONF[:OMIT_ON_ASSIGNMENT] = nil
|
56
55
|
@CONF[:VERBOSE] = nil
|
57
56
|
|
58
57
|
@CONF[:EVAL_HISTORY] = nil
|
@@ -109,14 +108,79 @@ module IRB # :nodoc:
|
|
109
108
|
@CONF[:PROMPT_MODE] = (STDIN.tty? ? :DEFAULT : :NULL)
|
110
109
|
@CONF[:AUTO_INDENT] = true
|
111
110
|
|
112
|
-
@CONF[:CONTEXT_MODE] =
|
111
|
+
@CONF[:CONTEXT_MODE] = 4 # use a copy of TOPLEVEL_BINDING
|
113
112
|
@CONF[:SINGLE_IRB] = false
|
114
113
|
|
114
|
+
@CONF[:MEASURE] = false
|
115
|
+
@CONF[:MEASURE_PROC] = {}
|
116
|
+
@CONF[:MEASURE_PROC][:TIME] = proc { |context, code, line_no, &block|
|
117
|
+
time = Time.now
|
118
|
+
result = block.()
|
119
|
+
now = Time.now
|
120
|
+
puts 'processing time: %fs' % (now - time) if IRB.conf[:MEASURE]
|
121
|
+
result
|
122
|
+
}
|
123
|
+
@CONF[:MEASURE_PROC][:STACKPROF] = proc { |context, code, line_no, arg, &block|
|
124
|
+
success = false
|
125
|
+
begin
|
126
|
+
require 'stackprof'
|
127
|
+
success = true
|
128
|
+
rescue LoadError
|
129
|
+
puts 'Please run "gem install stackprof" before measuring by StackProf.'
|
130
|
+
end
|
131
|
+
if success
|
132
|
+
result = nil
|
133
|
+
stackprof_result = StackProf.run(mode: arg ? arg : :cpu) do
|
134
|
+
result = block.()
|
135
|
+
end
|
136
|
+
StackProf::Report.new(stackprof_result).print_text if IRB.conf[:MEASURE]
|
137
|
+
result
|
138
|
+
else
|
139
|
+
block.()
|
140
|
+
end
|
141
|
+
}
|
142
|
+
@CONF[:MEASURE_CALLBACKS] = []
|
143
|
+
|
115
144
|
@CONF[:LC_MESSAGES] = Locale.new
|
116
145
|
|
117
146
|
@CONF[:AT_EXIT] = []
|
118
147
|
end
|
119
148
|
|
149
|
+
def IRB.set_measure_callback(type = nil, arg = nil)
|
150
|
+
added = nil
|
151
|
+
if type
|
152
|
+
type_sym = type.upcase.to_sym
|
153
|
+
if IRB.conf[:MEASURE_PROC][type_sym]
|
154
|
+
added = [type_sym, IRB.conf[:MEASURE_PROC][type_sym], arg]
|
155
|
+
end
|
156
|
+
elsif IRB.conf[:MEASURE_PROC][:CUSTOM]
|
157
|
+
added = [:CUSTOM, IRB.conf[:MEASURE_PROC][:CUSTOM], arg]
|
158
|
+
else
|
159
|
+
added = [:TIME, IRB.conf[:MEASURE_PROC][:TIME], arg]
|
160
|
+
end
|
161
|
+
if added
|
162
|
+
found = IRB.conf[:MEASURE_CALLBACKS].find{ |m| m[0] == added[0] && m[2] == added[2] }
|
163
|
+
if found
|
164
|
+
# already added
|
165
|
+
nil
|
166
|
+
else
|
167
|
+
IRB.conf[:MEASURE_CALLBACKS] << added if added
|
168
|
+
added
|
169
|
+
end
|
170
|
+
else
|
171
|
+
nil
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def IRB.unset_measure_callback(type = nil)
|
176
|
+
if type.nil?
|
177
|
+
IRB.conf[:MEASURE_CALLBACKS].clear
|
178
|
+
else
|
179
|
+
type_sym = type.upcase.to_sym
|
180
|
+
IRB.conf[:MEASURE_CALLBACKS].reject!{ |t, | t == type_sym }
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
120
184
|
def IRB.init_error
|
121
185
|
@CONF[:LC_MESSAGES].load("irb/error.rb")
|
122
186
|
end
|
@@ -132,7 +196,7 @@ module IRB # :nodoc:
|
|
132
196
|
$DEBUG = true
|
133
197
|
$VERBOSE = true
|
134
198
|
when "-w"
|
135
|
-
$VERBOSE = true
|
199
|
+
Warning[:deprecated] = $VERBOSE = true
|
136
200
|
when /^-W(.+)?/
|
137
201
|
opt = $1 || argv.shift
|
138
202
|
case opt
|
@@ -141,7 +205,7 @@ module IRB # :nodoc:
|
|
141
205
|
when "1"
|
142
206
|
$VERBOSE = false
|
143
207
|
else
|
144
|
-
$VERBOSE = true
|
208
|
+
Warning[:deprecated] = $VERBOSE = true
|
145
209
|
end
|
146
210
|
when /^-r(.+)?/
|
147
211
|
opt = $1 || argv.shift
|
@@ -178,10 +242,8 @@ module IRB # :nodoc:
|
|
178
242
|
@CONF[:ECHO_ON_ASSIGNMENT] = true
|
179
243
|
when "--noecho-on-assignment"
|
180
244
|
@CONF[:ECHO_ON_ASSIGNMENT] = false
|
181
|
-
when "--
|
182
|
-
@CONF[:
|
183
|
-
when "--noomit-on-assignment"
|
184
|
-
@CONF[:OMIT_ON_ASSIGNMENT] = false
|
245
|
+
when "--truncate-echo-on-assignment"
|
246
|
+
@CONF[:ECHO_ON_ASSIGNMENT] = :truncate
|
185
247
|
when "--verbose"
|
186
248
|
@CONF[:VERBOSE] = true
|
187
249
|
when "--noverbose"
|
data/lib/irb/input-method.rb
CHANGED
@@ -83,7 +83,15 @@ module IRB
|
|
83
83
|
#
|
84
84
|
# See IO#eof? for more information.
|
85
85
|
def eof?
|
86
|
-
@stdin.
|
86
|
+
rs, = IO.select([@stdin], [], [], 0.00001)
|
87
|
+
if rs and rs[0]
|
88
|
+
c = @stdin.getc
|
89
|
+
result = c.nil? ? true : false
|
90
|
+
@stdin.ungetc(c) unless c.nil?
|
91
|
+
result
|
92
|
+
else # buffer is empty
|
93
|
+
false
|
94
|
+
end
|
87
95
|
end
|
88
96
|
|
89
97
|
# Whether this input method is still readable when there is no more data to
|
data/lib/irb/inspector.rb
CHANGED
@@ -100,29 +100,27 @@ module IRB # :nodoc:
|
|
100
100
|
# Proc to call when the input is evaluated and output in irb.
|
101
101
|
def inspect_value(v)
|
102
102
|
@inspect.call(v)
|
103
|
+
rescue
|
104
|
+
puts "(Object doesn't support #inspect)"
|
105
|
+
''
|
103
106
|
end
|
104
107
|
end
|
105
108
|
|
106
109
|
Inspector.def_inspector([false, :to_s, :raw]){|v| v.to_s}
|
107
|
-
Inspector.def_inspector([
|
108
|
-
|
109
|
-
result = v.inspect
|
110
|
-
if IRB.conf[:MAIN_CONTEXT]&.use_colorize? && Color.inspect_colorable?(v)
|
111
|
-
result = Color.colorize_code(result)
|
112
|
-
end
|
113
|
-
result
|
114
|
-
rescue NoMethodError
|
115
|
-
puts "(Object doesn't support #inspect)"
|
116
|
-
''
|
117
|
-
end
|
118
|
-
}
|
119
|
-
Inspector.def_inspector([:pp, :pretty_inspect], proc{require "pp"}){|v|
|
120
|
-
result = v.pretty_inspect.chomp
|
110
|
+
Inspector.def_inspector([:p, :inspect]){|v|
|
111
|
+
result = v.inspect
|
121
112
|
if IRB.conf[:MAIN_CONTEXT]&.use_colorize? && Color.inspect_colorable?(v)
|
122
113
|
result = Color.colorize_code(result)
|
123
114
|
end
|
124
115
|
result
|
125
116
|
}
|
117
|
+
Inspector.def_inspector([true, :pp, :pretty_inspect], proc{require "irb/color_printer"}){|v|
|
118
|
+
if IRB.conf[:MAIN_CONTEXT]&.use_colorize?
|
119
|
+
IRB::ColorPrinter.pp(v, '').chomp
|
120
|
+
else
|
121
|
+
v.pretty_inspect.chomp
|
122
|
+
end
|
123
|
+
}
|
126
124
|
Inspector.def_inspector([:yaml, :YAML], proc{require "yaml"}){|v|
|
127
125
|
begin
|
128
126
|
YAML.dump(v)
|
data/lib/irb/ruby-lex.rb
CHANGED
@@ -60,11 +60,31 @@ class RubyLex
|
|
60
60
|
@io.dynamic_prompt do |lines|
|
61
61
|
lines << '' if lines.empty?
|
62
62
|
result = []
|
63
|
-
lines.
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
63
|
+
tokens = ripper_lex_without_warning(lines.map{ |l| l + "\n" }.join)
|
64
|
+
code = String.new
|
65
|
+
partial_tokens = []
|
66
|
+
unprocessed_tokens = []
|
67
|
+
line_num_offset = 0
|
68
|
+
tokens.each do |t|
|
69
|
+
partial_tokens << t
|
70
|
+
unprocessed_tokens << t
|
71
|
+
if t[2].include?("\n")
|
72
|
+
t_str = t[2]
|
73
|
+
t_str.each_line("\n") do |s|
|
74
|
+
code << s << "\n"
|
75
|
+
ltype, indent, continue, code_block_open = check_state(code, partial_tokens)
|
76
|
+
result << @prompt.call(ltype, indent, continue || code_block_open, @line_no + line_num_offset)
|
77
|
+
line_num_offset += 1
|
78
|
+
end
|
79
|
+
unprocessed_tokens = []
|
80
|
+
else
|
81
|
+
code << t[2]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
unless unprocessed_tokens.empty?
|
85
|
+
ltype, indent, continue, code_block_open = check_state(code, unprocessed_tokens)
|
86
|
+
result << @prompt.call(ltype, indent, continue || code_block_open, @line_no + line_num_offset)
|
87
|
+
end
|
68
88
|
result
|
69
89
|
end
|
70
90
|
end
|
@@ -86,24 +106,72 @@ class RubyLex
|
|
86
106
|
end
|
87
107
|
end
|
88
108
|
|
109
|
+
ERROR_TOKENS = [
|
110
|
+
:on_parse_error,
|
111
|
+
:compile_error,
|
112
|
+
:on_assign_error,
|
113
|
+
:on_alias_error,
|
114
|
+
:on_class_name_error,
|
115
|
+
:on_param_error
|
116
|
+
]
|
117
|
+
|
89
118
|
def ripper_lex_without_warning(code)
|
90
119
|
verbose, $VERBOSE = $VERBOSE, nil
|
91
120
|
tokens = nil
|
92
121
|
self.class.compile_with_errors_suppressed(code) do |inner_code, line_no|
|
93
|
-
|
122
|
+
lexer = Ripper::Lexer.new(inner_code, '-', line_no)
|
123
|
+
if lexer.respond_to?(:scan) # Ruby 2.7+
|
124
|
+
tokens = []
|
125
|
+
pos_to_index = {}
|
126
|
+
lexer.scan.each do |t|
|
127
|
+
if pos_to_index.has_key?(t[0])
|
128
|
+
index = pos_to_index[t[0]]
|
129
|
+
found_tk = tokens[index]
|
130
|
+
if ERROR_TOKENS.include?(found_tk[1]) && !ERROR_TOKENS.include?(t[1])
|
131
|
+
tokens[index] = t
|
132
|
+
end
|
133
|
+
else
|
134
|
+
pos_to_index[t[0]] = tokens.size
|
135
|
+
tokens << t
|
136
|
+
end
|
137
|
+
end
|
138
|
+
else
|
139
|
+
tokens = lexer.parse
|
140
|
+
end
|
94
141
|
end
|
95
|
-
$VERBOSE = verbose
|
96
142
|
tokens
|
143
|
+
ensure
|
144
|
+
$VERBOSE = verbose
|
145
|
+
end
|
146
|
+
|
147
|
+
def find_prev_spaces(line_index)
|
148
|
+
return 0 if @tokens.size == 0
|
149
|
+
md = @tokens[0][2].match(/(\A +)/)
|
150
|
+
prev_spaces = md.nil? ? 0 : md[1].count(' ')
|
151
|
+
line_count = 0
|
152
|
+
@tokens.each_with_index do |t, i|
|
153
|
+
if t[2].include?("\n")
|
154
|
+
line_count += t[2].count("\n")
|
155
|
+
if line_count >= line_index
|
156
|
+
return prev_spaces
|
157
|
+
end
|
158
|
+
if (@tokens.size - 1) > i
|
159
|
+
md = @tokens[i + 1][2].match(/(\A +)/)
|
160
|
+
prev_spaces = md.nil? ? 0 : md[1].count(' ')
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
prev_spaces
|
97
165
|
end
|
98
166
|
|
99
167
|
def set_auto_indent(context)
|
100
168
|
if @io.respond_to?(:auto_indent) and context.auto_indent_mode
|
101
169
|
@io.auto_indent do |lines, line_index, byte_pointer, is_newline|
|
102
170
|
if is_newline
|
103
|
-
md = lines[line_index - 1].match(/(\A +)/)
|
104
|
-
prev_spaces = md.nil? ? 0 : md[1].count(' ')
|
105
171
|
@tokens = ripper_lex_without_warning(lines[0..line_index].join("\n"))
|
172
|
+
prev_spaces = find_prev_spaces(line_index)
|
106
173
|
depth_difference = check_newline_depth_difference
|
174
|
+
depth_difference = 0 if depth_difference < 0
|
107
175
|
prev_spaces + depth_difference * 2
|
108
176
|
else
|
109
177
|
code = line_index.zero? ? '' : lines[0..(line_index - 1)].map{ |l| l + "\n" }.join
|
@@ -121,12 +189,12 @@ class RubyLex
|
|
121
189
|
end
|
122
190
|
end
|
123
191
|
|
124
|
-
def check_state(code)
|
125
|
-
|
126
|
-
ltype = process_literal_type
|
127
|
-
indent = process_nesting_level
|
128
|
-
continue = process_continue
|
129
|
-
code_block_open = check_code_block(code)
|
192
|
+
def check_state(code, tokens = nil)
|
193
|
+
tokens = ripper_lex_without_warning(code) unless tokens
|
194
|
+
ltype = process_literal_type(tokens)
|
195
|
+
indent = process_nesting_level(tokens)
|
196
|
+
continue = process_continue(tokens)
|
197
|
+
code_block_open = check_code_block(code, tokens)
|
130
198
|
[ltype, indent, continue, code_block_open]
|
131
199
|
end
|
132
200
|
|
@@ -193,40 +261,45 @@ class RubyLex
|
|
193
261
|
line
|
194
262
|
end
|
195
263
|
|
196
|
-
def process_continue
|
264
|
+
def process_continue(tokens = @tokens)
|
197
265
|
# last token is always newline
|
198
|
-
if
|
266
|
+
if tokens.size >= 2 and tokens[-2][1] == :on_regexp_end
|
199
267
|
# end of regexp literal
|
200
268
|
return false
|
201
|
-
elsif
|
269
|
+
elsif tokens.size >= 2 and tokens[-2][1] == :on_semicolon
|
202
270
|
return false
|
203
|
-
elsif
|
271
|
+
elsif tokens.size >= 2 and tokens[-2][1] == :on_kw and ['begin', 'else', 'ensure'].include?(tokens[-2][2])
|
204
272
|
return false
|
205
|
-
elsif
|
273
|
+
elsif !tokens.empty? and tokens.last[2] == "\\\n"
|
206
274
|
return true
|
207
|
-
elsif
|
275
|
+
elsif tokens.size >= 1 and tokens[-1][1] == :on_heredoc_end # "EOH\n"
|
208
276
|
return false
|
209
|
-
elsif
|
277
|
+
elsif tokens.size >= 2 and defined?(Ripper::EXPR_BEG) and tokens[-2][3].anybits?(Ripper::EXPR_BEG | Ripper::EXPR_FNAME)
|
210
278
|
# end of literal except for regexp
|
211
279
|
return true
|
212
280
|
end
|
213
281
|
false
|
214
282
|
end
|
215
283
|
|
216
|
-
def check_code_block(code)
|
217
|
-
return true if
|
218
|
-
if
|
284
|
+
def check_code_block(code, tokens = @tokens)
|
285
|
+
return true if tokens.empty?
|
286
|
+
if tokens.last[1] == :on_heredoc_beg
|
219
287
|
return true
|
220
288
|
end
|
221
289
|
|
222
290
|
begin # check if parser error are available
|
223
291
|
verbose, $VERBOSE = $VERBOSE, nil
|
224
292
|
case RUBY_ENGINE
|
293
|
+
when 'ruby'
|
294
|
+
self.class.compile_with_errors_suppressed(code) do |inner_code, line_no|
|
295
|
+
RubyVM::InstructionSequence.compile(inner_code, nil, nil, line_no)
|
296
|
+
end
|
225
297
|
when 'jruby'
|
226
298
|
JRuby.compile_ir(code)
|
227
299
|
else
|
228
|
-
|
229
|
-
|
300
|
+
catch(:valid) do
|
301
|
+
eval("BEGIN { throw :valid, true }\n#{code}")
|
302
|
+
false
|
230
303
|
end
|
231
304
|
end
|
232
305
|
rescue EncodingError
|
@@ -282,7 +355,7 @@ class RubyLex
|
|
282
355
|
end
|
283
356
|
|
284
357
|
if defined?(Ripper::EXPR_BEG)
|
285
|
-
last_lex_state =
|
358
|
+
last_lex_state = tokens.last[3]
|
286
359
|
if last_lex_state.allbits?(Ripper::EXPR_BEG)
|
287
360
|
return false
|
288
361
|
elsif last_lex_state.allbits?(Ripper::EXPR_DOT)
|
@@ -301,10 +374,10 @@ class RubyLex
|
|
301
374
|
false
|
302
375
|
end
|
303
376
|
|
304
|
-
def process_nesting_level
|
377
|
+
def process_nesting_level(tokens = @tokens)
|
305
378
|
indent = 0
|
306
379
|
in_oneliner_def = nil
|
307
|
-
|
380
|
+
tokens.each_with_index { |t, index|
|
308
381
|
# detecting one-liner method definition
|
309
382
|
if in_oneliner_def.nil?
|
310
383
|
if t[3].allbits?(Ripper::EXPR_ENDFN)
|
@@ -317,14 +390,12 @@ class RubyLex
|
|
317
390
|
if t[2] == '='
|
318
391
|
in_oneliner_def = :BODY
|
319
392
|
end
|
320
|
-
|
393
|
+
else
|
321
394
|
if in_oneliner_def == :BODY
|
322
395
|
# one-liner method definition
|
323
396
|
indent -= 1
|
324
397
|
end
|
325
398
|
in_oneliner_def = nil
|
326
|
-
else
|
327
|
-
in_oneliner_def = nil
|
328
399
|
end
|
329
400
|
end
|
330
401
|
|
@@ -334,17 +405,11 @@ class RubyLex
|
|
334
405
|
when :on_rbracket, :on_rbrace, :on_rparen
|
335
406
|
indent -= 1
|
336
407
|
when :on_kw
|
337
|
-
next if index > 0 and
|
408
|
+
next if index > 0 and tokens[index - 1][3].allbits?(Ripper::EXPR_FNAME)
|
338
409
|
case t[2]
|
339
410
|
when 'do'
|
340
|
-
|
341
|
-
|
342
|
-
indent += 1
|
343
|
-
else
|
344
|
-
# while cond do; end # also "until" or "for"
|
345
|
-
# This "do" doesn't increment indent because "while" already
|
346
|
-
# incremented.
|
347
|
-
end
|
411
|
+
syntax_of_do = take_corresponding_syntax_to_kw_do(tokens, index)
|
412
|
+
indent += 1 if syntax_of_do == :method_calling
|
348
413
|
when 'def', 'case', 'for', 'begin', 'class', 'module'
|
349
414
|
indent += 1
|
350
415
|
when 'if', 'unless', 'while', 'until'
|
@@ -359,6 +424,40 @@ class RubyLex
|
|
359
424
|
indent
|
360
425
|
end
|
361
426
|
|
427
|
+
def take_corresponding_syntax_to_kw_do(tokens, index)
|
428
|
+
syntax_of_do = nil
|
429
|
+
# Finding a syntax correnponding to "do".
|
430
|
+
index.downto(0) do |i|
|
431
|
+
tk = tokens[i]
|
432
|
+
# In "continue", the token isn't the corresponding syntax to "do".
|
433
|
+
#is_continue = process_continue(@tokens[0..(i - 1)])
|
434
|
+
# continue ではなく、直前に (:on_ignored_nl|:on_nl|:on_comment):on_sp* みたいなのがあるかどうかを調べる
|
435
|
+
non_sp_index = tokens[0..(i - 1)].rindex{ |t| t[1] != :on_sp }
|
436
|
+
first_in_fomula = false
|
437
|
+
if non_sp_index.nil?
|
438
|
+
first_in_fomula = true
|
439
|
+
elsif [:on_ignored_nl, :on_nl, :on_comment].include?(tokens[non_sp_index][1])
|
440
|
+
first_in_fomula = true
|
441
|
+
end
|
442
|
+
if tk[3].anybits?(Ripper::EXPR_CMDARG) and tk[1] == :on_ident
|
443
|
+
# The target method call to pass the block with "do".
|
444
|
+
syntax_of_do = :method_calling
|
445
|
+
break if first_in_fomula
|
446
|
+
elsif tk[1] == :on_kw && %w{while until for}.include?(tk[2])
|
447
|
+
# A loop syntax in front of "do" found.
|
448
|
+
#
|
449
|
+
# while cond do # also "until" or "for"
|
450
|
+
# end
|
451
|
+
#
|
452
|
+
# This "do" doesn't increment indent because the loop syntax already
|
453
|
+
# incremented.
|
454
|
+
syntax_of_do = :loop_syntax
|
455
|
+
break if first_in_fomula
|
456
|
+
end
|
457
|
+
end
|
458
|
+
syntax_of_do
|
459
|
+
end
|
460
|
+
|
362
461
|
def check_newline_depth_difference
|
363
462
|
depth_difference = 0
|
364
463
|
open_brace_on_line = 0
|
@@ -376,20 +475,18 @@ class RubyLex
|
|
376
475
|
if t[2] == '='
|
377
476
|
in_oneliner_def = :BODY
|
378
477
|
end
|
379
|
-
|
478
|
+
else
|
380
479
|
if in_oneliner_def == :BODY
|
381
|
-
# one
|
480
|
+
# one-liner method definition
|
382
481
|
depth_difference -= 1
|
383
482
|
end
|
384
483
|
in_oneliner_def = nil
|
385
|
-
else
|
386
|
-
in_oneliner_def = nil
|
387
484
|
end
|
388
485
|
end
|
389
486
|
|
390
487
|
case t[1]
|
391
488
|
when :on_ignored_nl, :on_nl, :on_comment
|
392
|
-
if index != (@tokens.size - 1)
|
489
|
+
if index != (@tokens.size - 1) and in_oneliner_def != :BODY
|
393
490
|
depth_difference = 0
|
394
491
|
open_brace_on_line = 0
|
395
492
|
end
|
@@ -407,14 +504,8 @@ class RubyLex
|
|
407
504
|
next if index > 0 and @tokens[index - 1][3].allbits?(Ripper::EXPR_FNAME)
|
408
505
|
case t[2]
|
409
506
|
when 'do'
|
410
|
-
|
411
|
-
|
412
|
-
depth_difference += 1
|
413
|
-
else
|
414
|
-
# while cond do; end # also "until" or "for"
|
415
|
-
# This "do" doesn't increment indent because "while" already
|
416
|
-
# incremented.
|
417
|
-
end
|
507
|
+
syntax_of_do = take_corresponding_syntax_to_kw_do(@tokens, index)
|
508
|
+
depth_difference += 1 if syntax_of_do == :method_calling
|
418
509
|
when 'def', 'case', 'for', 'begin', 'class', 'module'
|
419
510
|
depth_difference += 1
|
420
511
|
when 'if', 'unless', 'while', 'until', 'rescue'
|
@@ -424,6 +515,8 @@ class RubyLex
|
|
424
515
|
end
|
425
516
|
when 'else', 'elsif', 'ensure', 'when', 'in'
|
426
517
|
depth_difference += 1
|
518
|
+
when 'end'
|
519
|
+
depth_difference -= 1
|
427
520
|
end
|
428
521
|
end
|
429
522
|
end
|
@@ -451,7 +544,7 @@ class RubyLex
|
|
451
544
|
if t[2] == '='
|
452
545
|
in_oneliner_def = :BODY
|
453
546
|
end
|
454
|
-
|
547
|
+
else
|
455
548
|
if in_oneliner_def == :BODY
|
456
549
|
# one-liner method definition
|
457
550
|
if is_first_printable_of_line
|
@@ -462,18 +555,18 @@ class RubyLex
|
|
462
555
|
end
|
463
556
|
end
|
464
557
|
in_oneliner_def = nil
|
465
|
-
else
|
466
|
-
in_oneliner_def = nil
|
467
558
|
end
|
468
559
|
end
|
469
560
|
|
470
561
|
case t[1]
|
471
562
|
when :on_ignored_nl, :on_nl, :on_comment
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
563
|
+
if in_oneliner_def != :BODY
|
564
|
+
corresponding_token_depth = nil
|
565
|
+
spaces_at_line_head = 0
|
566
|
+
is_first_spaces_of_line = true
|
567
|
+
is_first_printable_of_line = true
|
568
|
+
open_brace_on_line = 0
|
569
|
+
end
|
477
570
|
next
|
478
571
|
when :on_sp
|
479
572
|
spaces_at_line_head = t[2].count(' ') if is_first_spaces_of_line
|
@@ -495,7 +588,12 @@ class RubyLex
|
|
495
588
|
when :on_kw
|
496
589
|
next if index > 0 and @tokens[index - 1][3].allbits?(Ripper::EXPR_FNAME)
|
497
590
|
case t[2]
|
498
|
-
when '
|
591
|
+
when 'do'
|
592
|
+
syntax_of_do = take_corresponding_syntax_to_kw_do(@tokens, index)
|
593
|
+
if syntax_of_do == :method_calling
|
594
|
+
spaces_of_nest.push(spaces_at_line_head)
|
595
|
+
end
|
596
|
+
when 'def', 'case', 'for', 'begin', 'class', 'module'
|
499
597
|
spaces_of_nest.push(spaces_at_line_head)
|
500
598
|
when 'rescue'
|
501
599
|
unless t[3].allbits?(Ripper::EXPR_LABEL)
|
@@ -523,12 +621,12 @@ class RubyLex
|
|
523
621
|
corresponding_token_depth
|
524
622
|
end
|
525
623
|
|
526
|
-
def check_string_literal
|
624
|
+
def check_string_literal(tokens)
|
527
625
|
i = 0
|
528
626
|
start_token = []
|
529
627
|
end_type = []
|
530
|
-
while i <
|
531
|
-
t =
|
628
|
+
while i < tokens.size
|
629
|
+
t = tokens[i]
|
532
630
|
case t[1]
|
533
631
|
when :on_tstring_beg
|
534
632
|
start_token << t
|
@@ -538,7 +636,7 @@ class RubyLex
|
|
538
636
|
end_type << :on_regexp_end
|
539
637
|
when :on_symbeg
|
540
638
|
acceptable_single_tokens = %i{on_ident on_const on_op on_cvar on_ivar on_gvar on_kw}
|
541
|
-
if (i + 1) <
|
639
|
+
if (i + 1) < tokens.size and acceptable_single_tokens.all?{ |st| tokens[i + 1][1] != st }
|
542
640
|
start_token << t
|
543
641
|
end_type << :on_tstring_end
|
544
642
|
end
|
@@ -560,8 +658,8 @@ class RubyLex
|
|
560
658
|
start_token.last.nil? ? '' : start_token.last
|
561
659
|
end
|
562
660
|
|
563
|
-
def process_literal_type
|
564
|
-
start_token = check_string_literal
|
661
|
+
def process_literal_type(tokens = @tokens)
|
662
|
+
start_token = check_string_literal(tokens)
|
565
663
|
case start_token[1]
|
566
664
|
when :on_tstring_beg
|
567
665
|
case start_token[2]
|
data/lib/irb/version.rb
CHANGED
data/lib/irb/workspace.rb
CHANGED
@@ -51,11 +51,13 @@ EOF
|
|
51
51
|
end
|
52
52
|
@binding = BINDING_QUEUE.pop
|
53
53
|
|
54
|
-
when 3 # binding in function on TOPLEVEL_BINDING
|
55
|
-
@binding = eval("self.class.
|
54
|
+
when 3 # binding in function on TOPLEVEL_BINDING
|
55
|
+
@binding = eval("self.class.remove_method(:irb_binding) if defined?(irb_binding); private; def irb_binding; binding; end; irb_binding",
|
56
56
|
TOPLEVEL_BINDING,
|
57
57
|
__FILE__,
|
58
58
|
__LINE__ - 3)
|
59
|
+
when 4 # binding is a copy of TOPLEVEL_BINDING (default)
|
60
|
+
@binding = TOPLEVEL_BINDING.dup
|
59
61
|
end
|
60
62
|
end
|
61
63
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: irb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Keiju ISHITSUKA
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: reline
|
@@ -76,10 +76,12 @@ files:
|
|
76
76
|
- lib/irb/cmd/fork.rb
|
77
77
|
- lib/irb/cmd/help.rb
|
78
78
|
- lib/irb/cmd/load.rb
|
79
|
+
- lib/irb/cmd/measure.rb
|
79
80
|
- lib/irb/cmd/nop.rb
|
80
81
|
- lib/irb/cmd/pushws.rb
|
81
82
|
- lib/irb/cmd/subirb.rb
|
82
83
|
- lib/irb/color.rb
|
84
|
+
- lib/irb/color_printer.rb
|
83
85
|
- lib/irb/completion.rb
|
84
86
|
- lib/irb/context.rb
|
85
87
|
- lib/irb/easter-egg.rb
|
@@ -134,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
134
136
|
- !ruby/object:Gem::Version
|
135
137
|
version: '0'
|
136
138
|
requirements: []
|
137
|
-
rubygems_version: 3.
|
139
|
+
rubygems_version: 3.2.3
|
138
140
|
signing_key:
|
139
141
|
specification_version: 4
|
140
142
|
summary: Interactive Ruby command-line tool for REPL (Read Eval Print Loop).
|