Skip to content

Commit bb74e88

Browse files
committed
add switch to disable color and fix tests
1 parent bcffe3f commit bb74e88

File tree

2 files changed

+58
-19
lines changed

2 files changed

+58
-19
lines changed

pkg/aicli/cmd.go

+52-18
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ type Cmd struct {
3333
Verbose bool `help:"Enables debug output."`
3434
ContextLimit int `help:"Maximum number of bytes of context to keep. Earlier parts of the conversation are discarded."`
3535
EnableAWS bool `help:"Enable AWS Bedrock as an AI option. Disabled by default because it slows startup time."`
36+
Color bool `help:"Enable colored output"`
3637

3738
rl *readline.Instance
3839

@@ -55,6 +56,7 @@ func NewCmd() *Cmd {
5556
Model: "gpt-3.5-turbo",
5657
Temperature: 0.7,
5758
ContextLimit: 10000, // 10,000 bytes ~2000 tokens
59+
Color: true,
5860

5961
messages: []Message{},
6062

@@ -82,15 +84,7 @@ func (cmd *Cmd) Run() error {
8284
}
8385

8486
var err error
85-
cmd.rl, err = readline.NewEx(&readline.Config{
86-
Prompt: "> ",
87-
HistoryFile: cmd.getHistoryFilePath(),
88-
HistoryLimit: 1000000,
89-
90-
Stdin: cmd.stdin,
91-
Stdout: &colorWriter{w: cmd.stdout, color: colorCyan}, // Color the user input
92-
Stderr: cmd.stderr,
93-
})
87+
cmd.rl, err = readline.NewEx(cmd.getReadlineConfig())
9488
if err != nil {
9589
return err
9690
}
@@ -138,7 +132,7 @@ func (cmd *Cmd) sendMessages() error {
138132
Temperature: cmd.Temperature,
139133
Messages: cmd.messagesWithinLimit(),
140134
}
141-
msg, err := cmd.client().GenerateStream(req, &colorWriter{w: cmd.stdout, color: colorYellow})
135+
msg, err := cmd.client().GenerateStream(req, &colorWriter{w: cmd.stdout, color: cmd.getColor(colorYellow)})
142136
if err != nil {
143137
return err
144138
}
@@ -286,13 +280,16 @@ func (cmd *Cmd) readMulti(until string) (string, error) {
286280
func (cmd *Cmd) Set(param, value string) error {
287281
switch param {
288282
case "ai":
283+
if _, ok := cmd.ais[value]; !ok {
284+
return errors.Errorf("unknown ai '%s'", value)
285+
}
289286
cmd.AI = value
290287
case "model":
291288
cmd.Model = value
292-
case "temperature":
289+
case "temp", "temperature":
293290
temp, err := strconv.ParseFloat(value, 64)
294291
if err != nil {
295-
return errors.Wrap(err, "parsing temp value")
292+
return errors.Wrapf(err, "parsing '%s' to float", value)
296293
}
297294
cmd.Temperature = temp
298295
case "verbose":
@@ -304,12 +301,27 @@ func (cmd *Cmd) Set(param, value string) error {
304301
default:
305302
return errors.Errorf("could not parse '%s' as bool", value)
306303
}
307-
case "context-limit":
304+
case "context":
308305
lim, err := strconv.Atoi(value)
309306
if err != nil {
310307
return errors.Wrapf(err, "parsing '%s' to int", value)
311308
}
312309
cmd.ContextLimit = lim
310+
case "color":
311+
switch strings.ToLower(value) {
312+
case "1", "true", "yes", "on":
313+
cmd.Color = true
314+
case "0", "false", "no", "off":
315+
cmd.Color = false
316+
default:
317+
return errors.Errorf("could not parse '%s' as bool", value)
318+
}
319+
// Update readline config with new color setting
320+
var err error
321+
cmd.rl, err = readline.NewEx(cmd.getReadlineConfig())
322+
if err != nil {
323+
return errors.Wrap(err, "updating readline config")
324+
}
313325
default:
314326
return errors.Errorf("unknown parameter '%s'", param)
315327
}
@@ -349,9 +361,9 @@ func (cmd *Cmd) appendMessage(msg Message) {
349361
func (cmd *Cmd) printMessages() {
350362
for _, msg := range cmd.messages {
351363
if msg.Role() == "user" {
352-
cmd.out(colorCyan+"%9s: %s"+colorReset, msg.Role(), msg.Content())
364+
cmd.out(cmd.getColor(colorCyan)+"%9s: %s"+cmd.getColor(colorReset), msg.Role(), msg.Content())
353365
} else {
354-
cmd.out(colorYellow+"%9s: %s"+colorReset, msg.Role(), msg.Content())
366+
cmd.out(cmd.getColor(colorYellow)+"%9s: %s"+cmd.getColor(colorReset), msg.Role(), msg.Content())
355367
}
356368
}
357369
}
@@ -367,16 +379,16 @@ func (cmd *Cmd) out(format string, a ...any) {
367379
}
368380

369381
func (cmd *Cmd) sysOut(format string, a ...any) {
370-
fmt.Fprintf(cmd.stdout, colorBlue+format+colorReset+"\n", a...)
382+
fmt.Fprintf(cmd.stdout, cmd.getColor(colorBlue)+format+cmd.getColor(colorReset)+"\n", a...)
371383
}
372384

373385
func (cmd *Cmd) err(err error) {
374-
fmt.Fprintf(cmd.stderr, colorRed+"%s"+colorReset+"\n", err.Error())
386+
fmt.Fprintf(cmd.stderr, cmd.getColor(colorRed)+"%s"+cmd.getColor(colorReset)+"\n", err.Error())
375387
}
376388

377389
// errOut wraps the error and writes it to the user on stderr.
378390
func (cmd *Cmd) errOut(err error, format string, a ...any) {
379-
fmt.Fprintf(cmd.stderr, colorRed+"%s: %v"+colorReset+"\n", fmt.Sprintf(format, a...), err.Error())
391+
fmt.Fprintf(cmd.stderr, cmd.getColor(colorRed)+"%s: %v"+cmd.getColor(colorReset)+"\n", fmt.Sprintf(format, a...), err.Error())
380392
}
381393

382394
// checkConfig ensures the command configuration is valid before proceeding.
@@ -393,6 +405,7 @@ func (cmd *Cmd) printConfig() {
393405
fmt.Fprintf(cmd.stderr, "Temperature: %f\n", cmd.Temperature)
394406
fmt.Fprintf(cmd.stderr, "Verbose: %v\n", cmd.Verbose)
395407
fmt.Fprintf(cmd.stderr, "ContextLimit: %d\n", cmd.ContextLimit)
408+
fmt.Fprintf(cmd.stderr, "Color: %v\n", cmd.Color)
396409
}
397410

398411
func (cmd *Cmd) setupConfigDir() error {
@@ -444,13 +457,27 @@ func (cmd *Cmd) readConfigFile() error {
444457
return nil
445458
}
446459

460+
func (cmd *Cmd) getReadlineConfig() *readline.Config {
461+
return &readline.Config{
462+
Prompt: "> ",
463+
HistoryFile: cmd.getHistoryFilePath(),
464+
HistoryLimit: 1000000,
465+
Stdin: cmd.stdin,
466+
Stdout: &colorWriter{w: cmd.stdout, color: cmd.getColor(colorCyan)},
467+
Stderr: cmd.stderr,
468+
}
469+
}
470+
447471
// colorWriter wraps an io.Writer and adds color codes
448472
type colorWriter struct {
449473
w io.Writer
450474
color string
451475
}
452476

453477
func (cw *colorWriter) Write(p []byte) (n int, err error) {
478+
if cw.color == "" {
479+
return cw.w.Write(p)
480+
}
454481
// Write the color code, then the content, then reset
455482
if _, err := cw.w.Write([]byte(cw.color)); err != nil {
456483
return 0, err
@@ -462,3 +489,10 @@ func (cw *colorWriter) Write(p []byte) (n int, err error) {
462489
_, err = cw.w.Write([]byte(colorReset))
463490
return n, err
464491
}
492+
493+
func (cmd *Cmd) getColor(col string) string {
494+
if !cmd.Color {
495+
return ""
496+
}
497+
return col
498+
}

pkg/aicli/cmd_test.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package aicli
22

33
import (
4+
"fmt"
45
"io"
56
"testing"
67
"time"
@@ -11,6 +12,7 @@ import (
1112
func TestCmd(t *testing.T) {
1213
cmd := NewCmd()
1314
cmd.AI = "echo"
15+
cmd.Color = false
1416
cmd.AddAI("echo", &Echo{})
1517
stdinr, stdinw := io.Pipe()
1618
stdout, stdoutw := io.Pipe()
@@ -25,6 +27,9 @@ func TestCmd(t *testing.T) {
2527
var runErr error
2628
go func() {
2729
runErr = cmd.Run()
30+
if runErr != nil {
31+
fmt.Printf("error: %v\n", runErr)
32+
}
2833
close(done)
2934
}()
3035

@@ -42,7 +47,7 @@ func TestCmd(t *testing.T) {
4247
write(t, stdinw, []byte("\\reset\n"))
4348
require.NoError(t, runErr)
4449
write(t, stdinw, []byte("\\config\n"))
45-
expect(t, stderr, []byte("AI: echo\nModel: gpt-3.5-turbo\nTemperature: 0.700000\nVerbose: false\nContextLimit: 10000\n"))
50+
expect(t, stderr, []byte("AI: echo\nModel: gpt-3.5-turbo\nTemperature: 0.700000\nVerbose: false\nContextLimit: 10000\nColor: false\n"))
4651
write(t, stdinw, []byte("\\reset\n"))
4752
write(t, stdinw, []byte("\\file ./testdata/myfile\n"))
4853
write(t, stdinw, []byte("\\messages\n"))

0 commit comments

Comments
 (0)