Refactor store and config handling

- Moved global `store` and `config` variables to cli.go
- Add Fatal() function for outputting an error and exiting
This commit is contained in:
Matt Low 2023-11-04 19:58:48 +00:00
parent 9f75be615e
commit 04478cbbd1
5 changed files with 42 additions and 39 deletions

14
pkg/cli/cli.go Normal file
View File

@ -0,0 +1,14 @@
package cli
import (
"fmt"
"os"
)
var config = InitializeConfig()
var store = InitializeStore()
func Fatal(format string, args ...any) {
fmt.Fprintf(os.Stderr, format, args...)
os.Exit(1)
}

View File

@ -7,22 +7,11 @@ import (
"github.com/spf13/cobra"
)
var config = LoadConfig()
var store, storeError = InitializeStore()
func checkStore() {
if storeError != nil {
fmt.Fprintf(os.Stderr, "Error establishing connection to store: %v\n", storeError)
os.Exit(1)
}
}
var rootCmd = &cobra.Command{
Use: "lm",
Short: "Interact with Large Language Models",
Long: `lm is a CLI tool to interact with OpenAI's GPT 3.5 and GPT 4.`,
Run: func(cmd *cobra.Command, args []string) {
checkStore()
// execute `lm ls` by default
},
}
@ -83,13 +72,13 @@ var newCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
messageContents, err := InputFromEditor("# What would you like to say?", "message.*.md")
if err != nil {
fmt.Fprintf(os.Stderr, "Error receiving message input: %v\n", err)
os.Exit(1)
Fatal("Failed to get input: %v\n", err)
return
}
if messageContents == "" {
fmt.Fprintf(os.Stderr, "No message was provided.\n")
os.Exit(1)
Fatal("No message was provided.\n")
return
}
fmt.Printf("> %s\n", messageContents)
@ -103,8 +92,8 @@ var newCmd = &cobra.Command{
err = CreateChatCompletionStream("You are a helpful assistant.", messages, os.Stdout)
if err != nil {
fmt.Fprintf(os.Stderr, "An error occured: %v\n", err)
os.Exit(1)
Fatal("%v\n", err)
return
}
fmt.Println()
@ -125,8 +114,8 @@ var promptCmd = &cobra.Command{
err := CreateChatCompletionStream("You are a helpful assistant.", messages, os.Stdout)
if err != nil {
fmt.Fprintf(os.Stderr, "An error occured: %v\n", err)
os.Exit(1)
Fatal("%v\n", err)
return
}
fmt.Println()

View File

@ -29,7 +29,7 @@ func getConfigDir() string {
return configDir
}
func LoadConfig() *Config {
func InitializeConfig() *Config {
configFile := filepath.Join(getConfigDir(), "config.yaml")
configBytes, err := os.ReadFile(configFile)
@ -40,8 +40,8 @@ func LoadConfig() *Config {
file, err := os.Create(configFile)
if err != nil {
fmt.Fprintf(os.Stderr, "Could not open config file for writing: %v", err)
os.Exit(1)
Fatal("Could not open config file for writing: %v", err)
return nil
}
fmt.Printf("Writing default configuration to: %s\n", configFile)
@ -50,12 +50,12 @@ func LoadConfig() *Config {
_, err = file.Write(bytes)
if err != nil {
fmt.Fprintf(os.Stderr, "Could not save default configuratoin: %v", err)
os.Exit(1)
Fatal("Could not save default configuratoin: %v", err)
return nil
}
} else if err != nil {
fmt.Fprintf(os.Stderr, "Could not read config file: %v", err)
os.Exit(1)
Fatal("Could not read config file: %v", err)
return nil
}
config := &Config{}

View File

@ -44,11 +44,12 @@ func getDataDir() string {
return dataDir
}
func InitializeStore() (*Store, error) {
func InitializeStore() *Store {
databaseFile := filepath.Join(getDataDir(), "conversations.db")
db, err := gorm.Open(sqlite.Open(databaseFile), &gorm.Config{})
if err != nil {
return nil, err
Fatal("Error establishing connection to store: %v\n", err)
return nil
}
models := []any{
@ -59,15 +60,13 @@ func InitializeStore() (*Store, error) {
for _, x := range(models) {
err := db.AutoMigrate(x)
if err != nil {
return nil, err
Fatal("Could not perform database migrations: %v\n", err)
return nil
}
}
_sqids, _ := sqids.New(sqids.Options{
MinLength: 4,
})
return &Store{db: db, sqids: _sqids}, nil
_sqids, _ := sqids.New(sqids.Options{MinLength: 4})
return &Store{db, _sqids}
}
func (s *Store) SaveConversation(conversation *Conversation) error {

View File

@ -5,11 +5,12 @@ import (
"os/exec"
)
// InputFromEditor retrieves user input by opening an editor on a temporary
// file. Once the editor closes, the contents of the temporary file are
// returned. If the contents exactly match the placeholder (no edits to the
// file were made), then an empty string is returned.
// Example patten: message.*.md
// InputFromEditor retrieves user input by opening an editor (one specified by
// $EDITOR or 'vim' if $EDITOR is not set) on a temporary file. Once the editor
// closes, the contents of the file are read and the file is deleted. If the
// contents of the file exactly match the value of placeholder (no edits to the
// file were made), then an empty string is returned. Otherwise, the contents
// are returned. Example patten: message.*.md
func InputFromEditor(placeholder string, pattern string) (string, error) {
msgFile, _ := os.CreateTemp("/tmp", pattern)
defer os.Remove(msgFile.Name())