Skip to content

Commit

Permalink
hof/tui: add support for outputting playground content, update help t…
Browse files Browse the repository at this point in the history
…ext and some styling (#324)
  • Loading branch information
verdverm authored Sep 10, 2023
1 parent 39aa491 commit b9d8214
Show file tree
Hide file tree
Showing 11 changed files with 374 additions and 205 deletions.
2 changes: 1 addition & 1 deletion lib/tui/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func Cmd(args []string, rflags flags.RootPflagpole) error {
// some latent locksups occur randomly
time.Sleep(time.Millisecond * 23)
tui.SendCustomEvent("/router/dispatch", context)
tui.SendCustomEvent("/status/message", "Welcome to [gold]_[ivory]Hofstadter[-]!!")
tui.SendCustomEvent("/status/message", "[blue::b]Welcome to [gold::bi]_[ivory]Hofstadter[-::-]")
}()

// Start the Main (Blocking) Loop
Expand Down
45 changes: 45 additions & 0 deletions lib/tui/components/cue/browser/codec.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
package browser

import (
"fmt"

"cuelang.org/go/cue/format"

"github.com/hofstadter-io/hof/lib/gen"
)

func (V *Browser) Encode() (map[string]any, error) {
m := map[string]any{
"type": V.TypeName(),
Expand All @@ -24,3 +32,40 @@ func (V *Browser) Encode() (map[string]any, error) {
}


func (C *Browser) GetValueText(mode string) (string, error) {
var (
b []byte
err error
)
switch mode {
case "cue":
syn := C.value.Syntax(C.Options()...)

b, err = format.Node(syn)
if !C.ignore {
if err != nil {
return "", err
}
}

case "json":
f := &gen.File{}
b, err = f.FormatData(C.value, "json")
if err != nil {
return "", err
}

case "yaml":
f := &gen.File{}
b, err = f.FormatData(C.value, "yaml")
if err != nil {
return "", err
}

default:
return "", fmt.Errorf("unknown file type %q", mode)

}

return string(b), err
}
43 changes: 43 additions & 0 deletions lib/tui/components/cue/playground/events.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package playground

import (
"github.com/gdamore/tcell/v2"

"github.com/hofstadter-io/hof/lib/tui/tview"
)
func (C *Playground) setupKeybinds() {
// events (hotkeys)
C.SetInputCapture(func(evt *tcell.EventKey) *tcell.EventKey {
switch evt.Key() {
case tcell.KeyRune:
if (evt.Modifiers() & tcell.ModAlt) == tcell.ModAlt {
switch evt.Rune() {
case 'f':
flexDir := C.GetDirection()
if flexDir == tview.FlexRow {
C.SetDirection(tview.FlexColumn)
} else {
C.SetDirection(tview.FlexRow)
}

case 'S':
C.useScope = !C.useScope
C.Rebuild(false)

case 'R':
C.Rebuild(true)

default:
return evt
}

return nil
}

return evt

default:
return evt
}
})
}
56 changes: 56 additions & 0 deletions lib/tui/components/cue/playground/output.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package playground

import (
"fmt"
"os"
"path/filepath"
"strings"

"github.com/parnurzeal/gorequest"
)

const HTTP2_GOAWAY_CHECK = "http2: server sent GOAWAY and closed the connection"

func (C *Playground) PushToPlayground() (string, error) {
src := C.edit.GetText()

url := "https://cuelang.org/.netlify/functions/snippets"
req := gorequest.New().Post(url)
req.Set("Content-Type", "text/plain")
req.Send(src)

resp, body, errs := req.End()

if len(errs) != 0 && !strings.Contains(errs[0].Error(), HTTP2_GOAWAY_CHECK) {
fmt.Println("errs:", errs)
fmt.Println("resp:", resp)
fmt.Println("body:", body)
return body, errs[0]
}

if len(errs) != 0 || resp.StatusCode >= 500 {
return body, fmt.Errorf("Internal Error: " + body)
}
if resp.StatusCode >= 400 {
return body, fmt.Errorf("Bad Request: " + body)
}

return body, nil
}

func (C *Playground) WriteEditToFile(filename string) (error) {
src := C.edit.GetText()

return os.WriteFile(filename, []byte(src), 0644)
}

func (C *Playground) ExportFinalToFile(filename string) (error) {
ext := filepath.Ext(filename)
ext = strings.TrimPrefix(ext, ".")
src, err := C.final.viewer.GetValueText(ext)
if err != nil {
return err
}

return os.WriteFile(filename, []byte(src), 0644)
}
139 changes: 0 additions & 139 deletions lib/tui/components/cue/playground/playground.go
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
package playground

import (
"fmt"
"strings"
"time"

"cuelang.org/go/cue"
"cuelang.org/go/cue/cuecontext"
"github.com/gdamore/tcell/v2"
"github.com/parnurzeal/gorequest"

"github.com/hofstadter-io/hof/lib/tui"
"github.com/hofstadter-io/hof/lib/tui/components/cue/browser"
"github.com/hofstadter-io/hof/lib/tui/components/cue/helpers"
"github.com/hofstadter-io/hof/lib/tui/tview"
"github.com/hofstadter-io/hof/lib/watch"
)


type valPack struct {
config helpers.SourceConfig
value cue.Value
Expand Down Expand Up @@ -153,102 +146,6 @@ func (C *Playground) SetFlexDirection(dir int) {
}


const HTTP2_GOAWAY_CHECK = "http2: server sent GOAWAY and closed the connection"

func (C *Playground) PushToPlayground() (string, error) {
src := C.edit.GetText()

url := "https://cuelang.org/.netlify/functions/snippets"
req := gorequest.New().Post(url)
req.Set("Content-Type", "text/plain")
req.Send(src)

resp, body, errs := req.End()

if len(errs) != 0 && !strings.Contains(errs[0].Error(), HTTP2_GOAWAY_CHECK) {
fmt.Println("errs:", errs)
fmt.Println("resp:", resp)
fmt.Println("body:", body)
return body, errs[0]
}

if len(errs) != 0 || resp.StatusCode >= 500 {
return body, fmt.Errorf("Internal Error: " + body)
}
if resp.StatusCode >= 400 {
return body, fmt.Errorf("Bad Request: " + body)
}

return body, nil
}

func (C *Playground) Rebuild(rebuildScope bool) error {
// tui.Log("info", fmt.Sprintf("Play.rebuildScope %v %v %v", rebuildScope, C.useScope, C.scope.config))
var (
v cue.Value
err error
)

ctx := cuecontext.New()
src := C.edit.GetText()

// compile a value
if !C.useScope {
// just compile the text
v = ctx.CompileString(src, cue.InferBuiltins(true))
} else {
// compile the text with a scope

// tui.Log("warn", fmt.Sprintf("%#v", s))
sv, serr := C.scope.config.GetValue()
err = serr

if err != nil {
tui.Log("error", err)
}
// we shouldn't have to worry about this, but we aren't catching all the ways
// that we get into this code, in particular, hotkey can set scope to true when none exists
if !sv.Exists() {
tui.Log("error", "scope value does not exist")
err = fmt.Errorf("scope value does not exist")
}

if err == nil && sv.Exists() {
if rebuildScope {
// C.scope.config.Rebuild()
cfg := helpers.SourceConfig{Value: sv}
C.scope.viewer.SetSourceConfig(cfg)
C.scope.viewer.Rebuild()
}

// tui.Log("warn", fmt.Sprintf("recompile with scope: %v", rebuildScope))
ctx := sv.Context()
v = ctx.CompileString(src, cue.InferBuiltins(true), cue.Scope(sv))
}
}

cfg := helpers.SourceConfig{Value: v}
if err != nil {
tui.Log("error", err)
cfg = helpers.SourceConfig{Text: err.Error()}
}
// only update view value, that way, if we erase everything, we still see the value
C.final.viewer.SetUsingScope(C.useScope)
C.final.viewer.SetSourceConfig(cfg)
C.final.viewer.Rebuild()

// show/hide scope as needed
if C.useScope {
C.SetItem(0, C.scope.viewer, 0, 1, true)
} else {
C.SetItem(0, nil, 0, 0, false)
}


// tui.Draw()
return nil
}

func (C *Playground) Mount(context map[string]any) error {

return nil
Expand All @@ -265,39 +162,3 @@ func (C *Playground) Focus(delegate func(p tview.Primitive)) {
}


func (C *Playground) setupKeybinds() {
// events (hotkeys)
C.SetInputCapture(func(evt *tcell.EventKey) *tcell.EventKey {
switch evt.Key() {
case tcell.KeyRune:
if (evt.Modifiers() & tcell.ModAlt) == tcell.ModAlt {
switch evt.Rune() {
case 'f':
flexDir := C.GetDirection()
if flexDir == tview.FlexRow {
C.SetDirection(tview.FlexColumn)
} else {
C.SetDirection(tview.FlexRow)
}

case 'S':
C.useScope = !C.useScope
C.Rebuild(false)

case 'R':
C.Rebuild(true)

default:
return evt
}

return nil
}

return evt

default:
return evt
}
})
}
Loading

0 comments on commit b9d8214

Please sign in to comment.