Skip to content

Commit

Permalink
.aicli directory containing history and config
Browse files Browse the repository at this point in the history
now you can set a system message in the config file so it gets set at startup

also fixd races in the tests, using pipe instead of buffer
  • Loading branch information
jaffee committed Nov 15, 2023
1 parent ce2c5aa commit 5b17674
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 16 deletions.
55 changes: 50 additions & 5 deletions pkg/aicli/cmd.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package aicli

import (
"bufio"
"fmt"
"io"
"os"
Expand All @@ -27,6 +28,7 @@ type Cmd struct {
stdout io.Writer
stderr io.Writer

dotAICLIDir string
historyPath string

client AI
Expand Down Expand Up @@ -56,6 +58,12 @@ func (cmd *Cmd) Run() error {
if err := cmd.checkConfig(); err != nil {
return errors.Wrap(err, "checking config")
}
if err := cmd.setupConfigDir(); err != nil {
return errors.Wrap(err, "setting up config dir")
}
if err := cmd.readConfigFile(); err != nil {
return errors.Wrap(err, "reading config file")
}

rl, err := readline.NewEx(&readline.Config{
Prompt: "> ",
Expand Down Expand Up @@ -207,14 +215,51 @@ func (cmd *Cmd) printConfig() {
fmt.Fprintf(cmd.stderr, "Verbose: %v\n", cmd.Verbose)
}

func (cmd *Cmd) setupConfigDir() error {
if cmd.dotAICLIDir != "" {
return nil
}
home, err := os.UserHomeDir()
if err != nil {
return err
}
path := filepath.Join(home, ".aicli")
if err := os.MkdirAll(path, 0755); err != nil {
return err
}
cmd.dotAICLIDir = path
return nil
}

func (cmd *Cmd) getHistoryFilePath() string {
if cmd.historyPath != "" {
return cmd.historyPath
}
home, err := os.UserHomeDir()
if err != nil {
// if we can't get a home dir, we'll use the local directory
return ".aicli_history"
return filepath.Join(cmd.dotAICLIDir, "history")
}

func (cmd *Cmd) readConfigFile() error {
path := filepath.Join(cmd.dotAICLIDir, "config")
f, err := os.Open(path)
if os.IsNotExist(err) {
return nil
} else if err != nil {
return errors.Wrap(err, "opening file")
}
return filepath.Join(home, ".aicli_history")
sc := bufio.NewScanner(f)
for sc.Scan() {
line := sc.Text()
if len(line) == 0 {
continue
}
if isMeta(line) {
cmd.handleMeta(line)
continue
} else if line[0] == '#' {
continue
} else {
return err
}
}
return nil
}
24 changes: 13 additions & 11 deletions pkg/aicli/cmd_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package aicli

import (
"bytes"
"io"
"testing"
"time"
Expand All @@ -12,13 +11,13 @@ import (
func TestCmd(t *testing.T) {
cmd := NewCmd(&Echo{})
stdinr, stdinw := io.Pipe()
stdout := &bytes.Buffer{}
stderr := &bytes.Buffer{}
stdout, stdoutw := io.Pipe()
stderr, stderrw := io.Pipe()

cmd.stdin = stdinr
cmd.stdout = stdout
cmd.stderr = stderr
cmd.historyPath = t.TempDir() + "/.aicli_history"
cmd.stdout = stdoutw
cmd.stderr = stderrw
cmd.dotAICLIDir = t.TempDir()
cmd.OpenAIAPIKey = "blah"

done := make(chan struct{})
Expand All @@ -27,8 +26,9 @@ func TestCmd(t *testing.T) {
runErr = cmd.Run()
close(done)
}()

time.Sleep(time.Millisecond)
require.NoError(t, runErr)
// expect(t, stdout, []byte{0x20, 0x08, 0x1b, 0x5b, 0x36, 0x6e, 0x3e, 0x20})
_, _ = stdinw.Write([]byte("blah\n"))
require.NoError(t, runErr)
expect(t, stdout, []byte("blah\n"))
Expand Down Expand Up @@ -64,22 +64,24 @@ func expect(t *testing.T, r io.Reader, exp []byte) {
t.Helper()
buffer := make([]byte, len(exp)*20)
i := 0
var tot int
var n int
var err error
for {
i++
n, err = r.Read(buffer)
n, err = r.Read(buffer[tot:])
if err != nil && err.Error() != "EOF" {
require.NoError(t, err)
}
if n > 0 {
tot += n
if tot >= len(exp) {
break
}
if i > 100 {
if i > 20 {
t.Fatal("spent too long waiting for output")
}
time.Sleep(time.Millisecond)
}

require.Equal(t, exp, buffer[:n])
require.Equal(t, exp, buffer[:tot])
}

0 comments on commit 5b17674

Please sign in to comment.