irb 1.2.6 → 1.3.1
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/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).
|