Files
beads/cmd/bd/completions.go
beads/crew/dave 5dfb838d60 feat(completion): optimize ID prefix filtering and add completions to more commands
Improvements to shell completions from PR #935:

1. Add IDPrefix field to IssueFilter for efficient database-level filtering
   - Queries are now filtered at SQL level instead of fetching all issues
   - Updated sqlite, transaction, and memory stores to support IDPrefix

2. Add ValidArgsFunction to additional commands:
   - dep (add, remove, list, tree)
   - comments, comment (add)
   - delete
   - graph
   - label (add, remove, list)
   - duplicate, supersede
   - audit
   - move
   - relate, unrelate
   - refile
   - gate (show, resolve, add-waiter)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Executed-By: beads/crew/dave
Rig: beads
Role: crew
2026-01-06 19:05:34 -08:00

72 lines
2.0 KiB
Go

package main
import (
"context"
"fmt"
"path/filepath"
"time"
"github.com/spf13/cobra"
"github.com/steveyegge/beads/internal/beads"
"github.com/steveyegge/beads/internal/storage/sqlite"
"github.com/steveyegge/beads/internal/types"
)
// issueIDCompletion provides shell completion for issue IDs by querying the storage
// and returning a list of IDs with their titles as descriptions
func issueIDCompletion(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
// Initialize storage if not already initialized
ctx := context.Background()
if rootCtx != nil {
ctx = rootCtx
}
// Get database path - use same logic as in PersistentPreRun
currentDBPath := dbPath
if currentDBPath == "" {
// Try to find database path
foundDB := beads.FindDatabasePath()
if foundDB != "" {
currentDBPath = foundDB
} else {
// Default path
currentDBPath = filepath.Join(".beads", beads.CanonicalDatabaseName)
}
}
// Open database if store is not initialized
currentStore := store
if currentStore == nil {
var err error
timeout := 30 * time.Second
if lockTimeout > 0 {
timeout = lockTimeout
}
currentStore, err = sqlite.NewReadOnlyWithTimeout(ctx, currentDBPath, timeout)
if err != nil {
// If we can't open database, return empty completion
return nil, cobra.ShellCompDirectiveNoFileComp
}
defer currentStore.Close()
}
// Use SearchIssues with IDPrefix filter to efficiently query matching issues
filter := types.IssueFilter{
IDPrefix: toComplete, // Filter at database level for better performance
}
issues, err := currentStore.SearchIssues(ctx, "", filter)
if err != nil {
// If we can't list issues, return empty completion
return nil, cobra.ShellCompDirectiveNoFileComp
}
// Build completion list
completions := make([]string, 0, len(issues))
for _, issue := range issues {
// Format: ID\tTitle (shown during completion)
completions = append(completions, fmt.Sprintf("%s\t%s", issue.ID, issue.Title))
}
return completions, cobra.ShellCompDirectiveNoFileComp
}