package main import ( "fmt" "log" "os" "os/exec" "time" table "git.sealight.xyz/aynish/poms/table" task "git.sealight.xyz/aynish/poms/task" timer "git.sealight.xyz/aynish/poms/timer" "github.com/charmbracelet/bubbles/list" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" "github.com/looplab/fsm" ) var ( tasks = task.GetTasks() columns = []table.Column{ {Title: "ID", Width: 4}, {Title: "Project", Width: 20}, {Title: "Tags", Width: 20}, {Title: "Description", Width: 35}, // {Title: "Urgency", Width: 10}, } baseStyle = lipgloss.NewStyle(). BorderStyle(lipgloss.NormalBorder()). BorderForeground(lipgloss.Color("240")) ) type model struct { FSM *fsm.FSM taskList table.Model activeList list.Model timer timer.Model } type LoadedTasksMsg struct { TaskList table.Model } func loadTasks() tea.Msg { var t table.Model rows := task.TasksToRows(tasks) t = table.New( table.WithColumns(columns), table.WithRows(rows), table.WithFocused(true), table.WithHeight(15), ) s := table.DefaultStyles() s.Header = s.Header. BorderStyle(lipgloss.NormalBorder()). BorderForeground(lipgloss.Color("240")). BorderBottom(true). Bold(false) s.Selected = s.Selected. Foreground(lipgloss.Color("229")). Background(lipgloss.Color("57")). Bold(false) s.Active = s.Active. Foreground(lipgloss.Color("0")). Background(lipgloss.Color("120")) t.SetStyles(s) return LoadedTasksMsg{t} } type editorFinishedMsg struct{ err error } func (m model) writeFile() string { t := time.Now() var path, full_path string // create pom-note path = t.Format(time.DateOnly) full_path = "/home/anish/kitaab/vimwiki/poms/" + string(path) + ".wiki" f, err := os.Create(full_path) if err != nil { log.Fatal(err) } defer f.Close() fmt.Fprintln(f, "%title ") fmt.Fprintln(f, ":pom:priv:plan:") fmt.Fprintln(f, "%date "+t.Format("2006-01-02 15:06")) fmt.Fprintln(f, "") rows := task.RowsToFile(m.taskList.Rows(), m.taskList.ActiveIndex()) for _, value := range rows { fmt.Fprintln(f, value) // print values to f, one per line } return full_path } func (m model) setActive() { //TODO // Create a bubbles list of active tasks to select the one to focus on during worktime } func (m model) openEditor() tea.Cmd { m.setActive() path := m.writeFile() editor := os.Getenv("EDITOR") if editor == "" { editor = "vim" } c := exec.Command(editor, path) //nolint:gosec return tea.ExecProcess(c, func(err error) tea.Msg { return editorFinishedMsg{err} }) } func (m model) Init() tea.Cmd { m.FSM = fsm.NewFSM( "taskTable", fsm.Events{ {Name: "toEdit", Src: []string{"taskTable", "workTimer", "breakTimer"}, Dst: "editor"}, {Name: "workTime", Src: []string{"editor", "taskList"}, Dst: "workTimer"}, {Name: "breakTime", Src: []string{"workTimer", "taskList", "editor"}, Dst: "workTimer"}, }, fsm.Callbacks{}, ) return loadTasks } func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { var cmd tea.Cmd switch msg := msg.(type) { case tea.KeyMsg: switch msg.String() { case "q", "ctrl+c", "esc": return m, tea.Quit case "enter": return m, m.openEditor() } case tea.WindowSizeMsg: //top, right, bottom, left := baseStyle.GetMargin() m.taskList.SetWidth(msg.Width - 5) m.taskList.SetHeight(msg.Height - 5) case LoadedTasksMsg: m.taskList = msg.TaskList } m.taskList, cmd = m.taskList.Update(msg) return m, cmd } func (m model) View() string { return baseStyle.Render(m.taskList.View()) } func main() { var m model if _, err := tea.NewProgram(m).Run(); err != nil { fmt.Println("Error running program:", err) os.Exit(1) } }