Files
u-tabs/internal/util.go
绝尘 36aeef4bb7 新增: 会话分叉功能,优化增量扫描缓存
- 会话分叉: 按 c 键从历史会话分叉,支持带方向提示
- 启动自动加载历史记录
- 增量扫描: 缓存内存化、目录 modTime 跳过、已删除条目裁剪
- 刷新按钮复用 onTabSwitch 单一入口
2026-05-31 21:40:20 +08:00

135 lines
2.5 KiB
Go

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())
}