mirror of
https://github.com/cjdenio/crossword.git
synced 2026-10-03 11:06:19 +00:00
ssh
This commit is contained in:
6 files changed
+222
-113
No files matched your search
@@ -3,3 +3,9 @@ todo
|
|||||||
- fix bug with that one 6x6 puzzle
|
- fix bug with that one 6x6 puzzle
|
||||||
- correctly calculate uiHeight with multi-line clues
|
- correctly calculate uiHeight with multi-line clues
|
||||||
- timer
|
- timer
|
||||||
|
- reveal grid/word
|
||||||
|
- .puz checksums
|
||||||
|
- fix shift+enter in other terminals
|
||||||
|
- after entering letter, jump to next unfilled cell (even if it's backwards)
|
||||||
|
- tab/shift+tab
|
||||||
|
- clear grid
|
||||||
+114
-12
@@ -1,11 +1,13 @@
|
|||||||
package main
|
package game
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
"github.com/cjdenio/crossword/puz"
|
"github.com/cjdenio/crossword/puz"
|
||||||
)
|
)
|
||||||
@@ -189,7 +191,7 @@ func (state *State) CheckPuzzle() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (state *State) RenderUI() int {
|
func (state *State) RenderUI(w io.Writer) int {
|
||||||
selectedClueCells := []int{}
|
selectedClueCells := []int{}
|
||||||
if state.SelectedClue != nil {
|
if state.SelectedClue != nil {
|
||||||
selectedClueCells = state.SelectedClue.Cells
|
selectedClueCells = state.SelectedClue.Cells
|
||||||
@@ -197,39 +199,39 @@ func (state *State) RenderUI() int {
|
|||||||
|
|
||||||
uiHeight := 0
|
uiHeight := 0
|
||||||
|
|
||||||
fmt.Printf("\r\nTITLE: %s\r\n", state.Puzzle.Title)
|
fmt.Fprintf(w, "\r\nTITLE: %s\r\n", state.Puzzle.Title)
|
||||||
uiHeight += 2
|
uiHeight += 2
|
||||||
fmt.Printf("AUTHOR: %s\r\n", state.Puzzle.Author)
|
fmt.Fprintf(w, "AUTHOR: %s\r\n", state.Puzzle.Author)
|
||||||
uiHeight += 1
|
uiHeight += 1
|
||||||
fmt.Print(RenderPuzzle(state.PuzzleState, state.Puzzle.Width, state.Puzzle.Height, selectedClueCells, state.SelectedCell) + "\r\n")
|
fmt.Fprint(w, RenderPuzzle(state.PuzzleState, state.Puzzle.Width, state.Puzzle.Height, selectedClueCells, state.SelectedCell)+"\r\n")
|
||||||
uiHeight += state.Puzzle.Height + 3
|
uiHeight += state.Puzzle.Height + 3
|
||||||
if state.SelectedClue != nil {
|
if state.SelectedClue != nil {
|
||||||
if state.SelectedClue.Direction == puz.DirectionAcross {
|
if state.SelectedClue.Direction == puz.DirectionAcross {
|
||||||
fmt.Printf("%d-across: %s\r\n\r\n", state.SelectedClue.Number, state.SelectedClue.Clue)
|
fmt.Fprintf(w, "%d-across: %s\r\n\r\n", state.SelectedClue.Number, state.SelectedClue.Clue)
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("%d-down: %s\r\n\r\n", state.SelectedClue.Number, state.SelectedClue.Clue)
|
fmt.Fprintf(w, "%d-down: %s\r\n\r\n", state.SelectedClue.Number, state.SelectedClue.Clue)
|
||||||
}
|
}
|
||||||
uiHeight += 2
|
uiHeight += 2
|
||||||
}
|
}
|
||||||
fmt.Printf("%s\r\n", state.Puzzle.Copyright)
|
fmt.Fprintf(w, "%s\r\n", state.Puzzle.Copyright)
|
||||||
uiHeight += 1
|
uiHeight += 1
|
||||||
|
|
||||||
switch state.SolveState {
|
switch state.SolveState {
|
||||||
case 1:
|
case 1:
|
||||||
fmt.Printf("\r\n%s\r\n", AnsiRed("The puzzle was filled, but at least 1 letter is incorrect..."))
|
fmt.Fprintf(w, "\r\n%s\r\n", AnsiRed("The puzzle was filled, but at least 1 letter is incorrect..."))
|
||||||
uiHeight += 2
|
uiHeight += 2
|
||||||
case 2:
|
case 2:
|
||||||
fmt.Printf("\r\n%s\r\n", AnsiGreen("The puzzle was solved!"))
|
fmt.Fprintf(w, "\r\n%s\r\n", AnsiGreen("The puzzle was solved!"))
|
||||||
uiHeight += 2
|
uiHeight += 2
|
||||||
}
|
}
|
||||||
|
|
||||||
if state.LastKeySequence != "" && state.DebugMode {
|
if state.LastKeySequence != "" && state.DebugMode {
|
||||||
fmt.Printf("\r\n%s\r\n", AnsiDimmed(state.LastKeySequence))
|
fmt.Fprintf(w, "\r\n%s\r\n", AnsiDimmed(state.LastKeySequence))
|
||||||
uiHeight += 2
|
uiHeight += 2
|
||||||
}
|
}
|
||||||
|
|
||||||
if state.Goodbye {
|
if state.Goodbye {
|
||||||
fmt.Print("\r\nsee ya\r\n")
|
fmt.Fprint(w, "\r\nsee ya\r\n")
|
||||||
uiHeight += 2
|
uiHeight += 2
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,3 +347,103 @@ func (state *State) LoadSaveFile(f []byte) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (state *State) HandleInput(buffer []byte) (exited bool) {
|
||||||
|
state.LastKeySequence = fmt.Sprintf("%v", buffer)
|
||||||
|
|
||||||
|
if buffer[0] == 3 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if buffer[0] == ' ' {
|
||||||
|
switch state.SelectedClue.Direction {
|
||||||
|
case puz.DirectionAcross:
|
||||||
|
if state.Puzzle.Cells[state.SelectedCell][1] != nil {
|
||||||
|
state.SelectedClue = state.Puzzle.Cells[state.SelectedCell][1]
|
||||||
|
}
|
||||||
|
case puz.DirectionDown:
|
||||||
|
if state.Puzzle.Cells[state.SelectedCell][0] != nil {
|
||||||
|
state.SelectedClue = state.Puzzle.Cells[state.SelectedCell][0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if buffer[0] >= 0x61 && buffer[0] <= 0x7a {
|
||||||
|
cellWasFilled := state.PuzzleState[state.SelectedCell] != '-'
|
||||||
|
state.PuzzleState[state.SelectedCell] = unicode.ToUpper(rune(buffer[0]))
|
||||||
|
|
||||||
|
i := slices.Index(state.SelectedClue.Cells, state.SelectedCell)
|
||||||
|
|
||||||
|
if !cellWasFilled {
|
||||||
|
// jump to next unfilled cell in clue
|
||||||
|
for x := i + 1; x < len(state.SelectedClue.Cells); x++ {
|
||||||
|
if state.PuzzleState[state.SelectedClue.Cells[x]] == '-' {
|
||||||
|
state.SelectedCell = state.SelectedClue.Cells[x]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// jump to next cell
|
||||||
|
if i < len(state.SelectedClue.Cells)-1 {
|
||||||
|
state.SelectedCell = state.SelectedClue.Cells[i+1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if state.GridFilled() {
|
||||||
|
if state.CheckPuzzle() {
|
||||||
|
state.SolveState = 2
|
||||||
|
} else {
|
||||||
|
state.SolveState = 1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
state.SolveState = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if buffer[0] == 0x7f {
|
||||||
|
// is there a filled cell underneath the cursor?
|
||||||
|
if state.PuzzleState[state.SelectedCell] != '-' {
|
||||||
|
state.PuzzleState[state.SelectedCell] = '-'
|
||||||
|
} else {
|
||||||
|
i := slices.Index(state.SelectedClue.Cells, state.SelectedCell)
|
||||||
|
if i > 0 {
|
||||||
|
state.PuzzleState[state.SelectedClue.Cells[i-1]] = '-' // clear the previous cell
|
||||||
|
state.SelectedCell = state.SelectedClue.Cells[i-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if buffer[0] == '\r' {
|
||||||
|
state.NextWord()
|
||||||
|
}
|
||||||
|
if buffer[0] == '~' {
|
||||||
|
state.PreviousWord()
|
||||||
|
}
|
||||||
|
|
||||||
|
if string(buffer[0:2]) == "\x1b[" {
|
||||||
|
if (buffer[2] == 68 || buffer[2] == 67) && state.SelectedClue != nil && state.SelectedClue.Direction == puz.DirectionDown {
|
||||||
|
state.SelectedClue = state.Puzzle.Cells[state.SelectedCell][0]
|
||||||
|
} else if (buffer[2] == 65 || buffer[2] == 66) && state.SelectedClue != nil && state.SelectedClue.Direction == puz.DirectionAcross {
|
||||||
|
state.SelectedClue = state.Puzzle.Cells[state.SelectedCell][1]
|
||||||
|
} else {
|
||||||
|
switch buffer[2] {
|
||||||
|
case 68: // left
|
||||||
|
state.MoveCursor(3)
|
||||||
|
case 67: // right
|
||||||
|
state.MoveCursor(1)
|
||||||
|
case 65: // up
|
||||||
|
state.MoveCursor(0)
|
||||||
|
case 66: // down
|
||||||
|
state.MoveCursor(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch state.SelectedClue.Direction {
|
||||||
|
case puz.DirectionAcross:
|
||||||
|
state.SelectedClue = state.Puzzle.Cells[state.SelectedCell][0]
|
||||||
|
case puz.DirectionDown:
|
||||||
|
state.SelectedClue = state.Puzzle.Cells[state.SelectedCell][1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
@@ -7,4 +7,12 @@ require (
|
|||||||
golang.org/x/text v0.41.0
|
golang.org/x/text v0.41.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require golang.org/x/sys v0.47.0 // indirect
|
require (
|
||||||
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
|
||||||
|
golang.org/x/crypto v0.31.0 // indirect
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/gliderlabs/ssh v0.3.8
|
||||||
|
golang.org/x/sys v0.47.0 // indirect
|
||||||
|
)
|
||||||
@@ -1,3 +1,9 @@
|
|||||||
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||||
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||||
|
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
|
||||||
|
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
|
||||||
|
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||||
|
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||||
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
|
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
|
||||||
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||||
golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0=
|
golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0=
|
||||||
|
|||||||
@@ -6,9 +6,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"slices"
|
|
||||||
"unicode"
|
|
||||||
|
|
||||||
|
"github.com/cjdenio/crossword/game"
|
||||||
"github.com/cjdenio/crossword/puz"
|
"github.com/cjdenio/crossword/puz"
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
)
|
)
|
||||||
@@ -51,7 +50,7 @@ func main() {
|
|||||||
|
|
||||||
defer term.Restore(int(os.Stdin.Fd()), termState)
|
defer term.Restore(int(os.Stdin.Fd()), termState)
|
||||||
|
|
||||||
state := State{
|
state := game.State{
|
||||||
Puzzle: puzzle,
|
Puzzle: puzzle,
|
||||||
PuzzleState: []rune(puzzle.State),
|
PuzzleState: []rune(puzzle.State),
|
||||||
SelectedClue: puzzle.Clues[0],
|
SelectedClue: puzzle.Clues[0],
|
||||||
@@ -70,7 +69,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uiHeight := state.RenderUI()
|
uiHeight := state.RenderUI(os.Stdout)
|
||||||
|
|
||||||
scanner := bufio.NewScanner(os.Stdin)
|
scanner := bufio.NewScanner(os.Stdin)
|
||||||
scanner.Split(func(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
scanner.Split(func(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||||
@@ -93,9 +92,8 @@ func main() {
|
|||||||
scanner.Scan()
|
scanner.Scan()
|
||||||
buffer := scanner.Bytes()
|
buffer := scanner.Bytes()
|
||||||
|
|
||||||
state.LastKeySequence = fmt.Sprintf("%v", buffer)
|
exited := state.HandleInput(buffer)
|
||||||
|
if exited {
|
||||||
if buffer[0] == 3 {
|
|
||||||
saveFile, err := state.CreateSaveFile()
|
saveFile, err := state.CreateSaveFile()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = os.WriteFile(filename+".save", saveFile, fileInfo.Mode())
|
err = os.WriteFile(filename+".save", saveFile, fileInfo.Mode())
|
||||||
@@ -108,104 +106,13 @@ func main() {
|
|||||||
state.Goodbye = true
|
state.Goodbye = true
|
||||||
fmt.Printf("\r\x1b[%dA", uiHeight)
|
fmt.Printf("\r\x1b[%dA", uiHeight)
|
||||||
fmt.Print("\x1b[J")
|
fmt.Print("\x1b[J")
|
||||||
state.RenderUI()
|
state.RenderUI(os.Stdout)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if buffer[0] == ' ' {
|
|
||||||
switch state.SelectedClue.Direction {
|
|
||||||
case puz.DirectionAcross:
|
|
||||||
if state.Puzzle.Cells[state.SelectedCell][1] != nil {
|
|
||||||
state.SelectedClue = state.Puzzle.Cells[state.SelectedCell][1]
|
|
||||||
}
|
|
||||||
case puz.DirectionDown:
|
|
||||||
if state.Puzzle.Cells[state.SelectedCell][0] != nil {
|
|
||||||
state.SelectedClue = state.Puzzle.Cells[state.SelectedCell][0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if buffer[0] >= 0x61 && buffer[0] <= 0x7a {
|
|
||||||
cellWasFilled := state.PuzzleState[state.SelectedCell] != '-'
|
|
||||||
state.PuzzleState[state.SelectedCell] = unicode.ToUpper(rune(buffer[0]))
|
|
||||||
|
|
||||||
i := slices.Index(state.SelectedClue.Cells, state.SelectedCell)
|
|
||||||
|
|
||||||
if !cellWasFilled {
|
|
||||||
// jump to next unfilled cell in clue
|
|
||||||
for x := i + 1; x < len(state.SelectedClue.Cells); x++ {
|
|
||||||
if state.PuzzleState[state.SelectedClue.Cells[x]] == '-' {
|
|
||||||
state.SelectedCell = state.SelectedClue.Cells[x]
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// jump to next cell
|
|
||||||
if i < len(state.SelectedClue.Cells)-1 {
|
|
||||||
state.SelectedCell = state.SelectedClue.Cells[i+1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if state.GridFilled() {
|
|
||||||
if state.CheckPuzzle() {
|
|
||||||
state.SolveState = 2
|
|
||||||
} else {
|
|
||||||
state.SolveState = 1
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
state.SolveState = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if buffer[0] == 0x7f {
|
|
||||||
// is there a filled cell underneath the cursor?
|
|
||||||
if state.PuzzleState[state.SelectedCell] != '-' {
|
|
||||||
state.PuzzleState[state.SelectedCell] = '-'
|
|
||||||
} else {
|
|
||||||
i := slices.Index(state.SelectedClue.Cells, state.SelectedCell)
|
|
||||||
if i > 0 {
|
|
||||||
state.PuzzleState[state.SelectedClue.Cells[i-1]] = '-' // clear the previous cell
|
|
||||||
state.SelectedCell = state.SelectedClue.Cells[i-1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if buffer[0] == '\r' {
|
|
||||||
state.NextWord()
|
|
||||||
}
|
|
||||||
if buffer[0] == '~' {
|
|
||||||
state.PreviousWord()
|
|
||||||
}
|
|
||||||
|
|
||||||
if string(buffer[0:2]) == "\x1b[" {
|
|
||||||
if (buffer[2] == 68 || buffer[2] == 67) && state.SelectedClue != nil && state.SelectedClue.Direction == puz.DirectionDown {
|
|
||||||
state.SelectedClue = state.Puzzle.Cells[state.SelectedCell][0]
|
|
||||||
} else if (buffer[2] == 65 || buffer[2] == 66) && state.SelectedClue != nil && state.SelectedClue.Direction == puz.DirectionAcross {
|
|
||||||
state.SelectedClue = state.Puzzle.Cells[state.SelectedCell][1]
|
|
||||||
} else {
|
|
||||||
switch buffer[2] {
|
|
||||||
case 68: // left
|
|
||||||
state.MoveCursor(3)
|
|
||||||
case 67: // right
|
|
||||||
state.MoveCursor(1)
|
|
||||||
case 65: // up
|
|
||||||
state.MoveCursor(0)
|
|
||||||
case 66: // down
|
|
||||||
state.MoveCursor(2)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch state.SelectedClue.Direction {
|
|
||||||
case puz.DirectionAcross:
|
|
||||||
state.SelectedClue = state.Puzzle.Cells[state.SelectedCell][0]
|
|
||||||
case puz.DirectionDown:
|
|
||||||
state.SelectedClue = state.Puzzle.Cells[state.SelectedCell][1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("\r\x1b[%dA", uiHeight)
|
fmt.Printf("\r\x1b[%dA", uiHeight)
|
||||||
fmt.Print("\x1b[J")
|
fmt.Print("\x1b[J")
|
||||||
|
|
||||||
uiHeight = state.RenderUI()
|
uiHeight = state.RenderUI(os.Stdout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+80
@@ -0,0 +1,80 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/cjdenio/crossword/game"
|
||||||
|
"github.com/cjdenio/crossword/puz"
|
||||||
|
"github.com/gliderlabs/ssh"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ssh.Handle(func(s ssh.Session) {
|
||||||
|
file, err := os.ReadFile(os.Args[1])
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
puzzle, err := puz.ParsePuz(file)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
state := game.State{
|
||||||
|
Puzzle: puzzle,
|
||||||
|
PuzzleState: []rune(puzzle.State),
|
||||||
|
SelectedClue: puzzle.Clues[0],
|
||||||
|
SelectedCell: puzzle.Clues[0].Cells[0],
|
||||||
|
}
|
||||||
|
|
||||||
|
io.WriteString(s, "\x1b[?25l")
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
io.WriteString(s, "\x1b[?25h")
|
||||||
|
}()
|
||||||
|
|
||||||
|
uiHeight := state.RenderUI(s)
|
||||||
|
|
||||||
|
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 {
|
||||||
|
scanner.Scan()
|
||||||
|
buffer := scanner.Bytes()
|
||||||
|
|
||||||
|
exited := state.HandleInput(buffer)
|
||||||
|
if exited {
|
||||||
|
state.SelectedClue = nil
|
||||||
|
state.SelectedCell = -1
|
||||||
|
state.Goodbye = true
|
||||||
|
fmt.Fprintf(s, "\r\x1b[%dA", uiHeight)
|
||||||
|
fmt.Fprint(s, "\x1b[J")
|
||||||
|
state.RenderUI(s)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(s, "\r\x1b[%dA", uiHeight)
|
||||||
|
fmt.Fprint(s, "\x1b[J")
|
||||||
|
|
||||||
|
uiHeight = state.RenderUI(s)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
log.Fatal(ssh.ListenAndServe(":1234", nil))
|
||||||
|
}
|
||||||
Reference in new issue
Block a user