mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 21:28:11 +09:00 
			
		
		
		
	* update code.gitea.io/sdk/gitea v0.13.1 -> v0.13.2 * update github.com/go-swagger/go-swagger v0.25.0 -> v0.26.0 * update github.com/google/uuid v1.1.2 -> v1.2.0 * update github.com/klauspost/compress v1.11.3 -> v1.11.7 * update github.com/lib/pq 083382b7e6fc -> v1.9.0 * update github.com/markbates/goth v1.65.0 -> v1.66.1 * update github.com/mattn/go-sqlite3 v1.14.4 -> v1.14.6 * update github.com/mgechev/revive 246eac737dc7 -> v1.0.3 * update github.com/minio/minio-go/v7 v7.0.6 -> v7.0.7 * update github.com/niklasfasching/go-org v1.3.2 -> v1.4.0 * update github.com/olivere/elastic/v7 v7.0.21 -> v7.0.22 * update github.com/pquerna/otp v1.2.0 -> v1.3.0 * update github.com/xanzy/go-gitlab v0.39.0 -> v0.42.0 * update github.com/yuin/goldmark v1.2.1 -> v1.3.1
		
			
				
	
	
		
			242 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
			
		
		
	
	
			242 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
| package runewidth
 | |
| 
 | |
| import (
 | |
| 	"os"
 | |
| 
 | |
| 	"github.com/rivo/uniseg"
 | |
| )
 | |
| 
 | |
| //go:generate go run script/generate.go
 | |
| 
 | |
| var (
 | |
| 	// EastAsianWidth will be set true if the current locale is CJK
 | |
| 	EastAsianWidth bool
 | |
| 
 | |
| 	// DefaultCondition is a condition in current locale
 | |
| 	DefaultCondition = &Condition{}
 | |
| )
 | |
| 
 | |
| func init() {
 | |
| 	handleEnv()
 | |
| }
 | |
| 
 | |
| func handleEnv() {
 | |
| 	env := os.Getenv("RUNEWIDTH_EASTASIAN")
 | |
| 	if env == "" {
 | |
| 		EastAsianWidth = IsEastAsian()
 | |
| 	} else {
 | |
| 		EastAsianWidth = env == "1"
 | |
| 	}
 | |
| 	// update DefaultCondition
 | |
| 	DefaultCondition.EastAsianWidth = EastAsianWidth
 | |
| }
 | |
| 
 | |
| type interval struct {
 | |
| 	first rune
 | |
| 	last  rune
 | |
| }
 | |
| 
 | |
| type table []interval
 | |
| 
 | |
| func inTables(r rune, ts ...table) bool {
 | |
| 	for _, t := range ts {
 | |
| 		if inTable(r, t) {
 | |
| 			return true
 | |
| 		}
 | |
| 	}
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| func inTable(r rune, t table) bool {
 | |
| 	if r < t[0].first {
 | |
| 		return false
 | |
| 	}
 | |
| 
 | |
| 	bot := 0
 | |
| 	top := len(t) - 1
 | |
| 	for top >= bot {
 | |
| 		mid := (bot + top) >> 1
 | |
| 
 | |
| 		switch {
 | |
| 		case t[mid].last < r:
 | |
| 			bot = mid + 1
 | |
| 		case t[mid].first > r:
 | |
| 			top = mid - 1
 | |
| 		default:
 | |
| 			return true
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| 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 {
 | |
| 	EastAsianWidth bool
 | |
| }
 | |
| 
 | |
| // NewCondition return new instance of Condition which is current locale.
 | |
| func NewCondition() *Condition {
 | |
| 	return &Condition{
 | |
| 		EastAsianWidth: EastAsianWidth,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // RuneWidth returns the number of cells in r.
 | |
| // See http://www.unicode.org/reports/tr11/
 | |
| func (c *Condition) RuneWidth(r rune) int {
 | |
| 	switch {
 | |
| 	case r < 0 || r > 0x10FFFF || inTables(r, nonprint, combining, notassigned):
 | |
| 		return 0
 | |
| 	case (c.EastAsianWidth && IsAmbiguousWidth(r)) || inTables(r, doublewidth):
 | |
| 		return 2
 | |
| 	default:
 | |
| 		return 1
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // StringWidth return width as you can see
 | |
| func (c *Condition) StringWidth(s string) (width int) {
 | |
| 	g := uniseg.NewGraphemes(s)
 | |
| 	for g.Next() {
 | |
| 		var chWidth int
 | |
| 		for _, r := range g.Runes() {
 | |
| 			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
 | |
| 	}
 | |
| 	return
 | |
| }
 | |
| 
 | |
| // Truncate return string truncated with w cells
 | |
| func (c *Condition) Truncate(s string, w int, tail string) string {
 | |
| 	if c.StringWidth(s) <= w {
 | |
| 		return s
 | |
| 	}
 | |
| 	w -= c.StringWidth(tail)
 | |
| 	var width int
 | |
| 	pos := len(s)
 | |
| 	g := uniseg.NewGraphemes(s)
 | |
| 	for g.Next() {
 | |
| 		var chWidth int
 | |
| 		for _, r := range g.Runes() {
 | |
| 			chWidth = c.RuneWidth(r)
 | |
| 			if chWidth > 0 {
 | |
| 				break // See StringWidth() for details.
 | |
| 			}
 | |
| 		}
 | |
| 		if width+chWidth > w {
 | |
| 			pos, _ = g.Positions()
 | |
| 			break
 | |
| 		}
 | |
| 		width += chWidth
 | |
| 	}
 | |
| 	return s[:pos] + tail
 | |
| }
 | |
| 
 | |
| // Wrap return string wrapped with w cells
 | |
| func (c *Condition) Wrap(s string, w int) string {
 | |
| 	width := 0
 | |
| 	out := ""
 | |
| 	for _, r := range []rune(s) {
 | |
| 		cw := c.RuneWidth(r)
 | |
| 		if r == '\n' {
 | |
| 			out += string(r)
 | |
| 			width = 0
 | |
| 			continue
 | |
| 		} else if width+cw > w {
 | |
| 			out += "\n"
 | |
| 			width = 0
 | |
| 			out += string(r)
 | |
| 			width += cw
 | |
| 			continue
 | |
| 		}
 | |
| 		out += string(r)
 | |
| 		width += cw
 | |
| 	}
 | |
| 	return out
 | |
| }
 | |
| 
 | |
| // FillLeft return string filled in left by spaces in w cells
 | |
| 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 s
 | |
| }
 | |
| 
 | |
| // FillRight return string filled in left by spaces in w cells
 | |
| 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
 | |
| }
 | |
| 
 | |
| // RuneWidth returns the number of cells in r.
 | |
| // See http://www.unicode.org/reports/tr11/
 | |
| func RuneWidth(r rune) int {
 | |
| 	return DefaultCondition.RuneWidth(r)
 | |
| }
 | |
| 
 | |
| // IsAmbiguousWidth returns whether is ambiguous width or not.
 | |
| func IsAmbiguousWidth(r rune) bool {
 | |
| 	return inTables(r, private, ambiguous)
 | |
| }
 | |
| 
 | |
| // IsNeutralWidth returns whether is neutral width or not.
 | |
| func IsNeutralWidth(r rune) bool {
 | |
| 	return inTable(r, neutral)
 | |
| }
 | |
| 
 | |
| // StringWidth return width as you can see
 | |
| func StringWidth(s string) (width int) {
 | |
| 	return DefaultCondition.StringWidth(s)
 | |
| }
 | |
| 
 | |
| // Truncate return string truncated with w cells
 | |
| func Truncate(s string, w int, tail string) string {
 | |
| 	return DefaultCondition.Truncate(s, w, tail)
 | |
| }
 | |
| 
 | |
| // Wrap return string wrapped with w cells
 | |
| func Wrap(s string, w int) string {
 | |
| 	return DefaultCondition.Wrap(s, w)
 | |
| }
 | |
| 
 | |
| // FillLeft return string filled in left by spaces in w cells
 | |
| func FillLeft(s string, w int) string {
 | |
| 	return DefaultCondition.FillLeft(s, w)
 | |
| }
 | |
| 
 | |
| // FillRight return string filled in left by spaces in w cells
 | |
| func FillRight(s string, w int) string {
 | |
| 	return DefaultCondition.FillRight(s, w)
 | |
| }
 |