irb 1.18.0 → 1.19.0

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: f5228c22000696caa8318b56171e1238202f103e63c470db4d215ce2d0e46625
4
- data.tar.gz: ac556bc9f4fe3abfef0310a1330d609d424c1196e4a75ba086bae789b0e973d1
3
+ metadata.gz: 1659fa380cb8e67dca7525396830d9319b6aaf5c1c4d12523a6434169f1ed442
4
+ data.tar.gz: 45978084c34df26dc1b4b963f4cceb1f40e9ec051088a8f75adecfc40f6a69c8
5
5
  SHA512:
6
- metadata.gz: fe37b6ecb5348d4cee255f42fd0be29d75b609b7edf45e0e8b6699dcb2865c4d888fbb282087acbfe2eaa9235890e60f7be80545ddb292b9adb4d4c29fd8b111
7
- data.tar.gz: 063aab58e48c5ff5e6bb5ca306ad820469c96a691d1f90d227a045c6fb2d9a5b423c76e4099a213fee21f079c52839556e13b8a8529779df982f418756eb89ff
6
+ metadata.gz: c8fb9da5edd1a1ae78623dff1d3738e99ce3d25a9c0b124b5a5e44333233a68542c1f140f700d26d4e9563cb4fafe1e3135911760bf0fb286d5f0a6bb573f1ec
7
+ data.tar.gz: d5cb86a37083e309207fee3809114aec127d90e5f54a6ec9539b1f2da3355bbe00618acd2150dc36bb98907f6e3461cab1e2b024dd2572d7453ede51c816abb5
data/Gemfile CHANGED
@@ -33,5 +33,5 @@ else
33
33
  end
34
34
 
35
35
  if RUBY_VERSION >= "3.0.0" && !is_truffleruby
36
- gem "repl_type_completor"
36
+ gem "repl_type_completor", github: "ruby/repl_type_completor"
37
37
  end
data/doc/Index.md CHANGED
@@ -98,7 +98,7 @@ To learn more about debugging with IRB, see [Debugging with IRB](#label-Debuggin
98
98
  At startup, IRB:
99
99
 
100
100
  1. Interprets (as Ruby code) the content of the [configuration file](rdoc-ref:Configurations.md) (if given).
101
- 2. Constructs the initial session context from [hash IRB.conf](#label-Hash+IRB.conf) and from default values; the hash content may have been affected by [command-line options](#command-line-options), and by direct assignments in the configuration file.
101
+ 2. Constructs the initial session context from [hash IRB.conf](rdoc-ref:Configurations.md@Hash+IRB.conf) and from default values; the hash content may have been affected by [command-line options](#command-line-options), and by direct assignments in the configuration file.
102
102
  3. Assigns the context to variable `conf`.
103
103
  4. Assigns command-line arguments to variable `ARGV`.
104
104
  5. Prints the prompt.
@@ -692,7 +692,7 @@ Command-line option `-U` sets both to UTF-8.
692
692
 
693
693
  ## Contributing
694
694
 
695
- See [CONTRIBUTING.md](https://github.com/ruby/irb/blob/main/CONTRIBUTING.md) for more information.
695
+ See [CONTRIBUTING.md](https://github.com/ruby/irb/blob/master/CONTRIBUTING.md) for more information.
696
696
 
697
697
  ## Extending IRB
698
698
 
data/lib/irb/color.rb CHANGED
@@ -99,6 +99,7 @@ module IRB # :nodoc:
99
99
  REGEXP_BEGIN: [RED, BOLD],
100
100
  REGEXP_END: [RED, BOLD],
101
101
  STRING_BEGIN: [RED, BOLD],
102
+ XSTRING_BEGIN: [RED, BOLD],
102
103
  STRING_CONTENT: [RED],
103
104
  STRING_END: [RED, BOLD],
104
105
  __END__: [GREEN],
@@ -258,6 +259,11 @@ module IRB # :nodoc:
258
259
  super
259
260
  end
260
261
 
262
+ def visit_implicit_node(_node)
263
+ # Label of implicit nodes are colored as LABEL in visit_symbol_node.
264
+ # We need to prevent value part from being colored with another type.
265
+ end
266
+
261
267
  def visit_call_node(node)
262
268
  if node.call_operator_loc.nil? && OPERATORS.include?(node.name)
263
269
  # Operators should not be colored as method call
@@ -45,7 +45,7 @@ module IRB
45
45
  def execute_internal(file_name = nil)
46
46
  raise_cmd_argument_error unless file_name
47
47
 
48
- rex = Regexp.new("#{Regexp.quote(file_name)}(\.o|\.rb)?")
48
+ rex = Regexp.new("(?:\\A|/)#{Regexp.escape(file_name)}(?:\\.o|\\.rb)?\\z")
49
49
  return false if $".find{|f| f =~ rex}
50
50
 
51
51
  case file_name
@@ -58,15 +58,15 @@ module IRB
58
58
  rescue LoadError
59
59
  end
60
60
  when /\.(so|o|sl)$/
61
- return ruby_require(file_name)
61
+ return require(file_name)
62
62
  end
63
63
 
64
64
  begin
65
65
  irb_load(f = file_name + ".rb")
66
66
  $".push f
67
- return true
67
+ true
68
68
  rescue LoadError
69
- return ruby_require(file_name)
69
+ require(file_name)
70
70
  end
71
71
  end
72
72
  end
@@ -35,13 +35,19 @@ module IRB
35
35
  end
36
36
  when :on
37
37
  added = IRB.set_measure_callback(arg)
38
- puts "#{added[0]} is added." if added
38
+ display_added_message(added[0]) if added
39
39
  else
40
40
  added = IRB.set_measure_callback(type, arg)
41
- puts "#{added[0]} is added." if added
41
+ display_added_message(added[0]) if added
42
42
  end
43
43
  nil
44
44
  end
45
+
46
+ private
47
+
48
+ def display_added_message(added)
49
+ puts "#{added} is added."
50
+ end
45
51
  end
46
52
  end
47
53
 
@@ -15,20 +15,26 @@ module IRB
15
15
  description "Show workspaces."
16
16
 
17
17
  def execute(_arg)
18
- inspection_resuls = irb_context.instance_variable_get(:@workspace_stack).map do |ws|
18
+ inspection_results = irb_context.instance_variable_get(:@workspace_stack).map do |ws|
19
19
  truncated_inspect(ws.main)
20
20
  end
21
21
 
22
- puts "[" + inspection_resuls.join(", ") + "]"
22
+ puts "[" + inspection_results.join(", ") + "]"
23
23
  end
24
24
 
25
25
  private
26
26
 
27
27
  def truncated_inspect(obj)
28
+ threshold = 20
28
29
  obj_inspection = obj.inspect
29
30
 
30
- if obj_inspection.size > 20
31
- obj_inspection = obj_inspection[0, 19] + "...>"
31
+ if obj_inspection.size > threshold
32
+ closing = obj_inspection[-1]
33
+ # Support closing characters for objects like:
34
+ # #<Object...>, [array...], {hash...}, (123/456...), "string...", /regexp.../
35
+ # Other objects will be truncated without a closing character.
36
+ closing = nil unless '>]})"/'.include?(closing)
37
+ obj_inspection = "#{obj_inspection[...threshold - 1]}...#{closing}"
32
38
  end
33
39
 
34
40
  obj_inspection
@@ -302,7 +302,7 @@ module IRB
302
302
  rescue EncodingError
303
303
  # ignore
304
304
  end
305
- candidates.grep(/^#{Regexp.quote(sym)}/)
305
+ candidates.grep(/^#{Regexp.quote(sym)}/).sort
306
306
  end
307
307
  when /^::([A-Z][^:\.\(\)]*)$/
308
308
  # Absolute Constant or class methods
@@ -313,7 +313,7 @@ module IRB
313
313
  if doc_namespace
314
314
  candidates.find { |i| i == receiver }
315
315
  else
316
- candidates.grep(/^#{Regexp.quote(receiver)}/).collect{|e| "::" + e}
316
+ candidates.grep(/^#{Regexp.quote(receiver)}/).sort.collect{|e| "::" + e}
317
317
  end
318
318
 
319
319
  when /^([A-Z].*)::([^:.]*)$/
@@ -331,7 +331,7 @@ module IRB
331
331
  candidates = []
332
332
  end
333
333
 
334
- select_message(receiver, message, candidates.sort, "::")
334
+ select_message(receiver, message, candidates, "::")
335
335
  end
336
336
 
337
337
  when /^(:[^:.]+)(\.|::)([^.]*)$/
@@ -400,7 +400,7 @@ module IRB
400
400
  if doc_namespace
401
401
  all_gvars.find{ |i| i == gvar }
402
402
  else
403
- all_gvars.grep(Regexp.new(Regexp.quote(gvar)))
403
+ all_gvars.grep(Regexp.new(Regexp.quote(gvar))).sort
404
404
  end
405
405
 
406
406
  when /^([^.:"].*)(\.|::)([^.]*)$/
@@ -452,7 +452,7 @@ module IRB
452
452
  if doc_namespace
453
453
  "String.#{candidates.find{ |i| i == message }}"
454
454
  else
455
- select_message(receiver, message, candidates.sort)
455
+ select_message(receiver, message, candidates)
456
456
  end
457
457
  when /^\s*$/
458
458
  # empty input
@@ -491,7 +491,11 @@ module IRB
491
491
  Operators = %w[% & * ** + - / < << <= <=> == === =~ > >= >> [] []= ^ ! != !~]
492
492
 
493
493
  def select_message(receiver, message, candidates, sep = ".")
494
- candidates.grep(/^#{Regexp.quote(message)}/).collect do |e|
494
+ sorted_candidates = candidates.grep(/^#{Regexp.quote(message)}/).sort_by do |e|
495
+ # Alphabetical order, but internal methods (leading underscore) last
496
+ [e.start_with?('_') ? 1 : 0, e]
497
+ end
498
+ sorted_candidates.collect do |e|
495
499
  case e
496
500
  when /^[a-zA-Z_]/
497
501
  receiver + sep + e
data/lib/irb/context.rb CHANGED
@@ -475,8 +475,8 @@ module IRB
475
475
  @prompt_c = pconf[:PROMPT_C]
476
476
  @return_format = pconf[:RETURN]
477
477
  @return_format = "%s\n" if @return_format == nil
478
- if ai = pconf.include?(:AUTO_INDENT)
479
- @auto_indent_mode = ai
478
+ if pconf.include?(:AUTO_INDENT)
479
+ @auto_indent_mode = pconf[:AUTO_INDENT]
480
480
  else
481
481
  @auto_indent_mode = IRB.conf[:AUTO_INDENT]
482
482
  end
@@ -50,7 +50,7 @@ module IRB # :nodoc:
50
50
  @eval_history_values = EvalHistory.new(no)
51
51
  IRB.conf[:__TMP__EHV__] = @eval_history_values
52
52
  workspace.evaluate("__ = IRB.conf[:__TMP__EHV__]")
53
- IRB.conf.delete(:__TMP_EHV__)
53
+ IRB.conf.delete(:__TMP__EHV__)
54
54
  end
55
55
  else
56
56
  @eval_history_values = nil
@@ -97,8 +97,8 @@ module IRB # :nodoc:
97
97
  end
98
98
 
99
99
  def size(size) # :nodoc:
100
- if size != 0 && size < @size
101
- @contents = @contents[@size - size .. @size]
100
+ if size.positive? && @contents.size > size
101
+ @contents = @contents.last(size)
102
102
  end
103
103
  @size = size
104
104
  end
@@ -13,9 +13,6 @@ module IRB # :nodoc:
13
13
  # See ExtendCommandBundle for more information.
14
14
  module IrbLoader
15
15
 
16
- alias ruby_load load
17
- alias ruby_require require
18
-
19
16
  # Loads the given file similarly to Kernel#load
20
17
  def irb_load(fn, priv = nil)
21
18
  path = search_file_from_ruby_path(fn)
data/lib/irb/history.rb CHANGED
@@ -64,13 +64,6 @@ module IRB
64
64
  def save_history
65
65
  return unless History.save_history?
66
66
  return unless (history_file = History.history_file)
67
- unless ensure_history_file_writable(history_file)
68
- warn <<~WARN
69
- Can't write history to #{History.history_file.inspect} due to insufficient permissions.
70
- Please verify the value of `IRB.conf[:HISTORY_FILE]`. Ensure the folder exists and that both the folder and file (if it exists) are writable.
71
- WARN
72
- return
73
- end
74
67
 
75
68
  history = self.class::HISTORY.to_a
76
69
 
@@ -80,36 +73,43 @@ module IRB
80
73
  append_history = true
81
74
  end
82
75
 
83
- File.open(history_file, (append_history ? "a" : "w"), 0o600, encoding: IRB.conf[:LC_MESSAGES]&.encoding) do |f|
84
- hist = history.map { |l| l.scrub.split("\n").join("\\\n") }
76
+ begin
77
+ ensure_history_file_permissions(history_file)
85
78
 
86
- unless append_history || History.infinite?
87
- # Check size before slicing because array.last(huge_number) raises RangeError.
88
- hist = hist.last(History.save_history) if hist.size > History.save_history
89
- end
79
+ File.open(history_file, (append_history ? "a" : "w"), 0o600, encoding: IRB.conf[:LC_MESSAGES]&.encoding) do |f|
80
+ hist = history.map { |l| l.scrub.split("\n").join("\\\n") }
81
+
82
+ unless append_history || History.infinite?
83
+ # Check size before slicing because array.last(huge_number) raises RangeError.
84
+ hist = hist.last(History.save_history) if hist.size > History.save_history
85
+ end
90
86
 
91
- f.puts(hist)
87
+ f.puts(hist)
88
+ end
89
+ rescue Errno::ENOENT
90
+ warn <<~WARN
91
+ Can't write history to #{History.history_file.inspect} because the folder does not exist.
92
+ Please verify the value of `IRB.conf[:HISTORY_FILE]`. Ensure the folder exists.
93
+ WARN
94
+ rescue Errno::EACCES, Errno::EPERM
95
+ warn <<~WARN
96
+ Can't write history to #{History.history_file.inspect} due to insufficient permissions.
97
+ Please verify the value of `IRB.conf[:HISTORY_FILE]`. Ensure the folder exists and that both the folder and file (if it exists) are writable.
98
+ WARN
92
99
  end
93
100
  end
94
101
 
95
102
  private
96
103
 
97
- # Returns boolean whether writing to +history_file+ will be possible.
98
104
  # Permissions of already existing +history_file+ are changed to
99
105
  # owner-only-readable if necessary [BUG #7694].
100
- def ensure_history_file_writable(history_file)
106
+ def ensure_history_file_permissions(history_file)
101
107
  history_file = Pathname.new(history_file)
102
108
 
103
- return false unless history_file.dirname.writable?
104
- return true unless history_file.exist?
109
+ return unless history_file.exist?
105
110
 
106
- begin
107
- if history_file.stat.mode & 0o66 != 0
108
- history_file.chmod 0o600
109
- end
110
- true
111
- rescue Errno::EPERM # no permissions
112
- false
111
+ if history_file.stat.mode & 0o66 != 0
112
+ history_file.chmod 0o600
113
113
  end
114
114
  end
115
115
  end
data/lib/irb/init.rb CHANGED
@@ -148,9 +148,12 @@ module IRB # :nodoc:
148
148
  @CONF[:MEASURE_PROC] = {}
149
149
  @CONF[:MEASURE_PROC][:TIME] = proc { |context, code, line_no, &block|
150
150
  time = Time.now
151
- result = block.()
152
- now = Time.now
153
- puts 'processing time: %fs' % (now - time) if IRB.conf[:MEASURE]
151
+ begin
152
+ result = block.()
153
+ ensure
154
+ now = Time.now
155
+ puts 'processing time: %fs' % (now - time) if IRB.conf[:MEASURE]
156
+ end
154
157
  result
155
158
  }
156
159
  # arg can be either a symbol for the mode (:cpu, :wall, ..) or a hash for
@@ -404,12 +404,29 @@ module IRB
404
404
  end
405
405
 
406
406
  def rdoc_dialog_contents(name, width)
407
+ formatter = RDoc::Markup::ToAnsi.new
408
+ formatter.width = width
409
+
410
+ begin
411
+ document = retrieve_rdoc_document(name)
412
+ rescue RDoc::RI::Driver::NotFoundError
413
+ return
414
+ rescue => e
415
+ raise if $DEBUG
416
+ return rdoc_error_document(e).accept(formatter).split("\n")
417
+ end
418
+ return unless document
419
+
420
+ [PRESS_ALT_D_TO_READ_FULL_DOC] + document.accept(formatter).split("\n")
421
+ end
422
+
423
+ def retrieve_rdoc_document(name)
407
424
  driver = rdoc_ri_driver
408
425
  return unless driver
409
426
 
410
427
  name = driver.expand_name(name)
411
428
 
412
- doc = if name =~ /#|\./
429
+ if name =~ /#|\./
413
430
  d = RDoc::Markup::Document.new
414
431
  driver.add_method(d, name)
415
432
  d
@@ -423,11 +440,15 @@ module IRB
423
440
  driver.class_document(name, found, klasses, includes, extends)
424
441
  end
425
442
  end
443
+ end
426
444
 
427
- formatter = RDoc::Markup::ToAnsi.new
428
- formatter.width = width
429
- [PRESS_ALT_D_TO_READ_FULL_DOC] + doc.accept(formatter).split("\n")
430
- rescue RDoc::RI::Driver::NotFoundError
445
+ def rdoc_error_document(error)
446
+ document = RDoc::Markup::Document.new
447
+ document << RDoc::Markup::Paragraph.new("Failed to load the document:")
448
+ document << RDoc::Markup::Paragraph.new("#{error.class}: #{error.message}")
449
+ document << RDoc::Markup::BlankLine.new
450
+ document << RDoc::Markup::Paragraph.new("Restart IRB with -d to see the backtrace.")
451
+ document
431
452
  end
432
453
 
433
454
  def dialog_doc_position(cursor_pos_to_render, autocomplete_dialog, screen_width)
@@ -14,7 +14,6 @@ module IRB
14
14
  '"cd object" to navigate into an object',
15
15
  '"show_source method" to view source code',
16
16
  '"copy expr" to copy the output to clipboard',
17
- '"debug" to start integration with the "debug" gem',
18
17
  '"history -g pattern" to search history',
19
18
  ].freeze
20
19
 
data/lib/irb/version.rb CHANGED
@@ -5,7 +5,7 @@
5
5
  #
6
6
 
7
7
  module IRB # :nodoc:
8
- VERSION = "1.18.0"
8
+ VERSION = "1.19.0"
9
9
  @RELEASE_VERSION = VERSION
10
- @LAST_UPDATE_DATE = "2026-04-21"
10
+ @LAST_UPDATE_DATE = "2026-11-06"
11
11
  end
data/lib/irb.rb CHANGED
@@ -53,7 +53,7 @@ module IRB
53
53
  irb = Irb.new
54
54
 
55
55
  # Only display the banner in the irb executable
56
- if @CONF[:SHOW_BANNER] && ap_path&.end_with?("exe/irb")
56
+ if @CONF[:SHOW_BANNER] && ap_path&.end_with?("exe/irb") && STDIN.tty?
57
57
  StartupMessage.display
58
58
  end
59
59
  end
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.18.0
4
+ version: 1.19.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - aycabta