Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1import unicodedata 

2from functools import lru_cache 

3 

4 

5@lru_cache(100) 

6def wcwidth(c: str) -> int: 

7 """Determine how many columns are needed to display a character in a terminal. 

8 

9 Returns -1 if the character is not printable. 

10 Returns 0, 1 or 2 for other characters. 

11 """ 

12 o = ord(c) 

13 

14 # ASCII fast path. 

15 if 0x20 <= o < 0x07F: 

16 return 1 

17 

18 # Some Cf/Zp/Zl characters which should be zero-width. 

19 if ( 

20 o == 0x0000 

21 or 0x200B <= o <= 0x200F 

22 or 0x2028 <= o <= 0x202E 

23 or 0x2060 <= o <= 0x2063 

24 ): 

25 return 0 

26 

27 category = unicodedata.category(c) 

28 

29 # Control characters. 

30 if category == "Cc": 

31 return -1 

32 

33 # Combining characters with zero width. 

34 if category in ("Me", "Mn"): 

35 return 0 

36 

37 # Full/Wide east asian characters. 

38 if unicodedata.east_asian_width(c) in ("F", "W"): 

39 return 2 

40 

41 return 1 

42 

43 

44def wcswidth(s: str) -> int: 

45 """Determine how many columns are needed to display a string in a terminal. 

46 

47 Returns -1 if the string contains non-printable characters. 

48 """ 

49 width = 0 

50 for c in unicodedata.normalize("NFC", s): 

51 wc = wcwidth(c) 

52 if wc < 0: 

53 return -1 

54 width += wc 

55 return width