on main help sign in
chore(noninteractive): accept a writer for output
389a6abChristian Rocha
internal/app/app.go+4−3
@@ -5,6 +5,7 @@ import (
5 "database/sql"
5 "database/sql"
6 "errors"
6 "errors"
7 "fmt"
7 "fmt"
8+ "io"
8 "log/slog"
9 "log/slog"
9 "sync"
10 "sync"
10 "time"
11 "time"
@@ -103,7 +104,7 @@ func (app *App) Config() *config.Config {
103
104
104// RunNonInteractive runs the application in non-interactive mode with the
105// RunNonInteractive runs the application in non-interactive mode with the
105// given prompt, printing to stdout.
106// given prompt, printing to stdout.
106−func (app *App) RunNonInteractive(ctx context.Context, prompt string, quiet bool) error {
107+func (app *App) RunNonInteractive(ctx context.Context, output io.Writer, prompt string, quiet bool) error {
107 slog.Info("Running in non-interactive mode")
108 slog.Info("Running in non-interactive mode")
108
109
109 ctx, cancel := context.WithCancel(ctx)
110 ctx, cancel := context.WithCancel(ctx)
@@ -170,7 +171,7 @@ func (app *App) RunNonInteractive(ctx context.Context, prompt string, quiet bool
170
171
171 // Always print a newline at the end. If output is a TTY this will
172 // Always print a newline at the end. If output is a TTY this will
172 // prevent the prompt from overwriting the last line of output.
173 // prevent the prompt from overwriting the last line of output.
173− _, _ = fmt.Print('\n')
174+ _, _ = fmt.Fprintln(output)
174 }()
175 }()
175
176
176 for {
177 for {
@@ -204,7 +205,7 @@ func (app *App) RunNonInteractive(ctx context.Context, prompt string, quiet bool
204 }
205 }
205
206
206 part := content[readBytes:]
207 part := content[readBytes:]
207− fmt.Print(part)
208+ fmt.Fprint(output, part)
208 messageReadBytes[msg.ID] = len(content)
209 messageReadBytes[msg.ID] = len(content)
209 }
210 }
210
211
internal/cmd/run.go+8−4
@@ -3,6 +3,7 @@ package cmd
3import (
3import (
4 "fmt"
4 "fmt"
5 "log/slog"
5 "log/slog"
6+ "os"
6 "strings"
7 "strings"
7
8
8 "github.com/spf13/cobra"
9 "github.com/spf13/cobra"
@@ -18,10 +19,13 @@ The prompt can be provided as arguments or piped from stdin.`,
18crush run Explain the use of context in Go
19crush run Explain the use of context in Go
19
20
20# Pipe input from stdin
21# Pipe input from stdin
21−echo "What is this code doing?" | crush run
22+curl https://charm.land | crush run "Summarize this website"
22
23
24+# Read from a file
25+crush run "What is this code doing?" <<< prrr.go
26+
23−# Run with quiet mode (no spinner)
27+# Run in quiet mode (hide the spinner)
24−crush run -q "Generate a README for this project"
28+crush run --quiet "Generate a README for this project"
25 `,
29 `,
26 RunE: func(cmd *cobra.Command, args []string) error {
30 RunE: func(cmd *cobra.Command, args []string) error {
27 quiet, _ := cmd.Flags().GetBool("quiet")
31 quiet, _ := cmd.Flags().GetBool("quiet")
@@ -54,7 +58,7 @@ crush run -q "Generate a README for this project"
54 // echo "Do something fancy" | crush run > output.txt
58 // echo "Do something fancy" | crush run > output.txt
55 //
59 //
56 // TODO: We currently need to press ^c twice to cancel. Fix that.
60 // TODO: We currently need to press ^c twice to cancel. Fix that.
57− return app.RunNonInteractive(cmd.Context(), prompt, quiet)
61+ return app.RunNonInteractive(cmd.Context(), os.Stdout, prompt, quiet)
58 },
62 },
59}
63}
60
64