summaryrefslogtreecommitdiff
path: root/internal/askcli
diff options
context:
space:
mode:
Diffstat (limited to 'internal/askcli')
-rw-r--r--internal/askcli/command_complete_uuids.go28
-rw-r--r--internal/askcli/command_complete_uuids_test.go54
-rw-r--r--internal/askcli/completion.go27
-rw-r--r--internal/askcli/completion_test.go8
-rw-r--r--internal/askcli/dispatch.go2
-rw-r--r--internal/askcli/dispatch_test.go21
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