package internal import ( "crypto/rand" "encoding/base64" "math/big" "runtime" "strings" "unicode/utf16" "unicode/utf8" ) // 平台信息(启动时确定) var ( isWindows = runtime.GOOS == "windows" platformKey = runtime.GOOS + "-" + runtime.GOARCH ) // toWinPath 将路径中的 / 替换为 \ func toWinPath(s string) string { return strings.ReplaceAll(s, "/", "\\") } // --- 字符串宽度 --- func stringWidth(s string) int { w := 0 for _, r := range s { w += runeWidth(r) } return w } func runeWidth(r rune) int { if r >= 0x1100 && (r <= 0x115F || r == 0x2329 || r == 0x232A || (r >= 0x2E80 && r <= 0xA4CF && r != 0x303F) || (r >= 0xAC00 && r <= 0xD7A3) || (r >= 0xF900 && r <= 0xFAFF) || (r >= 0xFE10 && r <= 0xFE19) || (r >= 0xFE30 && r <= 0xFE6F) || (r >= 0xFF01 && r <= 0xFF60) || (r >= 0xFFE0 && r <= 0xFFE6) || (r >= 0x20000 && r <= 0x2FFFD) || (r >= 0x30000 && r <= 0x3FFFD)) { return 2 } return 1 } func padRightByWidth(s string, targetW int) string { w := stringWidth(s) if w >= targetW { return s } return s + strings.Repeat(" ", targetW-w) } func truncateByWidth(s string, maxW int) string { w := 0 for i := 0; i < len(s); { r, size := utf8.DecodeRuneInString(s[i:]) rw := runeWidth(r) if w+rw > maxW { return s[:i] } w += rw i += size } return s } func wrapByWidth(s string, maxW int) []string { if maxW <= 0 || s == "" { return []string{s} } var lines []string for s != "" { cut := truncateByWidth(s, maxW) lines = append(lines, cut) s = s[len(cut):] } return lines } func fitWidth(s string, w int) string { return padRightByWidth(truncateByWidth(s, w), w) } // --- 视口 --- func viewport(cursor, total, height int) (int, int) { if total <= height { return 0, total } half := height / 2 start := cursor - half if start < 0 { start = 0 } end := start + height if end > total { end = total start = end - height if start < 0 { start = 0 } } return start, end } func padLinesTo(lines []string, w, target int) string { for len(lines) < target { lines = append(lines, strings.Repeat(" ", w)) } return strings.Join(lines, "\n") } // --- Windows Terminal --- func encodePSCommand(script string) string { u16 := utf16.Encode([]rune(script)) b := make([]byte, len(u16)*2) for i, r := range u16 { b[i*2] = byte(r) b[i*2+1] = byte(r >> 8) } return base64.StdEncoding.EncodeToString(b) } func randRange(min, max int) int { n, _ := rand.Int(rand.Reader, big.NewInt(int64(max-min))) return min + int(n.Int64()) }