diff --git a/lib/unicode/display_width.rb b/lib/unicode/display_width.rb index a95a77e..48381b8 100644 --- a/lib/unicode/display_width.rb +++ b/lib/unicode/display_width.rb @@ -61,8 +61,9 @@ def self.of(string, ambiguous = nil, overwrite = nil, old_options = {}, **option width = 0 - unless options[:overwrite].empty? - width, string = width_custom(string, options[:overwrite]) + overwrite = options[:overwrite] + unless overwrite.respond_to?(:empty?) && overwrite.empty? + width, string = width_custom(string, overwrite) end if string.ascii_only? @@ -118,8 +119,8 @@ def self.width_custom(string, overwrite) width = 0 string = string.each_codepoint.select{ |codepoint| - if overwrite[codepoint] - width += overwrite[codepoint] + if overwrite_width = overwrite[codepoint] + width += overwrite_width nil else codepoint @@ -211,7 +212,7 @@ def self.normalize_options(string, ambiguous = nil, overwrite = nil, old_options raise ArgumentError, "Unicode::DisplayWidth: Ambiguous width must be 1 or 2" end - if overwrite && !overwrite.empty? + if overwrite && (!overwrite.respond_to?(:empty?) || !overwrite.empty?) warn "Unicode::DisplayWidth: Please migrate to keyword arguments - overwrite: #{overwrite.inspect}" options[:overwrite] = overwrite end diff --git a/spec/display_width_spec.rb b/spec/display_width_spec.rb index 067dd97..7afdfcc 100644 --- a/spec/display_width_spec.rb +++ b/spec/display_width_spec.rb @@ -3,6 +3,24 @@ require_relative '../lib/unicode/display_width/string_ext' describe 'Unicode::DisplayWidth.of' do + describe 'overwrite fast path' do + it 'skips custom processing for omitted, nil, false and empty overwrites' do + expect(Unicode::DisplayWidth).not_to receive(:width_custom) + expect(Unicode::DisplayWidth.of('ABC')).to eq 3 + [nil, false, {}, double(empty?: true)].each do |overwrite| + expect(Unicode::DisplayWidth.of('ABC', overwrite: overwrite)).to eq 3 + end + end + + it 'applies non-empty hashes, procs and lookup objects' do + lookup = double(empty?: false) + allow(lookup).to receive(:[]).with(65).and_return(4) + [{65 => 4}, ->(codepoint) { 4 if codepoint == 65 }, lookup].each do |overwrite| + expect(Unicode::DisplayWidth.of('A', overwrite: overwrite)).to eq 4 + end + end + end + describe '[east asian width]' do it 'returns 2 for F' do expect( '!'.display_width ).to eq 2