Files
TaskPool/cmd/clibase/clilog.go
T
2026-05-14 09:55:35 +08:00

72 lines
1.3 KiB
Go

package clibase
import (
"bytes"
"io"
"regexp"
"strings"
)
// AnsiRegex 匹配终端 ANSI 控制序列的通用正则表达式
var AnsiRegex = regexp.MustCompile("\x1b\\[[0-9;]*[a-zA-Z]")
// CleanWriter 过滤输出流中的终端回车符覆写及 ANSI 色彩代码
type CleanWriter struct {
out io.Writer
buf []byte
}
// NewCleanWriter 构造输出清洗器
func NewCleanWriter(out io.Writer) *CleanWriter {
return &CleanWriter{out: out}
}
func (c *CleanWriter) Write(p []byte) (n int, err error) {
c.buf = append(c.buf, p...)
for {
idx := bytes.IndexAny(c.buf, "\r\n")
if idx == -1 {
break
}
if c.buf[idx] == '\r' && idx == len(c.buf)-1 {
// 跨块截断的回车,等待下一块
break
}
char := c.buf[idx]
line := string(c.buf[:idx])
c.buf = c.buf[idx+1:]
if char == '\r' && len(c.buf) > 0 && c.buf[0] == '\n' {
c.buf = c.buf[1:]
char = '\n'
}
s := AnsiRegex.ReplaceAllString(line, "")
if char == '\r' {
continue // 忽略终端进度条的同行覆盖
}
if s != "" {
c.out.Write([]byte(s + "\n"))
}
}
return len(p), nil
}
// Flush 输出末尾缓冲
func (c *CleanWriter) Flush() {
if len(c.buf) > 0 {
s := string(c.buf)
s = strings.TrimSuffix(s, "\r")
s = AnsiRegex.ReplaceAllString(s, "")
if s != "" {
c.out.Write([]byte(s + "\n"))
}
c.buf = nil
}
}