summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-03-27 07:18:04 +0200
committerPaul Buetow <paul@buetow.org>2026-03-27 07:18:04 +0200
commitd3586ad2b2b140435055c349393154ae7cfffaea (patch)
treede03bb45cb75b138d71f54b105e695672b7d802c /internal
parentf146fbc4cc25bcdeab19a0c1055c839776cebff4 (diff)
task 3a4c0f14-16ad-487f-af7c-bd99ee6464e6: use pointer Dispatcher receivers
Diffstat (limited to 'internal')
-rw-r--r--internal/askcli/command_complete_uuids.go2
-rw-r--r--internal/askcli/command_delete.go2
-rw-r--r--internal/askcli/command_dep.go6
-rw-r--r--internal/askcli/command_fish.go2
-rw-r--r--internal/askcli/command_info_add.go12
-rw-r--r--internal/askcli/command_list.go8
-rw-r--r--internal/askcli/command_urgency.go2
-rw-r--r--internal/askcli/command_write.go16
-rw-r--r--internal/askcli/dispatch.go6
-rw-r--r--internal/askcli/dispatch_test.go28
-rw-r--r--internal/askcli/task_selector.go2
11 files changed, 57 insertions, 29 deletions
diff --git a/internal/askcli/command_complete_uuids.go b/internal/askcli/command_complete_uuids.go
index 8d37a80..3a2ef9e 100644
--- a/internal/askcli/command_complete_uuids.go
+++ b/internal/askcli/command_complete_uuids.go
@@ -7,7 +7,7 @@ import (
"io"
)
-func (d Dispatcher) handleCompleteUUIDs(ctx context.Context, stdout, stderr io.Writer) (int, error) {
+func (d *Dispatcher) handleCompleteUUIDs(ctx context.Context, stdout, stderr io.Writer) (int, error) {
var outBuf bytes.Buffer
code, err := d.runner.Run(ctx, []string{"status:pending", "export"}, nil, &outBuf, stderr)
if code != 0 {
diff --git a/internal/askcli/command_delete.go b/internal/askcli/command_delete.go
index 1efaad9..4e93add 100644
--- a/internal/askcli/command_delete.go
+++ b/internal/askcli/command_delete.go
@@ -6,7 +6,7 @@ import (
"io"
)
-func (d Dispatcher) handleDelete(ctx context.Context, args []string, stdin io.Reader, stdout, stderr io.Writer) (int, error) {
+func (d *Dispatcher) handleDelete(ctx context.Context, args []string, stdin io.Reader, stdout, stderr io.Writer) (int, error) {
if len(args) < 2 {
io.WriteString(stderr, "error: ask delete requires an ID or UUID argument\n")
return 1, nil
diff --git a/internal/askcli/command_dep.go b/internal/askcli/command_dep.go
index adfb232..83a4803 100644
--- a/internal/askcli/command_dep.go
+++ b/internal/askcli/command_dep.go
@@ -8,7 +8,7 @@ import (
"strings"
)
-func (d Dispatcher) handleDep(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
+func (d *Dispatcher) handleDep(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
if len(args) < 2 {
io.WriteString(stderr, "error: ask dep requires an operation (add/rm/list) and arguments\n")
return 1, nil
@@ -25,7 +25,7 @@ func (d Dispatcher) handleDep(ctx context.Context, args []string, stdout, stderr
}
}
-func (d Dispatcher) handleDepAddRm(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
+func (d *Dispatcher) handleDepAddRm(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
if len(args) < 4 {
io.WriteString(stderr, "error: ask dep add/rm requires <id|uuid> <dep-id|dep-uuid>\n")
return 1, nil
@@ -57,7 +57,7 @@ func (d Dispatcher) handleDepAddRm(ctx context.Context, args []string, stdout, s
return 0, nil
}
-func (d Dispatcher) handleDepList(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
+func (d *Dispatcher) handleDepList(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
if len(args) < 3 {
io.WriteString(stderr, "error: ask dep list requires <id|uuid>\n")
return 1, nil
diff --git a/internal/askcli/command_fish.go b/internal/askcli/command_fish.go
index 89a8457..3d3e709 100644
--- a/internal/askcli/command_fish.go
+++ b/internal/askcli/command_fish.go
@@ -6,7 +6,7 @@ import (
"os"
)
-func (d Dispatcher) handleFish(args []string, stdout, stderr io.Writer) (int, error) {
+func (d *Dispatcher) handleFish(args []string, stdout, stderr io.Writer) (int, error) {
if len(args) != 1 {
fmt.Fprintln(stderr, "usage: ask fish")
return 1, nil
diff --git a/internal/askcli/command_info_add.go b/internal/askcli/command_info_add.go
index 737b0d0..3bb57fb 100644
--- a/internal/askcli/command_info_add.go
+++ b/internal/askcli/command_info_add.go
@@ -9,7 +9,7 @@ import (
"strings"
)
-func (d Dispatcher) handleInfo(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
+func (d *Dispatcher) handleInfo(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
tasks, code, err := d.infoTasks(ctx, args, stderr)
if err != nil {
writeInfoError(stderr, err)
@@ -35,7 +35,7 @@ func (d Dispatcher) handleInfo(ctx context.Context, args []string, stdout, stder
return 0, nil
}
-func (d Dispatcher) infoTasks(ctx context.Context, args []string, stderr io.Writer) ([]TaskExport, int, error) {
+func (d *Dispatcher) infoTasks(ctx context.Context, args []string, stderr io.Writer) ([]TaskExport, int, error) {
if len(args) >= 2 {
_, tasks, code, err := d.resolveTaskSelector(ctx, args[1], stderr)
return tasks, code, err
@@ -43,7 +43,7 @@ func (d Dispatcher) infoTasks(ctx context.Context, args []string, stderr io.Writ
return d.startedInfoTasks(ctx, stderr)
}
-func (d Dispatcher) startedInfoTasks(ctx context.Context, stderr io.Writer) ([]TaskExport, int, error) {
+func (d *Dispatcher) startedInfoTasks(ctx context.Context, stderr io.Writer) ([]TaskExport, int, error) {
tasks, code, err := d.exportTasks(ctx, []string{"started", "export"}, stderr)
if err != nil {
return nil, code, err
@@ -58,7 +58,7 @@ func (d Dispatcher) startedInfoTasks(ctx context.Context, stderr io.Writer) ([]T
}
}
-func (d Dispatcher) exportTasks(ctx context.Context, args []string, stderr io.Writer) ([]TaskExport, int, error) {
+func (d *Dispatcher) exportTasks(ctx context.Context, args []string, stderr io.Writer) ([]TaskExport, int, error) {
var outBuf bytes.Buffer
code, err := d.runner.Run(ctx, args, nil, &outBuf, stderr)
if code != 0 {
@@ -83,7 +83,7 @@ func writeInfoError(stderr io.Writer, err error) {
fmt.Fprintf(stderr, "error: %v\n", err)
}
-func (d Dispatcher) handleAdd(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
+func (d *Dispatcher) handleAdd(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
if len(args) < 2 {
io.WriteString(stderr, "error: ask add requires a description\n")
return 1, nil
@@ -129,7 +129,7 @@ func (d Dispatcher) handleAdd(ctx context.Context, args []string, stdout, stderr
return 0, nil
}
-func (d Dispatcher) resolveAddDependencyUUIDs(ctx context.Context, selectors []string, stderr io.Writer) ([]string, int, error) {
+func (d *Dispatcher) resolveAddDependencyUUIDs(ctx context.Context, selectors []string, stderr io.Writer) ([]string, int, error) {
dependencies := make([]string, 0, len(selectors))
for _, selector := range selectors {
resolved, _, code, err := d.resolveTaskSelector(ctx, selector, stderr)
diff --git a/internal/askcli/command_list.go b/internal/askcli/command_list.go
index 2e5dfa2..76b5302 100644
--- a/internal/askcli/command_list.go
+++ b/internal/askcli/command_list.go
@@ -10,22 +10,22 @@ import (
"strings"
)
-func (d Dispatcher) handleList(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
+func (d *Dispatcher) handleList(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
return d.handleListWithFilters(ctx, []string{"status:pending"}, args[1:], stdout, stderr)
}
-func (d Dispatcher) handleAll(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
+func (d *Dispatcher) handleAll(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
return d.handleListWithFilters(ctx, nil, args[1:], stdout, stderr)
}
-func (d Dispatcher) handleReady(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
+func (d *Dispatcher) handleReady(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
return d.handleListWithFilters(ctx, []string{"+READY"}, args[1:], stdout, stderr)
}
// handleListWithFilters is the shared implementation for list/all/ready.
// initialFilters seeds the taskwarrior filter; extraArgs are user-supplied
// filter modifiers (limit:, sort:, +tag, started).
-func (d Dispatcher) handleListWithFilters(ctx context.Context, initialFilters, extraArgs []string, stdout, stderr io.Writer) (int, error) {
+func (d *Dispatcher) handleListWithFilters(ctx context.Context, initialFilters, extraArgs []string, stdout, stderr io.Writer) (int, error) {
filterArgs := append([]string(nil), initialFilters...)
for _, arg := range extraArgs {
if strings.HasPrefix(arg, "limit:") || strings.HasPrefix(arg, "sort:") ||
diff --git a/internal/askcli/command_urgency.go b/internal/askcli/command_urgency.go
index c1ec24c..a6f545c 100644
--- a/internal/askcli/command_urgency.go
+++ b/internal/askcli/command_urgency.go
@@ -9,7 +9,7 @@ import (
"sort"
)
-func (d Dispatcher) handleUrgency(ctx context.Context, stdout, stderr io.Writer) (int, error) {
+func (d *Dispatcher) handleUrgency(ctx context.Context, stdout, stderr io.Writer) (int, error) {
var outBuf bytes.Buffer
code, err := d.runner.Run(ctx, []string{"export"}, nil, &outBuf, stderr)
if code != 0 {
diff --git a/internal/askcli/command_write.go b/internal/askcli/command_write.go
index 477e097..efc634a 100644
--- a/internal/askcli/command_write.go
+++ b/internal/askcli/command_write.go
@@ -7,7 +7,7 @@ import (
"strings"
)
-func (d Dispatcher) handleDenotate(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
+func (d *Dispatcher) handleDenotate(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
if len(args) < 3 {
io.WriteString(stderr, "error: ask denotate requires an ID or UUID and text argument\n")
return 1, nil
@@ -27,7 +27,7 @@ func (d Dispatcher) handleDenotate(ctx context.Context, args []string, stdout, s
return 0, nil
}
-func (d Dispatcher) handleModify(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
+func (d *Dispatcher) handleModify(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
if len(args) < 3 {
io.WriteString(stderr, "error: ask modify requires an ID or UUID and modification args\n")
return 1, nil
@@ -47,7 +47,7 @@ func (d Dispatcher) handleModify(ctx context.Context, args []string, stdout, std
return 0, nil
}
-func (d Dispatcher) handleAnnotate(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
+func (d *Dispatcher) handleAnnotate(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
if len(args) < 3 {
io.WriteString(stderr, "error: ask annotate requires an ID or UUID and note argument\n")
return 1, nil
@@ -67,7 +67,7 @@ func (d Dispatcher) handleAnnotate(ctx context.Context, args []string, stdout, s
return 0, nil
}
-func (d Dispatcher) handleStart(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
+func (d *Dispatcher) handleStart(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
if len(args) < 2 {
io.WriteString(stderr, "error: ask start requires an ID or UUID argument\n")
return 1, nil
@@ -88,7 +88,7 @@ func (d Dispatcher) handleStart(ctx context.Context, args []string, stdout, stde
return 0, nil
}
-func (d Dispatcher) handleStop(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
+func (d *Dispatcher) handleStop(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
if len(args) < 2 {
io.WriteString(stderr, "error: ask stop requires an ID or UUID argument\n")
return 1, nil
@@ -107,7 +107,7 @@ func (d Dispatcher) handleStop(ctx context.Context, args []string, stdout, stder
return 0, nil
}
-func (d Dispatcher) handleDone(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
+func (d *Dispatcher) handleDone(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
if len(args) < 2 {
io.WriteString(stderr, "error: ask done requires an ID or UUID argument\n")
return 1, nil
@@ -126,7 +126,7 @@ func (d Dispatcher) handleDone(ctx context.Context, args []string, stdout, stder
return 0, nil
}
-func (d Dispatcher) handlePriority(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
+func (d *Dispatcher) handlePriority(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
if len(args) < 3 {
io.WriteString(stderr, "error: ask priority requires an ID or UUID and priority (H/M/L)\n")
return 1, nil
@@ -146,7 +146,7 @@ func (d Dispatcher) handlePriority(ctx context.Context, args []string, stdout, s
return 0, nil
}
-func (d Dispatcher) handleTag(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
+func (d *Dispatcher) handleTag(ctx context.Context, args []string, stdout, stderr io.Writer) (int, error) {
if len(args) < 3 {
io.WriteString(stderr, "error: ask tag requires an ID or UUID and +/-tag\n")
return 1, nil
diff --git a/internal/askcli/dispatch.go b/internal/askcli/dispatch.go
index 510f2cd..5160abb 100644
--- a/internal/askcli/dispatch.go
+++ b/internal/askcli/dispatch.go
@@ -23,7 +23,7 @@ func NewDispatcher(runner Runner) *Dispatcher {
return &Dispatcher{runner: runner}
}
-func (d Dispatcher) Dispatch(ctx context.Context, args []string, stdin io.Reader, stdout, stderr io.Writer) (int, error) {
+func (d *Dispatcher) Dispatch(ctx context.Context, args []string, stdin io.Reader, stdout, stderr io.Writer) (int, error) {
// Extract --json flag before dispatching.
var jsonOutput bool
var filtered []string
@@ -85,7 +85,7 @@ func (d Dispatcher) Dispatch(ctx context.Context, args []string, stdin io.Reader
}
}
-func (d Dispatcher) help(w io.Writer) (int, error) {
+func (d *Dispatcher) help(w io.Writer) (int, error) {
io.WriteString(w, "ask - task management CLI\n")
io.WriteString(w, "\nSubcommands:\n")
io.WriteString(w, " ask add [mods...] [depends:<id|uuid>,...] <description...> Create a new task and print its ID\n")
@@ -110,7 +110,7 @@ func (d Dispatcher) help(w io.Writer) (int, error) {
return 0, nil
}
-func (d Dispatcher) unknownCommand(w io.Writer, subcommand string) (int, error) {
+func (d *Dispatcher) unknownCommand(w io.Writer, subcommand string) (int, error) {
fmt.Fprintf(w, "ask: unknown subcommand %q\n", subcommand)
return 1, nil
}
diff --git a/internal/askcli/dispatch_test.go b/internal/askcli/dispatch_test.go
index cd83e48..48c3e55 100644
--- a/internal/askcli/dispatch_test.go
+++ b/internal/askcli/dispatch_test.go
@@ -123,6 +123,34 @@ func TestDispatcher_FishSubcommandRejectsExtraArgs(t *testing.T) {
}
}
+func TestDispatcher_DispatchPersistsJSONFlagOnDispatcher(t *testing.T) {
+ d := NewDispatcher(&spyRunner{runFn: func(ctx context.Context, args []string, stdin io.Reader, stdout, stderr io.Writer) (int, error) {
+ if strings.Join(args, " ") != "status:pending export" {
+ t.Fatalf("args = %v, want list export args", args)
+ }
+ _, _ = io.WriteString(stdout, `[]`)
+ return 0, nil
+ }})
+
+ var stdout, stderr bytes.Buffer
+ code, err := d.Dispatch(context.Background(), []string{"--json", "list"}, nil, &stdout, &stderr)
+ if err != nil {
+ t.Fatalf("Dispatch returned error: %v", err)
+ }
+ if code != 0 {
+ t.Fatalf("Dispatch code = %d, want 0", code)
+ }
+ if !d.jsonOutput {
+ t.Fatal("Dispatch did not persist jsonOutput on the dispatcher")
+ }
+ if got := stdout.String(); got != "[]\n" {
+ t.Fatalf("stdout = %q, want JSON output", got)
+ }
+ if stderr.Len() != 0 {
+ t.Fatalf("stderr = %q, want empty", stderr.String())
+ }
+}
+
func TestDispatcher_AllSubcommandsReachExecutor(t *testing.T) {
subcommands := []string{}
subcommandArgs := map[string][]string{
diff --git a/internal/askcli/task_selector.go b/internal/askcli/task_selector.go
index 7702153..ccae234 100644
--- a/internal/askcli/task_selector.go
+++ b/internal/askcli/task_selector.go
@@ -14,7 +14,7 @@ type resolvedTaskSelector struct {
UsedAlias bool
}
-func (d Dispatcher) resolveTaskSelector(ctx context.Context, selector string, stderr io.Writer) (resolvedTaskSelector, []TaskExport, int, error) {
+func (d *Dispatcher) resolveTaskSelector(ctx context.Context, selector string, stderr io.Writer) (resolvedTaskSelector, []TaskExport, int, error) {
normalized, requiresLookup, err := normalizeTaskSelectorInput(selector)
if err != nil {
return resolvedTaskSelector{}, nil, 1, err