Skip to content

Commit

Permalink
🚧 great start to infinite children
Browse files Browse the repository at this point in the history
  • Loading branch information
acidjazz committed Feb 14, 2025
1 parent b69d2b0 commit 02e1f18
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 113 deletions.
119 changes: 49 additions & 70 deletions mvc.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,95 +94,74 @@ func (m *Model) checkTasksState() (allDone, anyFailed bool) {
return
}

func (m *Model) View() string {
// In mvc.go, update the renderTask function:

for _, runner := range m.Runners {
if runner.Task.HideView {
return ""
}
for _, child := range runner.Children {
if child.Task.HideView {
return ""
func renderChildren(runner Runner, indent string) string {
var view string
for _, child := range runner.Children {
status := ""

// Only process children when parent is running or in CI mode
if runner.State == Running || IsCI() {
switch child.State {
case NotStarted:
status = Color(child.Config.Colors.Pending, child.Config.Chars.NotStarted) + " " + child.Task.Title
case Running:
if child.Task.ShowProgress.Total != 0 {
percent := float64(child.Task.ShowProgress.Current) / float64(child.Task.ShowProgress.Total)
status = child.Spinner.View() + " " + child.Task.Title + " " + child.Task.Bar.ViewAs(percent)
} else {
status = child.Spinner.View() + " " + child.Task.Title
}
case Completed:
status = Color(child.Config.Colors.Success, child.Config.Chars.Success) + " " + child.Task.Title
case Failed:
status = Color(child.Config.Colors.Failure, child.Config.Chars.Failure) + " " + child.Task.Title
}
}
}

var view string
if IsCI() {
view += indent + " " + status + "\n"
} else {
view += indent + " " + lipgloss.NewStyle().Render(status) + "\n"
}

// check if CI is set, if it is then don't return the view until all tasks are completed or one has failed
if IsCI() {
allDone, anyFailed := m.checkTasksState()
if !allDone && !anyFailed {
return ""
// Recursively render any nested children
if len(child.Children) > 0 {
view += renderChildren(child, indent+" ")
}
}
}
return view
}

// Update the View method to use renderChildren
func (m *Model) View() string {
// ... existing view code for hiding and CI checks ...

var view string
for _, runner := range m.Runners {
status := ""
switch runner.State {
case NotStarted:
status = Color(runner.Config.Colors.Pending, runner.Config.Chars.NotStarted) + " " + runner.Task.Title // Gray bullet
status = Color(runner.Config.Colors.Pending, runner.Config.Chars.NotStarted) + " " + runner.Task.Title
case Running:
if len(runner.Children) > 0 {
status = Color(runner.Config.Colors.ParentStarted, runner.Config.Chars.ParentStarted) + " " + runner.Task.Title
if runner.Task.ShowProgress.Total != 0 {
percent := float64(runner.Task.ShowProgress.Current) / float64(runner.Task.ShowProgress.Total)
status = runner.Spinner.View() + " " + runner.Task.Title + " " + runner.Task.Bar.ViewAs(percent)
} else {
if runner.Task.ShowProgress.Total != 0 {
percent := float64(runner.Task.ShowProgress.Current) / float64(runner.Task.ShowProgress.Total)
if runner.Spinner != nil {
status = runner.Spinner.View() + runner.Task.Title + " " + runner.Task.Bar.ViewAs(percent)
} else {
status = "⣟ " + runner.Task.Title + " " + runner.Task.Bar.ViewAs(percent)
}
} else {
if runner.Spinner != nil {
status = runner.Spinner.View() + runner.Task.Title
} else {
status = "⣟ " + runner.Task.Title
}
}
status = runner.Spinner.View() + " " + runner.Task.Title
}
case Completed:
status = Color(runner.Config.Colors.Success, runner.Config.Chars.Success) + " " + runner.Task.Title // Green checkmark
status = Color(runner.Config.Colors.Success, runner.Config.Chars.Success) + " " + runner.Task.Title
case Failed:
status = Color(runner.Config.Colors.Failure, runner.Config.Chars.Failure) + " " + runner.Task.Title // Red 'x'
status = Color(runner.Config.Colors.Failure, runner.Config.Chars.Failure) + " " + runner.Task.Title
}
view += lipgloss.NewStyle().Render(status) + "\n"

for _, child := range runner.Children {
view += lipgloss.NewStyle().Render(status) + "\n"

// Only show children if parent is Running
if runner.State != Running {
continue
}
status = ""
switch child.State {
case NotStarted:
status = Color(child.Config.Colors.Pending, runner.Config.Chars.NotStarted) + " " + child.Task.Title // Gray bullet
case Running:
if child.Task.ShowProgress.Total != 0 {
percent := float64(child.Task.ShowProgress.Current) / float64(child.Task.ShowProgress.Total)
if child.Spinner == nil {
status = "⣟ " + child.Task.Title + " " + child.Task.Bar.ViewAs(percent)
} else {
status = child.Spinner.View() + child.Task.Title + " " + child.Task.Bar.ViewAs(percent)
}
} else {
if child.Spinner == nil {
status = "⣟ " + child.Task.Title
} else {
status = child.Spinner.View() + child.Task.Title
}
}
case Completed:
status = Color(child.Config.Colors.Success, runner.Config.Chars.Success) + " " + child.Task.Title // Green checkmark
case Failed:
status = Color(child.Config.Colors.Failure, runner.Config.Chars.Failure) + " " + child.Task.Title // Red 'x'
}
if IsCI() {
view += " " + status + "\n"
} else {
view += " " + lipgloss.NewStyle().Render(status) + "\n"
}
// Render children if they exist
if len(runner.Children) > 0 {
view += renderChildren(runner, "")
}
}
return view
Expand Down
78 changes: 35 additions & 43 deletions taskin.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package taskin

import (
"dario.cat/mergo"
"fmt"
"io"
"os"
"regexp"

"dario.cat/mergo"
"github.com/charmbracelet/bubbles/progress"
"github.com/charmbracelet/bubbles/spinner"
tea "github.com/charmbracelet/bubbletea"
Expand Down Expand Up @@ -83,68 +83,60 @@ func (r *Runners) Run() error {
}

func New(tasks Tasks, cfg Config) Runners {

_ = mergo.Merge(&cfg, Defaults)
var runners Runners
for _, task := range tasks {
task.Config = cfg
runners = append(runners, NewRunner(task, cfg))
}

go func() {
for i := range runners {
// Helper function to run a task and its children recursively
var runTaskAndChildren func(runner *Runner) error
runTaskAndChildren = func(runner *Runner) error {
runner.State = Running

for _, runner := range runners[:i] {
if runner.State == Failed && runner.Config.Options.ExitOnFailure {
return
}
// Run the task itself first if it has a function
if runner.Task.Task != nil {
err := runner.Task.Task(&runner.Task)
if err != nil {
runner.Task.Title = fmt.Sprintf("%s - %s", runner.Task.Title, err.Error())
runner.State = Failed
return err
}
}

runners[i].State = Running
err := runners[i].Task.Task(&runners[i].Task)
// Run all children recursively
for i := range runner.Children {
err := runTaskAndChildren(&runner.Children[i])
if err != nil {
runners[i].Task.Title = fmt.Sprintf("%s - %s", runners[i].Task.Title, err.Error())
runners[i].State = Failed
if program != nil {
program.Send(TerminateWithError{Error: err})
}
continue
runner.State = Failed
return err
}
}

// Run child tasks
for j := range runners[i].Children {
runners[i].Children[j].State = Running
err := runners[i].Children[j].Task.Task(&runners[i].Children[j].Task)
if err != nil {
runners[i].Children[j].Task.Title = fmt.Sprintf("%s - Error: %s", runners[i].Children[j].Task.Title, err.Error())
runners[i].Children[j].State = Failed
runners[i].State = Failed // Mark parent task as Failed
if program != nil {
program.Send(TerminateWithError{Error: err})
}
break
}
runners[i].Children[j].State = Completed
}
runner.State = Completed
if program != nil {
program.Send(spinner.TickMsg{})
}
return nil
}

// Check if all child tasks are completed
allChildrenCompleted := true
for _, child := range runners[i].Children {
if child.State != Completed {
allChildrenCompleted = false
break
go func() {
for i := range runners {
// Check for previous failures
for _, prev := range runners[:i] {
if prev.State == Failed && prev.Config.Options.ExitOnFailure {
return
}
}

// If all child tasks are completed, mark the parent task as completed
if allChildrenCompleted && runners[i].State != Failed {
runners[i].State = Completed
if program != nil {
program.Send(spinner.TickMsg{})
}
err := runTaskAndChildren(&runners[i])
if err != nil && program != nil {
program.Send(TerminateWithError{Error: err})
}
}
}()

return runners
}

Expand Down

0 comments on commit 02e1f18

Please sign in to comment.