Skip to content

Conversation

@sampersand
Copy link

@sampersand sampersand commented Nov 18, 2025

This PR does a minor change to lib/irb.rb so that the .join done on error messages doesn't use $,. I use $, occasionally when debugging some older scripts, and having IRB's error messages use it is a bit annoying.

I've made another PR to reline which solves a much more egregious problem (it does this joining when printing chars out in prompts!)

Before

% irb
irb(main):001> def (Reline::Unicode).escape_for_print(str) # required until my PR for reline is merged
irb(main):002*   str.chars.map! { |gr|
irb(main):003*     case gr
irb(main):004*     when -"\n"
irb(main):005*       gr
irb(main):006*     when -"\t"
irb(main):007*       -'  '
irb(main):008*     else
irb(main):009*       Reline::Unicode::EscapedPairs[gr.ord] || gr
irb(main):010*     end
irb(main):011*   }.join('')
irb(main):012* end
=> :escape_for_print
irb(main):013> $, = '|'
=> "|"
irb(main):014> fail "oops"
(irb):14:in '<main>': oops (RuntimeError)
  from <internal:kernel>:168:in 'Kernel#loop'
| from /Users/me/.rbenv/versions/3.5.0-preview1/lib/ruby/gems/3.5.0+0/gems/irb-1.15.2/exe/irb:9:in '<top (required)>'
| from /Users/me/.rbenv/versions/3.5.0-preview1/bin/irb:25:in 'Kernel#load'
| from /Users/me/.rbenv/versions/3.5.0-preview1/bin/irb:25:in '<main>'

After

irb(main):001> def (Reline::Unicode).escape_for_print(str) # required until my PR for reline is merged
irb(main):002*   str.chars.map! { |gr|
irb(main):003*     case gr
irb(main):004*     when -"\n"
irb(main):005*       gr
irb(main):006*     when -"\t"
irb(main):007*       -'  '
irb(main):008*     else
irb(main):009*       Reline::Unicode::EscapedPairs[gr.ord] || gr
irb(main):010*     end
irb(main):011*   }.join('')
irb(main):012* end
=> :escape_for_print
irb(main):013> $, = '|'
=> "|"
irb(main):014> fail "oops"
(irb):14:in '<main>': oops (RuntimeError)
  from <internal:kernel>:168:in 'Kernel#loop'
  from /Users/me/.rbenv/versions/3.5.0-preview1/lib/ruby/gems/3.5.0+0/gems/irb-1.15.2/exe/irb:9:in '<top (required)>'
  from /Users/me/.rbenv/versions/3.5.0-preview1/bin/irb:25:in 'Kernel#load'
  from /Users/me/rbenv/versions/3.5.0-preview1/bin/irb:25:in '<main>'

@sampersand
Copy link
Author

cf ruby/reline#866 for the reline one

@tompng
Copy link
Member

tompng commented Nov 22, 2025

There are more .join, print(*args) (that uses $, for joiner character) to be fixed.
IRB depends on many other standard libraries (rdoc, reline, pp, repl_type_completor, rbs, json, and more) and it may not work if $, is overridden.
If you think this is a problem to be solved, all standard libraries should be $, override safe, please open an issue to bugs.ruby-lang.org

One way to fully support overriding $, is to set $, to nil after eval.

module IRB
  class WorkSpace
    def evaluate(statements, file = __FILE__, line = __LINE__)
      $, = somewhere.stored_dollar_comma
      eval(statements, @binding, file, line)
      somewhere.stored_dollar_comma = $,
      $, = nil
    end
  end
end

But I'm not confident if we should really support it. Changing $, is deprecated and has a serious side effect.
Rubyists can do it in their own risk and IRB gets unusable is one of the risk.
Because of this reason, some related issues are closed as not planned #143 #235 #960

For what is worth, Ruby 4.0 ships with Ruby::Box that can make a sandbox-like environment.
Here's a pull request that adds an command line option to eval inside Ruby::Box #1142

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants