runewidth_posix.go 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. //go:build !windows && !js && !appengine
  2. // +build !windows,!js,!appengine
  3. package runewidth
  4. import (
  5. "os"
  6. "regexp"
  7. "strings"
  8. )
  9. var reLoc = regexp.MustCompile(`^[a-z][a-z][a-z]?(?:_[A-Z][A-Z])?\.(.+)`)
  10. var mblenTable = map[string]int{
  11. "utf-8": 6,
  12. "utf8": 6,
  13. "jis": 8,
  14. "eucjp": 3,
  15. "euckr": 2,
  16. "euccn": 2,
  17. "sjis": 2,
  18. "cp932": 2,
  19. "cp51932": 2,
  20. "cp936": 2,
  21. "cp949": 2,
  22. "cp950": 2,
  23. "big5": 2,
  24. "gbk": 2,
  25. "gb2312": 2,
  26. }
  27. func isEastAsian(locale string) bool {
  28. charset := strings.ToLower(locale)
  29. r := reLoc.FindStringSubmatch(locale)
  30. if len(r) == 2 {
  31. charset = strings.ToLower(r[1])
  32. }
  33. if strings.HasSuffix(charset, "@cjk_narrow") {
  34. return false
  35. }
  36. for pos, b := range []byte(charset) {
  37. if b == '@' {
  38. charset = charset[:pos]
  39. break
  40. }
  41. }
  42. max := 1
  43. if m, ok := mblenTable[charset]; ok {
  44. max = m
  45. }
  46. if max > 1 && (charset[0] != 'u' ||
  47. strings.HasPrefix(locale, "ja") ||
  48. strings.HasPrefix(locale, "ko") ||
  49. strings.HasPrefix(locale, "zh")) {
  50. return true
  51. }
  52. return false
  53. }
  54. // IsEastAsian return true if the current locale is CJK
  55. func IsEastAsian() bool {
  56. locale := os.Getenv("LC_ALL")
  57. if locale == "" {
  58. locale = os.Getenv("LC_CTYPE")
  59. }
  60. if locale == "" {
  61. locale = os.Getenv("LANG")
  62. }
  63. // ignore C locale
  64. if locale == "POSIX" || locale == "C" {
  65. return false
  66. }
  67. if len(locale) > 1 && locale[0] == 'C' && (locale[1] == '.' || locale[1] == '-') {
  68. return false
  69. }
  70. return isEastAsian(locale)
  71. }