finish up minimal replacement for admin console with no deps
Ted Unangst tedu@tedunangst.com
Sun, 10 Nov 2019 19:13:28 -0500
1 files changed,
131 insertions(+),
6 deletions(-)
jump to
M
admin.go
→
admin.go
@@ -20,6 +20,7 @@ #include <termios.h>
*/ import "C" import ( + "bufio" "fmt" "io/ioutil" "log"@@ -28,27 +29,72 @@ )
func adminscreen() { log.SetOutput(ioutil.Discard) - stdout := os.Stdout + stdout := bufio.NewWriter(os.Stdout) esc := "\x1b" smcup := esc + "[?1049h" rmcup := esc + "[?1049l" + messages := []*struct { + name string + label string + text string + }{ + { + name: "servermsg", + label: "server", + text: string(serverMsg), + }, + { + name: "aboutmsg", + label: "about", + text: string(aboutMsg), + }, + { + name: "loginmsg", + label: "login", + text: string(loginMsg), + }, + } + cursel := 0 + hidecursor := func() { + stdout.WriteString(esc + "[?25l") } showcursor := func() { + stdout.WriteString(esc + "[?12;25h") } movecursor := func(x, y int) { - stdout.WriteString(fmt.Sprintf(esc+"[%d;%dH", x, y)) + stdout.WriteString(fmt.Sprintf(esc+"[%d;%dH", y, x)) + } + moveleft := func() { + stdout.WriteString(esc + "[1D") } clearscreen := func() { stdout.WriteString(esc + "[2J") } + clearline := func() { + stdout.WriteString(esc + "[2K") + } + colorfn := func(code int) func(string) string { + return func(s string) string { + return fmt.Sprintf(esc+"[%dm"+"%s"+esc+"[0m", code, s) + } + } + reverse := colorfn(7) + magenta := colorfn(35) + readchar := func() byte { + var buf [1]byte + os.Stdin.Read(buf[:]) + c := buf[0] + return c + } savedtio := new(C.struct_termios) C.tcgetattr(1, savedtio) restore := func() { stdout.WriteString(rmcup) showcursor() + stdout.Flush() C.tcsetattr(1, C.TCSAFLUSH, savedtio) } defer restore()@@ -63,19 +109,98 @@ hidecursor()
stdout.WriteString(smcup) clearscreen() movecursor(1, 1) + stdout.Flush() + } + + msglineno := func(idx int) int { + return 4 + idx*2 + } + + drawmessage := func(idx int) { + line := msglineno(idx) + movecursor(4, line) + label := messages[idx].label + if idx == cursel { + label = reverse(label) + } + stdout.WriteString(fmt.Sprintf("%s %s", label, messages[idx].text)) + } + + drawscreen := func() { + clearscreen() + movecursor(4, msglineno(-1)) + stdout.WriteString(magenta(serverName + " admin panel")) + for i := range messages { + drawmessage(i) + } + movecursor(4, msglineno(len(messages))) + stdout.WriteString(magenta("j/k to move - q to quit - enter to edit")) + stdout.Flush() + } + + selectnext := func() { + if cursel < len(messages)-1 { + cursel++ + } + drawscreen() + } + selectprev := func() { + if cursel > 0 { + cursel-- + } + drawscreen() + } + editsel := func() { + movecursor(4, msglineno(cursel)) + clearline() + m := messages[cursel] + stdout.WriteString(reverse(magenta(m.label))) + text := m.text + stdout.WriteString(" ") + stdout.WriteString(text) + showcursor() + stdout.Flush() + loop: + for { + c := readchar() + switch c { + case '\n': + break loop + case 127: + if len(text) > 0 { + moveleft() + stdout.WriteString(" ") + moveleft() + text = text[:len(text)-1] + } + default: + text = text + string(c) + stdout.WriteString(string(c)) + } + stdout.Flush() + } + m.text = text + updateconfig(m.name, m.text) + hidecursor() + drawscreen() } init() + drawscreen() for { - var buf [1]byte - os.Stdin.Read(buf[:]) - c := buf[0] + c := readchar() switch c { case 'q': return + case 'j': + selectnext() + case 'k': + selectprev() + case '\n': + editsel() default: - os.Stdout.Write(buf[:]) + } } }