@@ -33,6 +33,7 @@ type Cmd struct {
33
33
Verbose bool `help:"Enables debug output."`
34
34
ContextLimit int `help:"Maximum number of bytes of context to keep. Earlier parts of the conversation are discarded."`
35
35
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"`
36
37
37
38
rl * readline.Instance
38
39
@@ -55,6 +56,7 @@ func NewCmd() *Cmd {
55
56
Model : "gpt-3.5-turbo" ,
56
57
Temperature : 0.7 ,
57
58
ContextLimit : 10000 , // 10,000 bytes ~2000 tokens
59
+ Color : true ,
58
60
59
61
messages : []Message {},
60
62
@@ -82,15 +84,7 @@ func (cmd *Cmd) Run() error {
82
84
}
83
85
84
86
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 ())
94
88
if err != nil {
95
89
return err
96
90
}
@@ -138,7 +132,7 @@ func (cmd *Cmd) sendMessages() error {
138
132
Temperature : cmd .Temperature ,
139
133
Messages : cmd .messagesWithinLimit (),
140
134
}
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 ) })
142
136
if err != nil {
143
137
return err
144
138
}
@@ -286,13 +280,16 @@ func (cmd *Cmd) readMulti(until string) (string, error) {
286
280
func (cmd * Cmd ) Set (param , value string ) error {
287
281
switch param {
288
282
case "ai" :
283
+ if _ , ok := cmd .ais [value ]; ! ok {
284
+ return errors .Errorf ("unknown ai '%s'" , value )
285
+ }
289
286
cmd .AI = value
290
287
case "model" :
291
288
cmd .Model = value
292
- case "temperature" :
289
+ case "temp" , " temperature" :
293
290
temp , err := strconv .ParseFloat (value , 64 )
294
291
if err != nil {
295
- return errors .Wrap (err , "parsing temp value" )
292
+ return errors .Wrapf (err , "parsing '%s' to float" , value )
296
293
}
297
294
cmd .Temperature = temp
298
295
case "verbose" :
@@ -304,12 +301,27 @@ func (cmd *Cmd) Set(param, value string) error {
304
301
default :
305
302
return errors .Errorf ("could not parse '%s' as bool" , value )
306
303
}
307
- case "context-limit " :
304
+ case "context" :
308
305
lim , err := strconv .Atoi (value )
309
306
if err != nil {
310
307
return errors .Wrapf (err , "parsing '%s' to int" , value )
311
308
}
312
309
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
+ }
313
325
default :
314
326
return errors .Errorf ("unknown parameter '%s'" , param )
315
327
}
@@ -349,9 +361,9 @@ func (cmd *Cmd) appendMessage(msg Message) {
349
361
func (cmd * Cmd ) printMessages () {
350
362
for _ , msg := range cmd .messages {
351
363
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 ())
353
365
} 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 ())
355
367
}
356
368
}
357
369
}
@@ -367,16 +379,16 @@ func (cmd *Cmd) out(format string, a ...any) {
367
379
}
368
380
369
381
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 ... )
371
383
}
372
384
373
385
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 ())
375
387
}
376
388
377
389
// errOut wraps the error and writes it to the user on stderr.
378
390
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 ())
380
392
}
381
393
382
394
// checkConfig ensures the command configuration is valid before proceeding.
@@ -393,6 +405,7 @@ func (cmd *Cmd) printConfig() {
393
405
fmt .Fprintf (cmd .stderr , "Temperature: %f\n " , cmd .Temperature )
394
406
fmt .Fprintf (cmd .stderr , "Verbose: %v\n " , cmd .Verbose )
395
407
fmt .Fprintf (cmd .stderr , "ContextLimit: %d\n " , cmd .ContextLimit )
408
+ fmt .Fprintf (cmd .stderr , "Color: %v\n " , cmd .Color )
396
409
}
397
410
398
411
func (cmd * Cmd ) setupConfigDir () error {
@@ -444,13 +457,27 @@ func (cmd *Cmd) readConfigFile() error {
444
457
return nil
445
458
}
446
459
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
+
447
471
// colorWriter wraps an io.Writer and adds color codes
448
472
type colorWriter struct {
449
473
w io.Writer
450
474
color string
451
475
}
452
476
453
477
func (cw * colorWriter ) Write (p []byte ) (n int , err error ) {
478
+ if cw .color == "" {
479
+ return cw .w .Write (p )
480
+ }
454
481
// Write the color code, then the content, then reset
455
482
if _ , err := cw .w .Write ([]byte (cw .color )); err != nil {
456
483
return 0 , err
@@ -462,3 +489,10 @@ func (cw *colorWriter) Write(p []byte) (n int, err error) {
462
489
_ , err = cw .w .Write ([]byte (colorReset ))
463
490
return n , err
464
491
}
492
+
493
+ func (cmd * Cmd ) getColor (col string ) string {
494
+ if ! cmd .Color {
495
+ return ""
496
+ }
497
+ return col
498
+ }
0 commit comments