Skip to content

Commit 5d13cb1

Browse files
committed
Improve VS16 matching
1 parent b79047c commit 5d13cb1

File tree

4 files changed

+31
-44
lines changed

4 files changed

+31
-44
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# CHANGELOG
22

3+
## 3.1.1
4+
5+
- Performance improvements
6+
37
## 3.1.0
48

59
**Improve Emoji support:**

lib/unicode/display_width.rb

Lines changed: 22 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,17 @@ class DisplayWidth
3030
rgi_at: :REGEX_INCLUDE_MQE_UQE,
3131
possible: :REGEX_WELL_FORMED,
3232
}
33-
REGEX_EMOJI_BASIC_OR_KEYCAP = Regexp.union(Unicode::Emoji::REGEX_BASIC, Unicode::Emoji::REGEX_EMOJI_KEYCAP)
34-
REGEX_EMOJI_ALL_SEQUENCES = Regexp.union(/.[\u{1F3FB}-\u{1F3FF}\u{FE0F}]?(\u{200D}.[\u{1F3FB}-\u{1F3FF}\u{FE0F}]?)+/, Unicode::Emoji::REGEX_EMOJI_KEYCAP)
3533
REGEX_EMOJI_NOT_POSSIBLE = /\A[#*0-9]\z/
34+
REGEX_EMOJI_VS16 = Regexp.union(
35+
Regexp.compile(
36+
Unicode::Emoji::REGEX_TEXT_PRESENTATION.source +
37+
"(?<![#*0-9])" +
38+
"\u{FE0F}"
39+
),
40+
Unicode::Emoji::REGEX_EMOJI_KEYCAP
41+
)
42+
REGEX_EMOJI_ALL_SEQUENCES = Regexp.union(/.[\u{1F3FB}-\u{1F3FF}\u{FE0F}]?(\u{200D}.[\u{1F3FB}-\u{1F3FF}\u{FE0F}]?)+/, Unicode::Emoji::REGEX_EMOJI_KEYCAP)
43+
REGEX_EMOJI_ALL_SEQUENCES_AND_VS16 = Regexp.union(REGEX_EMOJI_ALL_SEQUENCES, REGEX_EMOJI_VS16)
3644

3745
# Returns monospace display width of string
3846
def self.of(string, ambiguous = nil, overwrite = nil, old_options = {}, **options)
@@ -177,45 +185,23 @@ def self.emoji_width(string, mode = :all, ambiguous = DEFAULT_AMBIGUOUS)
177185
mode == :rgi_at,
178186
ambiguous,
179187
)
188+
180189
elsif mode == :all_no_vs16
181-
emoji_width_all(string)
190+
no_emoji_string = string.gsub(REGEX_EMOJI_ALL_SEQUENCES){ res += 2; "" }
191+
[res, no_emoji_string]
192+
182193
elsif mode == :vs16
183-
emoji_width_basic(string)
194+
no_emoji_string = string.gsub(REGEX_EMOJI_VS16){ res += 2; "" }
195+
[res, no_emoji_string]
196+
184197
elsif mode == :all
185-
res_all, string = emoji_width_all(string)
186-
res_basic, string = emoji_width_basic(string)
187-
[res_all + res_basic, string]
198+
no_emoji_string = string.gsub(REGEX_EMOJI_ALL_SEQUENCES_AND_VS16){ res += 2; "" }
199+
[res, no_emoji_string]
200+
188201
else
189202
[0, string]
190-
end
191-
end
192-
193-
# Ensure all explicit VS16 sequences have width 2
194-
def self.emoji_width_basic(string)
195-
res = 0
196203

197-
no_emoji_string = string.gsub(REGEX_EMOJI_BASIC_OR_KEYCAP){ |basic_emoji|
198-
if basic_emoji.size >= 2 # VS16 present
199-
res += 2
200-
""
201-
else
202-
basic_emoji
203-
end
204-
}
205-
206-
[res, no_emoji_string]
207-
end
208-
209-
# Use simplistic ZWJ/modifier/kecap sequence matching
210-
def self.emoji_width_all(string)
211-
res = 0
212-
213-
no_emoji_string = string.gsub(REGEX_EMOJI_ALL_SEQUENCES){
214-
res += 2
215-
""
216-
}
217-
218-
[res, no_emoji_string]
204+
end
219205
end
220206

221207
# Match possible Emoji first, then refine
@@ -241,14 +227,7 @@ def self.emoji_width_via_possible(string, emoji_set_regex, strict_eaw = false, a
241227
else
242228
if !strict_eaw
243229
# Ensure all explicit VS16 sequences have width 2
244-
emoji_candidate.gsub!(Unicode::Emoji::REGEX_BASIC){ |basic_emoji|
245-
if basic_emoji.size == 2 # VS16 present
246-
res += 2
247-
""
248-
else
249-
basic_emoji
250-
end
251-
}
230+
emoji_candidate.gsub!(REGEX_EMOJI_VS16){ res += 2; "" }
252231
end
253232

254233
emoji_candidate

spec/display_width_spec.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,10 @@
255255
it 'counts default-text presentation Emoji with Emoji Presentation (VS16) as 2' do
256256
expect( "❣️".display_width(emoji: :vs16) ).to eq 2
257257
end
258+
259+
it 'works with keycaps: width 2' do
260+
expect( "1️⃣".display_width(emoji: :vs16) ).to eq 2
261+
end
258262
end
259263

260264
describe ':rgi' do

unicode-display_width.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
1313
s.extra_rdoc_files = ["README.md", "MIT-LICENSE.txt", "CHANGELOG.md"]
1414
s.license = 'MIT'
1515
s.required_ruby_version = '>= 2.5.0'
16-
s.add_dependency 'unicode-emoji', '~> 4.0'
16+
s.add_dependency 'unicode-emoji', '~> 4.0', '>= 4.0.4'
1717
s.add_development_dependency 'rspec', '~> 3.4'
1818
s.add_development_dependency 'rake', '~> 13.0'
1919

0 commit comments

Comments
 (0)