package repl import ( "context" "strings" "github.com/LazyBachelor/LazyPM/pkg/cli/commands" "github.com/c-bata/go-prompt" "github.com/muesli/reflow/truncate" ) var rootSuggestions = []prompt.Suggest{ {Text: "pm", Description: "Project Management System"}, {Text: "exit", Description: "Exit pm CLI"}, {Text: "help", Description: "Show help information"}, {Text: "title", Description: "Print the welcome title"}, {Text: "git", Description: "Version control system"}, } var baseSuggestions = []prompt.Suggest{ {Text: "help", Description: "Show help information"}, {Text: "delete", Description: "Delete an issue by ID"}, {Text: "create", Description: "Create a new issue with title"}, {Text: "update", Description: "Update an existing issue by ID"}, {Text: "describe", Description: "Get issue details by ID"}, {Text: "list", Description: "List all issues"}, } var createFlags = []prompt.Suggest{ {Text: "--desc", Description: "Issue description"}, {Text: "--status", Description: "Issue status (open, closed, in_progress)"}, {Text: "--type", Description: "Issue type (bug, feature, task)"}, {Text: "--priority", Description: "Issue priority (0-5)"}, } var updateFlags = []prompt.Suggest{ {Text: "--title", Description: "New issue title"}, {Text: "--desc", Description: "New issue description"}, {Text: "--status", Description: "New issue status (open, closed, in_progress)"}, {Text: "--type", Description: "New issue type (bug, feature, task)"}, {Text: "--priority", Description: "New issue priority (0-5)"}, } var listFlags = []prompt.Suggest{ {Text: "--title", Description: "Filter by title"}, {Text: "--desc", Description: "Filter by description"}, {Text: "--status", Description: "Filter by status (open, closed, in_progress)"}, {Text: "--type", Description: "Filter by type (bug, feature, task)"}, {Text: "--priority", Description: "Filter by priority (0-5)"}, {Text: "--limit", Description: "Limit number of results"}, } var statusValues = []prompt.Suggest{ {Text: "open", Description: "Open status"}, {Text: "closed", Description: "Closed status"}, {Text: "in_progress", Description: "In progress status"}, } var typeValues = []prompt.Suggest{ {Text: "bug", Description: "Bug issue type"}, {Text: "feature", Description: "Feature issue type"}, {Text: "task", Description: "Task issue type"}, } var priorityValues = []prompt.Suggest{ {Text: "0", Description: "Lowest priority"}, {Text: "1", Description: "Low priority"}, {Text: "2", Description: "Medium-low priority"}, {Text: "3", Description: "Medium priority"}, {Text: "4", Description: "High priority"}, {Text: "5", Description: "Highest priority"}, } func commandSuggestions(words []string) []prompt.Suggest { if len(words) == 0 { return baseSuggestions } return filterByPrefix(baseSuggestions, words[0]) } func flagSuggestions(cmd string, words []string, text string) []prompt.Suggest { lastWord, prevWord := parseWords(words, text) if values := getFlagValues(prevWord); values != nil { return filterByPrefix(values, lastWord) } if cmd == "describe" || cmd == "delete" || cmd == "del" || cmd == "rm" || cmd == "remove" || cmd == "get" || cmd == "read" { // For ID-oriented commands, pass the current partial argument (lastWord) // so issueIDSuggestions can distinguish between completing the command // name and completing the ID itself. return issueIDSuggestions(lastWord, len(words) >= 2) } // Update/edit: suggest issue IDs when typing the ID, flags after ID is provided if cmd == "update" || cmd == "edit" { if len(words) >= 2 && (lastWord == "" || strings.HasPrefix(lastWord, "-")) { // ID already provided (trailing space) or typing a flag - suggest flags flags := updateFlags if lastWord == "" { return flags } return filterByPrefix(flags, lastWord) } return issueIDSuggestions(lastWord, len(words) >= 2) } var flags []prompt.Suggest switch cmd { case "create", "add": flags = createFlags case "list", "ls", "search": flags = listFlags default: return nil } if lastWord == "" { return flags } return filterByPrefix(flags, lastWord) } func issueIDSuggestions(partial string, hasCommand bool) []prompt.Suggest { // Only show suggestions if we've typed the command already if !hasCommand { return nil } issues, _ := commands.GetIssueCompletions(context.Background(), partial) var suggestions []prompt.Suggest for _, issue := range issues { suggestions = append(suggestions, prompt.Suggest{ Text: issue.ID, Description: truncate.String(issue.Title, 20), }) } return suggestions } func parseWords(words []string, text string) (lastWord, prevWord string) { if len(words) > 0 && !strings.HasSuffix(text, " ") { lastWord = words[len(words)-1] if len(words) >= 2 { prevWord = words[len(words)-2] } } else if len(words) >= 1 { prevWord = words[len(words)-1] } return } func getFlagValues(flag string) []prompt.Suggest { switch flag { case "-s", "--status": return statusValues case "-t", "--type": return typeValues case "-p", "--priority": return priorityValues } return nil } func filterByPrefix(suggestions []prompt.Suggest, prefix string) []prompt.Suggest { if prefix == "" { return suggestions } var filtered []prompt.Suggest for _, s := range suggestions { if strings.HasPrefix(s.Text, prefix) { filtered = append(filtered, s) } } return filtered }