Issue #16006 has been updated by matz (Yukihiro Matsumoto).

Status changed from Open to Rejected

The display width of a string cannot be calculated without rendering information, which Ruby usually does not have.
Considering emojis or grapheme clusters, it is nearly impossible. It's the responsibility of the rendering engine.

Matz.


----------------------------------------
Feature #16006: String count and alignment that consider multibyte characters
https://bugs.ruby-lang.org/issues/16006#change-79678

* Author: sawa (Tsuyoshi Sawada)
* Status: Rejected
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
In non-proportional font, multibyte characters have twice the width of ASCII characters. Since `String#length`, `String#ljust`, `String#rjust`, and `String#center` do not take this into consideration, applying these methods do not give the desired output.

```ruby
array = ["aaあああ", "bいいいいいいいい", "cc"]

col_width = array.max(&:length)
array.each{|w| puts w.ljust(col_width, "*")}

# >> aaあああ****
# >> bいいいいいいいい
# >> cc*******
```

In order to do justification of strings that have multi-byte characters, we have to do something much more complicated such as the following:

```ruby
col_widths =
  array.to_h{|w| [
    w,
    w
    .chars
    .partition(&:ascii_only?)
    .then{|ascii, non| ascii.length + (non.length * 2)}
  ]}
col_width = col_widths.values.max
array.each{|w| puts w + "*" * (col_width - col_widths[w])}

#  Note that the following gives the desired alignment in non-proportional font, but may not appear so in this issue tracker.
# >> aaあああ*********
# >> bいいいいいいいい
# >> cc***************
```

This issue seems to be common, as several webpages can be found that attempt to do something similar.

I propose to give the relevant methods an option to take multibyte characters into consideration. Perhaps something like the `proportional` keyword in the following may work:

```ruby
"aaあああ".length(proportional: true) # => 8
"aaあああ".ljust(17, "*", proportional: true) # => "aaあああ*********"
```

Then, the desired output would be given by this code:

```ruby
col_width = array.max{|w| w.length(proportional: true)}
array.each{|w| puts w.ljust(col_width, "*", proportional: true)}

# >> aaあああ*********
# >> bいいいいいいいい
# >> cc***************
```




-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>