aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorima1zumi <mariimaizumi5@gmail.com>2020-12-11 22:18:36 +0900
committeraycabta <aycabta@gmail.com>2020-12-11 23:08:06 +0900
commit68d3952c52de3b7cf4aba10d61085244f1bf449b (patch)
tree2bc7a4cb74e5ef3b90dabc53ed263ac3ec356bba
parented343c76fbd94dfcd429668b72844e0db87a0b46 (diff)
downloadruby-68d3952c52de3b7cf4aba10d61085244f1bf449b.tar.gz
[ruby/reline] Fix breaking to input Emoji with ZWJ.
https://github.com/ruby/reline/commit/f21dfdbb11
-rw-r--r--lib/reline/line_editor.rb5
-rw-r--r--test/reline/test_key_actor_emacs.rb62
2 files changed, 67 insertions, 0 deletions
diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb
index 236993ffb0..df4903c9c4 100644
--- a/lib/reline/line_editor.rb
+++ b/lib/reline/line_editor.rb
@@ -1265,7 +1265,12 @@ class Reline::LineEditor
else
@line = byteinsert(@line, @byte_pointer, str)
end
+ last_byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @byte_pointer)
@byte_pointer += bytesize
+ last_mbchar = @line.byteslice((@byte_pointer - bytesize - last_byte_size), last_byte_size)
+ if last_byte_size != 0 and (last_mbchar + str).grapheme_clusters.size == 1
+ width = 0
+ end
@cursor += width
@cursor_max += width
end
diff --git a/test/reline/test_key_actor_emacs.rb b/test/reline/test_key_actor_emacs.rb
index a4b3b1c28f..275ff0e160 100644
--- a/test/reline/test_key_actor_emacs.rb
+++ b/test/reline/test_key_actor_emacs.rb
@@ -2105,6 +2105,68 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
assert_line('')
end
+ # Unicode emoji test
+ if RELINE_TEST_ENCODING == Encoding::UTF_8
+ def test_ed_insert_for_include_zwj_emoji
+ # U+1F468 U+200D U+1F469 U+200D U+1F467 U+200D U+1F466 is family: man, woman, girl, boy "๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ"
+ input_keys("\u{1F468}") # U+1F468 is man "๐Ÿ‘จ"
+ assert_line("\u{1F468}")
+ assert_byte_pointer_size("\u{1F468}")
+ assert_cursor(2)
+ assert_cursor_max(2)
+ input_keys("\u200D") # U+200D is ZERO WIDTH JOINER
+ assert_line("\u{1F468 200D}")
+ assert_byte_pointer_size("\u{1F468 200D}")
+ assert_cursor(2)
+ assert_cursor_max(2)
+ input_keys("\u{1F469}") # U+1F469 is woman "๐Ÿ‘ฉ"
+ assert_line("\u{1F468 200D 1F469}")
+ assert_byte_pointer_size("\u{1F468 200D 1F469}")
+ assert_cursor(2)
+ assert_cursor_max(2)
+ input_keys("\u200D") # U+200D is ZERO WIDTH JOINER
+ assert_line("\u{1F468 200D 1F469 200D}")
+ assert_byte_pointer_size("\u{1F468 200D 1F469 200D}")
+ assert_cursor(2)
+ assert_cursor_max(2)
+ input_keys("\u{1F467}") # U+1F467 is girl "๐Ÿ‘ง"
+ assert_line("\u{1F468 200D 1F469 200D 1F467}")
+ assert_byte_pointer_size("\u{1F468 200D 1F469 200D 1F467}")
+ assert_cursor(2)
+ assert_cursor_max(2)
+ input_keys("\u200D") # U+200D is ZERO WIDTH JOINER
+ assert_line("\u{1F468 200D 1F469 200D 1F467 200D}")
+ assert_byte_pointer_size("\u{1F468 200D 1F469 200D 1F467 200D}")
+ assert_cursor(2)
+ assert_cursor_max(2)
+ input_keys("\u{1F466}") # U+1F466 is boy "๐Ÿ‘ฆ"
+ assert_line("\u{1F468 200D 1F469 200D 1F467 200D 1F466}")
+ assert_byte_pointer_size("\u{1F468 200D 1F469 200D 1F467 200D 1F466}")
+ assert_cursor(2)
+ assert_cursor_max(2)
+ # U+1F468 U+200D U+1F469 U+200D U+1F467 U+200D U+1F466 is family: man, woman, girl, boy "๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ"
+ input_keys("\u{1F468 200D 1F469 200D 1F467 200D 1F466}")
+ assert_line("\u{1F468 200D 1F469 200D 1F467 200D 1F466 1F468 200D 1F469 200D 1F467 200D 1F466}")
+ assert_byte_pointer_size("\u{1F468 200D 1F469 200D 1F467 200D 1F466 1F468 200D 1F469 200D 1F467 200D 1F466}")
+ assert_cursor(4)
+ assert_cursor_max(4)
+ end
+
+ def test_ed_insert_for_include_valiation_selector
+ # U+0030 U+FE00 is DIGIT ZERO + VARIATION SELECTOR-1 "0๏ธ€"
+ input_keys("\u0030") # U+0030 is DIGIT ZERO
+ assert_line("\u0030")
+ assert_byte_pointer_size("\u0030")
+ assert_cursor(1)
+ assert_cursor_max(1)
+ input_keys("\uFE00") # U+FE00 is VARIATION SELECTOR-1
+ assert_line("\u{0030 FE00}")
+ assert_byte_pointer_size("\u{0030 FE00}")
+ assert_cursor(1)
+ assert_cursor_max(1)
+ end
+ end
+
=begin # TODO: move KeyStroke instance from Reline to LineEditor
def test_key_delete
input_keys('ab')