summary refs log tree commit diff
path: root/vendor/github.com/chzyer/readline/ansi_windows.go
diff options
context:
space:
mode:
authorEmile <git@emile.space>2024-10-25 15:55:50 +0200
committerEmile <git@emile.space>2024-10-25 15:55:50 +0200
commitc90f36e3dd179d2de96f4f5fe38d8dc9a9de6dfe (patch)
tree89e9afb41c5bf76f48cfb09305a2d3db8d302b06 /vendor/github.com/chzyer/readline/ansi_windows.go
parent98bbb0f559a8883bc47bae80607dbe326a448e61 (diff)
vendor HEAD main
Diffstat (limited to 'vendor/github.com/chzyer/readline/ansi_windows.go')
-rw-r--r--vendor/github.com/chzyer/readline/ansi_windows.go249
1 files changed, 249 insertions, 0 deletions
diff --git a/vendor/github.com/chzyer/readline/ansi_windows.go b/vendor/github.com/chzyer/readline/ansi_windows.go
new file mode 100644
index 0000000..63b908c
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/ansi_windows.go
@@ -0,0 +1,249 @@
+// +build windows
+
+package readline
+
+import (
+	"bufio"
+	"io"
+	"strconv"
+	"strings"
+	"sync"
+	"unicode/utf8"
+	"unsafe"
+)
+
+const (
+	_                = uint16(0)
+	COLOR_FBLUE      = 0x0001
+	COLOR_FGREEN     = 0x0002
+	COLOR_FRED       = 0x0004
+	COLOR_FINTENSITY = 0x0008
+
+	COLOR_BBLUE      = 0x0010
+	COLOR_BGREEN     = 0x0020
+	COLOR_BRED       = 0x0040
+	COLOR_BINTENSITY = 0x0080
+
+	COMMON_LVB_UNDERSCORE = 0x8000
+	COMMON_LVB_BOLD       = 0x0007
+)
+
+var ColorTableFg = []word{
+	0,                                       // 30: Black
+	COLOR_FRED,                              // 31: Red
+	COLOR_FGREEN,                            // 32: Green
+	COLOR_FRED | COLOR_FGREEN,               // 33: Yellow
+	COLOR_FBLUE,                             // 34: Blue
+	COLOR_FRED | COLOR_FBLUE,                // 35: Magenta
+	COLOR_FGREEN | COLOR_FBLUE,              // 36: Cyan
+	COLOR_FRED | COLOR_FBLUE | COLOR_FGREEN, // 37: White
+}
+
+var ColorTableBg = []word{
+	0,                                       // 40: Black
+	COLOR_BRED,                              // 41: Red
+	COLOR_BGREEN,                            // 42: Green
+	COLOR_BRED | COLOR_BGREEN,               // 43: Yellow
+	COLOR_BBLUE,                             // 44: Blue
+	COLOR_BRED | COLOR_BBLUE,                // 45: Magenta
+	COLOR_BGREEN | COLOR_BBLUE,              // 46: Cyan
+	COLOR_BRED | COLOR_BBLUE | COLOR_BGREEN, // 47: White
+}
+
+type ANSIWriter struct {
+	target io.Writer
+	wg     sync.WaitGroup
+	ctx    *ANSIWriterCtx
+	sync.Mutex
+}
+
+func NewANSIWriter(w io.Writer) *ANSIWriter {
+	a := &ANSIWriter{
+		target: w,
+		ctx:    NewANSIWriterCtx(w),
+	}
+	return a
+}
+
+func (a *ANSIWriter) Close() error {
+	a.wg.Wait()
+	return nil
+}
+
+type ANSIWriterCtx struct {
+	isEsc     bool
+	isEscSeq  bool
+	arg       []string
+	target    *bufio.Writer
+	wantFlush bool
+}
+
+func NewANSIWriterCtx(target io.Writer) *ANSIWriterCtx {
+	return &ANSIWriterCtx{
+		target: bufio.NewWriter(target),
+	}
+}
+
+func (a *ANSIWriterCtx) Flush() {
+	a.target.Flush()
+}
+
+func (a *ANSIWriterCtx) process(r rune) bool {
+	if a.wantFlush {
+		if r == 0 || r == CharEsc {
+			a.wantFlush = false
+			a.target.Flush()
+		}
+	}
+	if a.isEscSeq {
+		a.isEscSeq = a.ioloopEscSeq(a.target, r, &a.arg)
+		return true
+	}
+
+	switch r {
+	case CharEsc:
+		a.isEsc = true
+	case '[':
+		if a.isEsc {
+			a.arg = nil
+			a.isEscSeq = true
+			a.isEsc = false
+			break
+		}
+		fallthrough
+	default:
+		a.target.WriteRune(r)
+		a.wantFlush = true
+	}
+	return true
+}
+
+func (a *ANSIWriterCtx) ioloopEscSeq(w *bufio.Writer, r rune, argptr *[]string) bool {
+	arg := *argptr
+	var err error
+
+	if r >= 'A' && r <= 'D' {
+		count := short(GetInt(arg, 1))
+		info, err := GetConsoleScreenBufferInfo()
+		if err != nil {
+			return false
+		}
+		switch r {
+		case 'A': // up
+			info.dwCursorPosition.y -= count
+		case 'B': // down
+			info.dwCursorPosition.y += count
+		case 'C': // right
+			info.dwCursorPosition.x += count
+		case 'D': // left
+			info.dwCursorPosition.x -= count
+		}
+		SetConsoleCursorPosition(&info.dwCursorPosition)
+		return false
+	}
+
+	switch r {
+	case 'J':
+		killLines()
+	case 'K':
+		eraseLine()
+	case 'm':
+		color := word(0)
+		for _, item := range arg {
+			var c int
+			c, err = strconv.Atoi(item)
+			if err != nil {
+				w.WriteString("[" + strings.Join(arg, ";") + "m")
+				break
+			}
+			if c >= 30 && c < 40 {
+				color ^= COLOR_FINTENSITY
+				color |= ColorTableFg[c-30]
+			} else if c >= 40 && c < 50 {
+				color ^= COLOR_BINTENSITY
+				color |= ColorTableBg[c-40]
+			} else if c == 4 {
+				color |= COMMON_LVB_UNDERSCORE | ColorTableFg[7]
+			} else if c == 1 {
+				color |= COMMON_LVB_BOLD | COLOR_FINTENSITY
+			} else { // unknown code treat as reset
+				color = ColorTableFg[7]
+			}
+		}
+		if err != nil {
+			break
+		}
+		kernel.SetConsoleTextAttribute(stdout, uintptr(color))
+	case '\007': // set title
+	case ';':
+		if len(arg) == 0 || arg[len(arg)-1] != "" {
+			arg = append(arg, "")
+			*argptr = arg
+		}
+		return true
+	default:
+		if len(arg) == 0 {
+			arg = append(arg, "")
+		}
+		arg[len(arg)-1] += string(r)
+		*argptr = arg
+		return true
+	}
+	*argptr = nil
+	return false
+}
+
+func (a *ANSIWriter) Write(b []byte) (int, error) {
+	a.Lock()
+	defer a.Unlock()
+
+	off := 0
+	for len(b) > off {
+		r, size := utf8.DecodeRune(b[off:])
+		if size == 0 {
+			return off, io.ErrShortWrite
+		}
+		off += size
+		a.ctx.process(r)
+	}
+	a.ctx.Flush()
+	return off, nil
+}
+
+func killLines() error {
+	sbi, err := GetConsoleScreenBufferInfo()
+	if err != nil {
+		return err
+	}
+
+	size := (sbi.dwCursorPosition.y - sbi.dwSize.y) * sbi.dwSize.x
+	size += sbi.dwCursorPosition.x
+
+	var written int
+	kernel.FillConsoleOutputAttribute(stdout, uintptr(ColorTableFg[7]),
+		uintptr(size),
+		sbi.dwCursorPosition.ptr(),
+		uintptr(unsafe.Pointer(&written)),
+	)
+	return kernel.FillConsoleOutputCharacterW(stdout, uintptr(' '),
+		uintptr(size),
+		sbi.dwCursorPosition.ptr(),
+		uintptr(unsafe.Pointer(&written)),
+	)
+}
+
+func eraseLine() error {
+	sbi, err := GetConsoleScreenBufferInfo()
+	if err != nil {
+		return err
+	}
+
+	size := sbi.dwSize.x
+	sbi.dwCursorPosition.x = 0
+	var written int
+	return kernel.FillConsoleOutputCharacterW(stdout, uintptr(' '),
+		uintptr(size),
+		sbi.dwCursorPosition.ptr(),
+		uintptr(unsafe.Pointer(&written)),
+	)
+}