runewidth_posix.go

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