Project

General

Profile

Feature #16006

Updated by sawa (Tsuyoshi Sawada) about 2 years ago

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 multi-byte characters into consideration. Perhaps something like the `proportional` `non_ascii` keyword in the following may work: 

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

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

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

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

Back