align repl with cli
This commit is contained in:
@@ -27,4 +27,5 @@ var (
|
||||
TitleStyle = lipgloss.NewStyle().Foreground(PrimaryColor).Bold(true)
|
||||
TextStyle = lipgloss.NewStyle().Foreground(TextColor)
|
||||
HelpStyle = lipgloss.NewStyle().Align(lipgloss.Center).Foreground(AccentColor)
|
||||
ErrorStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("1")).Bold(true) // Red color for errors
|
||||
)
|
||||
|
||||
@@ -21,14 +21,70 @@ func execute(input string) (string, error) {
|
||||
return ReplTitle, nil
|
||||
}
|
||||
|
||||
if input == "status" {
|
||||
return executePMCommand("survey status")
|
||||
}
|
||||
|
||||
if after, ok := strings.CutPrefix(input, "pm"); ok {
|
||||
return executePMCommand(after)
|
||||
}
|
||||
return executeShellCommand(input)
|
||||
}
|
||||
|
||||
// shellSplit splits input respecting quoted strings and escapes
|
||||
// similar to how a shell would parse arguments
|
||||
func shellSplit(input string) []string {
|
||||
var args []string
|
||||
var current strings.Builder
|
||||
var inQuote rune
|
||||
var escaped bool
|
||||
|
||||
for _, ch := range input {
|
||||
if escaped {
|
||||
current.WriteRune(ch)
|
||||
escaped = false
|
||||
continue
|
||||
}
|
||||
|
||||
if ch == '\\' {
|
||||
escaped = true
|
||||
continue
|
||||
}
|
||||
|
||||
if inQuote != 0 {
|
||||
if ch == inQuote {
|
||||
inQuote = 0
|
||||
continue
|
||||
}
|
||||
current.WriteRune(ch)
|
||||
continue
|
||||
}
|
||||
|
||||
if ch == '"' || ch == '\'' {
|
||||
inQuote = ch
|
||||
continue
|
||||
}
|
||||
|
||||
if ch == ' ' || ch == '\t' {
|
||||
if current.Len() > 0 {
|
||||
args = append(args, current.String())
|
||||
current.Reset()
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
current.WriteRune(ch)
|
||||
}
|
||||
|
||||
if current.Len() > 0 {
|
||||
args = append(args, current.String())
|
||||
}
|
||||
|
||||
return args
|
||||
}
|
||||
|
||||
func executeShellCommand(input string) (string, error) {
|
||||
parts := strings.Fields(input)
|
||||
parts := shellSplit(input)
|
||||
if len(parts) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
@@ -39,7 +95,7 @@ func executeShellCommand(input string) (string, error) {
|
||||
}
|
||||
|
||||
func executePMCommand(input string) (string, error) {
|
||||
parts := strings.Fields(input)
|
||||
parts := shellSplit(input)
|
||||
if len(parts) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
@@ -22,8 +22,8 @@ type ValidationFeedback = models.ValidationFeedback
|
||||
|
||||
const (
|
||||
ReplHelp = `Type 'pm help' for available PM commands.
|
||||
Type 'pm status' to check task progress.
|
||||
You can also run shell commands directly. Type 'exit' or 'quit' to leave.`
|
||||
You can also run shell commands directly. Type 'exit' or 'quit' to leave.
|
||||
Type 'status' to check task progress.`
|
||||
|
||||
ReplTitle = "Welcome to Project Management CLI! " + ReplHelp
|
||||
)
|
||||
@@ -144,8 +144,19 @@ func (r *REPL) Run(ctx context.Context, config app.Config) error {
|
||||
// Add the input to the history for future navigation.
|
||||
history = append(history, input)
|
||||
|
||||
output, _ := execute(input) // Ignore errors for now, gives better ux
|
||||
fmt.Println(style.TextStyle.Render(output)) // Print the output of the command in a styled format.
|
||||
output, err := execute(input)
|
||||
if err != nil {
|
||||
// Show command output (even on error) in normal text style
|
||||
if output != "" {
|
||||
fmt.Println(style.TextStyle.Render(output))
|
||||
}
|
||||
// Show error message in red if no output was captured
|
||||
if output == "" {
|
||||
fmt.Println(style.ErrorStyle.Render(err.Error()))
|
||||
}
|
||||
} else if output != "" {
|
||||
fmt.Println(style.TextStyle.Render(output))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
// rootSuggestions is a list of prompt suggestions for root-level commands.
|
||||
var rootSuggestions = []prompt.Suggest{
|
||||
{Text: "pm", Description: "Project Management System"},
|
||||
{Text: "status", Description: "Show task status"},
|
||||
{Text: "exit", Description: "Exit pm CLI"},
|
||||
{Text: "help", Description: "Show help information"},
|
||||
{Text: "title", Description: "Print the welcome title"},
|
||||
@@ -38,7 +39,8 @@ 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)"},
|
||||
{Text: "--priority", Description: "Issue priority (0-4)"},
|
||||
{Text: "--assignee", Description: "Issue assignee"},
|
||||
}
|
||||
|
||||
// updateFlags is a list of prompt suggestions for the update command flags.
|
||||
@@ -47,7 +49,8 @@ var updateFlags = []prompt.Suggest{
|
||||
{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)"},
|
||||
{Text: "--priority", Description: "New issue priority (0-4)"},
|
||||
{Text: "--assignee", Description: "New issue assignee"},
|
||||
}
|
||||
|
||||
// listFlags is a list of prompt suggestions for the list command flags.
|
||||
@@ -56,8 +59,9 @@ var listFlags = []prompt.Suggest{
|
||||
{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: "--priority", Description: "Filter by priority (0-4)"},
|
||||
{Text: "--limit", Description: "Limit number of results"},
|
||||
{Text: "--assignee", Description: "Filter by assignee"},
|
||||
}
|
||||
|
||||
var deleteFlags = []prompt.Suggest{
|
||||
@@ -81,18 +85,19 @@ var statusValues = []prompt.Suggest{
|
||||
|
||||
// typeValues is a list of prompt suggestions for issue types
|
||||
var typeValues = []prompt.Suggest{
|
||||
{Text: "task", Description: "Task issue type"},
|
||||
{Text: "bug", Description: "Bug issue type"},
|
||||
{Text: "feature", Description: "Feature issue type"},
|
||||
{Text: "task", Description: "Task issue type"},
|
||||
{Text: "chore", Description: "Chore issue type"},
|
||||
}
|
||||
|
||||
// priorityValues is a list of prompt suggestions for issue priority levels
|
||||
var priorityValues = []prompt.Suggest{
|
||||
{Text: "0", Description: "Lowest priority"},
|
||||
{Text: "0", Description: "Irrelevant"},
|
||||
{Text: "1", Description: "Low priority"},
|
||||
{Text: "2", Description: "Medium-low priority"},
|
||||
{Text: "3", Description: "Medium priority"},
|
||||
{Text: "4", Description: "High priority"},
|
||||
{Text: "2", Description: "Normal priority"},
|
||||
{Text: "3", Description: "High priority"},
|
||||
{Text: "4", Description: "Critical priority"},
|
||||
}
|
||||
|
||||
// isIDCommand maps command names to a boolean indicating whether they expect an issue ID as an argument.
|
||||
|
||||
Reference in New Issue
Block a user