Skip to content

Commit

Permalink
Fix alignment of multi-byte fullwidth character comments (#575)
Browse files Browse the repository at this point in the history
This fixes alignment of Japanese, Korean and Chinese fullwidth character comments.

The displayed widths of multi-byte fullwidth characters are generally
twice as large as the ASCII characters, but String#size returns only the number of characters.
So if the column comment contains fullwidth multibyte characters, the alignment is broken.
  • Loading branch information
oieioi authored and ctran committed Sep 9, 2018
1 parent ca4090d commit 2614266
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 2 deletions.
18 changes: 16 additions & 2 deletions lib/annotate/annotate_models.rb
Expand Up @@ -301,7 +301,7 @@ def get_schema_info(klass, header, options = {})
type_remainder = (md_type_allowance - 2) - col_type.length
info << (sprintf("# **`%s`**%#{name_remainder}s | `%s`%#{type_remainder}s | `%s`", col_name, " ", col_type, " ", attrs.join(", ").rstrip)).gsub('``', ' ').rstrip + "\n"
else
info << sprintf("# %-#{max_size}.#{max_size}s:%-#{bare_type_allowance}.#{bare_type_allowance}s %s", col_name, col_type, attrs.join(", ")).rstrip + "\n"
info << format_default(col_name, max_size, col_type, bare_type_allowance, attrs)
end
end

Expand Down Expand Up @@ -884,7 +884,7 @@ def with_comments?(klass, options)
def max_schema_info_width(klass, options)
if with_comments?(klass, options)
max_size = klass.columns.map do |column|
column.name.size + (column.comment ? column.comment.size : 0)
column.name.size + (column.comment ? width(column.comment) : 0)
end.max || 0
max_size += 2
else
Expand All @@ -894,6 +894,20 @@ def max_schema_info_width(klass, options)

max_size
end

def format_default(col_name, max_size, col_type, bare_type_allowance, attrs)
sprintf("# %s:%s %s", mb_chars_ljust(col_name, max_size), mb_chars_ljust(col_type, bare_type_allowance), attrs.join(", ")).rstrip + "\n"
end

def width(string)
string.chars.inject(0) { |acc, elem| acc + (elem.bytesize == 1 ? 1 : 2) }
end

def mb_chars_ljust(string, length)
string = string.to_s
padding = length - width(string)
string + (' ' * padding)
end
end

class BadModelFileError < LoadError
Expand Down
23 changes: 23 additions & 0 deletions spec/annotate/annotate_models_spec.rb
Expand Up @@ -936,6 +936,29 @@ def self.when_called_with(options = {})
# notes(Notes) :text(55) not null
# no_comment :text(20) not null
#
EOS

mocked_columns_with_multibyte_comment = [
[:id, :integer, { limit: 8, comment: 'ID' }],
[:active, :boolean, { limit: 1, comment: 'ACTIVE' }],
[:name, :string, { limit: 50, comment: 'NAME' }],
[:notes, :text, { limit: 55, comment: 'NOTES' }],
[:no_comment, :text, { limit: 20, comment: nil }]
]

when_called_with with_comment: 'yes',
with_columns: mocked_columns_with_multibyte_comment, returns:
<<-EOS.strip_heredoc
# Schema Info
#
# Table name: users
#
# id(ID) :integer not null, primary key
# active(ACTIVE) :boolean not null
# name(NAME) :string(50) not null
# notes(NOTES) :text(55) not null
# no_comment :text(20) not null
#
EOS

it 'should get schema info as RDoc' do
Expand Down

0 comments on commit 2614266

Please sign in to comment.