diff --git a/cmd/task/task.go b/cmd/task/task.go index ae2d4f90..6af1632c 100644 --- a/cmd/task/task.go +++ b/cmd/task/task.go @@ -60,6 +60,7 @@ func main() { helpFlag bool init bool list bool + listAll bool status bool force bool watch bool @@ -79,6 +80,7 @@ func main() { pflag.BoolVarP(&helpFlag, "help", "h", false, "shows Task usage") pflag.BoolVarP(&init, "init", "i", false, "creates a new Taskfile.yaml in the current folder") pflag.BoolVarP(&list, "list", "l", false, "lists tasks with description of current Taskfile") + pflag.BoolVarP(&listAll, "list-all", "a", false, "list tasks with or without a description") pflag.BoolVar(&status, "status", false, "exits with non-zero exit code if any of the given tasks is not up-to-date") pflag.BoolVarP(&force, "force", "f", false, "forces execution even when the task is up-to-date") pflag.BoolVarP(&watch, "watch", "w", false, "enables watch of the given task") @@ -153,7 +155,11 @@ func main() { } if list { - e.PrintTasksHelp() + e.ListTasksWithDesc() + } + + if listAll { + e.ListAllTasks() return } diff --git a/help.go b/help.go index 256b13c8..01cf4f0c 100644 --- a/help.go +++ b/help.go @@ -9,10 +9,19 @@ import ( "github.com/go-task/task/v3/taskfile" ) -// PrintTasksHelp prints help os tasks that have a description -func (e *Executor) PrintTasksHelp() { - tasks := e.tasksWithDesc() +// PrintTasksHelp prints tasks' help. +// Behavior is governed by listAll. When false, only tasks with descriptions are reported. +// When true, all tasks are reported with descriptions shown where available. +func (e *Executor) PrintTasksHelp(listAll bool) { + var tasks []*taskfile.Task + if listAll == true { + tasks = e.allTaskNames() + } else { + tasks = e.tasksWithDesc() + } + if len(tasks) == 0 { + // TODO: This message should be more informative. Maybe a hint to try -la for showing all? e.Logger.Outf(logger.Yellow, "task: No tasks with description available") return } @@ -26,6 +35,15 @@ func (e *Executor) PrintTasksHelp() { w.Flush() } +func (e *Executor) allTaskNames() (tasks []*taskfile.Task) { + tasks = make([]*taskfile.Task, 0, len(e.Taskfile.Tasks)) + for _, task := range e.Taskfile.Tasks { + tasks = append(tasks, task) + } + sort.Slice(tasks, func(i, j int) bool { return tasks[i].Task < tasks[j].Task }) + return +} + func (e *Executor) tasksWithDesc() (tasks []*taskfile.Task) { tasks = make([]*taskfile.Task, 0, len(e.Taskfile.Tasks)) for _, task := range e.Taskfile.Tasks { @@ -40,3 +58,15 @@ func (e *Executor) tasksWithDesc() (tasks []*taskfile.Task) { sort.Slice(tasks, func(i, j int) bool { return tasks[i].Task < tasks[j].Task }) return } + +// ListTasksWithDesc reports tasks that have a description spec. +func (e *Executor) ListTasksWithDesc() { + e.PrintTasksHelp(false) + return +} + +// ListAllTasks reports all tasks, with or without a description spec. +func (e *Executor) ListAllTasks() { + e.PrintTasksHelp(true) + return +} diff --git a/task.go b/task.go index 34628db3..17e5be10 100644 --- a/task.go +++ b/task.go @@ -68,7 +68,7 @@ func (e *Executor) Run(ctx context.Context, calls ...taskfile.Call) error { for _, c := range calls { if _, ok := e.Taskfile.Tasks[c.Task]; !ok { // FIXME: move to the main package - e.PrintTasksHelp() + e.ListTasksWithDesc() return &taskNotFoundError{taskName: c.Task} } } diff --git a/task_test.go b/task_test.go index b82322ec..ce684b32 100644 --- a/task_test.go +++ b/task_test.go @@ -518,10 +518,58 @@ func TestLabelInList(t *testing.T) { Stderr: &buff, } assert.NoError(t, e.Setup()) - e.PrintTasksHelp() + e.PrintTasksHelp(false) assert.Contains(t, buff.String(), "foobar") } +// task -al case 1: listAll list all tasks +func TestListAllShowsNoDesc(t *testing.T) { + const dir = "testdata/list_mixed_desc" + + var buff bytes.Buffer + e := task.Executor{ + Dir: dir, + Stdout: &buff, + Stderr: &buff, + } + + assert.NoError(t, e.Setup()) + + var title string + e.ListAllTasks() + for _, title = range []string{ + "foo", + "voo", + "doo", + } { + assert.Contains(t, buff.String(), title) + } +} + +// task -al case 2: !listAll list some tasks (only those with desc) +func TestListCanListDescOnly(t *testing.T) { + const dir = "testdata/list_mixed_desc" + + var buff bytes.Buffer + e := task.Executor{ + Dir: dir, + Stdout: &buff, + Stderr: &buff, + } + + assert.NoError(t, e.Setup()) + e.ListTasksWithDesc() + + var title string + assert.Contains(t, buff.String(), "foo") + for _, title = range []string{ + "voo", + "doo", + } { + assert.NotContains(t, buff.String(), title) + } +} + func TestStatusVariables(t *testing.T) { const dir = "testdata/status_vars" diff --git a/testdata/list_mixed_desc/Taskfile.yml b/testdata/list_mixed_desc/Taskfile.yml new file mode 100644 index 00000000..72997d73 --- /dev/null +++ b/testdata/list_mixed_desc/Taskfile.yml @@ -0,0 +1,12 @@ +version: '3' + +tasks: + foo: + label: "foobar" + desc: "foo has desc and label" + + voo: + label: "voo has no desc" + + doo: + label: "doo has desc, no label"