diff --git a/cmd/ls.go b/cmd/ls.go index df35751..03075ee 100644 --- a/cmd/ls.go +++ b/cmd/ls.go @@ -18,6 +18,7 @@ var lsCmd = &cobra.Command{ `, RunE: func(cmd *cobra.Command, _ []string) error { filterFlag, _ := cmd.Flags().GetString("f") + oldUi, _ := cmd.Flags().GetBool("o") data, err := db.GetAllRecords(StatusBucket) if err != nil { return err @@ -26,11 +27,15 @@ var lsCmd = &cobra.Command{ fmt.Println("Filtering by status : ", filterFlag) data = utils.FilterByStatus(data, filterFlag) } - return ui.RenderTable(data) + if oldUi { + return ui.RenderTable(data) + } + return ui.RenderInteractiveTable(data) }, } func init() { rootCmd.AddCommand(lsCmd) - lsCmd.Flags().String("f", "", "Filter projects by status. Usage : pman ls -f ") + lsCmd.Flags().String("f", "", "Filter projects by status. Usage : pman ls --f ") + lsCmd.Flags().Bool("o", false, "list projects using the old ui. Usage : pman ls --o") } diff --git a/pkg/ui/interactiveTable.go b/pkg/ui/interactiveTable.go new file mode 100644 index 0000000..0ec3773 --- /dev/null +++ b/pkg/ui/interactiveTable.go @@ -0,0 +1,110 @@ +package ui + +import ( + "fmt" + "sort" + + "github.com/charmbracelet/bubbles/table" + tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/lipgloss" + + "github.com/theredditbandit/pman/pkg" + "github.com/theredditbandit/pman/pkg/db" + p "github.com/theredditbandit/pman/pkg/ui/pager" + "github.com/theredditbandit/pman/pkg/utils" +) + +var baseStyle = lipgloss.NewStyle(). + BorderStyle(lipgloss.NormalBorder()). + BorderForeground(lipgloss.Color("240")) + +type tableModel struct { + table table.Model +} + +func (m tableModel) Init() tea.Cmd { return nil } + +func (m tableModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + var cmd tea.Cmd + switch msg := msg.(type) { + case tea.KeyMsg: + switch msg.String() { + case "esc": + if m.table.Focused() { + m.table.Blur() + } else { + m.table.Focus() + } + case "q", "ctrl+c": + return m, tea.Quit + case "enter": + project := m.table.SelectedRow()[1] + p.LaunchRenderer(project) + } + } + m.table, cmd = m.table.Update(msg) + return m, cmd +} + +func (m tableModel) View() string { + return baseStyle.Render(m.table.View()) + "\n" +} + +func RenderInteractiveTable(data map[string]string) error { + col := []table.Column{ + {Title: "Status", Width: 20}, + {Title: "Project", Width: 40}, + {Title: "Last Edited", Width: 20}, + } + var rows []table.Row + for p, status := range data { + alias, err := db.GetRecord(p, pkg.ProjectAliasBucket) + lastEdited := utils.GetLastModifiedTime(p) + if err == nil { + pname := fmt.Sprintf("%s (%s)", p, alias) + row := []string{utils.TitleCase(status), pname, lastEdited} // Status | projectName (alias) | lastEdited + rows = append(rows, row) + } else { + row := []string{utils.TitleCase(status), p, lastEdited} // Status | projectName | lastEdited + rows = append(rows, row) + } + } + + if len(rows) == 0 { + fmt.Printf("No projects found in the database\n\n") + fmt.Printf("Add projects to the database using \n\n") + fmt.Println("pman init .") + fmt.Println("or") + fmt.Println("pman add ") + return nil + } + sort.Slice(rows, func(i, j int) bool { + valI := rows[i][1] + valJ := rows[j][1] + return valI < valJ + }) + t := table.New( + table.WithColumns(col), + table.WithRows(rows), + table.WithFocused(true), + table.WithHeight(10), + table.WithWidth(90), + ) + 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) + t.SetStyles(s) + + m := tableModel{t} + if _, err := tea.NewProgram(m).Run(); err != nil { + return fmt.Errorf("Error running program: %s", err) + } + return nil +} diff --git a/pkg/ui/statusTable.go b/pkg/ui/statusTable.go index e06df94..9850491 100644 --- a/pkg/ui/statusTable.go +++ b/pkg/ui/statusTable.go @@ -16,7 +16,6 @@ import ( // RenderTable: renders the given data as a table func RenderTable(data map[string]string) error { var TableData [][]string - for p, status := range data { alias, err := db.GetRecord(p, pkg.ProjectAliasBucket) lastEdited := utils.GetLastModifiedTime(p) @@ -35,7 +34,7 @@ func RenderTable(data map[string]string) error { fmt.Println("pman init .") fmt.Println("or") fmt.Println("pman add ") - return nil + return fmt.Errorf("no database initialised") } sort.Slice(TableData, func(i, j int) bool { valI := TableData[i][1] @@ -72,7 +71,6 @@ func RenderTable(data map[string]string) error { if ok { return baseStyle.Copy().Foreground(color) } - color = statusColors["Default"] return baseStyle.Copy().Foreground(color) })