Files

242 lines
8.8 KiB
Go

package main
import (
"fmt"
"strings"
"github.com/egoist/mygo/ui"
"git.zacharyzhang.com/ZacharyZhang-NY/MujicaUI/code"
"git.zacharyzhang.com/ZacharyZhang-NY/MujicaUI/core"
"git.zacharyzhang.com/ZacharyZhang-NY/MujicaUI/data"
"git.zacharyzhang.com/ZacharyZhang-NY/MujicaUI/input"
)
func codeSymbolDemo(c *ui.Context, log func(string)) {
type state struct {
s code.SymbolOutlineState
cursor float64
disabled bool
}
s := ui.Local(c.Root(), "333", func() *state { return &state{cursor: 15} })
st := *s
codeDemoControls(c, func() {
codeDemoCheck(c, &st.disabled, "Disabled", log)
ui.Text(c, fmt.Sprintf("Cursor line %.0f", st.cursor))
if input.Slider(c, &st.cursor, input.SliderOptions{Min: 1, Max: 34, Step: 1}).Changed() {
log(fmt.Sprintf("cursor %.0f", st.cursor))
}
})
symbols := []code.Symbol{
{Name: "Decree", Kind: code.SymbolType, Line: 6, EndLine: 9, Detail: "struct", Children: []code.Symbol{
{Name: "ID", Kind: code.SymbolField, Line: 7, EndLine: 7, Detail: "int"},
{Name: "Title", Kind: code.SymbolField, Line: 8, EndLine: 8, Detail: "string"},
}},
{Name: "Seal", Kind: code.SymbolFunction, Line: 13, EndLine: 21, Detail: "(d Decree) (string, error)"},
{Name: "Herald", Kind: code.SymbolFunction, Line: 23, EndLine: 31, Detail: "(ds []Decree) int"},
}
r := code.SymbolOutline(c, symbols, &st.s, code.SymbolOutlineOptions{CursorLine: int(st.cursor), Disabled: st.disabled})
r.Element.Size(420, 320)
if r.Jumped != nil {
log(fmt.Sprintf("jump to %s, line %d", r.Jumped.Name, r.Jumped.Line))
}
}
func codeCompletionDemo(c *ui.Context, log func(string)) {
type state struct {
text string
open bool
s code.CompletionMenuState
disabled bool
}
s := ui.Local(c.Root(), "334", func() *state { return &state{} })
st := *s
codeDemoControls(c, func() { codeDemoCheck(c, &st.disabled, "Disabled", log) })
all := []code.Completion{
{Label: "Seal", Kind: code.SymbolFunction, Detail: "func(d Decree) (string, error)", Doc: "Seal stamps a decree with the royal wax."},
{Label: "Search", Kind: code.SymbolFunction, Detail: "func(q string) []Decree"},
{Label: "Season", Kind: code.SymbolConstant, Detail: "= 4"},
{Label: "Herald", Kind: code.SymbolFunction, Detail: "func(ds []Decree) int"},
{Label: "Decree", Kind: code.SymbolType, Detail: "struct", Doc: "Decree is an order of the court."},
}
word := st.text[strings.LastIndexAny(st.text, " .(")+1:]
var items []code.Completion
for _, it := range all {
if word != "" && strings.HasPrefix(strings.ToLower(it.Label), strings.ToLower(word)) {
items = append(items, it)
}
}
ui.Column(c).Width(420).Gap(8).Children(func() {
ui.Text(c, "Type “se” or “de” to see suggestions.").TextColor(core.Tokens(c).TextMuted)
in := input.TextInput(c, &st.text, input.TextInputOptions{Label: "Code", Placeholder: "court.", Disabled: st.disabled})
if in.Changed() {
st.open = len(items) > 0
}
r := code.CompletionMenu(c, in.Input, &st.open, items, &st.s, code.CompletionMenuOptions{Disabled: st.disabled})
if r.Accepted != nil {
st.text = st.text[:len(st.text)-len(word)] + r.Accepted.Label
log("accept " + r.Accepted.Label)
}
})
}
func codeDebugDemo(c *ui.Context, log func(string)) {
type state struct {
dbg code.DebugState
disabled bool
}
s := ui.Local(c.Root(), "335", func() *state { return &state{dbg: code.DebugPaused} })
st := *s
names := []string{"Stopped", "Running", "Paused"}
codeDemoControls(c, func() {
codeDemoCheck(c, &st.disabled, "Disabled", log)
ui.Text(c, "State: "+names[st.dbg])
})
a := code.DebugToolbar(c, st.dbg, code.DebugToolbarOptions{Disabled: st.disabled}).Action
switch a {
case code.DebugNone:
return
case code.DebugContinue, code.DebugRestart:
st.dbg = code.DebugRunning
case code.DebugPause, code.DebugStepOver, code.DebugStepInto, code.DebugStepOut:
st.dbg = code.DebugPaused
case code.DebugStop:
st.dbg = code.DebugStopped
}
log(fmt.Sprintf("action %d, now %s", a, names[st.dbg]))
}
func codeBreakpointDemo(c *ui.Context, log func(string)) {
type state struct {
bps []code.Breakpoint
disabled bool
}
s := ui.Local(c.Root(), "336", func() *state {
return &state{bps: []code.Breakpoint{
{ID: "1", File: "court/seal.go", Line: 14, Enabled: true},
{ID: "2", File: "court/ledger.go", Line: 40, Condition: "n > 3"},
{ID: "3", File: "main.go", Line: 9, Enabled: true},
}}
})
st := *s
codeDemoControls(c, func() { codeDemoCheck(c, &st.disabled, "Disabled", log) })
r := code.BreakpointList(c, &st.bps, code.BreakpointListOptions{Disabled: st.disabled})
r.Element.Size(480, 240)
for _, e := range []struct{ what, id string }{{"toggled", r.Toggled}, {"condition", r.Edited}, {"open", r.Opened}} {
if e.id != "" {
log(e.what + " " + e.id)
}
}
}
func codeCallStackDemo(c *ui.Context, log func(string)) {
type state struct {
s code.CallStackState
disabled bool
}
s := ui.Local(c.Root(), "337", func() *state { return &state{s: code.CallStackState{Current: "f1"}} })
st := *s
codeDemoControls(c, func() { codeDemoCheck(c, &st.disabled, "Disabled", log) })
threads := []code.DebugThread{
{ID: "t1", Name: "main", Frames: []code.StackFrame{
{ID: "f1", Name: "court.Seal", File: "court/seal.go", Line: 14},
{ID: "f2", Name: "court.Herald", File: "court/seal.go", Line: 27},
{ID: "f3", Name: "main.main", File: "main.go", Line: 9},
}},
{ID: "t2", Name: "ledger writer", Frames: []code.StackFrame{{ID: "f4", Name: "ledger.Flush", File: "ledger/write.go", Line: 51}}},
}
r := code.CallStack(c, threads, &st.s, code.CallStackOptions{Disabled: st.disabled})
r.Element.Size(440, 300)
if r.Changed() {
log("frame " + st.s.Current)
}
}
func codeVariablesDemo(c *ui.Context, log func(string)) {
type state struct {
vars []code.Variable
s code.VariablesPanelState
disabled bool
}
s := ui.Local(c.Root(), "338", func() *state {
return &state{vars: []code.Variable{
{Name: "d", Type: "court.Decree", Value: "{…}", Children: []code.Variable{
{Name: "ID", Value: "42", Type: "int", Changed: true},
{Name: "Title", Value: `"Of seals"`, Type: "string"},
}},
{Name: "i", Value: "2", Type: "int", Changed: true},
{Name: "err", Value: "nil", Type: "error"},
}}
})
st := *s
codeDemoControls(c, func() { codeDemoCheck(c, &st.disabled, "Disabled", log) })
r := code.VariablesPanel(c, st.vars, &st.s, code.VariablesPanelOptions{Disabled: st.disabled})
r.Element.Size(440, 260)
if r.Edited != nil {
log(fmt.Sprintf("set %s = %s", r.Edited.Path, r.Edited.Value))
codeDemoSet(st.vars, strings.Split(r.Edited.Path, "."), r.Edited.Value)
}
}
// codeDemoSet writes value at the dotted path.
func codeDemoSet(vars []code.Variable, path []string, value string) {
for i := range vars {
if vars[i].Name != path[0] {
continue
}
if len(path) == 1 {
vars[i].Value, vars[i].Changed = value, true
return
}
codeDemoSet(vars[i].Children, path[1:], value)
}
}
func codeHexDemo(c *ui.Context, log func(string)) {
type state struct {
s code.HexViewerState
disabled bool
}
s := ui.Local(c.Root(), "339", func() *state { return &state{} })
st := *s
codeDemoControls(c, func() { codeDemoCheck(c, &st.disabled, "Disabled", log) })
data := []byte(strings.Join(codeDemoSource, "\n"))
r := code.HexViewer(c, data, &st.s, code.HexViewerOptions{Disabled: st.disabled})
r.Element.Size(720, 300)
if r.Changed() {
a, b := st.s.Selection()
log(fmt.Sprintf("bytes %d..%d", a, b))
}
}
func codeFlamegraphDemo(c *ui.Context, log func(string)) {
type state struct {
s code.FlamegraphState
status string
disabled bool
}
s := ui.Local(c.Root(), "340", func() *state { return &state{status: "Ready"} })
st := *s
codeDemoControls(c, func() {
codeDemoCheck(c, &st.disabled, "Disabled", log)
opts := []input.SelectOption[string]{{Value: "Ready", Label: "Ready"}, {Value: "Loading", Label: "Loading"}, {Value: "Failed", Label: "Failed"}}
if input.Select(c, &st.status, opts, input.SelectOptions{Label: "Status"}).Changed() {
log("status " + st.status)
}
})
root := &code.FlameNode{Name: "main", Value: 240, Children: []code.FlameNode{
{Name: "court.Herald", Value: 150, Children: []code.FlameNode{
{Name: "court.Seal", Value: 110, Children: []code.FlameNode{{Name: "wax.Melt", Value: 70}, {Name: "ink.Dry", Value: 25}}},
{Name: "ledger.Write", Value: 30},
}},
{Name: "archive.Load", Value: 60, Children: []code.FlameNode{{Name: "json.Decode", Value: 45}}},
{Name: "gc", Value: 20},
}}
status := map[string]data.DataStatus{"Ready": data.DataReady, "Loading": data.DataLoading, "Failed": data.DataFailed}[st.status]
ui.Column(c).Width(680).Children(func() {
if code.Flamegraph(c, root, &st.s, code.FlamegraphOptions{Unit: "ms", Status: status, Error: "Profile could not be read", Disabled: st.disabled}).Changed() {
log(fmt.Sprintf("zoom %v focus %v", st.s.Zoom, st.s.Focus))
}
})
}