Skip to content

Commit 2bcb9e9

Browse files
feat: add --exclude-archived flag to TUI
- Add -e/--exclude-archived flag to exclude beans with archive statuses - Add tui.exclude_archived config option in .beans.yml for default behavior - Filter out completed and scrapped beans when flag/config is enabled Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 0538bbc commit 2bcb9e9

4 files changed

Lines changed: 41 additions & 14 deletions

File tree

cmd/tui.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,23 @@ import (
55
"github.com/hmans/beans/internal/tui"
66
)
77

8+
var tuiExcludeArchived bool
9+
810
var tuiCmd = &cobra.Command{
911
Use: "tui",
1012
Short: "Open the interactive TUI",
1113
Long: `Opens an interactive terminal user interface for browsing and managing beans.`,
1214
RunE: func(cmd *cobra.Command, args []string) error {
13-
return tui.Run(core, cfg)
15+
// Use config default if flag wasn't explicitly set
16+
excludeArchived := tuiExcludeArchived
17+
if !cmd.Flags().Changed("exclude-archived") {
18+
excludeArchived = cfg.TUI.ExcludeArchived
19+
}
20+
return tui.Run(core, cfg, excludeArchived)
1421
},
1522
}
1623

1724
func init() {
25+
tuiCmd.Flags().BoolVarP(&tuiExcludeArchived, "exclude-archived", "e", false, "Exclude beans with archive statuses (completed, scrapped)")
1826
rootCmd.AddCommand(tuiCmd)
1927
}

internal/config/config.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,18 @@ type PriorityConfig struct {
7373
// Note: Statuses are no longer stored in config - they are hardcoded like types.
7474
type Config struct {
7575
Beans BeansConfig `yaml:"beans"`
76+
TUI TUIConfig `yaml:"tui,omitempty"`
7677

7778
// configDir is the directory containing the config file (not serialized)
7879
// Used to resolve relative paths
7980
configDir string `yaml:"-"`
8081
}
8182

83+
// TUIConfig defines settings for the TUI.
84+
type TUIConfig struct {
85+
ExcludeArchived bool `yaml:"exclude_archived,omitempty"`
86+
}
87+
8288
// BeansConfig defines settings for bean creation.
8389
type BeansConfig struct {
8490
// Path is the path to the beans directory (relative to config file location)

internal/tui/list.go

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@ type listModel struct {
115115
idColWidth int // ID column width (accounts for tree depth)
116116

117117
// Active filters
118-
tagFilter string // if set, only show beans with this tag
118+
tagFilter string // if set, only show beans with this tag
119+
excludeArchived bool // if true, exclude beans with archive statuses
119120

120121
// Multi-select state
121122
selectedBeans map[string]bool // IDs of beans marked for multi-edit
@@ -124,7 +125,7 @@ type listModel struct {
124125
statusMessage string
125126
}
126127

127-
func newListModel(resolver *graph.Resolver, cfg *config.Config) listModel {
128+
func newListModel(resolver *graph.Resolver, cfg *config.Config, excludeArchived bool) listModel {
128129
selectedBeans := make(map[string]bool)
129130
delegate := itemDelegate{cfg: cfg, selectedBeans: &selectedBeans}
130131

@@ -139,10 +140,11 @@ func newListModel(resolver *graph.Resolver, cfg *config.Config) listModel {
139140
l.Styles.FilterCursor = lipgloss.NewStyle().Foreground(ui.ColorPrimary)
140141

141142
return listModel{
142-
list: l,
143-
resolver: resolver,
144-
config: cfg,
145-
selectedBeans: selectedBeans,
143+
list: l,
144+
resolver: resolver,
145+
config: cfg,
146+
selectedBeans: selectedBeans,
147+
excludeArchived: excludeArchived,
146148
}
147149
}
148150

@@ -167,10 +169,21 @@ func (m listModel) Init() tea.Cmd {
167169
}
168170

169171
func (m listModel) loadBeans() tea.Msg {
170-
// Build filter if tag filter is set
172+
// Build filter based on active filters
171173
var filter *model.BeanFilter
172-
if m.tagFilter != "" {
173-
filter = &model.BeanFilter{Tags: []string{m.tagFilter}}
174+
if m.tagFilter != "" || m.excludeArchived {
175+
filter = &model.BeanFilter{}
176+
if m.tagFilter != "" {
177+
filter.Tags = []string{m.tagFilter}
178+
}
179+
if m.excludeArchived {
180+
// Exclude archive statuses (completed, scrapped)
181+
for _, s := range config.DefaultStatuses {
182+
if s.Archive {
183+
filter.ExcludeStatus = append(filter.ExcludeStatus, s.Name)
184+
}
185+
}
186+
}
174187
}
175188

176189
// Query filtered beans

internal/tui/tui.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,14 +128,14 @@ type App struct {
128128
}
129129

130130
// New creates a new TUI application
131-
func New(core *beancore.Core, cfg *config.Config) *App {
131+
func New(core *beancore.Core, cfg *config.Config, excludeArchived bool) *App {
132132
resolver := &graph.Resolver{Core: core}
133133
return &App{
134134
state: viewList,
135135
core: core,
136136
resolver: resolver,
137137
config: cfg,
138-
list: newListModel(resolver, cfg),
138+
list: newListModel(resolver, cfg, excludeArchived),
139139
preview: newPreviewModel(nil, 0, 0),
140140
}
141141
}
@@ -711,8 +711,8 @@ func getEditor() string {
711711
}
712712

713713
// Run starts the TUI application with file watching
714-
func Run(core *beancore.Core, cfg *config.Config) error {
715-
app := New(core, cfg)
714+
func Run(core *beancore.Core, cfg *config.Config, excludeArchived bool) error {
715+
app := New(core, cfg, excludeArchived)
716716
p := tea.NewProgram(app, tea.WithAltScreen())
717717

718718
// Store reference to program for sending messages from watcher

0 commit comments

Comments
 (0)