irb 1.2.4 → 1.2.9

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: 0b760eaf9b7cc0f0029395a3a6de59420595d82f9610442b6b382576e030b86b
4
- data.tar.gz: 0e50bdf359e3ccb0e9ae5ec351e47d34601e68a0073a65d9bf310df3fbe95360
3
+ metadata.gz: cb526faa67bbfaad97480a6e642dc161725c6c444dcb6e6080498fae665173a6
4
+ data.tar.gz: 58c89d71946d694826f2409eaf4a49ed88644bf640564e2f3a6c9ab3d8e9c0e1
5
5
  SHA512:
6
- metadata.gz: e82e4dac7bf886a261f2f2008c5e12eab54adfe75c5a42c6b870eb0c30c8dc87a18f48275857054ba19091737903e96a120ca69a2ccdb9cdcf3b494129997972
7
- data.tar.gz: 40b3e75fb3de5422b6cafaebd94ad0f4283999e957c719b86ef4ade5aca96e9eb47bb94794342985a557061326c93bff333e4b8950cbafe4239879301208e79c
6
+ metadata.gz: 9e101c1374b8ea161ec76217739ce5dbcd93c9e85e3cc147852717634085b97e5bd1aa71a9a6c316a660e9c60f0d16a03d08c26e7b7e65bdbb44886295bfa8dd
7
+ data.tar.gz: 6243fb79d8747f0c507ebbd7e3f4efd486b3848ea7b2bf4db5ee4bb48591ee20857bcf5d86f61520c7d17b1d9307dc28a2ac785a64dda83ba1c78ebff90d53b6
data/Gemfile CHANGED
@@ -3,8 +3,3 @@ source "https://rubygems.org"
3
3
  git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
5
  gemspec
6
-
7
- # TODO: remove this when reline with `Reline::Unicode.escape_for_print` is released.
8
- if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0')
9
- gem "reline", github: "ruby/reline"
10
- end
@@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
14
14
  spec.summary = %q{Interactive Ruby command-line tool for REPL (Read Eval Print Loop).}
15
15
  spec.description = %q{Interactive Ruby command-line tool for REPL (Read Eval Print Loop).}
16
16
  spec.homepage = "https://github.com/ruby/irb"
17
- spec.license = "BSD-2-Clause"
17
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
18
18
 
19
19
  spec.files = [
20
20
  ".document",
@@ -78,7 +78,7 @@ Gem::Specification.new do |spec|
78
78
 
79
79
  spec.required_ruby_version = Gem::Requirement.new(">= 2.5")
80
80
 
81
- spec.add_dependency "reline", ">= 0.0.1"
81
+ spec.add_dependency "reline", ">= 0.1.5"
82
82
  spec.add_development_dependency "bundler"
83
83
  spec.add_development_dependency "rake"
84
84
  end
data/lib/irb.rb CHANGED
@@ -10,18 +10,19 @@
10
10
  #
11
11
  #
12
12
  require "ripper"
13
+ require "reline"
13
14
 
14
- require "irb/init"
15
- require "irb/context"
16
- require "irb/extend-command"
15
+ require_relative "irb/init"
16
+ require_relative "irb/context"
17
+ require_relative "irb/extend-command"
17
18
 
18
- require "irb/ruby-lex"
19
- require "irb/input-method"
20
- require "irb/locale"
21
- require "irb/color"
19
+ require_relative "irb/ruby-lex"
20
+ require_relative "irb/input-method"
21
+ require_relative "irb/locale"
22
+ require_relative "irb/color"
22
23
 
23
- require "irb/version"
24
- require "irb/easter-egg"
24
+ require_relative "irb/version"
25
+ require_relative "irb/easter-egg"
25
26
 
26
27
  # IRB stands for "interactive Ruby" and is a tool to interactively execute Ruby
27
28
  # expressions read from the standard input.
@@ -399,7 +400,7 @@ module IRB
399
400
  irb.run(@CONF)
400
401
  end
401
402
 
402
- # 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.
403
404
  def IRB.irb_at_exit
404
405
  @CONF[:AT_EXIT].each{|hook| hook.call}
405
406
  end
@@ -537,8 +538,33 @@ module IRB
537
538
  signal_status(:IN_EVAL) do
538
539
  begin
539
540
  line.untaint if RUBY_VERSION < '2.7'
540
- @context.evaluate(line, line_no, exception: exc)
541
- output_value if @context.echo? && (@context.echo_on_assignment? || !assignment_expression?(line))
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
559
+ if @context.echo?
560
+ if assignment_expression?(line)
561
+ if @context.echo_on_assignment?
562
+ output_value(@context.echo_on_assignment? == :truncate)
563
+ end
564
+ else
565
+ output_value
566
+ end
567
+ end
542
568
  rescue Interrupt => exc
543
569
  rescue SystemExit, SignalException
544
570
  raise
@@ -737,9 +763,32 @@ module IRB
737
763
  p
738
764
  end
739
765
 
740
- def output_value # :nodoc:
766
+ def output_value(omit = false) # :nodoc:
741
767
  str = @context.inspect_last_value
742
768
  multiline_p = str.include?("\n")
769
+ if omit
770
+ winwidth = @context.io.winsize.last
771
+ if multiline_p
772
+ first_line = str.split("\n").first
773
+ result = @context.newline_before_multiline_output? ? (@context.return_format % first_line) : first_line
774
+ output_width = Reline::Unicode.calculate_width(result, true)
775
+ diff_size = output_width - Reline::Unicode.calculate_width(first_line, true)
776
+ if diff_size.positive? and output_width > winwidth
777
+ lines, _ = Reline::Unicode.split_by_width(first_line, winwidth - diff_size - 3)
778
+ str = "%s...\e[0m" % lines.first
779
+ multiline_p = false
780
+ else
781
+ str = str.gsub(/(\A.*?\n).*/m, "\\1...")
782
+ end
783
+ else
784
+ output_width = Reline::Unicode.calculate_width(@context.return_format % str, true)
785
+ diff_size = output_width - Reline::Unicode.calculate_width(str, true)
786
+ if diff_size.positive? and output_width > winwidth
787
+ lines, _ = Reline::Unicode.split_by_width(str, winwidth - diff_size - 3)
788
+ str = "%s...\e[0m" % lines.first
789
+ end
790
+ end
791
+ end
743
792
  if multiline_p && @context.newline_before_multiline_output?
744
793
  printf @context.return_format, "\n#{str}"
745
794
  else
@@ -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')
@@ -35,5 +35,3 @@ module IRB
35
35
  end
36
36
  end
37
37
  # :startdoc:
38
-
39
-
@@ -38,4 +38,3 @@ module IRB
38
38
  end
39
39
  end
40
40
  # :startdoc:
41
-
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  require 'reline'
3
3
  require 'ripper'
4
+ require 'irb/ruby-lex'
4
5
 
5
6
  module IRB # :nodoc:
6
7
  module Color
@@ -145,37 +146,38 @@ module IRB # :nodoc:
145
146
  seen.delete(obj)
146
147
  end
147
148
 
148
- # Ripper::Lexer::Elem#state is supported on Ruby 2.5+
149
149
  def supported?
150
150
  return @supported if defined?(@supported)
151
- @supported = Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.5.0')
151
+ @supported = Ripper::Lexer::Elem.method_defined?(:state)
152
152
  end
153
153
 
154
154
  def scan(code, allow_last_error:)
155
155
  pos = [1, 0]
156
156
 
157
157
  verbose, $VERBOSE = $VERBOSE, nil
158
- lexer = Ripper::Lexer.new(code)
159
- if lexer.respond_to?(:scan) # Ruby 2.7+
160
- lexer.scan.each do |elem|
161
- str = elem.tok
162
- next if allow_last_error and /meets end of file|unexpected end-of-input/ =~ elem.message
163
- next if ([elem.pos[0], elem.pos[1] + str.bytesize] <=> pos) <= 0
164
-
165
- str.each_line do |line|
166
- if line.end_with?("\n")
167
- pos[0] += 1
168
- pos[1] = 0
169
- else
170
- pos[1] += line.bytesize
158
+ RubyLex.compile_with_errors_suppressed(code) do |inner_code, line_no|
159
+ lexer = Ripper::Lexer.new(inner_code, '(ripper)', line_no)
160
+ if lexer.respond_to?(:scan) # Ruby 2.7+
161
+ lexer.scan.each do |elem|
162
+ str = elem.tok
163
+ next if allow_last_error and /meets end of file|unexpected end-of-input/ =~ elem.message
164
+ next if ([elem.pos[0], elem.pos[1] + str.bytesize] <=> pos) <= 0
165
+
166
+ str.each_line do |line|
167
+ if line.end_with?("\n")
168
+ pos[0] += 1
169
+ pos[1] = 0
170
+ else
171
+ pos[1] += line.bytesize
172
+ end
171
173
  end
172
- end
173
174
 
174
- yield(elem.event, str, elem.state)
175
- end
176
- else
177
- lexer.parse.each do |elem|
178
- yield(elem.event, elem.tok, elem.state)
175
+ yield(elem.event, str, elem.state)
176
+ end
177
+ else
178
+ lexer.parse.each do |elem|
179
+ yield(elem.event, elem.tok, elem.state)
180
+ end
179
181
  end
180
182
  end
181
183
  $VERBOSE = verbose
@@ -7,7 +7,6 @@
7
7
  # From Original Idea of shugo@ruby-lang.org
8
8
  #
9
9
 
10
- require "readline"
11
10
  autoload :RDoc, "rdoc"
12
11
 
13
12
  module IRB
@@ -97,17 +96,13 @@ module IRB
97
96
  when /^(:[^:.]*)$/
98
97
  # Symbol
99
98
  return nil if doc_namespace
100
- if Symbol.respond_to?(:all_symbols)
101
- sym = $1
102
- candidates = Symbol.all_symbols.collect do |s|
103
- ":" + s.id2name.encode(Encoding.default_external)
104
- rescue Encoding::UndefinedConversionError
105
- # ignore
106
- end
107
- candidates.grep(/^#{Regexp.quote(sym)}/)
108
- else
109
- []
99
+ sym = $1
100
+ candidates = Symbol.all_symbols.collect do |s|
101
+ ":" + s.id2name.encode(Encoding.default_external)
102
+ rescue Encoding::UndefinedConversionError
103
+ # ignore
110
104
  end
105
+ candidates.grep(/^#{Regexp.quote(sym)}/)
111
106
 
112
107
  when /^::([A-Z][^:\.\(]*)$/
113
108
  # Absolute Constant or class methods
@@ -273,7 +268,7 @@ module IRB
273
268
  PerfectMatchedProc = ->(matched, bind: IRB.conf[:MAIN_CONTEXT].workspace.binding) {
274
269
  RDocRIDriver ||= RDoc::RI::Driver.new
275
270
  if matched =~ /\A(?:::)?RubyVM/ and not ENV['RUBY_YES_I_AM_NOT_A_NORMAL_USER']
276
- IRB.send(:easter_egg)
271
+ IRB.__send__(:easter_egg)
277
272
  return
278
273
  end
279
274
  namespace = retrieve_completion_data(matched, bind: bind, doc_namespace: true)
@@ -131,7 +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 = false
134
+ @echo_on_assignment = :truncate
135
135
  end
136
136
 
137
137
  @newline_before_multiline_output = IRB.conf[:NEWLINE_BEFORE_MULTILINE_OUTPUT]
@@ -251,12 +251,23 @@ module IRB
251
251
  attr_accessor :echo
252
252
  # Whether to echo for assignment expressions
253
253
  #
254
- # Uses <code>IRB.conf[:ECHO_ON_ASSIGNMENT]</code> if available, or defaults to +false+.
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+.
255
261
  #
256
262
  # a = "omg"
263
+ # #=> omg
264
+ # a = "omg" * 10
265
+ # #=> omgomgomgomgomgomgomg...
266
+ # IRB.CurrentContext.echo_on_assignment = false
267
+ # a = "omg"
257
268
  # IRB.CurrentContext.echo_on_assignment = true
258
269
  # a = "omg"
259
- # #=> omg
270
+ # #=> omgomgomgomgomgomgomgomgomgomg
260
271
  attr_accessor :echo_on_assignment
261
272
  # Whether a newline is put before multiline output.
262
273
  #
@@ -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__
@@ -43,4 +43,3 @@ module IRB # :nodoc:
43
43
  end
44
44
  end
45
45
  end
46
-
@@ -153,5 +153,3 @@ module IRB # :nodoc:
153
153
  end
154
154
  end
155
155
  end
156
-
157
-
@@ -126,4 +126,3 @@ module IRB # :nodoc:
126
126
  end
127
127
  end
128
128
  end
129
-
@@ -9,8 +9,6 @@
9
9
  #
10
10
  #
11
11
 
12
- require "readline"
13
-
14
12
  module IRB
15
13
  module HistorySavingAbility # :nodoc:
16
14
  end
@@ -27,7 +25,7 @@ module IRB
27
25
  IRB.conf[:SAVE_HISTORY]
28
26
  end
29
27
 
30
- remove_method :save_history= if method_defined?(:save_history=)
28
+ remove_method(:save_history=) if method_defined?(:save_history=)
31
29
  # Sets <code>IRB.conf[:SAVE_HISTORY]</code> to the given +val+ and calls
32
30
  # #init_save_history with this context.
33
31
  #
@@ -89,7 +87,7 @@ module IRB
89
87
  def save_history
90
88
  return unless self.class.const_defined?(:HISTORY)
91
89
  history = self.class::HISTORY
92
- if num = IRB.conf[:SAVE_HISTORY] and (num = num.to_i) > 0
90
+ if num = IRB.conf[:SAVE_HISTORY] and (num = num.to_i) != 0
93
91
  if history_file = IRB.conf[:HISTORY_FILE]
94
92
  history_file = File.expand_path(history_file)
95
93
  end
@@ -109,7 +107,12 @@ module IRB
109
107
 
110
108
  open(history_file, "w:#{IRB.conf[:LC_MESSAGES].encoding}", 0600) do |f|
111
109
  hist = history.map{ |l| l.split("\n").join("\\\n") }
112
- f.puts(hist[-num..-1] || hist)
110
+ begin
111
+ hist = hist.last(num) if hist.size > num and num > 0
112
+ rescue RangeError # bignum too big to convert into `long'
113
+ # Do nothing because the bignum should be treated as inifinity
114
+ end
115
+ f.puts(hist)
113
116
  end
114
117
  end
115
118
  end
@@ -82,4 +82,3 @@ module IRB
82
82
 
83
83
  IRB.initialize_tracer
84
84
  end
85
-
@@ -73,5 +73,3 @@ module IRB
73
73
  end
74
74
  end
75
75
  end
76
-
77
-
@@ -64,4 +64,3 @@ module IRB # :nodoc:
64
64
  end
65
65
  end
66
66
  end
67
-
@@ -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:
@@ -180,7 +184,7 @@ module IRB # :nodoc:
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
@@ -34,4 +34,3 @@ module IRB
34
34
  }
35
35
  end
36
36
  end
37
-
@@ -108,14 +108,69 @@ module IRB # :nodoc:
108
108
  @CONF[:PROMPT_MODE] = (STDIN.tty? ? :DEFAULT : :NULL)
109
109
  @CONF[:AUTO_INDENT] = true
110
110
 
111
- @CONF[:CONTEXT_MODE] = 3 # use binding in function on TOPLEVEL_BINDING
111
+ @CONF[:CONTEXT_MODE] = 4 # use a copy of TOPLEVEL_BINDING
112
112
  @CONF[:SINGLE_IRB] = false
113
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
+
114
144
  @CONF[:LC_MESSAGES] = Locale.new
115
145
 
116
146
  @CONF[:AT_EXIT] = []
117
147
  end
118
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
+ IRB.conf[:MEASURE_CALLBACKS] << added if added
162
+ added
163
+ end
164
+
165
+ def IRB.unset_measure_callback(type = nil)
166
+ if type.nil?
167
+ IRB.conf[:MEASURE_CALLBACKS].clear
168
+ else
169
+ type_sym = type.upcase.to_sym
170
+ IRB.conf[:MEASURE_CALLBACKS].reject!{ |t, | t == type_sym }
171
+ end
172
+ end
173
+
119
174
  def IRB.init_error
120
175
  @CONF[:LC_MESSAGES].load("irb/error.rb")
121
176
  end
@@ -131,7 +186,7 @@ module IRB # :nodoc:
131
186
  $DEBUG = true
132
187
  $VERBOSE = true
133
188
  when "-w"
134
- $VERBOSE = true
189
+ Warning[:deprecated] = $VERBOSE = true
135
190
  when /^-W(.+)?/
136
191
  opt = $1 || argv.shift
137
192
  case opt
@@ -140,7 +195,7 @@ module IRB # :nodoc:
140
195
  when "1"
141
196
  $VERBOSE = false
142
197
  else
143
- $VERBOSE = true
198
+ Warning[:deprecated] = $VERBOSE = true
144
199
  end
145
200
  when /^-r(.+)?/
146
201
  opt = $1 || argv.shift
@@ -177,6 +232,8 @@ module IRB # :nodoc:
177
232
  @CONF[:ECHO_ON_ASSIGNMENT] = true
178
233
  when "--noecho-on-assignment"
179
234
  @CONF[:ECHO_ON_ASSIGNMENT] = false
235
+ when "--truncate-echo-on-assignment"
236
+ @CONF[:ECHO_ON_ASSIGNMENT] = :truncate
180
237
  when "--verbose"
181
238
  @CONF[:VERBOSE] = true
182
239
  when "--noverbose"
@@ -12,6 +12,7 @@
12
12
  require_relative 'src_encoding'
13
13
  require_relative 'magic-file'
14
14
  require_relative 'completion'
15
+ require 'io/console'
15
16
  require 'reline'
16
17
 
17
18
  module IRB
@@ -36,6 +37,14 @@ module IRB
36
37
  end
37
38
  public :gets
38
39
 
40
+ def winsize
41
+ if instance_variable_defined?(:@stdout)
42
+ @stdout.winsize
43
+ else
44
+ [24, 80]
45
+ end
46
+ end
47
+
39
48
  # Whether this input method is still readable when there is no more data to
40
49
  # read.
41
50
  #
@@ -143,11 +152,17 @@ module IRB
143
152
  end
144
153
 
145
154
  begin
146
- require "readline"
147
155
  class ReadlineInputMethod < InputMethod
148
- include Readline
156
+ def self.initialize_readline
157
+ require "readline"
158
+ rescue LoadError
159
+ else
160
+ include ::Readline
161
+ end
162
+
149
163
  # Creates a new input method object using Readline
150
164
  def initialize
165
+ self.class.initialize_readline
151
166
  if Readline.respond_to?(:encoding_system_needs)
152
167
  IRB.__send__(:set_encoding, Readline.encoding_system_needs.name, override: false)
153
168
  end
@@ -212,12 +227,6 @@ module IRB
212
227
  @stdin.external_encoding
213
228
  end
214
229
 
215
- if Readline.respond_to?("basic_word_break_characters=")
216
- Readline.basic_word_break_characters = IRB::InputCompletor::BASIC_WORD_BREAK_CHARACTERS
217
- end
218
- Readline.completion_append_character = nil
219
- Readline.completion_proc = IRB::InputCompletor::CompletionProc
220
-
221
230
  # For debug message
222
231
  def inspect
223
232
  readline_impl = (defined?(Reline) && Readline == Reline) ? 'Reline' : 'ext/readline'
@@ -227,7 +236,6 @@ module IRB
227
236
  str
228
237
  end
229
238
  end
230
- rescue LoadError
231
239
  end
232
240
 
233
241
  class ReidlineInputMethod < InputMethod
@@ -251,7 +259,7 @@ module IRB
251
259
  Reline.completion_proc = IRB::InputCompletor::CompletionProc
252
260
  Reline.output_modifier_proc =
253
261
  if IRB.conf[:USE_COLORIZE]
254
- proc do |output, complete:|
262
+ proc do |output, complete: |
255
263
  next unless IRB::Color.colorable?
256
264
  IRB::Color.colorize_code(output, complete: complete)
257
265
  end
@@ -327,7 +335,7 @@ module IRB
327
335
  config = Reline::Config.new
328
336
  str = "ReidlineInputMethod with Reline #{Reline::VERSION}"
329
337
  if config.respond_to?(:inputrc_path)
330
- inputrc_path = config.inputrc_path
338
+ inputrc_path = File.expand_path(config.inputrc_path)
331
339
  else
332
340
  inputrc_path = File.expand_path(ENV['INPUTRC'] || '~/.inputrc')
333
341
  end
@@ -113,6 +113,7 @@ module IRB # :nodoc:
113
113
  result
114
114
  rescue NoMethodError
115
115
  puts "(Object doesn't support #inspect)"
116
+ ''
116
117
  end
117
118
  }
118
119
  Inspector.def_inspector([:pp, :pretty_inspect], proc{require "pp"}){|v|
@@ -135,8 +136,3 @@ module IRB # :nodoc:
135
136
  Marshal.dump(v)
136
137
  }
137
138
  end
138
-
139
-
140
-
141
-
142
-
@@ -30,6 +30,18 @@ class RubyLex
30
30
  @prompt = nil
31
31
  end
32
32
 
33
+ def self.compile_with_errors_suppressed(code)
34
+ line_no = 1
35
+ begin
36
+ result = yield code, line_no
37
+ rescue ArgumentError
38
+ code = ";\n#{code}"
39
+ line_no = 0
40
+ result = yield code, line_no
41
+ end
42
+ result
43
+ end
44
+
33
45
  # io functions
34
46
  def set_input(io, p = nil, &block)
35
47
  @io = io
@@ -48,11 +60,26 @@ class RubyLex
48
60
  @io.dynamic_prompt do |lines|
49
61
  lines << '' if lines.empty?
50
62
  result = []
51
- lines.each_index { |i|
52
- c = lines[0..i].map{ |l| l + "\n" }.join
53
- ltype, indent, continue, code_block_open = check_state(c)
54
- result << @prompt.call(ltype, indent, continue || code_block_open, @line_no + i)
55
- }
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
+ code << t[2]
70
+ partial_tokens << t
71
+ unprocessed_tokens << t
72
+ if t[2].include?("\n")
73
+ ltype, indent, continue, code_block_open = check_state(code, partial_tokens)
74
+ result << @prompt.call(ltype, indent, continue || code_block_open, @line_no + line_num_offset)
75
+ line_num_offset += 1
76
+ unprocessed_tokens = []
77
+ end
78
+ end
79
+ unless unprocessed_tokens.empty?
80
+ ltype, indent, continue, code_block_open = check_state(code, unprocessed_tokens)
81
+ result << @prompt.call(ltype, indent, continue || code_block_open, @line_no + line_num_offset)
82
+ end
56
83
  result
57
84
  end
58
85
  end
@@ -76,7 +103,10 @@ class RubyLex
76
103
 
77
104
  def ripper_lex_without_warning(code)
78
105
  verbose, $VERBOSE = $VERBOSE, nil
79
- tokens = Ripper.lex(code)
106
+ tokens = nil
107
+ self.class.compile_with_errors_suppressed(code) do |inner_code, line_no|
108
+ tokens = Ripper.lex(inner_code, '-', line_no)
109
+ end
80
110
  $VERBOSE = verbose
81
111
  tokens
82
112
  end
@@ -106,12 +136,12 @@ class RubyLex
106
136
  end
107
137
  end
108
138
 
109
- def check_state(code)
110
- @tokens = ripper_lex_without_warning(code)
111
- ltype = process_literal_type
112
- indent = process_nesting_level
113
- continue = process_continue
114
- code_block_open = check_code_block(code)
139
+ def check_state(code, tokens = nil)
140
+ tokens = ripper_lex_without_warning(code) unless tokens
141
+ ltype = process_literal_type(tokens)
142
+ indent = process_nesting_level(tokens)
143
+ continue = process_continue(tokens)
144
+ code_block_open = check_code_block(code, tokens)
115
145
  [ltype, indent, continue, code_block_open]
116
146
  end
117
147
 
@@ -178,39 +208,46 @@ class RubyLex
178
208
  line
179
209
  end
180
210
 
181
- def process_continue
211
+ def process_continue(tokens = @tokens)
182
212
  # last token is always newline
183
- if @tokens.size >= 2 and @tokens[-2][1] == :on_regexp_end
213
+ if tokens.size >= 2 and tokens[-2][1] == :on_regexp_end
184
214
  # end of regexp literal
185
215
  return false
186
- elsif @tokens.size >= 2 and @tokens[-2][1] == :on_semicolon
216
+ elsif tokens.size >= 2 and tokens[-2][1] == :on_semicolon
187
217
  return false
188
- elsif @tokens.size >= 2 and @tokens[-2][1] == :on_kw and ['begin', 'else', 'ensure'].include?(@tokens[-2][2])
218
+ elsif tokens.size >= 2 and tokens[-2][1] == :on_kw and ['begin', 'else', 'ensure'].include?(tokens[-2][2])
189
219
  return false
190
- elsif !@tokens.empty? and @tokens.last[2] == "\\\n"
220
+ elsif !tokens.empty? and tokens.last[2] == "\\\n"
191
221
  return true
192
- elsif @tokens.size >= 1 and @tokens[-1][1] == :on_heredoc_end # "EOH\n"
222
+ elsif tokens.size >= 1 and tokens[-1][1] == :on_heredoc_end # "EOH\n"
193
223
  return false
194
- elsif @tokens.size >= 2 and defined?(Ripper::EXPR_BEG) and @tokens[-2][3].anybits?(Ripper::EXPR_BEG | Ripper::EXPR_FNAME)
224
+ elsif tokens.size >= 2 and defined?(Ripper::EXPR_BEG) and tokens[-2][3].anybits?(Ripper::EXPR_BEG | Ripper::EXPR_FNAME)
195
225
  # end of literal except for regexp
196
226
  return true
197
227
  end
198
228
  false
199
229
  end
200
230
 
201
- def check_code_block(code)
202
- return true if @tokens.empty?
203
- if @tokens.last[1] == :on_heredoc_beg
231
+ def check_code_block(code, tokens = @tokens)
232
+ return true if tokens.empty?
233
+ if tokens.last[1] == :on_heredoc_beg
204
234
  return true
205
235
  end
206
236
 
207
237
  begin # check if parser error are available
208
238
  verbose, $VERBOSE = $VERBOSE, nil
209
239
  case RUBY_ENGINE
240
+ when 'ruby'
241
+ self.class.compile_with_errors_suppressed(code) do |inner_code, line_no|
242
+ RubyVM::InstructionSequence.compile(inner_code, nil, nil, line_no)
243
+ end
210
244
  when 'jruby'
211
245
  JRuby.compile_ir(code)
212
246
  else
213
- RubyVM::InstructionSequence.compile(code)
247
+ catch(:valid) do
248
+ eval("BEGIN { throw :valid, true }\n#{code}")
249
+ false
250
+ end
214
251
  end
215
252
  rescue EncodingError
216
253
  # This is for a hash with invalid encoding symbol, {"\xAE": 1}
@@ -265,7 +302,7 @@ class RubyLex
265
302
  end
266
303
 
267
304
  if defined?(Ripper::EXPR_BEG)
268
- last_lex_state = @tokens.last[3]
305
+ last_lex_state = tokens.last[3]
269
306
  if last_lex_state.allbits?(Ripper::EXPR_BEG)
270
307
  return false
271
308
  elsif last_lex_state.allbits?(Ripper::EXPR_DOT)
@@ -284,19 +321,41 @@ class RubyLex
284
321
  false
285
322
  end
286
323
 
287
- def process_nesting_level
324
+ def process_nesting_level(tokens = @tokens)
288
325
  indent = 0
289
- @tokens.each_with_index { |t, index|
326
+ in_oneliner_def = nil
327
+ tokens.each_with_index { |t, index|
328
+ # detecting one-liner method definition
329
+ if in_oneliner_def.nil?
330
+ if t[3].allbits?(Ripper::EXPR_ENDFN)
331
+ in_oneliner_def = :ENDFN
332
+ end
333
+ else
334
+ if t[3].allbits?(Ripper::EXPR_ENDFN)
335
+ # continuing
336
+ elsif t[3].allbits?(Ripper::EXPR_BEG)
337
+ if t[2] == '='
338
+ in_oneliner_def = :BODY
339
+ end
340
+ else
341
+ if in_oneliner_def == :BODY
342
+ # one-liner method definition
343
+ indent -= 1
344
+ end
345
+ in_oneliner_def = nil
346
+ end
347
+ end
348
+
290
349
  case t[1]
291
- when :on_lbracket, :on_lbrace, :on_lparen
350
+ when :on_lbracket, :on_lbrace, :on_lparen, :on_tlambeg
292
351
  indent += 1
293
352
  when :on_rbracket, :on_rbrace, :on_rparen
294
353
  indent -= 1
295
354
  when :on_kw
296
- next if index > 0 and @tokens[index - 1][3].allbits?(Ripper::EXPR_FNAME)
355
+ next if index > 0 and tokens[index - 1][3].allbits?(Ripper::EXPR_FNAME)
297
356
  case t[2]
298
357
  when 'do'
299
- if index > 0 and @tokens[index - 1][3].anybits?(Ripper::EXPR_CMDARG | Ripper::EXPR_ENDFN | Ripper::EXPR_ARG)
358
+ if index > 0 and tokens[index - 1][3].anybits?(Ripper::EXPR_CMDARG | Ripper::EXPR_ENDFN | Ripper::EXPR_ARG)
300
359
  # method_with_block do; end
301
360
  indent += 1
302
361
  else
@@ -307,7 +366,7 @@ class RubyLex
307
366
  when 'def', 'case', 'for', 'begin', 'class', 'module'
308
367
  indent += 1
309
368
  when 'if', 'unless', 'while', 'until'
310
- # postfix if/unless/while/until/rescue must be Ripper::EXPR_LABEL
369
+ # postfix if/unless/while/until must be Ripper::EXPR_LABEL
311
370
  indent += 1 unless t[3].allbits?(Ripper::EXPR_LABEL)
312
371
  when 'end'
313
372
  indent -= 1
@@ -321,7 +380,29 @@ class RubyLex
321
380
  def check_newline_depth_difference
322
381
  depth_difference = 0
323
382
  open_brace_on_line = 0
383
+ in_oneliner_def = nil
324
384
  @tokens.each_with_index do |t, index|
385
+ # detecting one-liner method definition
386
+ if in_oneliner_def.nil?
387
+ if t[3].allbits?(Ripper::EXPR_ENDFN)
388
+ in_oneliner_def = :ENDFN
389
+ end
390
+ else
391
+ if t[3].allbits?(Ripper::EXPR_ENDFN)
392
+ # continuing
393
+ elsif t[3].allbits?(Ripper::EXPR_BEG)
394
+ if t[2] == '='
395
+ in_oneliner_def = :BODY
396
+ end
397
+ else
398
+ if in_oneliner_def == :BODY
399
+ # one-liner method definition
400
+ depth_difference -= 1
401
+ end
402
+ in_oneliner_def = nil
403
+ end
404
+ end
405
+
325
406
  case t[1]
326
407
  when :on_ignored_nl, :on_nl, :on_comment
327
408
  if index != (@tokens.size - 1)
@@ -333,7 +414,7 @@ class RubyLex
333
414
  next
334
415
  end
335
416
  case t[1]
336
- when :on_lbracket, :on_lbrace, :on_lparen
417
+ when :on_lbracket, :on_lbrace, :on_lparen, :on_tlambeg
337
418
  depth_difference += 1
338
419
  open_brace_on_line += 1
339
420
  when :on_rbracket, :on_rbrace, :on_rparen
@@ -352,12 +433,12 @@ class RubyLex
352
433
  end
353
434
  when 'def', 'case', 'for', 'begin', 'class', 'module'
354
435
  depth_difference += 1
355
- when 'if', 'unless', 'while', 'until'
436
+ when 'if', 'unless', 'while', 'until', 'rescue'
356
437
  # postfix if/unless/while/until/rescue must be Ripper::EXPR_LABEL
357
438
  unless t[3].allbits?(Ripper::EXPR_LABEL)
358
439
  depth_difference += 1
359
440
  end
360
- when 'else', 'elsif', 'rescue', 'ensure', 'when', 'in'
441
+ when 'else', 'elsif', 'ensure', 'when', 'in'
361
442
  depth_difference += 1
362
443
  end
363
444
  end
@@ -372,7 +453,34 @@ class RubyLex
372
453
  spaces_of_nest = []
373
454
  spaces_at_line_head = 0
374
455
  open_brace_on_line = 0
456
+ in_oneliner_def = nil
375
457
  @tokens.each_with_index do |t, index|
458
+ # detecting one-liner method definition
459
+ if in_oneliner_def.nil?
460
+ if t[3].allbits?(Ripper::EXPR_ENDFN)
461
+ in_oneliner_def = :ENDFN
462
+ end
463
+ else
464
+ if t[3].allbits?(Ripper::EXPR_ENDFN)
465
+ # continuing
466
+ elsif t[3].allbits?(Ripper::EXPR_BEG)
467
+ if t[2] == '='
468
+ in_oneliner_def = :BODY
469
+ end
470
+ else
471
+ if in_oneliner_def == :BODY
472
+ # one-liner method definition
473
+ if is_first_printable_of_line
474
+ corresponding_token_depth = spaces_of_nest.pop
475
+ else
476
+ spaces_of_nest.pop
477
+ corresponding_token_depth = nil
478
+ end
479
+ end
480
+ in_oneliner_def = nil
481
+ end
482
+ end
483
+
376
484
  case t[1]
377
485
  when :on_ignored_nl, :on_nl, :on_comment
378
486
  corresponding_token_depth = nil
@@ -387,7 +495,7 @@ class RubyLex
387
495
  next
388
496
  end
389
497
  case t[1]
390
- when :on_lbracket, :on_lbrace, :on_lparen
498
+ when :on_lbracket, :on_lbrace, :on_lparen, :on_tlambeg
391
499
  spaces_of_nest.push(spaces_at_line_head + open_brace_on_line * 2)
392
500
  open_brace_on_line += 1
393
501
  when :on_rbracket, :on_rbrace, :on_rparen
@@ -403,12 +511,16 @@ class RubyLex
403
511
  case t[2]
404
512
  when 'def', 'do', 'case', 'for', 'begin', 'class', 'module'
405
513
  spaces_of_nest.push(spaces_at_line_head)
514
+ when 'rescue'
515
+ unless t[3].allbits?(Ripper::EXPR_LABEL)
516
+ corresponding_token_depth = spaces_of_nest.last
517
+ end
406
518
  when 'if', 'unless', 'while', 'until'
407
- # postfix if/unless/while/until/rescue must be Ripper::EXPR_LABEL
519
+ # postfix if/unless/while/until must be Ripper::EXPR_LABEL
408
520
  unless t[3].allbits?(Ripper::EXPR_LABEL)
409
521
  spaces_of_nest.push(spaces_at_line_head)
410
522
  end
411
- when 'else', 'elsif', 'rescue', 'ensure', 'when', 'in'
523
+ when 'else', 'elsif', 'ensure', 'when', 'in'
412
524
  corresponding_token_depth = spaces_of_nest.last
413
525
  when 'end'
414
526
  if is_first_printable_of_line
@@ -425,12 +537,12 @@ class RubyLex
425
537
  corresponding_token_depth
426
538
  end
427
539
 
428
- def check_string_literal
540
+ def check_string_literal(tokens)
429
541
  i = 0
430
542
  start_token = []
431
543
  end_type = []
432
- while i < @tokens.size
433
- t = @tokens[i]
544
+ while i < tokens.size
545
+ t = tokens[i]
434
546
  case t[1]
435
547
  when :on_tstring_beg
436
548
  start_token << t
@@ -440,7 +552,7 @@ class RubyLex
440
552
  end_type << :on_regexp_end
441
553
  when :on_symbeg
442
554
  acceptable_single_tokens = %i{on_ident on_const on_op on_cvar on_ivar on_gvar on_kw}
443
- if (i + 1) < @tokens.size and acceptable_single_tokens.all?{ |t| @tokens[i + 1][1] != t }
555
+ if (i + 1) < tokens.size and acceptable_single_tokens.all?{ |t| tokens[i + 1][1] != t }
444
556
  start_token << t
445
557
  end_type << :on_tstring_end
446
558
  end
@@ -462,8 +574,8 @@ class RubyLex
462
574
  start_token.last.nil? ? '' : start_token.last
463
575
  end
464
576
 
465
- def process_literal_type
466
- start_token = check_string_literal
577
+ def process_literal_type(tokens = @tokens)
578
+ start_token = check_string_literal(tokens)
467
579
  case start_token[1]
468
580
  when :on_tstring_beg
469
581
  case start_token[2]
@@ -35,4 +35,3 @@
35
35
  m7 NW H N HSVO1z=?11-
36
36
  NgTH bB kH WBHWWHBHWmQgg&gggggNNN
37
37
  NNggggggNN
38
-
@@ -11,7 +11,7 @@
11
11
  #
12
12
 
13
13
  module IRB # :nodoc:
14
- VERSION = "1.2.4"
14
+ VERSION = "1.2.9"
15
15
  @RELEASE_VERSION = VERSION
16
- @LAST_UPDATE_DATE = "2020-05-02"
16
+ @LAST_UPDATE_DATE = "2020-12-22"
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
 
@@ -10,7 +10,7 @@
10
10
  #
11
11
  #
12
12
 
13
- require "irb"
13
+ require_relative "../irb"
14
14
  require_relative "frame"
15
15
 
16
16
  # An example printer for irb.
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.4
4
+ version: 1.2.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Keiju ISHITSUKA
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-02 00:00:00.000000000 Z
11
+ date: 2020-12-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: reline
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 0.0.1
19
+ version: 0.1.5
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 0.0.1
26
+ version: 0.1.5
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -116,9 +116,10 @@ files:
116
116
  - man/irb.1
117
117
  homepage: https://github.com/ruby/irb
118
118
  licenses:
119
+ - Ruby
119
120
  - BSD-2-Clause
120
121
  metadata: {}
121
- post_install_message:
122
+ post_install_message:
122
123
  rdoc_options: []
123
124
  require_paths:
124
125
  - lib
@@ -133,8 +134,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
133
134
  - !ruby/object:Gem::Version
134
135
  version: '0'
135
136
  requirements: []
136
- rubygems_version: 3.1.2
137
- signing_key:
137
+ rubygems_version: 3.1.4
138
+ signing_key:
138
139
  specification_version: 4
139
140
  summary: Interactive Ruby command-line tool for REPL (Read Eval Print Loop).
140
141
  test_files: []