irb 1.6.2 → 1.6.4

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.
data/lib/irb/ruby-lex.rb CHANGED
@@ -1,14 +1,8 @@
1
1
  # frozen_string_literal: false
2
2
  #
3
3
  # irb/ruby-lex.rb - ruby lexcal analyzer
4
- # $Release Version: 0.9.6$
5
- # $Revision$
6
4
  # by Keiju ISHITSUKA(keiju@ruby-lang.org)
7
5
  #
8
- # --
9
- #
10
- #
11
- #
12
6
 
13
7
  require "ripper"
14
8
  require "jruby" if RUBY_ENGINE == "jruby"
@@ -22,7 +16,8 @@ class RubyLex
22
16
  end
23
17
  end
24
18
 
25
- def initialize
19
+ def initialize(context)
20
+ @context = context
26
21
  @exp_line_no = @line_no = 1
27
22
  @indent = 0
28
23
  @continue = false
@@ -48,13 +43,13 @@ class RubyLex
48
43
  end
49
44
 
50
45
  # io functions
51
- def set_input(io, p = nil, context:, &block)
46
+ def set_input(io, &block)
52
47
  @io = io
53
48
  if @io.respond_to?(:check_termination)
54
49
  @io.check_termination do |code|
55
50
  if Reline::IOGate.in_pasting?
56
- lex = RubyLex.new
57
- rest = lex.check_termination_in_prev_line(code, context: context)
51
+ lex = RubyLex.new(@context)
52
+ rest = lex.check_termination_in_prev_line(code)
58
53
  if rest
59
54
  Reline.delete_text
60
55
  rest.bytes.reverse_each do |c|
@@ -67,12 +62,13 @@ class RubyLex
67
62
  else
68
63
  # Accept any single-line input for symbol aliases or commands that transform args
69
64
  command = code.split(/\s/, 2).first
70
- if context.symbol_alias?(command) || context.transform_args?(command)
65
+ if @context.symbol_alias?(command) || @context.transform_args?(command)
71
66
  next true
72
67
  end
73
68
 
74
69
  code.gsub!(/\s*\z/, '').concat("\n")
75
- ltype, indent, continue, code_block_open = check_state(code, context: context)
70
+ tokens = self.class.ripper_lex_without_warning(code, context: @context)
71
+ ltype, indent, continue, code_block_open = check_state(code, tokens)
76
72
  if ltype or indent > 0 or continue or code_block_open
77
73
  false
78
74
  else
@@ -85,7 +81,7 @@ class RubyLex
85
81
  @io.dynamic_prompt do |lines|
86
82
  lines << '' if lines.empty?
87
83
  result = []
88
- tokens = self.class.ripper_lex_without_warning(lines.map{ |l| l + "\n" }.join, context: context)
84
+ tokens = self.class.ripper_lex_without_warning(lines.map{ |l| l + "\n" }.join, context: @context)
89
85
  code = String.new
90
86
  partial_tokens = []
91
87
  unprocessed_tokens = []
@@ -96,8 +92,9 @@ class RubyLex
96
92
  if t.tok.include?("\n")
97
93
  t_str = t.tok
98
94
  t_str.each_line("\n") do |s|
99
- code << s << "\n"
100
- ltype, indent, continue, code_block_open = check_state(code, partial_tokens, context: context)
95
+ code << s
96
+ next unless s.include?("\n")
97
+ ltype, indent, continue, code_block_open = check_state(code, partial_tokens)
101
98
  result << @prompt.call(ltype, indent, continue || code_block_open, @line_no + line_num_offset)
102
99
  line_num_offset += 1
103
100
  end
@@ -108,29 +105,22 @@ class RubyLex
108
105
  end
109
106
 
110
107
  unless unprocessed_tokens.empty?
111
- ltype, indent, continue, code_block_open = check_state(code, unprocessed_tokens, context: context)
108
+ ltype, indent, continue, code_block_open = check_state(code, unprocessed_tokens)
112
109
  result << @prompt.call(ltype, indent, continue || code_block_open, @line_no + line_num_offset)
113
110
  end
114
111
  result
115
112
  end
116
113
  end
117
114
 
118
- if p.respond_to?(:call)
119
- @input = p
120
- elsif block_given?
115
+ if block_given?
121
116
  @input = block
122
117
  else
123
118
  @input = Proc.new{@io.gets}
124
119
  end
125
120
  end
126
121
 
127
- def set_prompt(p = nil, &block)
128
- p = block if block_given?
129
- if p.respond_to?(:call)
130
- @prompt = p
131
- else
132
- @prompt = Proc.new{print p}
133
- end
122
+ def set_prompt(&block)
123
+ @prompt = block
134
124
  end
135
125
 
136
126
  ERROR_TOKENS = [
@@ -158,19 +148,15 @@ class RubyLex
158
148
 
159
149
  compile_with_errors_suppressed(code, line_no: line_no) do |inner_code, line_no|
160
150
  lexer = Ripper::Lexer.new(inner_code, '-', line_no)
161
- if lexer.respond_to?(:scan) # Ruby 2.7+
162
- lexer.scan.each_with_object([]) do |t, tokens|
163
- next if t.pos.first == 0
164
- prev_tk = tokens.last
165
- position_overlapped = prev_tk && t.pos[0] == prev_tk.pos[0] && t.pos[1] < prev_tk.pos[1] + prev_tk.tok.bytesize
166
- if position_overlapped
167
- tokens[-1] = t if ERROR_TOKENS.include?(prev_tk.event) && !ERROR_TOKENS.include?(t.event)
168
- else
169
- tokens << t
170
- end
151
+ lexer.scan.each_with_object([]) do |t, tokens|
152
+ next if t.pos.first == 0
153
+ prev_tk = tokens.last
154
+ position_overlapped = prev_tk && t.pos[0] == prev_tk.pos[0] && t.pos[1] < prev_tk.pos[1] + prev_tk.tok.bytesize
155
+ if position_overlapped
156
+ tokens[-1] = t if ERROR_TOKENS.include?(prev_tk.event) && !ERROR_TOKENS.include?(t.event)
157
+ else
158
+ tokens << t
171
159
  end
172
- else
173
- lexer.parse.reject { |it| it.pos.first == 0 }.sort_by(&:pos)
174
160
  end
175
161
  end
176
162
  ensure
@@ -188,6 +174,7 @@ class RubyLex
188
174
  if line_count >= line_index
189
175
  return prev_spaces
190
176
  end
177
+ next if t.event == :on_tstring_content || t.event == :on_words_sep
191
178
  if (@tokens.size - 1) > i
192
179
  md = @tokens[i + 1].tok.match(/(\A +)/)
193
180
  prev_spaces = md.nil? ? 0 : md[1].count(' ')
@@ -197,11 +184,11 @@ class RubyLex
197
184
  prev_spaces
198
185
  end
199
186
 
200
- def set_auto_indent(context)
201
- if @io.respond_to?(:auto_indent) and context.auto_indent_mode
187
+ def set_auto_indent
188
+ if @io.respond_to?(:auto_indent) and @context.auto_indent_mode
202
189
  @io.auto_indent do |lines, line_index, byte_pointer, is_newline|
203
190
  if is_newline
204
- @tokens = self.class.ripper_lex_without_warning(lines[0..line_index].join("\n"), context: context)
191
+ @tokens = self.class.ripper_lex_without_warning(lines[0..line_index].join("\n"), context: @context)
205
192
  prev_spaces = find_prev_spaces(line_index)
206
193
  depth_difference = check_newline_depth_difference
207
194
  depth_difference = 0 if depth_difference < 0
@@ -210,19 +197,18 @@ class RubyLex
210
197
  code = line_index.zero? ? '' : lines[0..(line_index - 1)].map{ |l| l + "\n" }.join
211
198
  last_line = lines[line_index]&.byteslice(0, byte_pointer)
212
199
  code += last_line if last_line
213
- @tokens = self.class.ripper_lex_without_warning(code, context: context)
200
+ @tokens = self.class.ripper_lex_without_warning(code, context: @context)
214
201
  check_corresponding_token_depth(lines, line_index)
215
202
  end
216
203
  end
217
204
  end
218
205
  end
219
206
 
220
- def check_state(code, tokens = nil, context: nil)
221
- tokens = self.class.ripper_lex_without_warning(code, context: context) unless tokens
207
+ def check_state(code, tokens)
222
208
  ltype = process_literal_type(tokens)
223
209
  indent = process_nesting_level(tokens)
224
210
  continue = process_continue(tokens)
225
- lvars_code = self.class.generate_local_variables_assign_code(context.local_variables)
211
+ lvars_code = self.class.generate_local_variables_assign_code(@context.local_variables)
226
212
  code = "#{lvars_code}\n#{code}" if lvars_code
227
213
  code_block_open = check_code_block(code, tokens)
228
214
  [ltype, indent, continue, code_block_open]
@@ -243,13 +229,13 @@ class RubyLex
243
229
  @code_block_open = false
244
230
  end
245
231
 
246
- def each_top_level_statement(context)
232
+ def each_top_level_statement
247
233
  initialize_input
248
234
  catch(:TERM_INPUT) do
249
235
  loop do
250
236
  begin
251
237
  prompt
252
- unless l = lex(context)
238
+ unless l = lex
253
239
  throw :TERM_INPUT if @line == ''
254
240
  else
255
241
  @line_no += l.count("\n")
@@ -279,19 +265,19 @@ class RubyLex
279
265
  end
280
266
  end
281
267
 
282
- def lex(context)
268
+ def lex
283
269
  line = @input.call
284
270
  if @io.respond_to?(:check_termination)
285
271
  return line # multiline
286
272
  end
287
273
  code = @line + (line.nil? ? '' : line)
288
274
  code.gsub!(/\s*\z/, '').concat("\n")
289
- @tokens = self.class.ripper_lex_without_warning(code, context: context)
290
- @ltype, @indent, @continue, @code_block_open = check_state(code, @tokens, context: context)
275
+ @tokens = self.class.ripper_lex_without_warning(code, context: @context)
276
+ @ltype, @indent, @continue, @code_block_open = check_state(code, @tokens)
291
277
  line
292
278
  end
293
279
 
294
- def process_continue(tokens = @tokens)
280
+ def process_continue(tokens)
295
281
  # last token is always newline
296
282
  if tokens.size >= 2 and tokens[-2].event == :on_regexp_end
297
283
  # end of regexp literal
@@ -312,7 +298,7 @@ class RubyLex
312
298
  false
313
299
  end
314
300
 
315
- def check_code_block(code, tokens = @tokens)
301
+ def check_code_block(code, tokens)
316
302
  return true if tokens.empty?
317
303
  if tokens.last.event == :on_heredoc_beg
318
304
  return true
@@ -404,7 +390,7 @@ class RubyLex
404
390
  false
405
391
  end
406
392
 
407
- def process_nesting_level(tokens = @tokens)
393
+ def process_nesting_level(tokens)
408
394
  indent = 0
409
395
  in_oneliner_def = nil
410
396
  tokens.each_with_index { |t, index|
@@ -642,7 +628,7 @@ class RubyLex
642
628
  end
643
629
 
644
630
  case t.event
645
- when :on_ignored_nl, :on_nl, :on_comment
631
+ when :on_ignored_nl, :on_nl, :on_comment, :on_heredoc_end, :on_embdoc_end
646
632
  if in_oneliner_def != :BODY
647
633
  corresponding_token_depth = nil
648
634
  spaces_at_line_head = 0
@@ -760,7 +746,7 @@ class RubyLex
760
746
  pending_heredocs.first || start_token.last
761
747
  end
762
748
 
763
- def process_literal_type(tokens = @tokens)
749
+ def process_literal_type(tokens)
764
750
  start_token = check_string_literal(tokens)
765
751
  return nil if start_token == ""
766
752
 
@@ -781,20 +767,15 @@ class RubyLex
781
767
  when :on_qsymbols_beg then ?]
782
768
  when :on_symbols_beg then ?]
783
769
  when :on_heredoc_beg
784
- start_token&.tok =~ /<<[-~]?(['"`])[_a-zA-Z0-9]+\1/
785
- case $1
786
- when ?" then ?"
787
- when ?' then ?'
788
- when ?` then ?`
789
- else ?"
790
- end
770
+ start_token&.tok =~ /<<[-~]?(['"`])\w+\1/
771
+ $1 || ?"
791
772
  else
792
773
  nil
793
774
  end
794
775
  end
795
776
 
796
- def check_termination_in_prev_line(code, context: nil)
797
- tokens = self.class.ripper_lex_without_warning(code, context: context)
777
+ def check_termination_in_prev_line(code)
778
+ tokens = self.class.ripper_lex_without_warning(code, context: @context)
798
779
  past_first_newline = false
799
780
  index = tokens.rindex do |t|
800
781
  # traverse first token before last line
data/lib/irb/version.rb CHANGED
@@ -1,17 +1,11 @@
1
1
  # frozen_string_literal: false
2
2
  #
3
3
  # irb/version.rb - irb version definition file
4
- # $Release Version: 0.9.6$
5
- # $Revision$
6
4
  # by Keiju ISHITSUKA(keiju@ishitsuka.com)
7
5
  #
8
- # --
9
- #
10
- #
11
- #
12
6
 
13
7
  module IRB # :nodoc:
14
- VERSION = "1.6.2"
8
+ VERSION = "1.6.4"
15
9
  @RELEASE_VERSION = VERSION
16
- @LAST_UPDATE_DATE = "2022-12-13"
10
+ @LAST_UPDATE_DATE = "2023-04-07"
17
11
  end
data/lib/irb/workspace.rb CHANGED
@@ -1,14 +1,8 @@
1
1
  # frozen_string_literal: false
2
2
  #
3
3
  # irb/workspace-binding.rb -
4
- # $Release Version: 0.9.6$
5
- # $Revision$
6
4
  # by Keiju ISHITSUKA(keiju@ruby-lang.org)
7
5
  #
8
- # --
9
- #
10
- #
11
- #
12
6
 
13
7
  require "delegate"
14
8
 
@@ -115,7 +109,7 @@ EOF
115
109
  attr_reader :main
116
110
 
117
111
  # Evaluate the given +statements+ within the context of this workspace.
118
- def evaluate(context, statements, file = __FILE__, line = __LINE__)
112
+ def evaluate(statements, file = __FILE__, line = __LINE__)
119
113
  eval(statements, @binding, file, line)
120
114
  end
121
115
 
@@ -128,6 +122,8 @@ EOF
128
122
  end
129
123
 
130
124
  # error message manipulator
125
+ # WARN: Rails patches this method to filter its own backtrace. Be cautious when changing it.
126
+ # See: https://github.com/rails/rails/blob/main/railties/lib/rails/commands/console/console_command.rb#L8:~:text=def,filter_backtrace
131
127
  def filter_backtrace(bt)
132
128
  return nil if bt =~ /\/irb\/.*\.rb/
133
129
  return nil if bt =~ /\/irb\.rb/
@@ -142,11 +138,7 @@ EOF
142
138
  end
143
139
 
144
140
  def code_around_binding
145
- if @binding.respond_to?(:source_location)
146
- file, pos = @binding.source_location
147
- else
148
- file, pos = @binding.eval('[__FILE__, __LINE__]')
149
- end
141
+ file, pos = @binding.source_location
150
142
 
151
143
  if defined?(::SCRIPT_LINES__[file]) && lines = ::SCRIPT_LINES__[file]
152
144
  code = ::SCRIPT_LINES__[file].join('')
@@ -173,8 +165,5 @@ EOF
173
165
 
174
166
  "\nFrom: #{file} @ line #{pos + 1} :\n\n#{body}#{Color.clear}\n"
175
167
  end
176
-
177
- def IRB.delete_caller
178
- end
179
168
  end
180
169
  end
@@ -1,14 +1,8 @@
1
1
  # frozen_string_literal: false
2
2
  #
3
3
  # irb/ws-for-case-2.rb -
4
- # $Release Version: 0.9.6$
5
- # $Revision$
6
4
  # by Keiju ISHITSUKA(keiju@ruby-lang.org)
7
5
  #
8
- # --
9
- #
10
- #
11
- #
12
6
 
13
7
  while true
14
8
  IRB::BINDING_QUEUE.push _ = binding
data/lib/irb/xmp.rb CHANGED
@@ -1,14 +1,8 @@
1
1
  # frozen_string_literal: false
2
2
  #
3
3
  # xmp.rb - irb version of gotoken xmp
4
- # $Release Version: 0.9$
5
- # $Revision$
6
4
  # by Keiju ISHITSUKA(Nippon Rational Inc.)
7
5
  #
8
- # --
9
- #
10
- #
11
- #
12
6
 
13
7
  require_relative "../irb"
14
8
  require_relative "frame"
data/lib/irb.rb CHANGED
@@ -1,14 +1,9 @@
1
1
  # frozen_string_literal: false
2
2
  #
3
3
  # irb.rb - irb main module
4
- # $Release Version: 0.9.6 $
5
- # $Revision$
6
4
  # by Keiju ISHITSUKA(keiju@ruby-lang.org)
7
5
  #
8
- # --
9
- #
10
- #
11
- #
6
+
12
7
  require "ripper"
13
8
  require "reline"
14
9
 
@@ -421,11 +416,6 @@ module IRB
421
416
  irb.run(@CONF)
422
417
  end
423
418
 
424
- # Calls each event hook of <code>IRB.conf[:AT_EXIT]</code> when the current session quits.
425
- def IRB.irb_at_exit
426
- @CONF[:AT_EXIT].each{|hook| hook.call}
427
- end
428
-
429
419
  # Quits irb
430
420
  def IRB.irb_exit(irb, ret)
431
421
  throw :IRB_EXIT, ret
@@ -468,12 +458,16 @@ module IRB
468
458
  # be parsed as :assign and echo will be suppressed, but the latter is
469
459
  # parsed as a :method_add_arg and the output won't be suppressed
470
460
 
461
+ PROMPT_MAIN_TRUNCATE_LENGTH = 32
462
+ PROMPT_MAIN_TRUNCATE_OMISSION = '...'.freeze
463
+ CONTROL_CHARACTERS_PATTERN = "\x00-\x1F".freeze
464
+
471
465
  # Creates a new irb session
472
466
  def initialize(workspace = nil, input_method = nil)
473
467
  @context = Context.new(self, workspace, input_method)
474
468
  @context.main.extend ExtendCommandBundle
475
469
  @signal_status = :IN_IRB
476
- @scanner = RubyLex.new
470
+ @scanner = RubyLex.new(@context)
477
471
  end
478
472
 
479
473
  # A hook point for `debug` command's TracePoint after :IRB_EXIT as well as its clean-up
@@ -543,7 +537,7 @@ module IRB
543
537
  @context.io.prompt
544
538
  end
545
539
 
546
- @scanner.set_input(@context.io, context: @context) do
540
+ @scanner.set_input(@context.io) do
547
541
  signal_status(:IN_INPUT) do
548
542
  if l = @context.io.gets
549
543
  print l if @context.verbose?
@@ -561,12 +555,11 @@ module IRB
561
555
  end
562
556
  end
563
557
 
564
- @scanner.set_auto_indent(@context) if @context.auto_indent_mode
558
+ @scanner.set_auto_indent
565
559
 
566
- @scanner.each_top_level_statement(@context) do |line, line_no|
560
+ @scanner.each_top_level_statement do |line, line_no|
567
561
  signal_status(:IN_EVAL) do
568
562
  begin
569
- line.untaint if RUBY_VERSION < '2.7'
570
563
  if IRB.conf[:MEASURE] && IRB.conf[:MEASURE_CALLBACKS].empty?
571
564
  IRB.set_measure_callback
572
565
  end
@@ -780,6 +773,15 @@ module IRB
780
773
  end
781
774
  end
782
775
 
776
+ def truncate_prompt_main(str) # :nodoc:
777
+ str = str.tr(CONTROL_CHARACTERS_PATTERN, ' ')
778
+ if str.size <= PROMPT_MAIN_TRUNCATE_LENGTH
779
+ str
780
+ else
781
+ str[0, PROMPT_MAIN_TRUNCATE_LENGTH - PROMPT_MAIN_TRUNCATE_OMISSION.size] + PROMPT_MAIN_TRUNCATE_OMISSION
782
+ end
783
+ end
784
+
783
785
  def prompt(prompt, ltype, indent, line_no) # :nodoc:
784
786
  p = prompt.dup
785
787
  p.gsub!(/%([0-9]+)?([a-zA-Z])/) do
@@ -787,9 +789,9 @@ module IRB
787
789
  when "N"
788
790
  @context.irb_name
789
791
  when "m"
790
- @context.main.to_s
792
+ truncate_prompt_main(@context.main.to_s)
791
793
  when "M"
792
- @context.main.inspect
794
+ truncate_prompt_main(@context.main.inspect)
793
795
  when "l"
794
796
  ltype
795
797
  when "i"
@@ -889,11 +891,6 @@ module IRB
889
891
  ensure
890
892
  $VERBOSE = verbose
891
893
  end
892
-
893
- ATTR_TTY = "\e[%sm"
894
- def ATTR_TTY.[](*a) self % a.join(";"); end
895
- ATTR_PLAIN = ""
896
- def ATTR_PLAIN.[](*) self; end
897
894
  end
898
895
 
899
896
  def @CONF.inspect
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: irb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.2
4
+ version: 1.6.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - aycabta
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2022-12-20 00:00:00.000000000 Z
12
+ date: 2023-04-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: reline
@@ -110,7 +110,11 @@ homepage: https://github.com/ruby/irb
110
110
  licenses:
111
111
  - Ruby
112
112
  - BSD-2-Clause
113
- metadata: {}
113
+ metadata:
114
+ homepage_uri: https://github.com/ruby/irb
115
+ source_code_uri: https://github.com/ruby/irb
116
+ documentation_uri: https://github.com/ruby/irb
117
+ changelog_uri: https://github.com/ruby/irb/releases
114
118
  post_install_message:
115
119
  rdoc_options: []
116
120
  require_paths:
@@ -119,14 +123,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
119
123
  requirements:
120
124
  - - ">="
121
125
  - !ruby/object:Gem::Version
122
- version: '2.6'
126
+ version: '2.7'
123
127
  required_rubygems_version: !ruby/object:Gem::Requirement
124
128
  requirements:
125
129
  - - ">="
126
130
  - !ruby/object:Gem::Version
127
131
  version: '0'
128
132
  requirements: []
129
- rubygems_version: 3.3.7
133
+ rubygems_version: 3.4.8
130
134
  signing_key:
131
135
  specification_version: 4
132
136
  summary: Interactive Ruby command-line tool for REPL (Read Eval Print Loop).