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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5cafd02c241d954487f11903643ef4a4218d39352c889f3be57a1e9314acb174
4
- data.tar.gz: 0f4afd5294f5357835df0519b0a32cba425cf40a1afc225cf3acf0ae4d0cb04a
3
+ metadata.gz: e147abaf69084b92f2f7accaf7d83014b6c0f7b3b6cbe0cc9b9878c52baee8af
4
+ data.tar.gz: 9a770f98f44f4bf498c91a3d8546d13a1db418daa034639646c0df0c3720d23e
5
5
  SHA512:
6
- metadata.gz: 958f6f1750e5cb951110a1de09beebee65e24c931989da99dd05a1207f050e96f37490e6def0c484b18a23a91c66ad8119a7aa2c5e48c7ad6eacb4590ea4c397
7
- data.tar.gz: 1c6d64ed48b51f189ba9d5846ffdfeae02eff8e44554c66d54eeaab597b96381bdbe78aeba6f2f5fbb0929ee5517e87584eeebd50c65bc93e5cd3321c1b8260e
6
+ metadata.gz: f760ae68d08c7ae7f9f4ec07149935819f50df015a5f4a9453eca4a01574677ed5a29ae1c4eb8462b9cc92f5ad6b465b4e8b1c3f37748bd81ecde7159cf3a1c0
7
+ data.tar.gz: 3da91491f2e3928c8b619f120b6c6adcd020ed16760a4c176aee38bec5ca3964eb7cd0acc053a6a18dacec571b9a0b1e93d2a4c94a628a642b3b39bfd98b5284
@@ -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[:TA_EXIT]</code> when the current session quits.
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
- @context.evaluate(line, line_no, exception: exc)
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.omit_on_assignment?)
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
- count = 0
584
- exc.backtrace.each do |m|
585
- m = @context.workspace.filter_backtrace(m) or next unless irb_bug
586
- count += 1
587
- if attr == ATTR_TTY
588
- m = sprintf("%9d: from %s", count, m)
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
- m = "\tfrom #{m}"
624
+ message = exc.full_message(order: :top)
625
+ order = :top
591
626
  end
592
- if messages.size < @context.back_trace_limit
593
- messages.push(m)
594
- elsif lasts.size < @context.back_trace_limit
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!(/(\A.*?\n).*/m, "\\1...")
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)
@@ -16,7 +16,7 @@ module IRB
16
16
  module ExtendCommand
17
17
  class Fork < Nop
18
18
  def execute
19
- pid = send ExtendCommand.irb_original_method_name("fork")
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:
@@ -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 == :on_parse_error or token == :compile_error
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
@@ -47,7 +47,7 @@ module IRB
47
47
  when /^((["'`]).*\2)\.([^.]*)$/
48
48
  # String
49
49
  receiver = $1
50
- message = Regexp.quote($3)
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 = Regexp.quote($2)
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 = Regexp.quote($2)
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 = Regexp.quote($2)
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 = Regexp.quote($2)
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 = Regexp.quote($3)
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 = Regexp.quote($~[:mes])
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 = Regexp.quote($3)
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 = Regexp.quote($3)
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 = Regexp.quote($1)
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.send(:easter_egg)
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
@@ -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 = true
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
- # Uses <code>IRB.conf[:ECHO_ON_ASSIGNMENT]</code> if available, or defaults to +true+.
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.
@@ -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.send(:easter_egg, ARGV[0]&.to_sym) if $0 == __FILE__
138
+ IRB.__send__(:easter_egg, ARGV[0]&.to_sym) if $0 == __FILE__
@@ -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 self.class.class_variable_defined?(:@@#{cmd_name}_)
177
- self.class.class_variable_set(:@@#{cmd_name}_, true)
178
- def #{cmd_name}_(\#{args})
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
- send :#{cmd_name}_, *opts, &b
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
- send :#{cmd_name}, *opts, &b
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
- send :#{extend_method}, *opts
295
- send :#{alias_name}, *opts
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
- send :#{alias_name}, *opts
311
- send :#{extend_method}, *opts
314
+ __send__ :#{alias_name}, *opts
315
+ __send__ :#{extend_method}, *opts
312
316
  end
313
317
  ]
314
318
  end
@@ -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] = 3 # use binding in function on TOPLEVEL_BINDING
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 "--omit-on-assignment"
182
- @CONF[:OMIT_ON_ASSIGNMENT] = true
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"
@@ -83,7 +83,15 @@ module IRB
83
83
  #
84
84
  # See IO#eof? for more information.
85
85
  def eof?
86
- @stdin.eof?
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
@@ -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([true, :p, :inspect]){|v|
108
- begin
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)
@@ -60,11 +60,31 @@ class RubyLex
60
60
  @io.dynamic_prompt do |lines|
61
61
  lines << '' if lines.empty?
62
62
  result = []
63
- lines.each_index { |i|
64
- c = lines[0..i].map{ |l| l + "\n" }.join
65
- ltype, indent, continue, code_block_open = check_state(c)
66
- result << @prompt.call(ltype, indent, continue || code_block_open, @line_no + i)
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
- tokens = Ripper.lex(inner_code, '-', line_no)
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
- @tokens = ripper_lex_without_warning(code)
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 @tokens.size >= 2 and @tokens[-2][1] == :on_regexp_end
266
+ if tokens.size >= 2 and tokens[-2][1] == :on_regexp_end
199
267
  # end of regexp literal
200
268
  return false
201
- elsif @tokens.size >= 2 and @tokens[-2][1] == :on_semicolon
269
+ elsif tokens.size >= 2 and tokens[-2][1] == :on_semicolon
202
270
  return false
203
- elsif @tokens.size >= 2 and @tokens[-2][1] == :on_kw and ['begin', 'else', 'ensure'].include?(@tokens[-2][2])
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 !@tokens.empty? and @tokens.last[2] == "\\\n"
273
+ elsif !tokens.empty? and tokens.last[2] == "\\\n"
206
274
  return true
207
- elsif @tokens.size >= 1 and @tokens[-1][1] == :on_heredoc_end # "EOH\n"
275
+ elsif tokens.size >= 1 and tokens[-1][1] == :on_heredoc_end # "EOH\n"
208
276
  return false
209
- elsif @tokens.size >= 2 and defined?(Ripper::EXPR_BEG) and @tokens[-2][3].anybits?(Ripper::EXPR_BEG | Ripper::EXPR_FNAME)
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 @tokens.empty?
218
- if @tokens.last[1] == :on_heredoc_beg
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
- self.class.compile_with_errors_suppressed(code) do |inner_code, line_no|
229
- RubyVM::InstructionSequence.compile(inner_code, nil, nil, line_no)
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 = @tokens.last[3]
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
- @tokens.each_with_index { |t, index|
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
- elsif t[3].allbits?(Ripper::EXPR_END)
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 @tokens[index - 1][3].allbits?(Ripper::EXPR_FNAME)
408
+ next if index > 0 and tokens[index - 1][3].allbits?(Ripper::EXPR_FNAME)
338
409
  case t[2]
339
410
  when 'do'
340
- if index > 0 and @tokens[index - 1][3].anybits?(Ripper::EXPR_CMDARG | Ripper::EXPR_ENDFN | Ripper::EXPR_ARG)
341
- # method_with_block do; end
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
- elsif t[3].allbits?(Ripper::EXPR_END)
478
+ else
380
479
  if in_oneliner_def == :BODY
381
- # one[-liner method definition
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
- if index > 0 and @tokens[index - 1][3].anybits?(Ripper::EXPR_CMDARG | Ripper::EXPR_ENDFN | Ripper::EXPR_ARG)
411
- # method_with_block do; end
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
- elsif t[3].allbits?(Ripper::EXPR_END)
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
- corresponding_token_depth = nil
473
- spaces_at_line_head = 0
474
- is_first_spaces_of_line = true
475
- is_first_printable_of_line = true
476
- open_brace_on_line = 0
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 'def', 'do', 'case', 'for', 'begin', 'class', 'module'
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 < @tokens.size
531
- t = @tokens[i]
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) < @tokens.size and acceptable_single_tokens.all?{ |t| @tokens[i + 1][1] != t }
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]
@@ -11,7 +11,7 @@
11
11
  #
12
12
 
13
13
  module IRB # :nodoc:
14
- VERSION = "1.2.6"
14
+ VERSION = "1.3.1"
15
15
  @RELEASE_VERSION = VERSION
16
- @LAST_UPDATE_DATE = "2020-09-14"
16
+ @LAST_UPDATE_DATE = "2021-01-12"
17
17
  end
@@ -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(default)
55
- @binding = eval("self.class.send(:remove_method, :irb_binding) if defined?(irb_binding); private; def irb_binding; binding; end; irb_binding",
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.2.6
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: 2020-09-13 00:00:00.000000000 Z
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.1.2
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).