github.com/xeptore/docker-cli@v20.10.14+incompatible/cli/command/formatter/displayutils.go (about) 1 package formatter 2 3 import ( 4 "unicode/utf8" 5 6 "golang.org/x/text/width" 7 ) 8 9 // charWidth returns the number of horizontal positions a character occupies, 10 // and is used to account for wide characters when displaying strings. 11 // 12 // In a broad sense, wide characters include East Asian Wide, East Asian Full-width, 13 // (when not in East Asian context) see http://unicode.org/reports/tr11/. 14 func charWidth(r rune) int { 15 switch width.LookupRune(r).Kind() { 16 case width.EastAsianWide, width.EastAsianFullwidth: 17 return 2 18 default: 19 return 1 20 } 21 } 22 23 // Ellipsis truncates a string to fit within maxDisplayWidth, and appends ellipsis (…). 24 // For maxDisplayWidth of 1 and lower, no ellipsis is appended. 25 // For maxDisplayWidth of 1, first char of string will return even if its width > 1. 26 func Ellipsis(s string, maxDisplayWidth int) string { 27 if maxDisplayWidth <= 0 { 28 return "" 29 } 30 rs := []rune(s) 31 if maxDisplayWidth == 1 { 32 return string(rs[0]) 33 } 34 35 byteLen := len(s) 36 if byteLen == utf8.RuneCountInString(s) { 37 if byteLen <= maxDisplayWidth { 38 return s 39 } 40 return string(rs[:maxDisplayWidth-1]) + "…" 41 } 42 43 var ( 44 display []int 45 displayWidth int 46 ) 47 for _, r := range rs { 48 cw := charWidth(r) 49 displayWidth += cw 50 display = append(display, displayWidth) 51 } 52 if displayWidth <= maxDisplayWidth { 53 return s 54 } 55 for i := range display { 56 if display[i] <= maxDisplayWidth-1 && display[i+1] > maxDisplayWidth-1 { 57 return string(rs[:i+1]) + "…" 58 } 59 } 60 return s 61 }