make repl submit each command
This commit is contained in:
@@ -8,7 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// execute processes the input command and returns the output
|
// execute processes the input command and returns the output
|
||||||
func execute(input string) (string, error) {
|
func (r *REPL) execute(input string) (string, error) {
|
||||||
if input == "" {
|
if input == "" {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,10 +29,11 @@ Type 'status' to check task progress.`
|
|||||||
)
|
)
|
||||||
|
|
||||||
type REPL struct {
|
type REPL struct {
|
||||||
feedbackChan chan ValidationFeedback
|
feedbackChan chan ValidationFeedback
|
||||||
quitChan chan bool
|
quitChan chan bool
|
||||||
submitChan chan<- struct{}
|
submitChan chan<- struct{}
|
||||||
app *App
|
completionChan chan struct{}
|
||||||
|
app *App
|
||||||
|
|
||||||
currentFeedback ValidationFeedback
|
currentFeedback ValidationFeedback
|
||||||
exitRequested bool
|
exitRequested bool
|
||||||
@@ -49,6 +50,7 @@ func (r *REPL) Run(ctx context.Context, config app.Config) error {
|
|||||||
r.taskCompleted = false
|
r.taskCompleted = false
|
||||||
r.exitRequested = false
|
r.exitRequested = false
|
||||||
r.currentFeedback = ValidationFeedback{}
|
r.currentFeedback = ValidationFeedback{}
|
||||||
|
r.completionChan = make(chan struct{}, 1)
|
||||||
|
|
||||||
// Set terminal to raw mode to capture input properly in the REPL.
|
// Set terminal to raw mode to capture input properly in the REPL.
|
||||||
// This allows us to handle input character by character and provide a better user experience.
|
// This allows us to handle input character by character and provide a better user experience.
|
||||||
@@ -89,28 +91,33 @@ func (r *REPL) Run(ctx context.Context, config app.Config) error {
|
|||||||
|
|
||||||
// Start the REPL loop, which continues until the user types "exit" or "quit" or task completes.
|
// Start the REPL loop, which continues until the user types "exit" or "quit" or task completes.
|
||||||
reader := bufio.NewReader(os.Stdin)
|
reader := bufio.NewReader(os.Stdin)
|
||||||
|
replLoop:
|
||||||
for !r.exitRequested {
|
for !r.exitRequested {
|
||||||
// Check if task completed - wait for Enter before exiting
|
|
||||||
if r.taskCompleted {
|
|
||||||
fmt.Println(style.TitleStyle.Render("Task completed successfully!"))
|
|
||||||
fmt.Print("Press Enter to exit...")
|
|
||||||
// Restore terminal to normal mode for input
|
|
||||||
term.Restore(int(os.Stdin.Fd()), oldState)
|
|
||||||
reader.ReadString('\n')
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we should exit before prompting (non-blocking check)
|
// Check if we should exit before prompting (non-blocking check)
|
||||||
if r.exitRequested {
|
if r.exitRequested {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prompt the user for input, and provide suggestions.
|
// Prompt the user for input, and provide suggestions.
|
||||||
input := prompt.Input(
|
inputChan := make(chan string, 1)
|
||||||
PromptPrefix,
|
go func(hist []string) {
|
||||||
completer,
|
inputChan <- prompt.Input(
|
||||||
promptOptions(history)...,
|
PromptPrefix,
|
||||||
)
|
completer,
|
||||||
|
promptOptions(hist)...,
|
||||||
|
)
|
||||||
|
}(history)
|
||||||
|
|
||||||
|
var input string
|
||||||
|
select {
|
||||||
|
case input = <-inputChan:
|
||||||
|
case <-r.completionChan:
|
||||||
|
fmt.Println(style.TitleStyle.Render("Task completed successfully!"))
|
||||||
|
fmt.Print("Press Enter to exit...")
|
||||||
|
term.Restore(int(os.Stdin.Fd()), oldState)
|
||||||
|
reader.ReadString('\n')
|
||||||
|
break replLoop
|
||||||
|
}
|
||||||
|
|
||||||
// Check again after prompt returns (in case validation completed while waiting)
|
// Check again after prompt returns (in case validation completed while waiting)
|
||||||
if r.exitRequested {
|
if r.exitRequested {
|
||||||
@@ -118,15 +125,6 @@ func (r *REPL) Run(ctx context.Context, config app.Config) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if task completed while waiting at prompt
|
// Check if task completed while waiting at prompt
|
||||||
if r.taskCompleted {
|
|
||||||
fmt.Println(style.TitleStyle.Render("Task completed successfully!"))
|
|
||||||
fmt.Print("Press Enter to exit...")
|
|
||||||
// Restore terminal to normal mode for input
|
|
||||||
term.Restore(int(os.Stdin.Fd()), oldState)
|
|
||||||
reader.ReadString('\n')
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trim whitespace from the input to ensure consistent command processing.
|
// Trim whitespace from the input to ensure consistent command processing.
|
||||||
input = strings.TrimSpace(input)
|
input = strings.TrimSpace(input)
|
||||||
|
|
||||||
@@ -144,7 +142,16 @@ func (r *REPL) Run(ctx context.Context, config app.Config) error {
|
|||||||
// Add the input to the history for future navigation.
|
// Add the input to the history for future navigation.
|
||||||
history = append(history, input)
|
history = append(history, input)
|
||||||
|
|
||||||
output, err := execute(input)
|
output, err := r.execute(input)
|
||||||
|
|
||||||
|
// Send submit signal to trigger validation after any command
|
||||||
|
if r.submitChan != nil {
|
||||||
|
select {
|
||||||
|
case r.submitChan <- struct{}{}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Show command output (even on error) in normal text style
|
// Show command output (even on error) in normal text style
|
||||||
if output != "" {
|
if output != "" {
|
||||||
@@ -177,6 +184,12 @@ func (r *REPL) watchValidation() {
|
|||||||
}
|
}
|
||||||
if feedback.Success {
|
if feedback.Success {
|
||||||
r.taskCompleted = true
|
r.taskCompleted = true
|
||||||
|
if r.completionChan != nil {
|
||||||
|
select {
|
||||||
|
case r.completionChan <- struct{}{}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case <-r.quitChan:
|
case <-r.quitChan:
|
||||||
|
|||||||
Reference in New Issue
Block a user