Bug #17405
closedirb ---nomultiline gets exception when output contains some non-ascii characters
Description
When irb is called with the --nomultiline option (for example, when called from emacs), then if the output contains some special characters (such as the square root sign, or a single quotation mark), then irb gets an exception.
Without the --multiline option the problem does not happen.
Here is an example with a string assignment to variable m.
Without fix: Without --nomultiline there is no problem:
henry:tmp richard$ irb
irb(main):001:0> source 'test.rb'
test.rb(main):002:0> # coding: utf-8
=> nil
test.rb(main):003:0> m = "√10"
=> "√10"
test.rb(main):004:0> m
=> "√10"
=> nil
But with --nomultiline irb gets an exception (but the assignment did work):
henry:tmp richard$ irb --nomultiline
irb(main):001:0> source 'test.rb'
test.rb(main):002:0> # coding: utf-8
=> nil
test.rb(main):003:0> m = "√10"
Traceback (most recent call last):
8: from /Users/richard/.rbenv/versions/2.7.2/bin/irb:23:in <main>' 7: from /Users/richard/.rbenv/versions/2.7.2/bin/irb:23:in
load'
6: from /Users/richard/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/irb-1.2.6/exe/irb:11:in <top (required)>' 5: from (irb):1 4: from /Users/richard/.rbenv/versions/2.7.2/lib/ruby/2.7.0/reline/unicode.rb:99:in
calculate_width'
3: from /Users/richard/.rbenv/versions/2.7.2/lib/ruby/2.7.0/reline/unicode.rb:99:in scan' 2: from /Users/richard/.rbenv/versions/2.7.2/lib/ruby/2.7.0/reline/unicode.rb:108:in
block in calculate_width'
1: from /Users/richard/.rbenv/versions/2.7.2/lib/ruby/2.7.0/reline/unicode.rb:108:in `+'
TypeError (nil can't be coerced into Integer)
test.rb(main):004:0> m
=> "√10"
=> nil
The problem is that in method get_mbchar_width of class Reline::Unicode Reline.ambiguous_width can have a nil value, whereas the code seems to expect a low integer (unicode.rb line 84). This causes method calculate_width to add a nil value to width (line 109).
I don’t know what value Reline.ambiguous_width should be in these cases; the simple change below uses a value of 1 to avoid the exception:
bash-5.1$ diff unicode.rb{.orig,}
84c84,85
< Reline.ambiguous_width
---
> width = Reline.ambiguous_width
> width.nil? ? 1 : width # if nil then assume 1
bash-5.1$
With above fix:
henry:tmp richard$ irb --nomultiline
irb(main):001:0> source 'test.rb'
test.rb(main):002:0> # coding: utf-8
=> nil
test.rb(main):003:0> m = "√10"
=> "√10"
test.rb(main):004:0> m
=> "√10"
=> nil
henry:tmp richard$
Files
Updated by ima1zumi (Mari Imaizumi) about 4 years ago
Thank you for your notice.
However, this bug has already been fixed in the latest version.
❯ bin/console --nomultiline
irb(main):002:0> Reline::VERSION
=> "0.1.10"
irb(main):003:0> source 'test.rb'
test.rb(main):004:0> # coding: utf-8
=> nil
test.rb(main):005:0> m = "√10"
test.rb(main):006:0> m
=> "√10"
=> nil
Updated by marcandre (Marc-Andre Lafortune) about 4 years ago
- Assignee set to aycabta (aycabta .)
- ruby -v changed from ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-darwin17] to ruby 3.0.0dev (2020-12-21T02:23:01Z master ac78d90d5e) [x86_64-darwin18]
I can reproduce on master
. Maybe platform dependent?
Hopefully @aycabta (aycabta .) will figure something out...
$ ruby -v
ruby 3.0.0dev (2020-12-21T02:23:01Z master ac78d90d5e) [x86_64-darwin18]
$ irb --nomultiline
irb(main):001:0> Reline::VERSION
=> "0.1.10"
irb(main):001:0> source 'test.rb'
test.rb(main):002:0> # coding: utf-8
=> nil
test.rb(main):003:0> m = "√10"
Traceback (most recent call last):
8: from /Users/mal/.rbenv/versions/3/bin/irb:23:in `<main>'
7: from /Users/mal/.rbenv/versions/3/bin/irb:23:in `load'
6: from /Users/mal/.rbenv/versions/3.0.0-dev/lib/ruby/gems/3.0.0/gems/irb-1.2.8/exe/irb:11:in `<top (required)>'
5: from (irb):1:in `<main>'
4: from /Users/mal/.rbenv/versions/3.0.0-dev/lib/ruby/3.0.0/reline/unicode.rb:126:in `calculate_width'
3: from /Users/mal/.rbenv/versions/3.0.0-dev/lib/ruby/3.0.0/reline/unicode.rb:126:in `scan'
2: from /Users/mal/.rbenv/versions/3.0.0-dev/lib/ruby/3.0.0/reline/unicode.rb:136:in `block in calculate_width'
1: from /Users/mal/.rbenv/versions/3.0.0-dev/lib/ruby/3.0.0/reline/unicode.rb:136:in `+'
TypeError (nil can't be coerced into Integer)
test.rb(main):004:0> m
=> "√10"
=> nil
Updated by aycabta (aycabta .) about 4 years ago
@rsharman (Richard Sharman) and @marcandre (Marc-Andre Lafortune), would you show me the result of irb_info
command in IRB and what terminal emulator you are using?
Updated by aycabta (aycabta .) about 4 years ago
And, does https://github.com/ruby/reline/pull/224 resolve the problem? I can't reproduce in my environment...
Updated by marcandre (Marc-Andre Lafortune) about 4 years ago
aycabta (aycabta .) wrote in #note-3:
@rsharman (Richard Sharman) and @marcandre (Marc-Andre Lafortune), would you show me the result of
irb_info
command in IRB and what terminal emulator you are using?
irb(main):001:0> irb_info
=>
Ruby version: 3.0.0
IRB version: irb 1.2.8 (2020-12-20)
InputMethod: ReidlineInputMethod with Reline 0.1.10
.irbrc path: /Users/mal/.irbrc
Using iTerm2, Build 3.4.3, but reproduced also on Terminal.app Version 2.9.5 (421.2)
If Richard Sharman can try your patch that would be great, lots of things I'd like to finish before 3.0
Updated by osyo (manga osyo) about 4 years ago
hi.
This error is caused by calling Reline::Unicode.calculate_width
in irb
.
Reline::Unicode.calculate_width
should be initialized with #may_req_ambiguous_char_width
inside Reline.
However, in the case of --nomultiline
, #may_req_ambiguous_char_width
is not called and is not initialized because Reline is not used.
This was causing the call to Reline::Unicode.calculate_width
to fail, resulting in an error.
This problem has been solved by explicitly calling #may_req_ambiguous_char_width
inside Reline::Unicode.calculate_width
.
PR is merged : https://github.com/ruby/reline/pull/224
Updated by ima1zumi (Mari Imaizumi) about 4 years ago
- Status changed from Open to Closed
Applied in changeset git|299f5708a2274d069c624073ca3958f8625faf35.
[ruby/reline] Fixed an exception occurred when ambiguous width character was passed to #calculate_width
[Bug #17405]
Updated by rsharman (Richard Sharman) almost 4 years ago
Sorry not to have checked back recently. The patch mentioned above works great for me.
I doubt if this is required now but here it is:
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
.irbrc path: /Users/richard/.irbrc
irb(main):002:0>