114 lines
2.5 KiB
Go
114 lines
2.5 KiB
Go
// Package termenv provides detect color support of the current terminal.
|
|
// And with some utils for terminal env.
|
|
package termenv
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
|
|
"golang.org/x/term"
|
|
)
|
|
|
|
var (
|
|
lastErr error
|
|
// debug mode
|
|
debugMode bool
|
|
// support color of current terminal
|
|
supportColor bool
|
|
|
|
// value of os color render and display
|
|
//
|
|
// NOTICE:
|
|
// if ENV: NO_COLOR is not empty, will disable color render.
|
|
noColor = os.Getenv("NO_COLOR") != ""
|
|
|
|
// the color support level for current terminal
|
|
// needVTP - need enable VTP, only for Windows OS
|
|
colorLevel, needVTP = detectTermColorLevel()
|
|
)
|
|
|
|
// SetDebugMode sets debug mode.
|
|
func SetDebugMode(enable bool) { debugMode = enable }
|
|
|
|
// LastErr returns the last error.
|
|
func LastErr() error {
|
|
defer func() {
|
|
lastErr = nil // reset on get
|
|
}()
|
|
return lastErr
|
|
}
|
|
|
|
func debugf(tpl string, v ...any) {
|
|
if debugMode {
|
|
fmt.Printf("TERMENV: "+tpl+"\n", v...)
|
|
}
|
|
}
|
|
|
|
func setLastErr(err error) {
|
|
if err != nil {
|
|
debugf("TERMENV: last error: %v", err)
|
|
lastErr = err
|
|
}
|
|
}
|
|
|
|
// exec: `stty -a 2>&1`
|
|
// const (
|
|
// mac: speed 9600 baud; 97 rows; 362 columns;
|
|
// macSttyMsgPattern = `(\d+)\s+rows;\s*(\d+)\s+columns;`
|
|
// linux: speed 38400 baud; rows 97; columns 362; line = 0;
|
|
// linuxSttyMsgPattern = `rows\s+(\d+);\s*columns\s+(\d+);`
|
|
// )
|
|
var terminalWidth, terminalHeight int
|
|
|
|
// GetTermSize for current console terminal. will first try to get from environment variables COLUMNS and LINES.
|
|
func GetTermSize(refresh ...bool) (w int, h int) {
|
|
if terminalWidth > 0 && (len(refresh) == 0 || !refresh[0]) {
|
|
return terminalWidth, terminalHeight
|
|
}
|
|
|
|
// 首先尝试从环境变量获取
|
|
if cols := os.Getenv("COLUMNS"); cols != "" {
|
|
if width, err := strconv.Atoi(cols); err == nil && width > 0 {
|
|
terminalWidth = width
|
|
}
|
|
}
|
|
if rows := os.Getenv("LINES"); rows != "" {
|
|
if height, err := strconv.Atoi(rows); err == nil && height > 0 {
|
|
terminalHeight = height
|
|
}
|
|
}
|
|
if terminalWidth > 0 && terminalHeight > 0 {
|
|
return terminalWidth, terminalHeight
|
|
}
|
|
|
|
var err error
|
|
w, h, err = term.GetSize(syscallStdoutFd())
|
|
if err != nil {
|
|
debugf("get terminal size error: %v", err)
|
|
return
|
|
}
|
|
|
|
// cache result
|
|
terminalWidth, terminalHeight = w, h
|
|
debugf("get terminal size: %d,%d", w, h)
|
|
return
|
|
}
|
|
|
|
// ReadPassword from console terminal
|
|
func ReadPassword(question ...string) string {
|
|
if len(question) > 0 {
|
|
print(question[0])
|
|
} else {
|
|
print("Enter Password: ")
|
|
}
|
|
|
|
bs, err := term.ReadPassword(syscallStdinFd())
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
|
|
println() // new line
|
|
return string(bs)
|
|
}
|