Files
crossword/ssh/main.go
T
2026-10-01 16:07:45 -06:00

102 lines
1.8 KiB
Go

package main
import (
"bufio"
"fmt"
"io"
"log"
"os"
"github.com/cjdenio/crossword/game"
"github.com/cjdenio/crossword/puz"
"github.com/gliderlabs/ssh"
)
func main() {
file, err := os.ReadFile(os.Args[1])
if err != nil {
log.Fatal(err)
}
port := ":2222"
if portEnv, ok := os.LookupEnv("PORT"); ok && portEnv != "" {
port = ":" + portEnv
}
ssh.Handle(func(s ssh.Session) {
log.Printf("new connection from %s (username %s)\n", s.RemoteAddr().String(), s.User())
puzzle, err := puz.ParsePuz(file)
if err != nil {
log.Fatal(err)
}
state := game.NewState(puzzle)
io.WriteString(s, "\x1b[?25l")
defer func() {
io.WriteString(s, "\x1b[?25h")
}()
pty, winCh, isPty := s.Pty()
if !isPty {
return
}
windowWidth := pty.Window.Width
uiHeight := state.RenderUI(s, windowWidth)
go func() {
for window := range winCh {
windowWidth = window.Width
}
}()
scanner := bufio.NewScanner(s)
scanner.Split(func(data []byte, atEOF bool) (advance int, token []byte, err error) {
if len(data) == 0 {
return 0, nil, bufio.ErrFinalToken
}
if data[0] == 0x1b {
if len(data) < 3 {
return 0, nil, nil
}
return 3, data[0:3], nil
}
return 1, data[0:1], nil
})
for {
ok := scanner.Scan()
if !ok {
break
}
buffer := scanner.Bytes()
exited := state.HandleInput(buffer)
if exited {
state.SelectedClue = nil
state.SelectedCell = -1
fmt.Fprintf(s, "\r\x1b[%dA", uiHeight)
fmt.Fprint(s, "\x1b[J")
state.RenderUI(s, windowWidth)
break
}
fmt.Fprintf(s, "\r\x1b[%dA", uiHeight)
fmt.Fprint(s, "\x1b[J")
uiHeight = state.RenderUI(s, windowWidth)
}
log.Printf("%s disconnected\n", s.RemoteAddr().String())
})
log.Printf("starting on port %s...\n", port)
log.Fatal(ssh.ListenAndServe(port, nil))
}