72 lines
1.3 KiB
Go
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
|
|
}
|
|
}
|