You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
fx/new/main.go

170 lines
3.0 KiB
Go

10 months ago
package main
import (
"fmt"
"io"
"os"
"runtime/pprof"
10 months ago
"github.com/charmbracelet/bubbles/key"
tea "github.com/charmbracelet/bubbletea"
10 months ago
)
func main() {
10 months ago
f, err := os.Create("cpu.prof")
if err != nil {
panic(err)
10 months ago
}
10 months ago
err = pprof.StartCPUProfile(f)
if err != nil {
panic(err)
}
defer pprof.StopCPUProfile()
memProf, err := os.Create("mem.prof")
if err != nil {
panic(err)
}
defer pprof.WriteHeapProfile(memProf)
10 months ago
data, err := io.ReadAll(os.Stdin)
if err != nil {
panic(err)
}
head, err := parse(data)
if err != nil {
fmt.Print(err.Error())
os.Exit(1)
return
}
m := &model{
head: head,
}
p := tea.NewProgram(m, tea.WithAltScreen(), tea.WithMouseCellMotion())
_, err = p.Run()
if err != nil {
panic(err)
}
}
type model struct {
10 months ago
termWidth, termHeight int
head *node
cursor int // cursor position [0, termHeight)
10 months ago
}
func (m *model) Init() tea.Cmd {
return nil
}
func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.WindowSizeMsg:
10 months ago
m.termWidth = msg.Width
m.termHeight = msg.Height
10 months ago
case tea.MouseMsg:
switch msg.Type {
case tea.MouseWheelUp:
case tea.MouseWheelDown:
}
case tea.KeyMsg:
return m.handleKey(msg)
}
return m, nil
}
func (m *model) handleKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
switch {
case key.Matches(msg, keyMap.Quit):
return m, tea.Quit
case key.Matches(msg, keyMap.Up):
10 months ago
m.cursor--
if m.cursor < 0 {
m.cursor = 0
if m.head.prev != nil {
m.head = m.head.prev
}
}
10 months ago
return m, nil
case key.Matches(msg, keyMap.Down):
10 months ago
m.cursor++
if m.cursor >= m.viewHeight() {
m.cursor = m.viewHeight() - 1
if m.head.next != nil && !m.isCursorAtEnd() {
m.head = m.head.next
}
}
10 months ago
return m, nil
}
return m, nil
}
func (m *model) View() string {
var screen []byte
head := m.head
10 months ago
10 months ago
// Prerender syntax
colon := currentTheme.Syntax([]byte{':', ' '})
comma := currentTheme.Syntax([]byte{','})
for i := 0; i < m.viewHeight(); i++ {
10 months ago
if head == nil {
break
}
for ident := 0; ident < int(head.depth); ident++ {
screen = append(screen, ' ', ' ')
}
if head.key != nil {
10 months ago
keyColor := currentTheme.Key
if m.cursor == i {
keyColor = currentTheme.Cursor
}
screen = append(screen, keyColor(head.key)...)
screen = append(screen, colon...)
screen = append(screen, colorForValue(head.value)(head.value)...)
} else {
colorize := colorForValue(head.value)
if m.cursor == i {
colorize = currentTheme.Cursor
}
screen = append(screen, colorize(head.value)...)
10 months ago
}
if head.comma {
10 months ago
screen = append(screen, comma...)
10 months ago
}
screen = append(screen, '\n')
head = head.next
}
10 months ago
10 months ago
if len(screen) > 0 {
10 months ago
screen = screen[:len(screen)-1]
}
return string(screen)
}
10 months ago
func (m *model) viewHeight() int {
return m.termHeight
}
func (m *model) cursorPointsTo() *node {
head := m.head
for i := 0; i < m.cursor; i++ {
if head == nil {
return nil
}
head = head.next
}
return head
}
func (m *model) isCursorAtEnd() bool {
n := m.cursorPointsTo()
return n == nil || n.next == nil
}