Skip to content

Commit

Permalink
feat: improved std output handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
Valkyrie00 committed Feb 24, 2025
1 parent 7d2c082 commit 75a7716
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 46 deletions.
35 changes: 31 additions & 4 deletions internal/services/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package services

import (
"bbrew/internal/models"
"fmt"
"github.com/rivo/tview"
"io"
"os/exec"
"sync"
)

type CommandServiceInterface interface {
Expand Down Expand Up @@ -63,45 +65,70 @@ func (s *CommandService) executeCommand(
return err
}

// Add a WaitGroup to wait for all goroutines to finish
var wg sync.WaitGroup
wg.Add(3)

// Wait for the command to finish
go func() {
defer wg.Done()
defer stdoutWriter.Close()
defer stderrWriter.Close()
cmd.Wait()
}()

// Stdout handler
go func() {
defer wg.Done()
defer stdoutPipe.Close()
buf := make([]byte, 1024)
for {
n, err := stdoutPipe.Read(buf)
if n > 0 {
output := make([]byte, n)
copy(output, buf[:n])
app.QueueUpdateDraw(func() {
outputView.Write(buf[:n])
outputView.Write(output)
outputView.ScrollToEnd()
})
}
if err != nil {
if err != io.EOF {
app.QueueUpdateDraw(func() {
outputView.Write([]byte(fmt.Sprintf("\nError: %v\n", err)))
})
}
break
}
}
}()

// Stderr handler
go func() {
defer wg.Done()
defer stderrPipe.Close()
buf := make([]byte, 1024)
for {
n, err := stderrPipe.Read(buf)
if n > 0 {
output := make([]byte, n)
copy(output, buf[:n])
app.QueueUpdateDraw(func() {
outputView.Write(buf[:n])
outputView.Write(output)
outputView.ScrollToEnd()
})
}
if err != nil {
if err != io.EOF {
app.QueueUpdateDraw(func() {
outputView.Write([]byte(fmt.Sprintf("\nError: %v\n", err)))
})
}
break
}
}
}()

cmd.Wait()

wg.Wait()
return nil
}
90 changes: 49 additions & 41 deletions internal/services/io.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package services

import (
"bbrew/internal/models"
"fmt"
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
)

func (s *AppService) handleKeyEventInput(event *tcell.EventKey) *tcell.EventKey {
Expand Down Expand Up @@ -61,25 +59,34 @@ func (s *AppService) handleFilterPackagesEvent() {
}

func (s *AppService) showModal(text string, confirmFunc func(), cancelFunc func()) {
modal := s.layout.GetModal().Build(text, func() {
s.app.SetRoot(s.layout.Root(), true)
confirmFunc()
}, func() {
s.app.SetRoot(s.layout.Root(), true)
cancelFunc()
})
modal := s.layout.GetModal().Build(text, confirmFunc, cancelFunc)
s.app.SetRoot(modal, true)
}

func (s *AppService) closeModal() {
s.app.SetRoot(s.layout.Root(), true)
s.app.SetFocus(s.layout.GetTable().View())
}

func (s *AppService) handleInstallPackageEvent() {
row, _ := s.layout.GetTable().View().GetSelection()
if row > 0 {
info := (*s.filteredPackages)[row-1]
s.showModal(
fmt.Sprintf("Are you sure you want to install the package: %s?", info.Name),
s.createModalConfirmHandler(info, "Installing", s.CommandService.InstallPackage, "Installed"),
s.resetViewAfterModal,
)
func() {
s.closeModal()
s.layout.GetOutput().Clear()
go func() {
s.layout.GetNotifier().ShowWarning(fmt.Sprintf("Installing %s...", info.Name))
if err := s.CommandService.UpdatePackage(info, s.app, s.layout.GetOutput().View()); err != nil {
s.layout.GetNotifier().ShowError(fmt.Sprintf("Failed to install %s", info.Name))
return
}
s.layout.GetNotifier().ShowSuccess(fmt.Sprintf("Installed %s", info.Name))
s.forceRefreshResults()
}()
}, s.closeModal)
}
}

Expand All @@ -89,9 +96,19 @@ func (s *AppService) handleRemovePackageEvent() {
info := (*s.filteredPackages)[row-1]
s.showModal(
fmt.Sprintf("Are you sure you want to remove the package: %s?", info.Name),
s.createModalConfirmHandler(info, "Removing", s.CommandService.RemovePackage, "Removed"),
s.resetViewAfterModal,
)
func() {
s.closeModal()
s.layout.GetOutput().Clear()
go func() {
s.layout.GetNotifier().ShowWarning(fmt.Sprintf("Removing %s...", info.Name))
if err := s.CommandService.RemovePackage(info, s.app, s.layout.GetOutput().View()); err != nil {
s.layout.GetNotifier().ShowError(fmt.Sprintf("Failed to remove %s", info.Name))
return
}
s.layout.GetNotifier().ShowSuccess(fmt.Sprintf("Removed %s", info.Name))
s.forceRefreshResults()
}()
}, s.closeModal)
}
}

Expand All @@ -101,43 +118,34 @@ func (s *AppService) handleUpdatePackageEvent() {
info := (*s.filteredPackages)[row-1]
s.showModal(
fmt.Sprintf("Are you sure you want to update the package: %s?", info.Name),
s.createModalConfirmHandler(info, "Updating", s.CommandService.UpdatePackage, "Updated"),
s.resetViewAfterModal,
)
func() {
s.closeModal()
s.layout.GetOutput().Clear()
go func() {
s.layout.GetNotifier().ShowWarning(fmt.Sprintf("Updating %s...", info.Name))
if err := s.CommandService.UpdatePackage(info, s.app, s.layout.GetOutput().View()); err != nil {
s.layout.GetNotifier().ShowError(fmt.Sprintf("Failed to update %s", info.Name))
return
}
s.layout.GetNotifier().ShowSuccess(fmt.Sprintf("Updated %s", info.Name))
s.forceRefreshResults()
}()
}, s.closeModal)
}
}

func (s *AppService) handleUpdateAllPackagesEvent() {
s.showModal("Are you sure you want to update all packages?", func() {
s.layout.GetDetails().Clear()
s.closeModal()
s.layout.GetOutput().Clear()
go func() {
s.layout.GetNotifier().ShowWarning("Updating all packages...")
if err := s.CommandService.UpdateAllPackages(s.app, s.layout.GetDetails().View()); err != nil {
if err := s.CommandService.UpdateAllPackages(s.app, s.layout.GetOutput().View()); err != nil {
s.layout.GetNotifier().ShowError("Failed to update all packages")
return
}
s.layout.GetNotifier().ShowSuccess("Updated all packages")
s.forceRefreshResults()
}()
}, s.resetViewAfterModal)
}

func (s *AppService) resetViewAfterModal() {
s.app.SetFocus(s.layout.GetTable().View())
}

func (s *AppService) createModalConfirmHandler(info models.Formula, actionName string, action func(models.Formula, *tview.Application, *tview.TextView) error, completedAction string) func() {
return func() {
s.resetViewAfterModal()
s.layout.GetOutput().Clear()
go func() {
s.layout.GetNotifier().ShowWarning(fmt.Sprintf("%s %s...", actionName, info.Name))
if err := action(info, s.app, s.layout.GetOutput().View()); err != nil {
s.layout.GetNotifier().ShowError(fmt.Sprintf("Failed to %s %s", actionName, info.Name))
return
}
s.layout.GetNotifier().ShowSuccess(fmt.Sprintf("%s %s", info.Name, completedAction))
s.forceRefreshResults()
}()
}
}, s.closeModal)
}
2 changes: 1 addition & 1 deletion internal/services/selfupdate.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func (s *SelfUpdateService) CheckForUpdates(ctx context.Context) (string, error)
output, err := cmd.CombinedOutput()
if err != nil {
if ctx.Err() != nil {
return "", fmt.Errorf("operazione annullata: %v", ctx.Err())
return "", fmt.Errorf("context cancelled")
}
return "", fmt.Errorf("failed to fetch latest version from tap: %v", err)
}
Expand Down

0 comments on commit 75a7716

Please sign in to comment.