From dd55d6e96b3c91ec5cfeba5addc7d61cc84e4557 Mon Sep 17 00:00:00 2001 From: Pete Davison Date: Mon, 9 Sep 2024 16:19:01 +0000 Subject: [PATCH] refactor: better sort package --- cmd/task/task.go | 6 ++-- help.go | 14 ++++---- internal/sort/sorter.go | 46 +++++++++++------------- internal/sort/sorter_test.go | 68 +++++++++++++++++------------------- task.go | 21 ++++++----- 5 files changed, 77 insertions(+), 78 deletions(-) diff --git a/cmd/task/task.go b/cmd/task/task.go index 439ca9c5..79e422c6 100644 --- a/cmd/task/task.go +++ b/cmd/task/task.go @@ -100,12 +100,12 @@ func run() error { dir = home } - var taskSorter sort.TaskSorter + var taskSorter sort.Sorter switch flags.TaskSort { case "none": - taskSorter = &sort.Noop{} + taskSorter = nil case "alphanumeric": - taskSorter = &sort.AlphaNumeric{} + taskSorter = sort.AlphaNumeric } e := task.Executor{ diff --git a/help.go b/help.go index 622ef17b..6ee1f7e3 100644 --- a/help.go +++ b/help.go @@ -128,18 +128,20 @@ func (e *Executor) ListTaskNames(allTasks bool) error { w = e.Stdout } - // Get the list of tasks and sort them - tasks := e.Taskfile.Tasks.Values() - // Sort the tasks if e.TaskSorter == nil { - e.TaskSorter = &sort.AlphaNumericWithRootTasksFirst{} + e.TaskSorter = sort.AlphaNumericWithRootTasksFirst } - e.TaskSorter.Sort(tasks) + keys := e.Taskfile.Tasks.Keys() + e.TaskSorter(keys, nil) // Create a list of task names taskNames := make([]string, 0, e.Taskfile.Tasks.Len()) - for _, task := range tasks { + for _, key := range keys { + task, ok := e.Taskfile.Tasks.Get(key) + if !ok { + continue + } if (allTasks || task.Desc != "") && !task.Internal { taskNames = append(taskNames, strings.TrimRight(task.Task, ":")) for _, alias := range task.Aliases { diff --git a/internal/sort/sorter.go b/internal/sort/sorter.go index 4c1016cc..e3b9842c 100644 --- a/internal/sort/sorter.go +++ b/internal/sort/sorter.go @@ -3,42 +3,38 @@ package sort import ( "sort" "strings" - - "github.com/go-task/task/v3/taskfile/ast" ) -type TaskSorter interface { - Sort([]*ast.Task) -} +// A Sorter is any function that sorts a set of tasks. +type Sorter func(items []string, namespaces []string) []string -type Noop struct{} - -func (s *Noop) Sort(tasks []*ast.Task) {} - -type AlphaNumeric struct{} - -// Tasks that are not namespaced should be listed before tasks that are. -// We detect this by searching for a ':' in the task name. -func (s *AlphaNumeric) Sort(tasks []*ast.Task) { - sort.Slice(tasks, func(i, j int) bool { - return tasks[i].Task < tasks[j].Task +// AlphaNumeric sorts the JSON output so that tasks are in alpha numeric order +// by task name. +func AlphaNumeric(items []string, namespaces []string) []string { + sort.Slice(items, func(i, j int) bool { + return items[i] < items[j] }) + return items } -type AlphaNumericWithRootTasksFirst struct{} - -// Tasks that are not namespaced should be listed before tasks that are. -// We detect this by searching for a ':' in the task name. -func (s *AlphaNumericWithRootTasksFirst) Sort(tasks []*ast.Task) { - sort.Slice(tasks, func(i, j int) bool { - iContainsColon := strings.Contains(tasks[i].Task, ":") - jContainsColon := strings.Contains(tasks[j].Task, ":") +// AlphaNumericWithRootTasksFirst sorts the JSON output so that tasks are in +// alpha numeric order by task name. It will also ensure that tasks that are not +// namespaced will be listed before tasks that are. We detect this by searching +// for a ':' in the task name. +func AlphaNumericWithRootTasksFirst(items []string, namespaces []string) []string { + if len(namespaces) > 0 { + return AlphaNumeric(items, namespaces) + } + sort.Slice(items, func(i, j int) bool { + iContainsColon := strings.Contains(items[i], ":") + jContainsColon := strings.Contains(items[j], ":") if iContainsColon == jContainsColon { - return tasks[i].Task < tasks[j].Task + return items[i] < items[j] } if !iContainsColon && jContainsColon { return true } return false }) + return items } diff --git a/internal/sort/sorter_test.go b/internal/sort/sorter_test.go index d788c545..e388c48e 100644 --- a/internal/sort/sorter_test.go +++ b/internal/sort/sorter_test.go @@ -4,74 +4,70 @@ import ( "testing" "github.com/stretchr/testify/assert" - - "github.com/go-task/task/v3/taskfile/ast" ) func TestAlphaNumericWithRootTasksFirst_Sort(t *testing.T) { - task1 := &ast.Task{Task: "task1"} - task2 := &ast.Task{Task: "task2"} - task3 := &ast.Task{Task: "ns1:task3"} - task4 := &ast.Task{Task: "ns2:task4"} - task5 := &ast.Task{Task: "task5"} - task6 := &ast.Task{Task: "ns3:task6"} + item1 := "a-item1" + item2 := "m-item2" + item3 := "ns1:item3" + item4 := "ns2:item4" + item5 := "z-item5" + item6 := "ns3:item6" tests := []struct { name string - tasks []*ast.Task - want []*ast.Task + items []string + want []string }{ { - name: "no namespace tasks sorted alphabetically first", - tasks: []*ast.Task{task3, task2, task1}, - want: []*ast.Task{task1, task2, task3}, + name: "no namespace items sorted alphabetically first", + items: []string{item3, item2, item1}, + want: []string{item1, item2, item3}, }, { - name: "namespace tasks sorted alphabetically after non-namespaced tasks", - tasks: []*ast.Task{task3, task4, task5}, - want: []*ast.Task{task5, task3, task4}, + name: "namespace items sorted alphabetically after non-namespaced items", + items: []string{item3, item4, item5}, + want: []string{item5, item3, item4}, }, { - name: "all tasks sorted alphabetically with root tasks first", - tasks: []*ast.Task{task6, task5, task4, task3, task2, task1}, - want: []*ast.Task{task1, task2, task5, task3, task4, task6}, + name: "all items sorted alphabetically with root items first", + items: []string{item6, item5, item4, item3, item2, item1}, + want: []string{item1, item2, item5, item3, item4, item6}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - s := &AlphaNumericWithRootTasksFirst{} - s.Sort(tt.tasks) - assert.Equal(t, tt.want, tt.tasks) + AlphaNumericWithRootTasksFirst(tt.items, nil) + assert.Equal(t, tt.want, tt.items) }) } } func TestAlphaNumeric_Sort(t *testing.T) { - task1 := &ast.Task{Task: "task1"} - task2 := &ast.Task{Task: "task2"} - task3 := &ast.Task{Task: "ns1:task3"} - task4 := &ast.Task{Task: "ns2:task4"} - task5 := &ast.Task{Task: "task5"} - task6 := &ast.Task{Task: "ns3:task6"} + item1 := "a-item1" + item2 := "m-item2" + item3 := "ns1:item3" + item4 := "ns2:item4" + item5 := "z-item5" + item6 := "ns3:item6" tests := []struct { name string - tasks []*ast.Task - want []*ast.Task + items []string + want []string }{ { - name: "all tasks sorted alphabetically", - tasks: []*ast.Task{task3, task2, task5, task1, task4, task6}, - want: []*ast.Task{task3, task4, task6, task1, task2, task5}, + name: "all items sorted alphabetically", + items: []string{item3, item2, item5, item1, item4, item6}, + want: []string{item1, item2, item3, item4, item6, item5}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - s := &AlphaNumeric{} - s.Sort(tt.tasks) - assert.Equal(t, tt.tasks, tt.want) + AlphaNumeric(tt.items, nil) + assert.Equal(t, tt.want, tt.items) }) } } diff --git a/task.go b/task.go index dc6b7b09..2f956c0b 100644 --- a/task.go +++ b/task.go @@ -74,7 +74,7 @@ type Executor struct { Compiler *compiler.Compiler Output output.Output OutputStyle ast.Output - TaskSorter sort.TaskSorter + TaskSorter sort.Sorter UserWorkingDir string fuzzyModel *fuzzy.Model @@ -498,8 +498,19 @@ func (e *Executor) GetTaskList(filters ...FilterFunc) ([]*ast.Task, error) { // Create an error group to wait for each task to be compiled var g errgroup.Group + // Sort the tasks + if e.TaskSorter == nil { + e.TaskSorter = sort.AlphaNumericWithRootTasksFirst + } + keys := e.Taskfile.Tasks.Keys() + e.TaskSorter(keys, nil) + // Filter tasks based on the given filter functions - for _, task := range e.Taskfile.Tasks.Values() { + for _, key := range keys { + task, ok := e.Taskfile.Tasks.Get(key) + if !ok { + continue + } var shouldFilter bool for _, filter := range filters { if filter(task) { @@ -528,12 +539,6 @@ func (e *Executor) GetTaskList(filters ...FilterFunc) ([]*ast.Task, error) { return nil, err } - // Sort the tasks - if e.TaskSorter == nil { - e.TaskSorter = &sort.AlphaNumericWithRootTasksFirst{} - } - e.TaskSorter.Sort(tasks) - return tasks, nil }