-
Notifications
You must be signed in to change notification settings - Fork 11
feat: Multi-select with bulk install/uninstall #52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -58,6 +58,7 @@ type InputService struct { | |||||||||||||
| ActionHelp *InputAction | ||||||||||||||
| ActionBack *InputAction | ||||||||||||||
| ActionQuit *InputAction | ||||||||||||||
| ActionToggleSelection *InputAction | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| var NewInputService = func(appService *AppService, brewService BrewServiceInterface) InputServiceInterface { | ||||||||||||||
|
|
@@ -124,13 +125,17 @@ var NewInputService = func(appService *AppService, brewService BrewServiceInterf | |||||||||||||
| Key: tcell.KeyRune, Rune: 'q', KeySlug: "q", Name: "Quit", | ||||||||||||||
| Action: s.handleQuitEvent, HideFromLegend: true, | ||||||||||||||
| } | ||||||||||||||
| s.ActionToggleSelection = &InputAction{ | ||||||||||||||
| Key: tcell.KeyRune, Rune: ' ', KeySlug: "space", Name: "Select", | ||||||||||||||
| Action: s.handleToggleSelectionEvent, HideFromLegend: true, | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| // Build keyActions slice (InstallAll/RemoveAll added dynamically in Brewfile mode) | ||||||||||||||
| s.keyActions = []*InputAction{ | ||||||||||||||
| s.ActionSearch, s.ActionFilterInstalled, s.ActionFilterOutdated, | ||||||||||||||
| s.ActionFilterLeaves, s.ActionFilterCasks, s.ActionInstall, | ||||||||||||||
| s.ActionUpdate, s.ActionRemove, s.ActionUpdateAll, | ||||||||||||||
| s.ActionHelp, s.ActionBack, s.ActionQuit, | ||||||||||||||
| s.ActionHelp, s.ActionBack, s.ActionQuit, s.ActionToggleSelection, | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| // Convert keyActions to legend entries | ||||||||||||||
|
|
@@ -169,6 +174,12 @@ func (s *InputService) HandleKeyEventInput(event *tcell.EventKey) *tcell.EventKe | |||||||||||||
| return event | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| // Handle Space explicitly since it might conflict or need special handling | ||||||||||||||
| if event.Key() == tcell.KeyRune && event.Rune() == ' ' { | ||||||||||||||
| s.handleToggleSelectionEvent() | ||||||||||||||
| return nil | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| for _, input := range s.keyActions { | ||||||||||||||
|
||||||||||||||
| for _, input := range s.keyActions { | |
| for _, input := range s.keyActions { | |
| // Skip ActionToggleSelection here because space is already handled explicitly above. | |
| if input == s.ActionToggleSelection { | |
| continue | |
| } |
Copilot
AI
Jan 13, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove commented code and TODO comments. This appears to be debugging/development notes that should be cleaned up before merging. The actual implementation at line 211 (s.appService.search(...)) addresses the visual refresh concern mentioned in the comments.
| // Force redraw of table to remove selection visuals | |
| // s.appService.forceRefreshResults() // Might be too heavy? | |
| // Actually Table.ToggleSelection updates visual. | |
| // ClearSelection needs to update visual too. | |
| // But Table.ClearSelection just clears the map. I need to implement visual clear in Table or just force refresh. | |
| // For now, let's just assume we need to refresh. |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -8,14 +8,16 @@ import ( | |||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| type Table struct { | ||||||||||||||||||||||||||||||
| view *tview.Table | ||||||||||||||||||||||||||||||
| theme *theme.Theme | ||||||||||||||||||||||||||||||
| view *tview.Table | ||||||||||||||||||||||||||||||
| theme *theme.Theme | ||||||||||||||||||||||||||||||
| selectedRows map[int]bool | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| func NewTable(theme *theme.Theme) *Table { | ||||||||||||||||||||||||||||||
| table := &Table{ | ||||||||||||||||||||||||||||||
| view: tview.NewTable(), | ||||||||||||||||||||||||||||||
| theme: theme, | ||||||||||||||||||||||||||||||
| view: tview.NewTable(), | ||||||||||||||||||||||||||||||
| theme: theme, | ||||||||||||||||||||||||||||||
| selectedRows: make(map[int]bool), | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| table.view.SetBorders(false) | ||||||||||||||||||||||||||||||
| table.view.SetSelectable(true, false) | ||||||||||||||||||||||||||||||
|
|
@@ -37,6 +39,46 @@ func (t *Table) View() *tview.Table { | |||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| func (t *Table) Clear() { | ||||||||||||||||||||||||||||||
| t.view.Clear() | ||||||||||||||||||||||||||||||
| t.selectedRows = make(map[int]bool) | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| func (t *Table) ClearSelection() { | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
| func (t *Table) ClearSelection() { | |
| func (t *Table) ClearSelection() { | |
| // Reset visual state for all currently selected rows | |
| for row := range t.selectedRows { | |
| colCount := t.view.GetColumnCount() | |
| for col := 0; col < colCount; col++ { | |
| cell := t.view.GetCell(row, col) | |
| if cell != nil { | |
| cell.SetBackgroundColor(t.theme.DefaultBgColor) | |
| } | |
| } | |
| } | |
| // Clear logical selection state |
Copilot
AI
Jan 13, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The GetSelectedRows method returns rows in non-deterministic order since it iterates over a map. This could lead to unpredictable behavior when processing selected packages. Consider sorting the returned slice to ensure consistent ordering (e.g., ascending by row number).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes to BUILD_GOOS and BUILD_GOARCH appear unrelated to the multi-select feature. These settings change the build target from macOS ARM64 (darwin/arm64) to Linux AMD64 (linux/amd64). If this change is intentional, it should be documented in the PR description or split into a separate commit. If unintentional, it should be reverted to the original values.