mirror of
https://github.com/docker/cli.git
synced 2026-08-27 10:05:33 -05:00
Merge pull request #7248 from thaJeztah/bump_runewidth
vendor: github.com/mattn/go-runewidth v0.0.28
This commit is contained in:
+1
-1
@@ -30,7 +30,7 @@ require (
|
||||
github.com/google/go-cmp v0.7.0
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/mattn/go-runewidth v0.0.24
|
||||
github.com/mattn/go-runewidth v0.0.28
|
||||
github.com/moby/go-archive v0.3.3
|
||||
github.com/moby/moby/api v1.55.0
|
||||
github.com/moby/moby/client v0.5.1
|
||||
|
||||
+2
-2
@@ -103,8 +103,8 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/mattn/go-runewidth v0.0.24 h1:cpokDiIn0MGnhdHwuWnJBITySJ20QyNGnY2kR/ay2DU=
|
||||
github.com/mattn/go-runewidth v0.0.24/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
||||
github.com/mattn/go-runewidth v0.0.28 h1:rPyg2ybwEKPebvpzVWe1gKBkH8EQFkxO4Y0hjBeLaBU=
|
||||
github.com/mattn/go-runewidth v0.0.28/go.mod h1:3qAiGCV4Koz/yuveO58qUefmUTRm8r0IGEXZ9jeHp/8=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||
|
||||
+255
-86
@@ -4,6 +4,8 @@ import (
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/clipperhouse/uax29/v2/graphemes"
|
||||
@@ -18,6 +20,14 @@ var (
|
||||
// StrictEmojiNeutral should be set false if handle broken fonts
|
||||
StrictEmojiNeutral bool = true
|
||||
|
||||
// ZeroWidthJoiner is flag to set to use UTR#51 ZWJ.
|
||||
//
|
||||
// Deprecated: ZWJ sequences are always handled through Unicode
|
||||
// grapheme cluster segmentation now, so this flag has no effect.
|
||||
// It is kept only for compatibility with code written against
|
||||
// v0.0.9 and earlier.
|
||||
ZeroWidthJoiner bool
|
||||
|
||||
// DefaultCondition is a condition in current locale
|
||||
DefaultCondition = &Condition{
|
||||
EastAsianWidth: false,
|
||||
@@ -26,20 +36,73 @@ var (
|
||||
)
|
||||
|
||||
var (
|
||||
zerowidth table // combining + nonprint merged for faster zero-width lookup
|
||||
widewidth table // ambiguous + doublewidth merged for EA path
|
||||
eastAsianWidth widthTable
|
||||
eastAsianWidth0 [0x300]byte
|
||||
zerowidth table // combining + nonprint merged for faster zero-width lookup
|
||||
widewidth table // ambiguous + doublewidth merged for EA path
|
||||
eastAsianWidth widthTable
|
||||
tablesOnce sync.Once
|
||||
|
||||
// strictWidthLUT is mostly built lazily on the first width lookup so
|
||||
// that importing the package costs neither the build time nor the 2 MB
|
||||
// of resident memory; see issue #104. Only the entries below
|
||||
// strictWidthLUTLimit are valid: init fills the first 0x300 entries of
|
||||
// both planes, and the lazy build fills the rest — never rewriting the
|
||||
// low region, so readers of it cannot race with the build. The limit
|
||||
// is loaded with acquire semantics, which makes the non-atomic reads
|
||||
// of the high region safe once it reports 0x110000. Keeping the whole
|
||||
// check down to one compare-and-branch matters: RuneWidth is only a
|
||||
// dozen instructions long.
|
||||
strictWidthLUT [2][0x110000]byte
|
||||
strictWidthLUTLimit atomic.Int32
|
||||
strictWidthLUTOnce sync.Once
|
||||
)
|
||||
|
||||
func init() {
|
||||
initStrictWidthLUTLow()
|
||||
strictWidthLUTLimit.Store(0x300)
|
||||
handleEnv()
|
||||
}
|
||||
|
||||
// initStrictWidthLUTLow paints the first 0x300 entries of strictWidthLUT
|
||||
// from the static interval tables. The result must stay identical to
|
||||
// runeWidthNoLUT for runes below 0x300, which TestStrictWidthLUT verifies.
|
||||
func initStrictWidthLUTLow() {
|
||||
for i := 0; i < 0x300; i++ {
|
||||
r := rune(i)
|
||||
w := byte(1)
|
||||
if r < 0x20 || (r >= 0x7F && r <= 0x9F) || r == 0xAD { // nonprint
|
||||
w = 0
|
||||
}
|
||||
strictWidthLUT[0][i] = w
|
||||
}
|
||||
|
||||
ea := strictWidthLUT[1][:0x300]
|
||||
fillBytes(ea, 1)
|
||||
paint := func(t table, w byte) {
|
||||
for _, iv := range t {
|
||||
if iv.first >= 0x300 {
|
||||
break
|
||||
}
|
||||
last := iv.last
|
||||
if last > 0x2FF {
|
||||
last = 0x2FF
|
||||
}
|
||||
fillBytes(ea[iv.first:last+1], w)
|
||||
}
|
||||
}
|
||||
paint(ambiguous, 2)
|
||||
paint(doublewidth, 2)
|
||||
// zero-width wins over wide on overlap, so paint it last.
|
||||
paint(combining, 0)
|
||||
paint(nonprint, 0)
|
||||
}
|
||||
|
||||
// initTables builds the merged lookup tables. It runs lazily through
|
||||
// tablesOnce so that merely importing the package stays cheap; see issue
|
||||
// #104.
|
||||
func initTables() {
|
||||
zerowidth = mergeIntervals(combining, nonprint)
|
||||
widewidth = mergeIntervals(ambiguous, doublewidth)
|
||||
eastAsianWidth = makeWidthTable(zerowidth, widewidth)
|
||||
for r := range eastAsianWidth0 {
|
||||
eastAsianWidth0[r] = byte(runeWidthEastAsian(rune(r)))
|
||||
}
|
||||
handleEnv()
|
||||
}
|
||||
|
||||
func mergeIntervals(t1, t2 table) table {
|
||||
@@ -189,50 +252,9 @@ func inWidthTable(r rune, t widthTable) (int, bool) {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func runeWidthEastAsian(r rune) int {
|
||||
if w, ok := inWidthTable(r, eastAsianWidth); ok {
|
||||
return w
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
var private = table{
|
||||
{0x00E000, 0x00F8FF}, {0x0F0000, 0x0FFFFD}, {0x100000, 0x10FFFD},
|
||||
}
|
||||
|
||||
var nonprint = table{
|
||||
{0x0000, 0x001F}, {0x007F, 0x009F}, {0x00AD, 0x00AD},
|
||||
{0x070F, 0x070F}, {0x180B, 0x180E}, {0x200B, 0x200F},
|
||||
{0x2028, 0x202E}, {0x206A, 0x206F}, {0xD800, 0xDFFF},
|
||||
{0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, {0xFFFE, 0xFFFF},
|
||||
}
|
||||
|
||||
// Condition have flag EastAsianWidth whether the current locale is CJK or not.
|
||||
type Condition struct {
|
||||
combinedLut []byte
|
||||
EastAsianWidth bool
|
||||
StrictEmojiNeutral bool
|
||||
}
|
||||
|
||||
// NewCondition return new instance of Condition which is current locale.
|
||||
func NewCondition() *Condition {
|
||||
return &Condition{
|
||||
EastAsianWidth: EastAsianWidth,
|
||||
StrictEmojiNeutral: StrictEmojiNeutral,
|
||||
}
|
||||
}
|
||||
|
||||
// RuneWidth returns the number of cells in r.
|
||||
// See http://www.unicode.org/reports/tr11/
|
||||
func (c *Condition) RuneWidth(r rune) int {
|
||||
if r < 0 || r > 0x10FFFF {
|
||||
return 0
|
||||
}
|
||||
if len(c.combinedLut) > 0 {
|
||||
return int(c.combinedLut[r>>1]>>(uint(r&1)*4)) & 3
|
||||
}
|
||||
// optimized version, verified by TestRuneWidthChecksums()
|
||||
if !c.EastAsianWidth {
|
||||
func runeWidthNoLUT(r rune, eastAsian, strictEmojiNeutral bool) int {
|
||||
tablesOnce.Do(initTables)
|
||||
if !eastAsian {
|
||||
if r < 0x20 {
|
||||
return 0
|
||||
}
|
||||
@@ -253,17 +275,145 @@ func (c *Condition) RuneWidth(r rune) int {
|
||||
}
|
||||
|
||||
if r < 0x300 {
|
||||
return int(eastAsianWidth0[r])
|
||||
return int(strictWidthLUT[1][r])
|
||||
}
|
||||
if w, ok := inWidthTable(r, eastAsianWidth); ok {
|
||||
return w
|
||||
}
|
||||
if !c.StrictEmojiNeutral && inTable(r, emoji) {
|
||||
if !strictEmojiNeutral && inTable(r, emoji) {
|
||||
return 2
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
// fillBytes sets every byte of b to v. It doubles the copied region on each
|
||||
// iteration so large slices are filled at memcpy speed instead of one byte
|
||||
// per loop iteration.
|
||||
func fillBytes(b []byte, v byte) {
|
||||
if len(b) == 0 {
|
||||
return
|
||||
}
|
||||
b[0] = v
|
||||
for i := 1; i < len(b); i *= 2 {
|
||||
copy(b[i:], b[:i])
|
||||
}
|
||||
}
|
||||
|
||||
// buildStrictWidthLUT builds the strict-width lookup table above 0x300
|
||||
// exactly once. It paints whole intervals instead of computing every rune
|
||||
// through the binary searches in runeWidthNoLUT. It must not write below
|
||||
// 0x300: that region was filled by init and may be read concurrently. The
|
||||
// result must stay identical to runeWidthNoLUT(r, eastAsian, true), which
|
||||
// TestStrictWidthLUT verifies.
|
||||
func buildStrictWidthLUT() {
|
||||
strictWidthLUTOnce.Do(func() {
|
||||
tablesOnce.Do(initTables)
|
||||
|
||||
// paintHigh fills lut with w over each interval, clipped to 0x300+.
|
||||
paintHigh := func(lut []byte, first, last rune, w byte) {
|
||||
if first < 0x300 {
|
||||
if last < 0x300 {
|
||||
return
|
||||
}
|
||||
first = 0x300
|
||||
}
|
||||
fillBytes(lut[first:last+1], w)
|
||||
}
|
||||
|
||||
// EastAsianWidth=false, StrictEmojiNeutral=true
|
||||
lut := strictWidthLUT[0][:]
|
||||
fillBytes(lut[0x300:], 1)
|
||||
for _, iv := range doublewidth {
|
||||
paintHigh(lut, iv.first, iv.last, 2)
|
||||
}
|
||||
// zerowidth is checked before doublewidth, so it wins on overlap.
|
||||
for _, iv := range zerowidth {
|
||||
paintHigh(lut, iv.first, iv.last, 0)
|
||||
}
|
||||
|
||||
// EastAsianWidth=true, StrictEmojiNeutral=true
|
||||
lut = strictWidthLUT[1][:]
|
||||
fillBytes(lut[0x300:], 1)
|
||||
for _, iv := range eastAsianWidth {
|
||||
paintHigh(lut, iv.first, iv.last, iv.width)
|
||||
}
|
||||
|
||||
strictWidthLUTLimit.Store(0x110000)
|
||||
})
|
||||
}
|
||||
|
||||
var private = table{
|
||||
{0x00E000, 0x00F8FF}, {0x0F0000, 0x0FFFFD}, {0x100000, 0x10FFFD},
|
||||
}
|
||||
|
||||
var nonprint = table{
|
||||
{0x0000, 0x001F}, {0x007F, 0x009F}, {0x00AD, 0x00AD},
|
||||
{0x070F, 0x070F}, {0x180B, 0x180E}, {0x200B, 0x200F},
|
||||
{0x2028, 0x202E}, {0x206A, 0x206F}, {0xD800, 0xDFFF},
|
||||
{0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, {0xFFFE, 0xFFFF},
|
||||
}
|
||||
|
||||
// Condition have flag EastAsianWidth whether the current locale is CJK or not.
|
||||
type Condition struct {
|
||||
combinedLut []byte
|
||||
EastAsianWidth bool
|
||||
StrictEmojiNeutral bool
|
||||
|
||||
// Deprecated: ZWJ sequences are always handled through Unicode
|
||||
// grapheme cluster segmentation now, so this flag has no effect.
|
||||
// It is kept only for compatibility with code written against
|
||||
// v0.0.9 and earlier.
|
||||
ZeroWidthJoiner bool
|
||||
}
|
||||
|
||||
// NewCondition return new instance of Condition which is current locale.
|
||||
func NewCondition() *Condition {
|
||||
return &Condition{
|
||||
EastAsianWidth: EastAsianWidth,
|
||||
StrictEmojiNeutral: StrictEmojiNeutral,
|
||||
ZeroWidthJoiner: ZeroWidthJoiner,
|
||||
}
|
||||
}
|
||||
|
||||
// RuneWidth returns the number of cells in r.
|
||||
// See http://www.unicode.org/reports/tr11/
|
||||
func (c *Condition) RuneWidth(r rune) int {
|
||||
// This one compare doubles as the range check and the lazy-LUT check:
|
||||
// out-of-range runes and runes above the built portion of
|
||||
// strictWidthLUT both take the slow path. Once the LUT is fully built
|
||||
// the limit is 0x110000 and only invalid runes go slow.
|
||||
if uint32(r) >= uint32(strictWidthLUTLimit.Load()) {
|
||||
return c.runeWidthSlow(r)
|
||||
}
|
||||
if len(c.combinedLut) > 0 {
|
||||
return int(c.combinedLut[r>>1]>>(uint(r&1)*4)) & 3
|
||||
}
|
||||
if c.StrictEmojiNeutral {
|
||||
if c.EastAsianWidth {
|
||||
return int(strictWidthLUT[1][r])
|
||||
}
|
||||
return int(strictWidthLUT[0][r])
|
||||
}
|
||||
return runeWidthNoLUT(r, c.EastAsianWidth, c.StrictEmojiNeutral)
|
||||
}
|
||||
|
||||
func (c *Condition) runeWidthSlow(r rune) int {
|
||||
if r < 0 || r > 0x10FFFF {
|
||||
return 0
|
||||
}
|
||||
buildStrictWidthLUT()
|
||||
if len(c.combinedLut) > 0 {
|
||||
return int(c.combinedLut[r>>1]>>(uint(r&1)*4)) & 3
|
||||
}
|
||||
if c.StrictEmojiNeutral {
|
||||
if c.EastAsianWidth {
|
||||
return int(strictWidthLUT[1][r])
|
||||
}
|
||||
return int(strictWidthLUT[0][r])
|
||||
}
|
||||
return runeWidthNoLUT(r, c.EastAsianWidth, c.StrictEmojiNeutral)
|
||||
}
|
||||
|
||||
// CreateLUT will create an in-memory lookup table of 557056 bytes for faster operation.
|
||||
// This should not be called concurrently with other operations on c.
|
||||
// If options in c is changed, CreateLUT should be called again.
|
||||
@@ -285,6 +435,21 @@ func (c *Condition) CreateLUT() {
|
||||
c.combinedLut = lut
|
||||
}
|
||||
|
||||
// graphemeWidth returns the width of a single grapheme cluster: the sum of
|
||||
// the widths of its runes, capped at 2 cells. The cap keeps multi-rune
|
||||
// sequences that render as a single glyph (ZWJ emoji, flags, Hangul jamo)
|
||||
// from being counted wider than the two cells terminals give them.
|
||||
func (c *Condition) graphemeWidth(cluster string) int {
|
||||
width := 0
|
||||
for _, r := range cluster {
|
||||
width += c.RuneWidth(r)
|
||||
}
|
||||
if width > 2 {
|
||||
width = 2
|
||||
}
|
||||
return width
|
||||
}
|
||||
|
||||
// StringWidth return width as you can see
|
||||
func (c *Condition) StringWidth(s string) (width int) {
|
||||
if len(s) == 1 {
|
||||
@@ -316,14 +481,7 @@ graphemes:
|
||||
width = 0
|
||||
g := graphemes.FromString(s)
|
||||
for g.Next() {
|
||||
var chWidth int
|
||||
for _, r := range g.Value() {
|
||||
chWidth = c.RuneWidth(r)
|
||||
if chWidth > 0 {
|
||||
break // Our best guess at this point is to use the width of the first non-zero-width rune.
|
||||
}
|
||||
}
|
||||
width += chWidth
|
||||
width += c.graphemeWidth(g.Value())
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -338,13 +496,7 @@ func (c *Condition) Truncate(s string, w int, tail string) string {
|
||||
pos := len(s)
|
||||
g := graphemes.FromString(s)
|
||||
for g.Next() {
|
||||
var chWidth int
|
||||
for _, r := range g.Value() {
|
||||
chWidth = c.RuneWidth(r)
|
||||
if chWidth > 0 {
|
||||
break // See StringWidth() for details.
|
||||
}
|
||||
}
|
||||
chWidth := c.graphemeWidth(g.Value())
|
||||
if width+chWidth > w {
|
||||
pos = g.Start()
|
||||
break
|
||||
@@ -365,13 +517,7 @@ func (c *Condition) TruncateLeft(s string, w int, prefix string) string {
|
||||
|
||||
g := graphemes.FromString(s)
|
||||
for g.Next() {
|
||||
var chWidth int
|
||||
for _, r := range g.Value() {
|
||||
chWidth = c.RuneWidth(r)
|
||||
if chWidth > 0 {
|
||||
break // See StringWidth() for details.
|
||||
}
|
||||
}
|
||||
chWidth := c.graphemeWidth(g.Value())
|
||||
|
||||
if width+chWidth > w {
|
||||
if width < w {
|
||||
@@ -390,6 +536,32 @@ func (c *Condition) TruncateLeft(s string, w int, prefix string) string {
|
||||
return prefix + s[pos:]
|
||||
}
|
||||
|
||||
// TruncatePrefix cuts the beginning of `s` so the result fits in w cells, with prefix prepended
|
||||
func (c *Condition) TruncatePrefix(s string, w int, prefix string) string {
|
||||
if c.StringWidth(prefix) >= w {
|
||||
return prefix
|
||||
}
|
||||
|
||||
sw := c.StringWidth(s)
|
||||
if sw <= w {
|
||||
return s
|
||||
}
|
||||
w -= c.StringWidth(prefix)
|
||||
var width int
|
||||
var pos int
|
||||
g := graphemes.FromString(s)
|
||||
for g.Next() {
|
||||
chWidth := c.graphemeWidth(g.Value())
|
||||
if sw-(width+chWidth) <= w {
|
||||
pos = g.End()
|
||||
break
|
||||
}
|
||||
width += chWidth
|
||||
}
|
||||
|
||||
return prefix + s[pos:]
|
||||
}
|
||||
|
||||
// Wrap return string wrapped with w cells
|
||||
func (c *Condition) Wrap(s string, w int) string {
|
||||
width := 0
|
||||
@@ -419,11 +591,7 @@ func (c *Condition) FillLeft(s string, w int) string {
|
||||
width := c.StringWidth(s)
|
||||
count := w - width
|
||||
if count > 0 {
|
||||
b := make([]byte, count)
|
||||
for i := range b {
|
||||
b[i] = ' '
|
||||
}
|
||||
return string(b) + s
|
||||
return strings.Repeat(" ", count) + s
|
||||
}
|
||||
return s
|
||||
}
|
||||
@@ -433,11 +601,7 @@ func (c *Condition) FillRight(s string, w int) string {
|
||||
width := c.StringWidth(s)
|
||||
count := w - width
|
||||
if count > 0 {
|
||||
b := make([]byte, count)
|
||||
for i := range b {
|
||||
b[i] = ' '
|
||||
}
|
||||
return s + string(b)
|
||||
return s + strings.Repeat(" ", count)
|
||||
}
|
||||
return s
|
||||
}
|
||||
@@ -478,6 +642,11 @@ func TruncateLeft(s string, w int, prefix string) string {
|
||||
return DefaultCondition.TruncateLeft(s, w, prefix)
|
||||
}
|
||||
|
||||
// TruncatePrefix cuts the beginning of `s` so the result fits in w cells, with prefix prepended
|
||||
func TruncatePrefix(s string, w int, prefix string) string {
|
||||
return DefaultCondition.TruncatePrefix(s, w, prefix)
|
||||
}
|
||||
|
||||
// Wrap return string wrapped with w cells
|
||||
func Wrap(s string, w int) string {
|
||||
return DefaultCondition.Wrap(s, w)
|
||||
|
||||
+37
-25
@@ -5,35 +5,50 @@ package runewidth
|
||||
|
||||
import (
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var reLoc = regexp.MustCompile(`^[a-z][a-z][a-z]?(?:_[A-Z][A-Z])?\.(.+)`)
|
||||
func mblen(charset string) int {
|
||||
switch charset {
|
||||
case "utf-8", "utf8":
|
||||
return 6
|
||||
case "jis":
|
||||
return 8
|
||||
case "eucjp":
|
||||
return 3
|
||||
case "euckr", "euccn", "sjis", "cp932", "cp51932", "cp936", "cp949", "cp950", "big5", "gbk", "gb2312":
|
||||
return 2
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
var mblenTable = map[string]int{
|
||||
"utf-8": 6,
|
||||
"utf8": 6,
|
||||
"jis": 8,
|
||||
"eucjp": 3,
|
||||
"euckr": 2,
|
||||
"euccn": 2,
|
||||
"sjis": 2,
|
||||
"cp932": 2,
|
||||
"cp51932": 2,
|
||||
"cp936": 2,
|
||||
"cp949": 2,
|
||||
"cp950": 2,
|
||||
"big5": 2,
|
||||
"gbk": 2,
|
||||
"gb2312": 2,
|
||||
// localeCharset extracts the charset part of a locale name of the form
|
||||
// "ll.CHARSET" or "ll_CC.CHARSET" (two- or three-letter language code,
|
||||
// optional uppercase country code). It returns "" if locale does not have
|
||||
// that shape.
|
||||
func localeCharset(locale string) string {
|
||||
n := 0
|
||||
for n < len(locale) && locale[n] >= 'a' && locale[n] <= 'z' {
|
||||
n++
|
||||
}
|
||||
if n < 2 || n > 3 {
|
||||
return ""
|
||||
}
|
||||
rest := locale[n:]
|
||||
if len(rest) >= 3 && rest[0] == '_' &&
|
||||
rest[1] >= 'A' && rest[1] <= 'Z' && rest[2] >= 'A' && rest[2] <= 'Z' {
|
||||
rest = rest[3:]
|
||||
}
|
||||
if len(rest) >= 2 && rest[0] == '.' {
|
||||
return rest[1:]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func isEastAsian(locale string) bool {
|
||||
charset := strings.ToLower(locale)
|
||||
r := reLoc.FindStringSubmatch(locale)
|
||||
if len(r) == 2 {
|
||||
charset = strings.ToLower(r[1])
|
||||
if cs := localeCharset(locale); cs != "" {
|
||||
charset = strings.ToLower(cs)
|
||||
}
|
||||
|
||||
if strings.HasSuffix(charset, "@cjk_narrow") {
|
||||
@@ -46,10 +61,7 @@ func isEastAsian(locale string) bool {
|
||||
break
|
||||
}
|
||||
}
|
||||
max := 1
|
||||
if m, ok := mblenTable[charset]; ok {
|
||||
max = m
|
||||
}
|
||||
max := mblen(charset)
|
||||
if max > 1 && (charset[0] != 'u' ||
|
||||
strings.HasPrefix(locale, "ja") ||
|
||||
strings.HasPrefix(locale, "ko") ||
|
||||
|
||||
+121
-17
@@ -3,23 +3,127 @@
|
||||
package runewidth
|
||||
|
||||
var combining = table{
|
||||
{0x0300, 0x036F}, {0x0483, 0x0489}, {0x07EB, 0x07F3},
|
||||
{0x0C00, 0x0C00}, {0x0C04, 0x0C04}, {0x0CF3, 0x0CF3},
|
||||
{0x0D00, 0x0D01}, {0x135D, 0x135F}, {0x180B, 0x180D},
|
||||
{0x180F, 0x180F}, {0x1A7F, 0x1A7F}, {0x1AB0, 0x1ADD},
|
||||
{0x1AE0, 0x1AEB}, {0x1B6B, 0x1B73}, {0x1DC0, 0x1DFF},
|
||||
{0x20D0, 0x20F0}, {0x2CEF, 0x2CF1}, {0x2DE0, 0x2DFF},
|
||||
{0x3099, 0x309A}, {0xA66F, 0xA672}, {0xA674, 0xA67D},
|
||||
{0xA69E, 0xA69F}, {0xA6F0, 0xA6F1}, {0xA8E0, 0xA8F1},
|
||||
{0xFE00, 0xFE0F}, {0xFE20, 0xFE2F}, {0x101FD, 0x101FD},
|
||||
{0x10376, 0x1037A}, {0x10EAB, 0x10EAC}, {0x10F46, 0x10F50},
|
||||
{0x10F82, 0x10F85}, {0x11300, 0x11301}, {0x1133B, 0x1133C},
|
||||
{0x11366, 0x1136C}, {0x11370, 0x11374}, {0x16AF0, 0x16AF4},
|
||||
{0x1CF00, 0x1CF2D}, {0x1CF30, 0x1CF46}, {0x1D165, 0x1D169},
|
||||
{0x1D16D, 0x1D172}, {0x1D17B, 0x1D182}, {0x1D185, 0x1D18B},
|
||||
{0x1D1AA, 0x1D1AD}, {0x1D242, 0x1D244}, {0x1E000, 0x1E006},
|
||||
{0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, {0x1E023, 0x1E024},
|
||||
{0x1E026, 0x1E02A}, {0x1E08F, 0x1E08F}, {0x1E8D0, 0x1E8D6},
|
||||
{0x0300, 0x036F}, {0x0483, 0x0489}, {0x0591, 0x05BD},
|
||||
{0x05BF, 0x05BF}, {0x05C1, 0x05C2}, {0x05C4, 0x05C5},
|
||||
{0x05C7, 0x05C7}, {0x0610, 0x061A}, {0x064B, 0x065F},
|
||||
{0x0670, 0x0670}, {0x06D6, 0x06DC}, {0x06DF, 0x06E4},
|
||||
{0x06E7, 0x06E8}, {0x06EA, 0x06ED}, {0x0711, 0x0711},
|
||||
{0x0730, 0x074A}, {0x07A6, 0x07B0}, {0x07EB, 0x07F3},
|
||||
{0x07FD, 0x07FD}, {0x0816, 0x0819}, {0x081B, 0x0823},
|
||||
{0x0825, 0x0827}, {0x0829, 0x082D}, {0x0859, 0x085B},
|
||||
{0x0897, 0x089F}, {0x08CA, 0x08E1}, {0x08E3, 0x0902},
|
||||
{0x093A, 0x093A}, {0x093C, 0x093C}, {0x0941, 0x0948},
|
||||
{0x094D, 0x094D}, {0x0951, 0x0957}, {0x0962, 0x0963},
|
||||
{0x0981, 0x0981}, {0x09BC, 0x09BC}, {0x09C1, 0x09C4},
|
||||
{0x09CD, 0x09CD}, {0x09E2, 0x09E3}, {0x09FE, 0x09FE},
|
||||
{0x0A01, 0x0A02}, {0x0A3C, 0x0A3C}, {0x0A41, 0x0A42},
|
||||
{0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, {0x0A51, 0x0A51},
|
||||
{0x0A70, 0x0A71}, {0x0A75, 0x0A75}, {0x0A81, 0x0A82},
|
||||
{0x0ABC, 0x0ABC}, {0x0AC1, 0x0AC5}, {0x0AC7, 0x0AC8},
|
||||
{0x0ACD, 0x0ACD}, {0x0AE2, 0x0AE3}, {0x0AFA, 0x0AFF},
|
||||
{0x0B01, 0x0B01}, {0x0B3C, 0x0B3C}, {0x0B3F, 0x0B3F},
|
||||
{0x0B41, 0x0B44}, {0x0B4D, 0x0B4D}, {0x0B55, 0x0B56},
|
||||
{0x0B62, 0x0B63}, {0x0B82, 0x0B82}, {0x0BC0, 0x0BC0},
|
||||
{0x0BCD, 0x0BCD}, {0x0C00, 0x0C00}, {0x0C04, 0x0C04},
|
||||
{0x0C3C, 0x0C3C}, {0x0C3E, 0x0C40}, {0x0C46, 0x0C48},
|
||||
{0x0C4A, 0x0C4D}, {0x0C55, 0x0C56}, {0x0C62, 0x0C63},
|
||||
{0x0C81, 0x0C81}, {0x0CBC, 0x0CBC}, {0x0CBF, 0x0CBF},
|
||||
{0x0CC6, 0x0CC6}, {0x0CCC, 0x0CCD}, {0x0CE2, 0x0CE3},
|
||||
{0x0CF3, 0x0CF3}, {0x0D00, 0x0D01}, {0x0D3B, 0x0D3C},
|
||||
{0x0D41, 0x0D44}, {0x0D4D, 0x0D4D}, {0x0D62, 0x0D63},
|
||||
{0x0D81, 0x0D81}, {0x0DCA, 0x0DCA}, {0x0DD2, 0x0DD4},
|
||||
{0x0DD6, 0x0DD6}, {0x0E31, 0x0E31}, {0x0E34, 0x0E3A},
|
||||
{0x0E47, 0x0E4E}, {0x0EB1, 0x0EB1}, {0x0EB4, 0x0EBC},
|
||||
{0x0EC8, 0x0ECE}, {0x0F18, 0x0F19}, {0x0F35, 0x0F35},
|
||||
{0x0F37, 0x0F37}, {0x0F39, 0x0F39}, {0x0F71, 0x0F7E},
|
||||
{0x0F80, 0x0F84}, {0x0F86, 0x0F87}, {0x0F8D, 0x0F97},
|
||||
{0x0F99, 0x0FBC}, {0x0FC6, 0x0FC6}, {0x102D, 0x1030},
|
||||
{0x1032, 0x1037}, {0x1039, 0x103A}, {0x103D, 0x103E},
|
||||
{0x1058, 0x1059}, {0x105E, 0x1060}, {0x1071, 0x1074},
|
||||
{0x1082, 0x1082}, {0x1085, 0x1086}, {0x108D, 0x108D},
|
||||
{0x109D, 0x109D}, {0x135D, 0x135F}, {0x1712, 0x1714},
|
||||
{0x1732, 0x1733}, {0x1752, 0x1753}, {0x1772, 0x1773},
|
||||
{0x17B4, 0x17B5}, {0x17B7, 0x17BD}, {0x17C6, 0x17C6},
|
||||
{0x17C9, 0x17D3}, {0x17DD, 0x17DD}, {0x180B, 0x180D},
|
||||
{0x180F, 0x180F}, {0x1885, 0x1886}, {0x18A9, 0x18A9},
|
||||
{0x1920, 0x1922}, {0x1927, 0x1928}, {0x1932, 0x1932},
|
||||
{0x1939, 0x193B}, {0x1A17, 0x1A18}, {0x1A1B, 0x1A1B},
|
||||
{0x1A56, 0x1A56}, {0x1A58, 0x1A5E}, {0x1A60, 0x1A60},
|
||||
{0x1A62, 0x1A62}, {0x1A65, 0x1A6C}, {0x1A73, 0x1A7C},
|
||||
{0x1A7F, 0x1A7F}, {0x1AB0, 0x1ADD}, {0x1AE0, 0x1AEB},
|
||||
{0x1B00, 0x1B03}, {0x1B34, 0x1B34}, {0x1B36, 0x1B3A},
|
||||
{0x1B3C, 0x1B3C}, {0x1B42, 0x1B42}, {0x1B6B, 0x1B73},
|
||||
{0x1B80, 0x1B81}, {0x1BA2, 0x1BA5}, {0x1BA8, 0x1BA9},
|
||||
{0x1BAB, 0x1BAD}, {0x1BE6, 0x1BE6}, {0x1BE8, 0x1BE9},
|
||||
{0x1BED, 0x1BED}, {0x1BEF, 0x1BF1}, {0x1C2C, 0x1C33},
|
||||
{0x1C36, 0x1C37}, {0x1CD0, 0x1CD2}, {0x1CD4, 0x1CE0},
|
||||
{0x1CE2, 0x1CE8}, {0x1CED, 0x1CED}, {0x1CF4, 0x1CF4},
|
||||
{0x1CF8, 0x1CF9}, {0x1DC0, 0x1DFF}, {0x20D0, 0x20F0},
|
||||
{0x2CEF, 0x2CF1}, {0x2D7F, 0x2D7F}, {0x2DE0, 0x2DFF},
|
||||
{0x302A, 0x302D}, {0x3099, 0x309A}, {0xA66F, 0xA672},
|
||||
{0xA674, 0xA67D}, {0xA69E, 0xA69F}, {0xA6F0, 0xA6F1},
|
||||
{0xA802, 0xA802}, {0xA806, 0xA806}, {0xA80B, 0xA80B},
|
||||
{0xA825, 0xA826}, {0xA82C, 0xA82C}, {0xA8C4, 0xA8C5},
|
||||
{0xA8E0, 0xA8F1}, {0xA8FF, 0xA8FF}, {0xA926, 0xA92D},
|
||||
{0xA947, 0xA951}, {0xA980, 0xA982}, {0xA9B3, 0xA9B3},
|
||||
{0xA9B6, 0xA9B9}, {0xA9BC, 0xA9BD}, {0xA9E5, 0xA9E5},
|
||||
{0xAA29, 0xAA2E}, {0xAA31, 0xAA32}, {0xAA35, 0xAA36},
|
||||
{0xAA43, 0xAA43}, {0xAA4C, 0xAA4C}, {0xAA7C, 0xAA7C},
|
||||
{0xAAB0, 0xAAB0}, {0xAAB2, 0xAAB4}, {0xAAB7, 0xAAB8},
|
||||
{0xAABE, 0xAABF}, {0xAAC1, 0xAAC1}, {0xAAEC, 0xAAED},
|
||||
{0xAAF6, 0xAAF6}, {0xABE5, 0xABE5}, {0xABE8, 0xABE8},
|
||||
{0xABED, 0xABED}, {0xFB1E, 0xFB1E}, {0xFE00, 0xFE0F},
|
||||
{0xFE20, 0xFE2F}, {0x101FD, 0x101FD}, {0x102E0, 0x102E0},
|
||||
{0x10376, 0x1037A}, {0x10A01, 0x10A03}, {0x10A05, 0x10A06},
|
||||
{0x10A0C, 0x10A0F}, {0x10A38, 0x10A3A}, {0x10A3F, 0x10A3F},
|
||||
{0x10AE5, 0x10AE6}, {0x10D24, 0x10D27}, {0x10D69, 0x10D6D},
|
||||
{0x10EAB, 0x10EAC}, {0x10EFA, 0x10EFF}, {0x10F46, 0x10F50},
|
||||
{0x10F82, 0x10F85}, {0x11001, 0x11001}, {0x11038, 0x11046},
|
||||
{0x11070, 0x11070}, {0x11073, 0x11074}, {0x1107F, 0x11081},
|
||||
{0x110B3, 0x110B6}, {0x110B9, 0x110BA}, {0x110C2, 0x110C2},
|
||||
{0x11100, 0x11102}, {0x11127, 0x1112B}, {0x1112D, 0x11134},
|
||||
{0x11173, 0x11173}, {0x11180, 0x11181}, {0x111B6, 0x111BE},
|
||||
{0x111C9, 0x111CC}, {0x111CF, 0x111CF}, {0x1122F, 0x11231},
|
||||
{0x11234, 0x11234}, {0x11236, 0x11237}, {0x1123E, 0x1123E},
|
||||
{0x11241, 0x11241}, {0x112DF, 0x112DF}, {0x112E3, 0x112EA},
|
||||
{0x11300, 0x11301}, {0x1133B, 0x1133C}, {0x11340, 0x11340},
|
||||
{0x11366, 0x1136C}, {0x11370, 0x11374}, {0x113BB, 0x113C0},
|
||||
{0x113CE, 0x113CE}, {0x113D0, 0x113D0}, {0x113D2, 0x113D2},
|
||||
{0x113E1, 0x113E2}, {0x11438, 0x1143F}, {0x11442, 0x11444},
|
||||
{0x11446, 0x11446}, {0x1145E, 0x1145E}, {0x114B3, 0x114B8},
|
||||
{0x114BA, 0x114BA}, {0x114BF, 0x114C0}, {0x114C2, 0x114C3},
|
||||
{0x115B2, 0x115B5}, {0x115BC, 0x115BD}, {0x115BF, 0x115C0},
|
||||
{0x115DC, 0x115DD}, {0x11633, 0x1163A}, {0x1163D, 0x1163D},
|
||||
{0x1163F, 0x11640}, {0x116AB, 0x116AB}, {0x116AD, 0x116AD},
|
||||
{0x116B0, 0x116B5}, {0x116B7, 0x116B7}, {0x1171D, 0x1171D},
|
||||
{0x1171F, 0x1171F}, {0x11722, 0x11725}, {0x11727, 0x1172B},
|
||||
{0x1182F, 0x11837}, {0x11839, 0x1183A}, {0x1193B, 0x1193C},
|
||||
{0x1193E, 0x1193E}, {0x11943, 0x11943}, {0x119D4, 0x119D7},
|
||||
{0x119DA, 0x119DB}, {0x119E0, 0x119E0}, {0x11A01, 0x11A0A},
|
||||
{0x11A33, 0x11A38}, {0x11A3B, 0x11A3E}, {0x11A47, 0x11A47},
|
||||
{0x11A51, 0x11A56}, {0x11A59, 0x11A5B}, {0x11A8A, 0x11A96},
|
||||
{0x11A98, 0x11A99}, {0x11B60, 0x11B60}, {0x11B62, 0x11B64},
|
||||
{0x11B66, 0x11B66}, {0x11C30, 0x11C36}, {0x11C38, 0x11C3D},
|
||||
{0x11C3F, 0x11C3F}, {0x11C92, 0x11CA7}, {0x11CAA, 0x11CB0},
|
||||
{0x11CB2, 0x11CB3}, {0x11CB5, 0x11CB6}, {0x11D31, 0x11D36},
|
||||
{0x11D3A, 0x11D3A}, {0x11D3C, 0x11D3D}, {0x11D3F, 0x11D45},
|
||||
{0x11D47, 0x11D47}, {0x11D90, 0x11D91}, {0x11D95, 0x11D95},
|
||||
{0x11D97, 0x11D97}, {0x11EF3, 0x11EF4}, {0x11F00, 0x11F01},
|
||||
{0x11F36, 0x11F3A}, {0x11F40, 0x11F40}, {0x11F42, 0x11F42},
|
||||
{0x11F5A, 0x11F5A}, {0x13440, 0x13440}, {0x13447, 0x13455},
|
||||
{0x1611E, 0x16129}, {0x1612D, 0x1612F}, {0x16AF0, 0x16AF4},
|
||||
{0x16B30, 0x16B36}, {0x16F4F, 0x16F4F}, {0x16F8F, 0x16F92},
|
||||
{0x16FE4, 0x16FE4}, {0x1BC9D, 0x1BC9E}, {0x1CF00, 0x1CF2D},
|
||||
{0x1CF30, 0x1CF46}, {0x1D165, 0x1D169}, {0x1D16D, 0x1D172},
|
||||
{0x1D17B, 0x1D182}, {0x1D185, 0x1D18B}, {0x1D1AA, 0x1D1AD},
|
||||
{0x1D242, 0x1D244}, {0x1DA00, 0x1DA36}, {0x1DA3B, 0x1DA6C},
|
||||
{0x1DA75, 0x1DA75}, {0x1DA84, 0x1DA84}, {0x1DA9B, 0x1DA9F},
|
||||
{0x1DAA1, 0x1DAAF}, {0x1E000, 0x1E006}, {0x1E008, 0x1E018},
|
||||
{0x1E01B, 0x1E021}, {0x1E023, 0x1E024}, {0x1E026, 0x1E02A},
|
||||
{0x1E08F, 0x1E08F}, {0x1E130, 0x1E136}, {0x1E2AE, 0x1E2AE},
|
||||
{0x1E2EC, 0x1E2EF}, {0x1E4EC, 0x1E4EF}, {0x1E5EE, 0x1E5EF},
|
||||
{0x1E6E3, 0x1E6E3}, {0x1E6E6, 0x1E6E6}, {0x1E6EE, 0x1E6EF},
|
||||
{0x1E6F5, 0x1E6F5}, {0x1E8D0, 0x1E8D6}, {0x1E944, 0x1E94A},
|
||||
{0xE0100, 0xE01EF},
|
||||
}
|
||||
|
||||
|
||||
Vendored
+2
-2
@@ -156,8 +156,8 @@ github.com/klauspost/compress/internal/le
|
||||
github.com/klauspost/compress/internal/snapref
|
||||
github.com/klauspost/compress/zstd
|
||||
github.com/klauspost/compress/zstd/internal/xxhash
|
||||
# github.com/mattn/go-runewidth v0.0.24
|
||||
## explicit; go 1.20
|
||||
# github.com/mattn/go-runewidth v0.0.28
|
||||
## explicit; go 1.23
|
||||
github.com/mattn/go-runewidth
|
||||
# github.com/moby/docker-image-spec v1.3.1
|
||||
## explicit; go 1.18
|
||||
|
||||
Reference in New Issue
Block a user