package main import ( "github.com/elk-language/go-prompt" "slices" "strings" ) type Action func(args []string) type CommandArg struct { Name string Action Action Help string Children []CommandArg } var commandIssues = CommandArg{Name: "issues"} func option(name string, children ...CommandArg) CommandArg { return command(name, nil, children...) } func command(name string, action Action, children ...CommandArg) CommandArg { return CommandArg{ Name: name, Action: action, Children: children, } } func (arg CommandArg) WithHelp(help string) CommandArg { arg.Help = help return arg } var CommandTree = []CommandArg{ option("list", command("issues", ActionListIssues).WithHelp("List all issues in the current sprint"), command("boards", ActionListBoards).WithHelp("List all boards in the current project"), //command("sprints", ActionListIssues).WithHelp("List all issues in the current sprint"), //option("open", option("issues")), //option("closed", option("issues")), command("projects", ActionListProjects).WithHelp("List all projects"), ).WithHelp("List things"), option("use", command("project", ActionUseProject).WithHelp("Use project [project key]"), command("board", ActionUseBoard).WithHelp("Use board [board id]"), option("current", command("sprint", ActionUseCurrentSprint).WithHelp("Use the current sprint")), command("issue", ActionUseIssue).WithHelp("Use issue [issue id]"), option("my", command("issue", ActionUseMyIssue).WithHelp("Use an issue assigned to me")), ).WithHelp("Select something for further commands"), option("view", command("card", ActionViewCard).WithHelp("View general information about the issue"), command("description", ActionViewDescription).WithHelp("View description of a issue"), command("comments", ActionViewComments).WithHelp("View comments of an issue"), ).WithHelp("View data about something"), option("set", command("status", ActionSetStatus).WithHelp("Set status of a ticket"), command("title", ActionSetTitle).WithHelp("Set the title of a ticket"), ).WithHelp("Change something"), command("exit", ActionExit).WithHelp("Exit jirashell"), command("logout", ActionLogout).WithHelp("Logout from Jira"), command("back", ActionBack).WithHelp("Go back"), } func getCommandFor(parts []string, tree []CommandArg) (*CommandArg, []string) { for _, arg := range tree { if arg.Name == parts[0] { if len(parts) == 1 { return &arg, []string{} } else { result, args := getCommandFor(parts[1:], arg.Children) if result != nil { return result, args } else { return &arg, parts[1:] } } } } return nil, nil } func GetCommand(cmdline string) (*CommandArg, []string) { commandParts := strings.Split(cmdline, " ") command, args := getCommandFor(commandParts, CommandTree) if command == nil || command.Action == nil { return nil, nil } return command, args } func GetSuggestionsForPart(parts []string, tree []CommandArg, suggests []prompt.Suggest) []prompt.Suggest { for _, option := range tree { if len(parts) == 0 { suggests = append(suggests, prompt.Suggest{ Text: option.Name, Description: option.Help, }) } else if option.Name == parts[0] { suggests = GetSuggestionsForPart(parts[1:], option.Children, suggests) } else if len(parts) == 1 { if strings.HasPrefix(option.Name, parts[0]) { suggests = append(suggests, prompt.Suggest{ Text: option.Name, Description: option.Help, }) } } } return suggests } func GetSuggestionsFor(command string) []prompt.Suggest { commandParts := strings.Split(command, " ") suggestions := GetSuggestionsForPart(commandParts, CommandTree, []prompt.Suggest{}) slices.SortFunc(suggestions, func(a, b prompt.Suggest) int { return strings.Compare(a.Text, b.Text) }) return suggestions }