runewidth_posix.go

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