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 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).