mirror of
https://github.com/RoBaertschi/tt.git
synced 2025-04-15 21:43:30 +00:00
191 lines
3.7 KiB
Go
191 lines
3.7 KiB
Go
package term
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
)
|
|
|
|
const ESC = "\x1b"
|
|
const CSI = ESC + "["
|
|
const Reset = CSI + "0m"
|
|
|
|
// Colors
|
|
|
|
const (
|
|
BlackFg = "30"
|
|
BlackBg = "40"
|
|
RedFg = "31"
|
|
RedBg = "41"
|
|
GreenFg = "32"
|
|
GreenBg = "42"
|
|
YellowFg = "33"
|
|
YellowBg = "43"
|
|
BlueFg = "34"
|
|
BlueBg = "44"
|
|
MagentaFg = "35"
|
|
MagentaBg = "35"
|
|
CyanFg = "36"
|
|
CyanBg = "46"
|
|
WhiteFg = "37"
|
|
WhiteBg = "47"
|
|
)
|
|
|
|
func Color(col string) string {
|
|
return CSI + col + "m"
|
|
}
|
|
|
|
// Other CSI
|
|
|
|
func CursorUp(amount int) string {
|
|
return fmt.Sprintf("%s%dA", CSI, amount)
|
|
}
|
|
|
|
func CursorDown(amount int) string {
|
|
return fmt.Sprintf("%s%dB", CSI, amount)
|
|
}
|
|
|
|
func CursorForward(amount int) string {
|
|
return fmt.Sprintf("%s%dC", CSI, amount)
|
|
}
|
|
|
|
func CursorBack(amount int) string {
|
|
return fmt.Sprintf("%s%dD", CSI, amount)
|
|
}
|
|
|
|
// Not ANSI.SYS
|
|
func CursorNextLine(amount int) string {
|
|
return fmt.Sprintf("%s%dE", CSI, amount)
|
|
}
|
|
|
|
// Not ANSI.SYS
|
|
func CursorPreviousLine(amount int) string {
|
|
return fmt.Sprintf("%s%dF", CSI, amount)
|
|
}
|
|
|
|
// Not ANSI.SYS
|
|
// Moves cursor to column amount
|
|
func CursorHorizontalAbsolute(amount int) string {
|
|
return fmt.Sprintf("%s%dG", CSI, amount)
|
|
}
|
|
|
|
// Moves the cursor on the 1-based grid in the terminal
|
|
func CursorPostition(x, y int) string {
|
|
return fmt.Sprintf("%s%d;%dH", CSI, x, y)
|
|
}
|
|
|
|
type EraseInDisplayMode int
|
|
|
|
const (
|
|
ClearFromCursor EraseInDisplayMode = iota // clear from cursor to the end of the screen
|
|
ClearToCursor // clear to cursor from the begining of the screen
|
|
ClearEntireScreen
|
|
ClearEntireScreenAndScrollbackBuffer // xterm extension
|
|
)
|
|
|
|
func EraseInDisplay(mode EraseInDisplayMode) string {
|
|
return fmt.Sprintf("%s%dJ", CSI, mode)
|
|
}
|
|
|
|
type EraseInLineMode int
|
|
|
|
const (
|
|
FromCursorToEnd EraseInLineMode = iota
|
|
FromCursorToBegin
|
|
EntireLine
|
|
)
|
|
|
|
func EraseInLine(mode EraseInLineMode) string {
|
|
return fmt.Sprintf("%s%dK", CSI, mode)
|
|
}
|
|
|
|
// Not ANSI.SYS
|
|
func ScrollUp(amount int) string {
|
|
return fmt.Sprintf("%s%dS", CSI, amount)
|
|
}
|
|
|
|
// Not ANSI.SYS
|
|
func ScrollDown(amount int) string {
|
|
return fmt.Sprintf("%s%dT", CSI, amount)
|
|
}
|
|
|
|
// Moves the cursor on the 1-based grid in the terminal
|
|
// Same as Cursor Position but a format effector, not a editor function
|
|
// see https://en.wikipedia.org/wiki/ANSI_escape_code#Control_Sequence_Introducer_commands
|
|
func HorizontalVerticalPosition(x, y int) string {
|
|
return fmt.Sprintf("%s%d;%dH", CSI, x, y)
|
|
}
|
|
|
|
// Gets the cursor position by transmitting CSIn;mR n = row, m = column
|
|
// see https://en.wikipedia.org/wiki/ANSI_escape_code#Control_Sequence_Introducer_commands
|
|
// Use GetCursorPosition to get x and y
|
|
func DeviceStatusReport() string {
|
|
return CSI + "6n"
|
|
}
|
|
|
|
var DidNotGetCsi = errors.New("could not get csi from Device Status Report sequence")
|
|
|
|
func GetCursorPosition() (row, column int, err error) {
|
|
// _, err = os.Stdin.Seek(0, 2)
|
|
// if err != nil {
|
|
// return
|
|
// }
|
|
os.Stdout.Write([]byte(DeviceStatusReport()))
|
|
// CSI is ESC and [
|
|
csiBuffer := [2]byte{}
|
|
os.Stdin.Read(csiBuffer[:])
|
|
|
|
if string(csiBuffer[:]) != CSI {
|
|
err = DidNotGetCsi
|
|
return
|
|
}
|
|
|
|
miniBuff := [1]byte{}
|
|
for {
|
|
_, err = os.Stdin.Read(miniBuff[:])
|
|
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
if miniBuff[0] == ';' {
|
|
break
|
|
}
|
|
|
|
if '0' <= miniBuff[0] && miniBuff[0] <= '9' {
|
|
row *= 10
|
|
row += int(miniBuff[0] - '0')
|
|
} else {
|
|
err = fmt.Errorf("invalid byte for number %b", miniBuff[0])
|
|
return
|
|
}
|
|
}
|
|
|
|
for {
|
|
_, err = os.Stdin.Read(miniBuff[:])
|
|
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
if miniBuff[0] == 'R' {
|
|
break
|
|
}
|
|
|
|
if '0' <= miniBuff[0] && miniBuff[0] <= '9' {
|
|
column *= 10
|
|
column += int(miniBuff[0] - '0')
|
|
} else {
|
|
err = fmt.Errorf("invalid byte for number %b", miniBuff[0])
|
|
return
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func Exit(val int) {
|
|
LeaveRawMode()
|
|
os.Exit(val)
|
|
}
|