irb 1.2.4 → 1.2.9

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: 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: []