WIP
parent
6b86087c0e
commit
d7adcbf11f
|
@ -1,16 +1,13 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
"unicode/utf8"
|
|
||||||
|
|
||||||
|
"github.com/MakeNowJust/heredoc/v2"
|
||||||
|
"github.com/gdamore/tcell/v2"
|
||||||
"github.com/rivo/tview"
|
"github.com/rivo/tview"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -61,7 +58,19 @@ func cli(s *streams) error {
|
||||||
sidebar := tview.NewTextView()
|
sidebar := tview.NewTextView()
|
||||||
sidebar.SetBorder(true)
|
sidebar.SetBorder(true)
|
||||||
sidebar.SetDynamicColors(true)
|
sidebar.SetDynamicColors(true)
|
||||||
sidebar.SetText("[-:-:b]pbbt[-:-:-]")
|
sidebar.SetText(heredoc.Doc(`
|
||||||
|
[-:-:b]hey here are some hints[-:-:-]
|
||||||
|
|
||||||
|
quit by pressing [-:-:b]ctrl-c[-:-:-]
|
||||||
|
(your responses won't be saved)
|
||||||
|
|
||||||
|
type stuff. send it with [-:-:b]ctrl+d[-:-:-]
|
||||||
|
|
||||||
|
try a [-:-:b]verb[-:-:-] using [-:-:b]/[-:-:-] like:
|
||||||
|
|
||||||
|
[-:-:b]/go north[-:-:-]
|
||||||
|
|
||||||
|
`))
|
||||||
|
|
||||||
innerFlex.SetDirection(tview.FlexColumn)
|
innerFlex.SetDirection(tview.FlexColumn)
|
||||||
innerFlex.AddItem(msgScroll, 0, 2, false)
|
innerFlex.AddItem(msgScroll, 0, 2, false)
|
||||||
|
@ -77,9 +86,52 @@ func cli(s *streams) error {
|
||||||
app := tview.NewApplication()
|
app := tview.NewApplication()
|
||||||
app.SetRoot(pages, true)
|
app.SetRoot(pages, true)
|
||||||
|
|
||||||
|
player := newCharacter("you", "TODO")
|
||||||
|
|
||||||
|
handleInput := func(msg string) {
|
||||||
|
if strings.HasPrefix(msg, "/") {
|
||||||
|
// TODO handle command
|
||||||
|
}
|
||||||
|
fmt.Fprintln(msgScroll, player.Say(msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
||||||
|
switch event.Key() {
|
||||||
|
case tcell.KeyCtrlD:
|
||||||
|
handleInput(input.GetText())
|
||||||
|
input.SetText("", false)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return event
|
||||||
|
})
|
||||||
|
|
||||||
return app.Run()
|
return app.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type character struct {
|
||||||
|
Name string
|
||||||
|
Description string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCharacter(name, description string) *character {
|
||||||
|
return &character{
|
||||||
|
Name: name,
|
||||||
|
Description: description,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *character) Say(msg string) string {
|
||||||
|
verb := "says"
|
||||||
|
if c.Name == "you" {
|
||||||
|
verb = "say"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("[-:-:b]%s[-:-:-] %s: '%s'",
|
||||||
|
c.Name,
|
||||||
|
verb,
|
||||||
|
strings.TrimSpace(msg))
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
s := &streams{
|
s := &streams{
|
||||||
In: os.Stdin,
|
In: os.Stdin,
|
||||||
|
@ -93,141 +145,7 @@ func main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Prompter struct {
|
/*
|
||||||
in io.Reader
|
|
||||||
out io.Writer
|
|
||||||
width int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Prompter) Say(m string) {
|
|
||||||
for _, line := range wrap(m, p.width) {
|
|
||||||
fmt.Fprintln(p.out, line)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Prompter) CharSay(c, m string) {
|
|
||||||
sayPrefix := fmt.Sprintf("%s says: ", c)
|
|
||||||
prefixWidth := utf8.RuneCountInString(sayPrefix)
|
|
||||||
width := p.width - prefixWidth
|
|
||||||
indent := ""
|
|
||||||
for x := 0; x < utf8.RuneCountInString(sayPrefix); x++ {
|
|
||||||
indent += " "
|
|
||||||
}
|
|
||||||
for i, line := range wrap(m, width) {
|
|
||||||
if i == 0 {
|
|
||||||
fmt.Fprintln(p.out, sayPrefix+line)
|
|
||||||
} else {
|
|
||||||
fmt.Fprintln(p.out, indent+line)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type InputAnswer struct {
|
|
||||||
Value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func runeLen(s string) int {
|
|
||||||
return utf8.RuneCountInString(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func wrap(s string, width int) []string {
|
|
||||||
fielded := strings.Fields(s)
|
|
||||||
out := []string{}
|
|
||||||
line := ""
|
|
||||||
for i, field := range fielded {
|
|
||||||
if runeLen(field)+runeLen(line)+1 < width {
|
|
||||||
line += field + " "
|
|
||||||
} else {
|
|
||||||
out = append(out, line)
|
|
||||||
line = field + " "
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if i == len(fielded)-1 {
|
|
||||||
out = append(out, line)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Prompter) Confirm(m string) (bool, error) {
|
|
||||||
result := InputAnswer{}
|
|
||||||
|
|
||||||
for {
|
|
||||||
err := p.Ask(m, &result)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
val := strings.TrimSpace(result.Value)
|
|
||||||
|
|
||||||
switch val {
|
|
||||||
case "yes", "y":
|
|
||||||
return true, nil
|
|
||||||
case "no", "n":
|
|
||||||
return false, nil
|
|
||||||
default:
|
|
||||||
p.Say("sorry, please say y or n")
|
|
||||||
p.Pause()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Prompter) Ask(m string, result *InputAnswer) error {
|
|
||||||
fmt.Fprintf(p.out, "%s ", m)
|
|
||||||
var val string
|
|
||||||
var err error
|
|
||||||
|
|
||||||
reader := bufio.NewReader(p.in)
|
|
||||||
for val == "" {
|
|
||||||
val, err = reader.ReadString('\n')
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if val == "" {
|
|
||||||
p.Say("hmm, what was that?")
|
|
||||||
p.Pause()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result.Value = val
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Prompter) AskLong(m string, result *InputAnswer) error {
|
|
||||||
fmt.Fprintf(p.out, "%s\n", m)
|
|
||||||
var val []byte
|
|
||||||
var err error
|
|
||||||
|
|
||||||
reader := bufio.NewReader(p.in)
|
|
||||||
for len(val) == 0 {
|
|
||||||
val, err = ioutil.ReadAll(reader)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(val) == 0 {
|
|
||||||
fmt.Fprintf(p.out, "%s\n", m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result.Value = string(val)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Prompter) Pause() {
|
|
||||||
fmt.Fprintln(p.out)
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewPrompter(width int, s *streams) Prompter {
|
|
||||||
return Prompter{
|
|
||||||
in: s.In,
|
|
||||||
out: s.Out,
|
|
||||||
width: width,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type answers struct {
|
type answers struct {
|
||||||
username string
|
username string
|
||||||
email string
|
email string
|
||||||
|
@ -242,29 +160,6 @@ type answers struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func _main(args []string, s *streams) error {
|
func _main(args []string, s *streams) error {
|
||||||
a := answers{}
|
|
||||||
|
|
||||||
p := NewPrompter(80, s)
|
|
||||||
|
|
||||||
// disable input buffering
|
|
||||||
exec.Command("stty", "-F", "/dev/tty", "cbreak", "min", "1").Run()
|
|
||||||
|
|
||||||
// LOL i don't think this will work
|
|
||||||
//reader := bufio.NewReader(p.in)
|
|
||||||
//s, _ := reader.ReadString(4)
|
|
||||||
fmt.Printf("DBG %#v\n", s)
|
|
||||||
//var b []byte = make([]byte, 100)
|
|
||||||
//for {
|
|
||||||
// os.Stdin.Read(b)
|
|
||||||
// fmt.Println("I got the byte", b, "("+string(b)+")")
|
|
||||||
//}
|
|
||||||
|
|
||||||
var ia InputAnswer
|
|
||||||
if err := p.AskLong("lol give me stuff hit ctrl+d", &ia); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Printf("DBG %#v\n", ia.Value)
|
|
||||||
|
|
||||||
p.Say("you are standing in a field.")
|
p.Say("you are standing in a field.")
|
||||||
p.Pause()
|
p.Pause()
|
||||||
p.Say("there are flowers around you. you are standing in a slight depression and before you is grass touching a purple sky.")
|
p.Say("there are flowers around you. you are standing in a slight depression and before you is grass touching a purple sky.")
|
||||||
|
@ -345,54 +240,5 @@ func _main(args []string, s *streams) error {
|
||||||
|
|
||||||
p.CharSay("cube", "i know that was a lot so i appreciate it. i've got everything written down here. before i carry it off, do you want to review and edit what you wrote?")
|
p.CharSay("cube", "i know that was a lot so i appreciate it. i've got everything written down here. before i carry it off, do you want to review and edit what you wrote?")
|
||||||
|
|
||||||
confirmed, err := p.Confirm("type y or n: ")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if confirmed {
|
|
||||||
err := edit(s, &a)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("DBG %#v\n", confirmed)
|
|
||||||
|
|
||||||
fmt.Printf("DBG %#v\n", a)
|
|
||||||
|
|
||||||
// TODO allow for editing
|
|
||||||
// TODO write answers to disk
|
|
||||||
// TODO add a log
|
|
||||||
// TODO pretty colors
|
|
||||||
// TODO ascii art
|
|
||||||
// TODO IP throttling?
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func edit(s *streams, a *answers) error {
|
|
||||||
// TODO make more real
|
|
||||||
/*
|
|
||||||
username string
|
|
||||||
email string
|
|
||||||
applied time.Time
|
|
||||||
|
|
||||||
howDay string
|
|
||||||
howHeard string
|
|
||||||
reasons string
|
|
||||||
plans string
|
|
||||||
socials string
|
|
||||||
sshKey string
|
|
||||||
*/
|
|
||||||
// TODO add note about tabbing around
|
|
||||||
|
|
||||||
app := tview.NewApplication()
|
|
||||||
form := tview.NewForm().
|
|
||||||
AddInputField("how did you hear about the town?", a.howHeard, 0, nil, nil).
|
|
||||||
AddButton("cool i'm good", nil).
|
|
||||||
AddButton("cancel and discard all this please", func() { app.Stop() })
|
|
||||||
form.SetBorder(true).SetTitle("edit your stuff").SetTitleAlign(tview.AlignCenter)
|
|
||||||
|
|
||||||
return app.SetRoot(form, true).EnableMouse(true).Run()
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -4,6 +4,7 @@ go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/AlecAivazis/survey/v2 v2.3.5
|
github.com/AlecAivazis/survey/v2 v2.3.5
|
||||||
|
github.com/MakeNowJust/heredoc/v2 v2.0.1
|
||||||
github.com/charmbracelet/glamour v0.5.0
|
github.com/charmbracelet/glamour v0.5.0
|
||||||
github.com/rivo/tview v0.0.0-20230130130022-4a1b7a76c01c
|
github.com/rivo/tview v0.0.0-20230130130022-4a1b7a76c01c
|
||||||
github.com/spf13/cobra v1.5.0
|
github.com/spf13/cobra v1.5.0
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -1,5 +1,7 @@
|
||||||
github.com/AlecAivazis/survey/v2 v2.3.5 h1:A8cYupsAZkjaUmhtTYv3sSqc7LO5mp1XDfqe5E/9wRQ=
|
github.com/AlecAivazis/survey/v2 v2.3.5 h1:A8cYupsAZkjaUmhtTYv3sSqc7LO5mp1XDfqe5E/9wRQ=
|
||||||
github.com/AlecAivazis/survey/v2 v2.3.5/go.mod h1:4AuI9b7RjAR+G7v9+C4YSlX/YL3K3cWNXgWXOhllqvI=
|
github.com/AlecAivazis/survey/v2 v2.3.5/go.mod h1:4AuI9b7RjAR+G7v9+C4YSlX/YL3K3cWNXgWXOhllqvI=
|
||||||
|
github.com/MakeNowJust/heredoc/v2 v2.0.1 h1:rlCHh70XXXv7toz95ajQWOWQnN4WNLt0TdpZYIR/J6A=
|
||||||
|
github.com/MakeNowJust/heredoc/v2 v2.0.1/go.mod h1:6/2Abh5s+hc3g9nbWLe9ObDIOhaRrqsyY9MWy+4JdRM=
|
||||||
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
|
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
|
||||||
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
|
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
|
||||||
github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek=
|
github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek=
|
||||||
|
|
Loading…
Reference in New Issue