Skip to content

Commit 30e130f

Browse files
committed
fix: zero-width word paste can be wrong in default repl
Signed-off-by: yihong0618 <[email protected]>
1 parent 49e83e3 commit 30e130f

File tree

3 files changed

+25
-1
lines changed

3 files changed

+25
-1
lines changed

Lib/_pyrepl/utils.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ class ColorSpan(NamedTuple):
6363
def str_width(c: str) -> int:
6464
if ord(c) < 128:
6565
return 1
66+
# gh-139246 for zero-width joiner and combining characters
67+
if unicodedata.combining(c) or unicodedata.category(c) == "Cf":
68+
return 0
6669
w = unicodedata.east_asian_width(c)
6770
if w in ("N", "Na", "H", "A"):
6871
return 1

Lib/test/test_pyrepl/test_utils.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,28 @@
55

66
class TestUtils(TestCase):
77
def test_str_width(self):
8-
characters = ['a', '1', '_', '!', '\x1a', '\u263A', '\uffb9']
8+
characters = [
9+
'a',
10+
'1',
11+
'_',
12+
'!',
13+
'\x1a',
14+
'\u263A',
15+
'\uffb9',
16+
'\N{LATIN SMALL LETTER E WITH ACUTE}', # é
17+
'\N{LATIN SMALL LETTER E WITH CEDILLA}', # ȩ
18+
]
919
for c in characters:
1020
self.assertEqual(str_width(c), 1)
1121

22+
zero_width_characters = [
23+
'\N{COMBINING ACUTE ACCENT}',
24+
'\N{ZERO WIDTH JOINER}',
25+
]
26+
for c in zero_width_characters:
27+
with self.subTest(character=c):
28+
self.assertEqual(str_width(c), 0)
29+
1230
characters = [chr(99989), chr(99999)]
1331
for c in characters:
1432
self.assertEqual(str_width(c), 2)
@@ -25,6 +43,8 @@ def test_wlen(self):
2543

2644
self.assertEqual(wlen('hello'), 5)
2745
self.assertEqual(wlen('hello' + '\x1a'), 7)
46+
self.assertEqual(wlen('e\N{COMBINING ACUTE ACCENT}'), 1)
47+
self.assertEqual(wlen('a\N{ZERO WIDTH JOINER}b'), 2)
2848

2949
def test_prev_next_window(self):
3050
def gen_normal():
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fix: paste zero-width in default repl width is wrong.

0 commit comments

Comments
 (0)