Files
ptb/tui.go
2025-02-28 14:59:31 +01:00

182 lines
4.0 KiB
Go

package main
import (
"errors"
"fmt"
"github.com/TwiN/go-color"
"github.com/jroimartin/gocui"
"strings"
"time"
"unicode"
)
func printable(r rune) rune {
if r == '\u000d' || r == '\u000a' { // ctrl-r or ctrl-n
return '\u000a' //ctrl-n
}
if unicode.IsGraphic(r) {
return r
}
return '\u002e' // dot
}
func Ternary(condition bool, valueIfTrue, valueIfFalse interface{}) interface{} {
if condition {
return valueIfTrue
}
return valueIfFalse
}
func layout(g *gocui.Gui) error {
maxX, maxY := g.Size()
lwX := int(float32(maxX) * 0.8)
// "data" view: Top-left large view
if v, err := g.SetView("data", 0, 0, lwX-1, maxY/2-1); err != nil {
if !errors.Is(err, gocui.ErrUnknownView) {
return err
}
v.Title = "Data"
v.Wrap = true
v.Autoscroll = true
}
// "protocol" view: Bottom-left large view
if v, err := g.SetView("protocol", 0, maxY/2, lwX-1, maxY-1); err != nil {
if !errors.Is(err, gocui.ErrUnknownView) {
return err
}
v.Title = "Protocol"
v.Wrap = true
v.Autoscroll = true
}
// "status" view: Smaller view on the right
if v, err := g.SetView("status", lwX, 0, maxX-1, maxY-1); err != nil {
if !errors.Is(err, gocui.ErrUnknownView) {
return err
}
v.Title = "Status"
}
return nil
}
func keybindings(g *gocui.Gui) error {
// Quit the application with Ctrl+C
if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
return err
}
if err := g.SetKeybinding("", gocui.KeyCtrlT, gocui.ModNone, toggleMode); err != nil {
return err
}
return nil
}
func protocolUpdate(g *gocui.Gui) {
for {
msg := <-s.Protocol
g.Update(func(g *gocui.Gui) error {
v, err := g.View("protocol")
if err != nil {
writeDebug(err.Error(), 0)
return err
}
_, err = fmt.Fprint(v, msg)
if err != nil {
writeDebug(err.Error(), 0)
}
return nil
})
}
}
func pactorUpdate(g *gocui.Gui) {
for {
if s.ToPactor.GetLen() > 0 {
msg, err := s.ToPactor.Dequeue(256)
if err != nil {
writeDebug(err.Error(), 0)
continue
}
g.Update(func(g *gocui.Gui) error {
v, err := g.View("data")
if err != nil {
writeDebug(err.Error(), 0)
return err
}
_, err = fmt.Fprint(v, strings.Map(printable, string(msg)))
if err != nil {
writeDebug(err.Error(), 0)
}
return nil
})
}
if s.FromPactor.GetLen() > 0 {
msg, err := s.FromPactor.Dequeue(256)
if err != nil {
writeDebug(err.Error(), 0)
continue
}
g.Update(func(g *gocui.Gui) error {
v, err := g.View("data")
if err != nil {
writeDebug(err.Error(), 0)
return err
}
_, err = fmt.Fprint(v, color.InRed(strings.Map(printable, string(msg))))
if err != nil {
writeDebug(err.Error(), 0)
}
return nil
})
}
time.Sleep(3 * time.Second)
}
}
func statusUpdate(g *gocui.Gui) {
for {
time.Sleep(1 * time.Second)
g.Update(func(g *gocui.Gui) error {
v, err := g.View("status")
if err != nil {
writeDebug(err.Error(), 0)
} else {
v.Clear()
_, err := fmt.Fprintln(v, time.Now().Format("15:04:05"))
if err != nil {
writeDebug(err.Error(), 0)
}
_, err = fmt.Fprintln(v, Ternary(s.VARAMode, "VARA", "TCP"))
if err != nil {
writeDebug(err.Error(), 0)
}
_, err = fmt.Fprintln(v, Ternary(s.Status&StatusTCPCmdActive != 0, color.InGreen("TCP CMD"), color.InRed("TCP CMD")))
if err != nil {
writeDebug(err.Error(), 0)
}
_, err = fmt.Fprintln(v, Ternary(s.Status&StatusTCPDataActive != 0, color.InGreen("TCP DATA"), color.InRed("TCP DATA")))
if err != nil {
writeDebug(err.Error(), 0)
}
_, err = fmt.Fprintln(v, fmt.Sprintf("\nCMD S: %d\nCMD R: %d\nDTA S: %d\nDTA R: %d", s.Command.Cmd.GetLen(), s.Command.Response.GetLen(), s.Data.Data.GetLen(), s.Data.Response.GetLen()))
if err != nil {
writeDebug(err.Error(), 0)
}
}
return nil
})
}
}
func quit(_ *gocui.Gui, _ *gocui.View) error {
return gocui.ErrQuit
}
func toggleMode(_ *gocui.Gui, _ *gocui.View) error {
s.Protocol <- fmt.Sprintf(color.InPurple("Toggle mode\n"))
s.VARAMode = !s.VARAMode
return nil
}