diff options
Diffstat (limited to 'internal/askcli')
| -rw-r--r-- | internal/askcli/command_complete_uuids.go | 28 | ||||
| -rw-r--r-- | internal/askcli/command_complete_uuids_test.go | 54 | ||||
| -rw-r--r-- | internal/askcli/completion.go | 27 | ||||
| -rw-r--r-- | internal/askcli/completion_test.go | 8 | ||||
| -rw-r--r-- | internal/askcli/dispatch.go | 2 | ||||
| -rw-r--r-- | internal/askcli/dispatch_test.go | 21 |
6 files changed, 122 insertions, 18 deletions
diff --git a/internal/askcli/command_complete_uuids.go b/internal/askcli/command_complete_uuids.go new file mode 100644 index 0000000..99f1e0e --- /dev/null +++ b/internal/askcli/command_complete_uuids.go @@ -0,0 +1,28 @@ +package askcli + +import ( + "bytes" + "context" + "fmt" + "io" +) + +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 { + return code, err + } + tasks, err := ParseTaskExport(&outBuf) + if err != nil { + fmt.Fprintf(stderr, "error: failed to parse task data: %v\n", err) + return 1, nil + } + for _, task := range tasks { + if task.UUID == "" { + continue + } + _, _ = io.WriteString(stdout, task.UUID+"\n") + } + return 0, nil +} diff --git a/internal/askcli/command_complete_uuids_test.go b/internal/askcli/command_complete_uuids_test.go new file mode 100644 index 0000000..ff9d142 --- /dev/null +++ b/internal/askcli/command_complete_uuids_test.go @@ -0,0 +1,54 @@ +package askcli + +import ( + "bytes" + "context" + "io" + "strings" + "testing" +) + +func TestHandleCompleteUUIDs_PrintsPendingUUIDs(t *testing.T) { + d := NewDispatcher(&spyRunner{runFn: func(ctx context.Context, args []string, stdin io.Reader, stdout, stderr io.Writer) (int, error) { + want := []string{"status:pending", "export"} + if strings.Join(args, " ") != strings.Join(want, " ") { + t.Fatalf("args = %v, want %v", args, want) + } + _, _ = io.WriteString(stdout, `[{"uuid":"uuid-1"},{"uuid":"uuid-2"},{"uuid":""}]`) + return 0, nil + }}) + + var stdout, stderr bytes.Buffer + code, err := d.handleCompleteUUIDs(context.Background(), &stdout, &stderr) + if err != nil { + t.Fatalf("handleCompleteUUIDs returned error: %v", err) + } + if code != 0 { + t.Fatalf("handleCompleteUUIDs code = %d, want 0", code) + } + if got := stdout.String(); got != "uuid-1\nuuid-2\n" { + t.Fatalf("stdout = %q, want UUID list", got) + } + if stderr.Len() != 0 { + t.Fatalf("stderr = %q, want empty", stderr.String()) + } +} + +func TestHandleCompleteUUIDs_ParseError(t *testing.T) { + d := NewDispatcher(&spyRunner{runFn: func(ctx context.Context, args []string, stdin io.Reader, stdout, stderr io.Writer) (int, error) { + _, _ = io.WriteString(stdout, `not-json`) + return 0, nil + }}) + + var stdout, stderr bytes.Buffer + code, err := d.handleCompleteUUIDs(context.Background(), &stdout, &stderr) + if err != nil { + t.Fatalf("handleCompleteUUIDs returned error: %v", err) + } + if code != 1 { + t.Fatalf("handleCompleteUUIDs code = %d, want 1", code) + } + if !strings.Contains(stderr.String(), "failed to parse task data") { + t.Fatalf("stderr = %q, want parse error", stderr.String()) + } +} diff --git a/internal/askcli/completion.go b/internal/askcli/completion.go index e947495..6033415 100644 --- a/internal/askcli/completion.go +++ b/internal/askcli/completion.go @@ -48,12 +48,6 @@ var askUUIDCompletionItems = []fishCompletionItem{ {name: "delete", description: "Delete a task"}, } -var askDepUUIDCompletionItems = []fishCompletionItem{ - {name: "add", description: "Add a dependency"}, - {name: "rm", description: "Remove a dependency"}, - {name: "list", description: "List dependencies"}, -} - func FishCompletion() string { var b strings.Builder writeFishPreamble(&b) @@ -67,12 +61,8 @@ func FishCompletion() string { for _, item := range askDepCompletionItems { writeFishCompletionLine(&b, "__ask_in_dep_context", item) } - for _, item := range askUUIDCompletionItems { - writeFishUUIDCompletionLine(&b, "__ask_in_uuid_context", item.description) - } - for _, item := range askDepUUIDCompletionItems { - writeFishUUIDCompletionLine(&b, "__ask_in_dep_uuid_context", item.description) - } + writeFishUUIDCompletionLine(&b, "__ask_in_uuid_context", "Task UUID") + writeFishUUIDCompletionLine(&b, "__ask_in_dep_uuid_context", "Task UUID") return b.String() } @@ -189,7 +179,18 @@ func writeFishDepUUIDContextFunction(b *strings.Builder) { func writeFishTaskUUIDFunction(b *strings.Builder) { b.WriteString("function __ask_task_uuids\n") - b.WriteString(" command ask all --json 2>/dev/null | jq -r '.[] | select(.status != \"completed\" and .status != \"deleted\") | .uuid' 2>/dev/null\n") + b.WriteString(" set -l now (date +%s)\n") + b.WriteString(" if set -q __ask_task_uuid_cache_until; and test $__ask_task_uuid_cache_until -ge $now\n") + b.WriteString(" printf '%s\\n' $__ask_task_uuid_cache\n") + b.WriteString(" return 0\n") + b.WriteString(" end\n") + b.WriteString(" set -l uuids (command ask complete-uuids 2>/dev/null)\n") + b.WriteString(" if test $status -ne 0\n") + b.WriteString(" return 1\n") + b.WriteString(" end\n") + b.WriteString(" set -g __ask_task_uuid_cache $uuids\n") + b.WriteString(" set -g __ask_task_uuid_cache_until (math $now + 2)\n") + b.WriteString(" printf '%s\\n' $uuids\n") b.WriteString("end\n\n") } diff --git a/internal/askcli/completion_test.go b/internal/askcli/completion_test.go index 52cdce8..5cab89b 100644 --- a/internal/askcli/completion_test.go +++ b/internal/askcli/completion_test.go @@ -36,11 +36,9 @@ func TestFishCompletion_IncludesCommandsAndExcludesExport(t *testing.T) { "complete -c ask -n '__ask_in_dep_context' -a 'rm' -d 'Remove a dependency'", "complete -c ask -n '__ask_in_dep_context' -a 'list' -d 'List dependencies'", "function __ask_task_uuids", - "command ask all --json 2>/dev/null | jq -r '.[] | select(.status != \"completed\" and .status != \"deleted\") | .uuid' 2>/dev/null", - "complete -c ask -n '__ask_in_uuid_context' -a '(__ask_task_uuids)' -d 'Show task details'", - "complete -c ask -n '__ask_in_dep_uuid_context' -a '(__ask_task_uuids)' -d 'Add a dependency'", - "complete -c ask -n '__ask_in_dep_uuid_context' -a '(__ask_task_uuids)' -d 'Remove a dependency'", - "complete -c ask -n '__ask_in_dep_uuid_context' -a '(__ask_task_uuids)' -d 'List dependencies'", + "set -l uuids (command ask complete-uuids 2>/dev/null)", + "complete -c ask -n '__ask_in_uuid_context' -a '(__ask_task_uuids)' -d 'Task UUID'", + "complete -c ask -n '__ask_in_dep_uuid_context' -a '(__ask_task_uuids)' -d 'Task UUID'", } { if !strings.Contains(script, line) { t.Fatalf("script missing dep completion line %q", line) diff --git a/internal/askcli/dispatch.go b/internal/askcli/dispatch.go index 19e9b58..bc4715c 100644 --- a/internal/askcli/dispatch.go +++ b/internal/askcli/dispatch.go @@ -76,6 +76,8 @@ func (d Dispatcher) Dispatch(ctx context.Context, args []string, stdin io.Reader return d.handleDelete(ctx, args, stdin, stdout, stderr) case "help": return d.help(stdout) + case "complete-uuids": + return d.handleCompleteUUIDs(ctx, stdout, stderr) default: return d.unknownCommand(stderr, subcommand) } diff --git a/internal/askcli/dispatch_test.go b/internal/askcli/dispatch_test.go index 1586447..9a1bf43 100644 --- a/internal/askcli/dispatch_test.go +++ b/internal/askcli/dispatch_test.go @@ -46,6 +46,27 @@ func TestDispatcher_UnknownSubcommand(t *testing.T) { } } +func TestDispatcher_CompleteUUIDsSubcommand(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 pending export", args) + } + _, _ = io.WriteString(stdout, `[{"uuid":"uuid-1"}]`) + return 0, nil + }}) + var stdout, stderr bytes.Buffer + code, err := d.Dispatch(context.Background(), []string{"complete-uuids"}, nil, &stdout, &stderr) + if err != nil { + t.Fatalf("complete-uuids returned error: %v", err) + } + if code != 0 { + t.Fatalf("complete-uuids code = %d, want 0", code) + } + if got := stdout.String(); got != "uuid-1\n" { + t.Fatalf("stdout = %q, want UUID list", got) + } +} + func TestDispatcher_LongHelp(t *testing.T) { d := NewDispatcher(nil) var stdout bytes.Buffer |
