procurator/tui.go

185 lines
5.0 KiB
Go

package main
import (
"fmt"
// "os"
// "path/filepath"
// "github.com/kardianos/osext"
// "unicode"
// "strings"
// "time"
"github.com/charmbracelet/bubbles/list"
"github.com/charmbracelet/bubbles/viewport"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
// "github.com/fsnotify/fsnotify"
)
var skipNextViewportUpdate bool
type model struct {
viewport viewport.Model
ready bool
// choices []string // items on the to-do list
list list.Model
// choice string
quitting bool
// cursor int // which to-do list item our cursor is pointing at
// selected map[int]struct{} // which to-do items are selected
}
func initialModel() model {
items := []list.Item{
item("fmt code"),
item("git add ."),
// item("git commit"), TODO
item("git push"),
// item("add to gitignore"), TODO
// item("go mod init github_repo"), TODO
// item("remove file from git history"), TODO
}
l := list.New(items, itemDelegate{}, defaultWidth, listHeight)
// l.Title = "What do you want for dinner?"
l.SetShowStatusBar(false)
l.SetShowTitle(false)
// l.SetShowStatusBar(true)
l.SetFilteringEnabled(false)
l.Styles.Title = titleStyle
l.Styles.PaginationStyle = paginationStyle
l.Styles.HelpStyle = helpStyle
return model{
// Our to-do list is a grocery list
// choices: []string{"Buy carrots", "Buy celery", "Buy kohlrabi"},
// A map which indicates which choices are selected. We're using
// the map like a mathematical set. The keys refer to the indexes
// of the `choices` slice, above.
// selected: make(map[int]struct{}),
list: l,
}
}
type dataMsg struct {
// reflex string
}
func (m *model) Init() tea.Cmd {
// Just return `nil`, which means "no I/O right now, please."
// return m.reflex("")
return nil
}
func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
// var (
// // cmd tea.Cmd
// cmds []tea.Cmd
// )
switch msg := msg.(type) {
// Is it a key press?
case tea.KeyMsg:
// Cool, what was the actual key pressed?
switch msg.String() {
case "ctrl+c", "q":
return m, tea.Quit
// // The "up" and "k" keys move the cursor up
// case "up", "k":
// if m.cursor > 0 {
// m.cursor--
// }
//
// // The "down" and "j" keys move the cursor down
// case "down", "j":
// if m.cursor < len(m.choices)-1 {
// m.cursor++
// }
// The "enter" key and the spacebar (a literal space) toggle
// the selected state for the item that the cursor is pointing at.
case "enter", " ":
i, ok := m.list.SelectedItem().(item)
if ok {
// m.choice = string(i)
skipNextViewportUpdate = true
m.viewport.SetContent("[Running...]")
m.viewport.SetContent(choiceAction(string(i)))
m.viewport.GotoBottom()
}
}
case tea.WindowSizeMsg:
headerHeight := lipgloss.Height(m.headerView())
footerHeight := lipgloss.Height(m.footerView())
verticalMarginHeight := headerHeight + footerHeight
m.list.SetWidth(msg.Width)
m.list.SetHeight(msg.Height / 2)
if !m.ready {
// Since this program is using the full size of the viewport we
// need to wait until we've received the window dimensions before
// we can initialize the viewport. The initial dimensions come in
// quickly, though asynchronously, which is why we wait for them
// here.
m.viewport = viewport.New(msg.Width, msg.Height/2-verticalMarginHeight)
m.viewport.YPosition = headerHeight
m.viewport.HighPerformanceRendering = useHighPerformanceRenderer
m.viewport.SetContent("[READY]")
m.ready = true
// This is only necessary for high performance rendering, which in
// most cases you won't need.
//
// Render the viewport one line below the header.
m.viewport.YPosition = headerHeight + 1
} else {
m.viewport.Width = msg.Width
m.viewport.Height = msg.Height/2 - verticalMarginHeight
}
// if useHighPerformanceRenderer {
// // Render (or re-render) the whole viewport. Necessary both to
// // initialize the viewport and when the window is resized.
// //
// // This is needed for high-performance rendering only.
// cmds = append(cmds, viewport.Sync(m.viewport))
// }
case fileUpdated:
if !skipNextViewportUpdate {
m.viewport.SetContent("[Running...]")
m.viewport.SetContent(watchRun())
m.viewport.GotoBottom()
return m, nil
}
skipNextViewportUpdate = false
}
// Return the updated model to the Bubble Tea runtime for processing.
// Note that we're not returning a command.
var cmd tea.Cmd
m.list, cmd = m.list.Update(msg)
return m, cmd
// return m, nil
}
func (m *model) View() string {
if !m.ready {
return "\n Initializing..."
}
// return fmt.Sprintf("%s\n%s\n%s\n%s", m.headerView(), m.viewport.View(), m.footerView(), m.choicesView())
// TODO if window too small, hide list.View
return fmt.Sprintf("%s\n%s\n%s\n%s", m.headerView(), m.viewport.View(), m.footerView(), m.list.View())
}