From 1c3366d2835755c40fa2674c416204a52c429e95 Mon Sep 17 00:00:00 2001 From: aryan <85390033+theredditbandit@users.noreply.github.com> Date: Wed, 22 May 2024 00:10:29 +0530 Subject: [PATCH] replace the old pman interactive ui with a more minimalist one (#40) this removes the need to specify pman ls --c as that is now the default pman ls behaviour --- cmd/i.go | 21 ++++- cmd/ls.go | 7 +- pkg/ui/delegate.go | 87 -------------------- pkg/ui/tui.go | 192 --------------------------------------------- 4 files changed, 20 insertions(+), 287 deletions(-) delete mode 100644 pkg/ui/delegate.go delete mode 100644 pkg/ui/tui.go diff --git a/cmd/i.go b/cmd/i.go index 975b17f..60e2b29 100644 --- a/cmd/i.go +++ b/cmd/i.go @@ -1,9 +1,14 @@ package cmd import ( + "fmt" + "strings" + "github.com/spf13/cobra" + "github.com/theredditbandit/pman/pkg/db" "github.com/theredditbandit/pman/pkg/ui" + "github.com/theredditbandit/pman/pkg/utils" ) // iCmd represents the interactive command @@ -11,11 +16,23 @@ var iCmd = &cobra.Command{ Use: "i", Short: "Launches pman in interactive mode", Aliases: []string{"interactive", "iteractive"}, - RunE: func(_ *cobra.Command, _ []string) error { - return ui.Tui() + RunE: func(cmd *cobra.Command, _ []string) error { + filterFlag, _ := cmd.Flags().GetString("f") + refreshLastEditTime, _ := cmd.Flags().GetBool("r") + data, err := db.GetAllRecords(db.DBName, StatusBucket) + if err != nil { + return err + } + if filterFlag != "" { + fmt.Println("Filtering by status : ", filterFlag) + data = utils.FilterByStatuses(data, strings.Split(filterFlag, ",")) + } + return ui.RenderInteractiveTable(data, refreshLastEditTime) }, } func init() { rootCmd.AddCommand(iCmd) + iCmd.Flags().String("f", "", "Filter projects by status. Usage : pman ls --f ") + iCmd.Flags().Bool("r", false, "Refresh Last Edited time: pman ls --r") } diff --git a/cmd/ls.go b/cmd/ls.go index 1ad9b3b..579e65e 100644 --- a/cmd/ls.go +++ b/cmd/ls.go @@ -19,7 +19,6 @@ var lsCmd = &cobra.Command{ `, RunE: func(cmd *cobra.Command, _ []string) error { filterFlag, _ := cmd.Flags().GetString("f") - oldUI, _ := cmd.Flags().GetBool("c") refreshLastEditTime, _ := cmd.Flags().GetBool("r") data, err := db.GetAllRecords(db.DBName, StatusBucket) if err != nil { @@ -29,16 +28,12 @@ var lsCmd = &cobra.Command{ fmt.Println("Filtering by status : ", filterFlag) data = utils.FilterByStatuses(data, strings.Split(filterFlag, ",")) } - if oldUI { - return ui.RenderTable(data, refreshLastEditTime) - } - return ui.RenderInteractiveTable(data, refreshLastEditTime) + return ui.RenderTable(data, refreshLastEditTime) }, } func init() { rootCmd.AddCommand(lsCmd) lsCmd.Flags().String("f", "", "Filter projects by status. Usage : pman ls --f ") - lsCmd.Flags().Bool("c", false, "list projects using the colorful table. Usage : pman ls --c") lsCmd.Flags().Bool("r", false, "Refresh Last Edited time: pman ls --r") } diff --git a/pkg/ui/delegate.go b/pkg/ui/delegate.go deleted file mode 100644 index a4f3928..0000000 --- a/pkg/ui/delegate.go +++ /dev/null @@ -1,87 +0,0 @@ -package ui - -import ( - "github.com/charmbracelet/bubbles/key" - "github.com/charmbracelet/bubbles/list" - tea "github.com/charmbracelet/bubbletea" - - p "github.com/theredditbandit/pman/pkg/ui/pager" -) - -func newItemDelegate(keys *delegateKeyMap) list.DefaultDelegate { - d := list.NewDefaultDelegate() - d.UpdateFunc = func(msg tea.Msg, m *list.Model) tea.Cmd { - i, ok := m.SelectedItem().(item) - if !ok { - return nil - } - title := i.Title() - if msg, ok := msg.(tea.KeyMsg); ok { - switch { - case key.Matches(msg, keys.choose): - err := p.LaunchRenderer(title) - if err == nil { - return tea.Quit // TODO : change this to return to the list - } - case key.Matches(msg, keys.remove): - index := m.Index() - m.RemoveItem(index) - if len(m.Items()) == 0 { - keys.remove.SetEnabled(false) - } - return m.NewStatusMessage(statusMessageStyle("Deleted " + title)) - } - } - return nil - } - - help := []key.Binding{keys.choose, keys.remove} - - d.ShortHelpFunc = func() []key.Binding { - return help - } - - d.FullHelpFunc = func() [][]key.Binding { - return [][]key.Binding{help} - } - - return d -} - -type delegateKeyMap struct { - choose key.Binding - remove key.Binding -} - -// Additional short help entries. This satisfies the help.KeyMap interface and -// is entirely optional. -func (d delegateKeyMap) ShortHelp() []key.Binding { - return []key.Binding{ - d.choose, - d.remove, - } -} - -// Additional full help entries. This satisfies the help.KeyMap interface and -// is entirely optional. -func (d delegateKeyMap) FullHelp() [][]key.Binding { - return [][]key.Binding{ - { - d.choose, - d.remove, - }, - } -} - -func newDelegateKeyMap() *delegateKeyMap { - return &delegateKeyMap{ - choose: key.NewBinding( - key.WithKeys("enter"), - key.WithHelp("enter", "choose"), - ), - remove: key.NewBinding( - key.WithKeys("x", "backspace"), - key.WithHelp("x", "delete"), - ), - } -} diff --git a/pkg/ui/tui.go b/pkg/ui/tui.go deleted file mode 100644 index 94dc92d..0000000 --- a/pkg/ui/tui.go +++ /dev/null @@ -1,192 +0,0 @@ -package ui - -import ( - "fmt" - - "github.com/charmbracelet/bubbles/key" - "github.com/charmbracelet/bubbles/list" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" - "github.com/thoas/go-funk" - - "github.com/theredditbandit/pman/pkg" - "github.com/theredditbandit/pman/pkg/db" -) - -var ( - appStyle = lipgloss.NewStyle().Padding(1, 2) - titleStyle = lipgloss.NewStyle(). - Foreground(lipgloss.Color("#FFFDF5")). - Background(lipgloss.Color("#25A065")). - Padding(0, 1) - statusMessageStyle = lipgloss.NewStyle(). - Foreground(lipgloss.AdaptiveColor{Light: "#04B575", Dark: "#04B575"}). - Render -) - -type item struct { - name string - status string -} - -func (i item) Title() string { return i.name } -func (i item) Description() string { return i.status } -func (i item) FilterValue() string { return i.status } - -type listKeyMap struct { - setStatus key.Binding - toggleTitleBar key.Binding - toggleStatusBar key.Binding - togglePagination key.Binding - toggleHelpMenu key.Binding - insertItem key.Binding -} - -func newListKeyMap() *listKeyMap { - return &listKeyMap{ - setStatus: key.NewBinding( - key.WithKeys("s"), - key.WithHelp("s", "set status"), - ), - toggleTitleBar: key.NewBinding( - key.WithKeys("T"), - key.WithHelp("T", "toggle title"), - ), - toggleStatusBar: key.NewBinding( - key.WithKeys("S"), - key.WithHelp("S", "toggle status"), - ), - togglePagination: key.NewBinding( - key.WithKeys("P"), - key.WithHelp("P", "toggle pagination"), - ), - toggleHelpMenu: key.NewBinding( - key.WithKeys("H"), - key.WithHelp("H", "toggle help"), - ), - } -} - -type model struct { - list list.Model - keys *listKeyMap - delegateKeys *delegateKeyMap -} - -func newModel() (model, error) { - var ( - listKeys = newListKeyMap() - delegateKeys = newDelegateKeyMap() - ) - - data, err := db.GetAllRecords(db.DBName, pkg.StatusBucket) - if err != nil { - return model{}, err - } - - d := funk.Map(data, func(k, v string) item { - return item{ - name: k, - status: v, - } - }) - - formattedData, ok := d.([]item) - if !ok { - return model{}, fmt.Errorf("something went wrong while creating a list of items") - } - items := make([]list.Item, len(data)) - for i := 0; i < len(data); i++ { - items[i] = formattedData[i] - } - - delegate := newItemDelegate(delegateKeys) - projectList := list.New(items, delegate, 0, 0) - projectList.Title = "pman" - projectList.Styles.Title = titleStyle - - projectList.AdditionalFullHelpKeys = func() []key.Binding { - return []key.Binding{ - listKeys.setStatus, - listKeys.insertItem, - listKeys.toggleTitleBar, - listKeys.toggleStatusBar, - listKeys.togglePagination, - listKeys.toggleHelpMenu, - } - } - return model{ - list: projectList, - keys: listKeys, - delegateKeys: delegateKeys, - }, nil -} - -func (model) Init() tea.Cmd { - return nil -} - -func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - var cmds []tea.Cmd - - switch msg := msg.(type) { - case tea.WindowSizeMsg: - h, v := appStyle.GetFrameSize() - m.list.SetSize(msg.Width-h, msg.Height-v) - - case tea.KeyMsg: - // Don't match any of the keys below if we're actively filtering. - if m.list.FilterState() == list.Filtering { - break - } - - switch { - case key.Matches(msg, m.keys.setStatus): - cmd := m.list.ToggleSpinner() - return m, cmd - - case key.Matches(msg, m.keys.toggleTitleBar): - v := !m.list.ShowTitle() - m.list.SetShowTitle(v) - m.list.SetShowFilter(v) - m.list.SetFilteringEnabled(v) - return m, nil - - case key.Matches(msg, m.keys.toggleStatusBar): - m.list.SetShowStatusBar(!m.list.ShowStatusBar()) - return m, nil - - case key.Matches(msg, m.keys.togglePagination): - m.list.SetShowPagination(!m.list.ShowPagination()) - return m, nil - - case key.Matches(msg, m.keys.toggleHelpMenu): - m.list.SetShowHelp(!m.list.ShowHelp()) - return m, nil - } - } - - // This will also call our delegate's update function. - newListModel, cmd := m.list.Update(msg) - m.list = newListModel - cmds = append(cmds, cmd) - - return m, tea.Batch(cmds...) -} - -func (m model) View() string { - return appStyle.Render(m.list.View()) -} - -func Tui() error { - model, err := newModel() - if err != nil { - return err - } - - if _, err := tea.NewProgram(model, tea.WithAltScreen()).Run(); err != nil { - return fmt.Errorf("error running program: %w", err) - } - - return nil -}