@@ -124,7 +124,7 @@ func RunTUI() error {
124124 }
125125
126126 m := newTUIModel (entries )
127- p := tea .NewProgram (m )
127+ p := tea .NewProgram (& m )
128128 if _ , err := p .Run (); err != nil {
129129 return fmt .Errorf ("TUI error: %w" , err )
130130 }
@@ -183,8 +183,8 @@ func newTUIModel(entries []Entry) tuiModel {
183183 }
184184
185185 rows := make ([]table.Row , len (entries ))
186- for i , e := range entries {
187- rows [i ] = entryToRow (e , false , false )
186+ for i := range entries {
187+ rows [i ] = entryToRow (& entries [ i ] , false , false )
188188 }
189189
190190 totalWidth := 0
@@ -222,7 +222,7 @@ func newTUIModel(entries []Entry) tuiModel {
222222 return m
223223}
224224
225- func entryToRow (e Entry , selected bool , sizesLoaded bool ) table.Row {
225+ func entryToRow (e * Entry , selected bool , sizesLoaded bool ) table.Row {
226226 // Selection indicator column
227227 check := " "
228228 if selected {
@@ -330,7 +330,7 @@ func (m *tuiModel) tableHeight() int {
330330 return min (rows , 25 )
331331}
332332
333- func (m tuiModel ) Init () tea.Cmd {
333+ func (m * tuiModel ) Init () tea.Cmd {
334334 return m .computeSizesCmd ()
335335}
336336
@@ -354,90 +354,25 @@ func (m *tuiModel) computeSizesCmd() tea.Cmd {
354354 }
355355}
356356
357- func (m tuiModel ) Update (msg tea.Msg ) (tea.Model , tea.Cmd ) {
357+ func (m * tuiModel ) Update (msg tea.Msg ) (tea.Model , tea.Cmd ) {
358358 switch msg := msg .(type ) {
359- // Auto-dismiss handlers
360359 case dismissToastMsg :
361- for i , t := range m .toasts {
362- if t .id == msg .id {
363- m .toasts = append (m .toasts [:i ], m .toasts [i + 1 :]... )
364- break
365- }
366- }
367- return m , nil
368-
360+ return m , m .handleDismissToast (msg )
369361 case dismissMessageMsg :
370- if msg .seq == m .messageSeq {
371- m .message = ""
372- }
373- return m , nil
374-
362+ return m , m .handleDismissMessage (msg )
375363 case sizeResultMsg :
376- // Discard stale results from a previous generation
377- if msg .generation != m .generation {
378- return m , nil
379- }
380- for i , sz := range msg .sizes {
381- if i < len (m .entries ) {
382- m .entries [i ].DiskSize = sz
383- }
384- }
385- m .sizesLoaded = true
386- m .refreshRows ()
387- return m , nil
388-
389- // Async result handlers
364+ return m , m .handleSizeResult (msg )
390365 case deleteResultMsg :
391- m .busy = false
392- var cmds []tea.Cmd
393- cmds = append (cmds , m .setMessage (fmt .Sprintf ("Removed %d worktree(s), freed %s" , msg .removed , humanSize (msg .freedBytes ))))
394- for _ , errText := range msg .errors {
395- cmds = append (cmds , m .pushToast (errText ))
396- }
397- reloadCmd := m .reloadCmd ()
398- cmds = append (cmds , reloadCmd )
399- return m , tea .Batch (cmds ... )
400-
366+ return m , m .handleDeleteResult (msg )
401367 case pruneResultMsg :
402- m .busy = false
403- if msg .err != nil {
404- cmd := m .pushToast (msg .err .Error ())
405- return m , cmd
406- }
407- var cmds []tea.Cmd
408- cmds = append (cmds , m .setMessage ("Pruned stale worktree references" ))
409- reloadCmd := m .reloadCmd ()
410- cmds = append (cmds , reloadCmd )
411- return m , tea .Batch (cmds ... )
412-
368+ return m , m .handlePruneResult (msg )
413369 case reloadResultMsg :
414- m .busy = false
415- if msg .err != nil {
416- cmd := m .pushToast (msg .err .Error ())
417- return m , cmd
418- }
419- m .entries = msg .entries
420- m .selected = make (map [int ]bool )
421- m .sizesLoaded = false
422- m .generation ++
423- m .refreshRows ()
424- m .table .SetHeight (m .tableHeight ())
425- // Re-trigger async size computation for the new entries
426- sizeCmd := m .computeSizesCmd ()
427- // If no message was set by a prior handler (e.g. deleteResultMsg),
428- // show a brief "Refreshed" note
429- if m .message == "Refreshing..." {
430- return m , tea .Batch (m .setMessage ("Refreshed" ), sizeCmd )
431- }
432- return m , sizeCmd
433-
370+ return m , m .handleReloadResult (msg )
434371 case tea.WindowSizeMsg :
435372 m .windowHeight = msg .Height
436373 m .table .SetHeight (m .tableHeight ())
437374 return m , nil
438-
439375 case tea.KeyPressMsg :
440- // Ignore keys while busy
441376 if m .busy {
442377 return m , nil
443378 }
@@ -449,8 +384,79 @@ func (m tuiModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
449384 return m , cmd
450385}
451386
387+ func (m * tuiModel ) handleDismissToast (msg dismissToastMsg ) tea.Cmd {
388+ for i , t := range m .toasts {
389+ if t .id == msg .id {
390+ m .toasts = append (m .toasts [:i ], m .toasts [i + 1 :]... )
391+ break
392+ }
393+ }
394+ return nil
395+ }
396+
397+ func (m * tuiModel ) handleDismissMessage (msg dismissMessageMsg ) tea.Cmd {
398+ if msg .seq == m .messageSeq {
399+ m .message = ""
400+ }
401+ return nil
402+ }
403+
404+ func (m * tuiModel ) handleSizeResult (msg sizeResultMsg ) tea.Cmd {
405+ if msg .generation != m .generation {
406+ return nil
407+ }
408+ for i , sz := range msg .sizes {
409+ if i < len (m .entries ) {
410+ m .entries [i ].DiskSize = sz
411+ }
412+ }
413+ m .sizesLoaded = true
414+ m .refreshRows ()
415+ return nil
416+ }
417+
418+ func (m * tuiModel ) handleDeleteResult (msg deleteResultMsg ) tea.Cmd {
419+ m .busy = false
420+ var cmds []tea.Cmd
421+ cmds = append (cmds , m .setMessage (fmt .Sprintf ("Removed %d worktree(s), freed %s" , msg .removed , humanSize (msg .freedBytes ))))
422+ for _ , errText := range msg .errors {
423+ cmds = append (cmds , m .pushToast (errText ))
424+ }
425+ cmds = append (cmds , m .reloadCmd ())
426+ return tea .Batch (cmds ... )
427+ }
428+
429+ func (m * tuiModel ) handlePruneResult (msg pruneResultMsg ) tea.Cmd {
430+ m .busy = false
431+ if msg .err != nil {
432+ return m .pushToast (msg .err .Error ())
433+ }
434+ var cmds []tea.Cmd
435+ cmds = append (cmds , m .setMessage ("Pruned stale worktree references" ))
436+ cmds = append (cmds , m .reloadCmd ())
437+ return tea .Batch (cmds ... )
438+ }
439+
440+ func (m * tuiModel ) handleReloadResult (msg reloadResultMsg ) tea.Cmd {
441+ m .busy = false
442+ if msg .err != nil {
443+ return m .pushToast (msg .err .Error ())
444+ }
445+ m .entries = msg .entries
446+ m .selected = make (map [int ]bool )
447+ m .sizesLoaded = false
448+ m .generation ++
449+ m .refreshRows ()
450+ m .table .SetHeight (m .tableHeight ())
451+ sizeCmd := m .computeSizesCmd ()
452+ if m .message == "Refreshing..." {
453+ return tea .Batch (m .setMessage ("Refreshed" ), sizeCmd )
454+ }
455+ return sizeCmd
456+ }
457+
452458// handleKeyPress processes keyboard input, extracted from Update to reduce cyclomatic complexity.
453- func (m tuiModel ) handleKeyPress (msg tea.KeyPressMsg ) (tea.Model , tea.Cmd ) {
459+ func (m * tuiModel ) handleKeyPress (msg tea.KeyPressMsg ) (tea.Model , tea.Cmd ) {
454460 switch msg .String () {
455461 case "q" , "ctrl+c" :
456462 m .quitting = true
@@ -585,8 +591,8 @@ func (m *tuiModel) reloadCmd() tea.Cmd {
585591
586592func (m * tuiModel ) refreshRows () {
587593 rows := make ([]table.Row , len (m .entries ))
588- for i , e := range m .entries {
589- rows [i ] = entryToRow (e , m .selected [i ], m .sizesLoaded )
594+ for i := range m .entries {
595+ rows [i ] = entryToRow (& m . entries [ i ] , m .selected [i ], m .sizesLoaded )
590596 }
591597 m .table .SetRows (rows )
592598}
@@ -596,8 +602,7 @@ func helpItem(key, desc string) string {
596602 return styleHelpKey .Render (key ) + " " + styleHelpDesc .Render (desc )
597603}
598604
599- //nolint:gocritic // hugeParam: value receiver required by tea.Model interface
600- func (m tuiModel ) View () tea.View {
605+ func (m * tuiModel ) View () tea.View {
601606 if m .quitting {
602607 return tea .NewView ("" )
603608 }
0 commit comments