cli/tx/term.go

185 lines
3.1 KiB
Go

package tx
import "golang.org/x/term"
import "surdeus.su/core/cli/aes"
import "bufio"
import "fmt"
import "os"
import "os/signal"
import "syscall"
type Signal = os.Signal
const (
SignalWinChange = syscall.SIGWINCH
)
type Terminal struct {
x *term.Terminal
file *os.File
input *bufio.Reader
fd int
prevState *term.State
signals chan Signal
keys chan Key
}
func NewTerminal(input *os.File) (*Terminal, error) {
if input == nil {
return nil, ErrNoInputProvided
}
fd := int(input.Fd())
if !term.IsTerminal(fd) {
return nil, ErrNotTerminal
}
ret := Terminal{}
ret.file = input
ret.input = bufio.NewReader(input)
ret.fd = fd
ret.x = term.NewTerminal(input, "")
return &ret, nil
}
func (t *Terminal) MakeRaw() (chan Key, chan Signal, error) {
state, err := term.MakeRaw(t.fd)
if err != nil {
return nil, nil, err
}
t.prevState = state
t.signals = make(chan Signal, 1)
signal.Notify(
t.signals,
syscall.SIGWINCH,
)
t.keys = make(chan Key, 1)
go func() {
for {
r, _, _ := t.input.ReadRune()
t.keys <- Key(r)
}
} ()
return t.keys, t.signals, nil
}
func (t *Terminal) Restore() error {
t.DisableAltBuffer()
if t == nil || t.prevState == nil {
return nil
}
err := term.Restore(t.fd, t.prevState)
if err != nil {
return err
}
return nil
}
func (t *Terminal) Size() (int, int, error) {
return term.GetSize(t.fd)
}
func (t *Terminal) ReadLine() (string, error) {
return t.x.ReadLine()
}
/*
func (t *Terminal) ReadKey() (Key, int, error) {
r, size, err := t.input.ReadRune()
return Key(r), size, err
}
*/
func (t *Terminal) Write(bts []byte) (int, error) {
return t.x.Write(bts)
}
func (t *Terminal) Printf(
format string, v ...any,
) (int, error) {
str := fmt.Sprintf(format, v...)
return t.Write([]byte(str))
}
func (t *Terminal) Print(v ...any) (int, error) {
str := fmt.Sprint(v...)
return t.Write([]byte(str))
}
func (t *Terminal) MoveCursorRight(n int) {
t.Printf(aes.MoveCursorRightFormat, n)
}
func (t *Terminal) MoveCursorLeft(n int) {
t.Printf(aes.MoveCursorLeftFormat, n)
}
func (t *Terminal) MoveCursorUp(n int) {
t.Printf(aes.MoveCursorUpFormat, n)
}
func (t *Terminal) MoveCursorDown(n int) {
t.Printf(aes.MoveCursorDownFormat, n)
}
func (t *Terminal) MoveCursorBy(xd, yd int) {
if xd != 0 {
if yd < 0 {
t.MoveCursorLeft(xd)
} else {
t.MoveCursorRight(xd)
}
}
if yd != 0 {
if yd < 0 {
t.MoveCursorUp(yd)
} else {
t.MoveCursorDown(yd)
}
}
}
func (t *Terminal) MoveCursorTo(x, y int) {
t.Printf(aes.MoveCursorToFormat, y, x)
}
func (t *Terminal) MoveCursorHome() {
t.Printf("%s", aes.MoveCursorHome)
}
func (t *Terminal) SaveCursor() {
t.Printf("%s", aes.SaveCursorPositionSCO)
}
func (t *Terminal) UndoCursor() {
t.Printf("%s", aes.UndoCursorPositionSCO)
}
func (t *Terminal) NextLine(n int) {
t.Printf(
aes.MoveCursorToBeginOfNextLineDownFormat,
n,
)
}
func (t *Terminal) EraseLine() {
t.Print(aes.EraseEntireLine)
}
func (t *Terminal) EnableAltBuffer() {
t.Printf("%s", aes.EnableAltBuffer)
}
func (t *Terminal) DisableAltBuffer() {
t.Printf("%s", aes.DisableAltBuffer)
}
func (t *Terminal) ClearScreen() {
t.Write([]byte(aes.EraseEntireScreen))
}