procurator/tui.go

236 lines
6.2 KiB
Go

package main
import (
"fmt"
// "os"
// "path/filepath"
// "github.com/kardianos/osext"
// "unicode"
// "strings"
// "time"
// "log"
"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
}
type continueExec string
var fileUpdatedBool bool
var choiceActionBool bool
func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var (
cmd tea.Cmd
// cmds []tea.Cmd
// continueExec string
)
if fileUpdatedBool {
m.viewport.SetContent(watchRun())
m.viewport.GotoBottom()
fileUpdatedBool = false
}
if choiceActionBool {
i, ok := m.list.SelectedItem().(item)
if ok {
m.viewport.SetContent(choiceAction(string(i)))
m.viewport.GotoBottom()
}
fileUpdatedBool = false
choiceActionBool = false
}
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", " ":
skipNextViewportUpdate = true
m.viewport.SetContent("[Running...]") //TODO not working, probably need do in another update, so need to mkae it set here and return msg
// continueExecVar = "choiceAction"
// TUI.Send(func() tea.Msg{return continueExecVar})
// continueExecVar = ""
go TUI.Send(func() tea.Msg { // foroce rerender probably there are better solutions
// time.Sleep(time.Second / 10)
return ""
})
choiceActionBool = true
return m, nil
}
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 { //TODO useless
m.viewport.SetContent("[Running...]")
go TUI.Send(func() tea.Msg { //probably there are better solutions
// time.Sleep(time.Second / 10)
return ""
})
fileUpdatedBool = true
// time.Sleep(time.Second*2)
// continueExecVar = ""
// return m, nil
// }
// skipNextViewportUpdate = false //TODO useless
// case continueExec:
// switch msg{
// case "choiceAction":
// i, ok := m.list.SelectedItem().(item)
// if ok {
// m.viewport.SetContent(choiceAction(string(i)))
// m.viewport.GotoBottom()
// }
// // return m, nil
// case "watchRun":
// // log.Println("tets")
// m.viewport.SetContent(watchRun())
// m.viewport.GotoBottom()
// // return m, nil
//
// }
}
// 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())
}