Skip to content

Navigating multiline code blocks can cause IRB to crash and exit #239

@richardmcmillen

Description

@richardmcmillen

I am not sure if this is the right place to log this, should it be in the ruby/irb repo? Please let me know if this issue belongs anywhere else.

Description

Navigating multi-line code samples can cause IRB to crash. Using Ruby 3.0.0 with Reline 0.2.0

irb(main):001:0> irb_info
=>
Ruby version: 3.0.0
IRB version: irb 1.3.0 (2020-12-25)
InputMethod: ReidlineInputMethod with Reline 0.2.0

Steps to reproduce

  1. Install ruby 3.0.0 without readline so reline is used.
  2. Start irb
  3. Hit "
  4. Hit enter/return
  5. Hit 12

The prompt will look like this:

irb(main):001:0" "
irb(main):002:0> 12█

█ denoting the cursor position

  1. Hit the up arrow

Observed behaviour

The cursor moves to the line above directly above where it was just placed.

The terminal will look like this:

irb(main):001:0" " █
irb(main):002:0" 12
  1. Hit the left arrow

💥 An exception is thrown and IRB exits with status code 1

irb(main):001:0" " /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/reline/unicode.rb:188:in `get_next_mbchar_size': undefined method `grapheme_clusters' for nil:NilClass (NoMethodError)
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/reline/line_editor.rb:1413:in `ed_next_char'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/reline/line_editor.rb:951:in `call'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/reline/line_editor.rb:951:in `wrap_method_call'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/reline/line_editor.rb:968:in `process_key'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/reline/line_editor.rb:1076:in `input_key'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/reline.rb:247:in `block (3 levels) in inner_readline'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/reline.rb:246:in `each'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/reline.rb:246:in `block (2 levels) in inner_readline'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/reline.rb:298:in `block in read_io'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/reline.rb:284:in `loop'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/reline.rb:284:in `read_io'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/reline.rb:245:in `block in inner_readline'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/reline.rb:243:in `loop'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/reline.rb:243:in `inner_readline'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/reline.rb:175:in `readmultiline'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/forwardable.rb:238:in `readmultiline'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/forwardable.rb:238:in `readmultiline'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/irb/input-method.rb:302:in `gets'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/irb.rb:519:in `block (2 levels) in eval_input'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/irb.rb:721:in `signal_status'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/irb.rb:518:in `block in eval_input'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/irb/ruby-lex.rb:202:in `lex'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/irb/ruby-lex.rb:174:in `block (2 levels) in each_top_level_statement'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/irb/ruby-lex.rb:171:in `loop'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/irb/ruby-lex.rb:171:in `block in each_top_level_statement'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/irb/ruby-lex.rb:170:in `catch'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/irb/ruby-lex.rb:170:in `each_top_level_statement'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/irb.rb:537:in `eval_input'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/irb.rb:472:in `block in run'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/irb.rb:471:in `catch'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/irb.rb:471:in `run'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/3.0.0/irb.rb:400:in `start'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/irb-1.3.0/exe/irb:11:in `<top (required)>'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/bin/irb:23:in `load'
	from /Users/rickymcmillen/.rbenv/versions/3.0.0/bin/irb:23:in `<main>'

Expected behaviour

The cursor position is moved to the end of the line.

Ruby 2.7.2

This behaviour doesn't appear to be happening in Ruby version 2.7.2
The cursor is moved to the end of the line. Further navigation doesn't crash IRB.

irb(main):001:0" "█
irb(main):002:0" 12
irb(main):001:0> irb_info
=>
Ruby version: 2.7.2
IRB version: irb 1.2.6 (2020-09-14)
InputMethod: ReidlineInputMethod with Reline 0.1.5

Terminal Emulator

I have witnessed this happening in:

  • iTerm2 build 3.4.3
  • OSX Terminal Version 2.10 (433)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions