1
0

Initial push

This commit is contained in:
Gürkan 2023-03-17 13:28:36 +01:00
parent 350d9680a2
commit 1347b66ab8
7 changed files with 152 additions and 1 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
oh-my-gpt-correction

View File

@ -1,3 +1,21 @@
# oh-my-gpt-correction
A Zsh helper to auto-correct the current command via ChatGPT
A Zsh helper to auto-correct the current command via ChatGPT.
Just compile the go code to executable. Code is written _badly_ but it does its job:
- Looks for an API key in CHATGPT_API_KEY environment variable
- It accepts one argument, intended to get a whole command inside this argument
- Exit codes are:
- 1: Chat completion error (remote or lib-wise issues)
- 2: No API key given
- 3: Can't find an issue with given command
- 4: No command given
- In case of a suggestion, it prints 2 lines:
- First line is colored diff from original command
- Second line is the original suggestion
- We are catching this output on [ZSH part](./example.zsh) and utilise accordingly
### Demo
![A simple demo](./demo.gif)

BIN
demo.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

44
example.zsh Normal file
View File

@ -0,0 +1,44 @@
export GPT_ERROR_LOGFILE=/tmp/gptresult
export OH_MY_GPT_CORRECTION_PATH=/wherever/you/put/the/executable
export CHATGPT_API_KEY="your_api_key"
gpt-command-line() {
[[ -z $BUFFER ]] && zle up-history
# Run and collect possible errors
GPTRESULTARRAY=("${(@f)$($OH_MY_GPT_CORRECTION_PATH ''$LBUFFER'' 2>> $GPT_ERROR_LOGFILE)}")
# We're using return code
GPTRESCODE="$?"
if [[ $GPTRESCODE = 1 ]]; then
BUFFER="$BUFFER # ❓ChatGPT response error, check /tmp/gptresult"
elif [[ $GPTRESCODE = 2 ]]; then
BUFFER="$BUFFER # 🔑 API key error"
elif [[ $GPTRESCODE = 3 ]]; then
BUFFER="$BUFFER # 🤖 it looks fine to me?"
elif [[ $GPTRESCODE = 4 ]]; then
BUFFER="$BUFFER # ❓No prompt given"
else
# Keep the old buffer for now
OLDBUFFER="${BUFFER}"
zle .reset-prompt
echo
# Ask user
GPTPROMPTTXT=" >🤖 ChatGPT suggest following, does this look better? [y/N]\n
$GPTRESULTARRAY[1]
"
echo -e "$GPTPROMPTTXT"
read -k 1 GPTCHOICEANSWER
if [[ $GPTCHOICEANSWER = y ]]; then
# Replace the current prompt with the suggestion
zle .reset-prompt
BUFFER="${GPTRESULTARRAY[2]} # 🚀"
else
# Reset to old prompt
zle .reset-prompt
BUFFER="${OLDBUFFER} # Restored original buffer"
fi
fi
}
zle -N gpt-command-line
# Defined shortcut key: [Esc] o
bindkey "^[o" gpt-command-line

8
go.mod Normal file
View File

@ -0,0 +1,8 @@
module oh-my-gpt-correction/m/v2
go 1.19
require (
github.com/sashabaranov/go-openai v1.5.2
github.com/sergi/go-diff v1.3.1
)

20
go.sum Normal file
View File

@ -0,0 +1,20 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sashabaranov/go-openai v1.5.2 h1:Gtn5HZEL25//rDDLEX+Anw5FI8TUC6gqIeM9BDBOO18=
github.com/sashabaranov/go-openai v1.5.2/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=

60
oh-my-gpt-correction.go Normal file
View File

@ -0,0 +1,60 @@
package main
import (
"context"
"fmt"
"os"
"regexp"
"strings"
openai "github.com/sashabaranov/go-openai"
"github.com/sergi/go-diff/diffmatchpatch"
)
func main() {
apiKey := os.Getenv("CHATGPT_API_KEY")
query := os.Args[1]
if query == "" {
os.Exit(4)
}
if apiKey == "" {
os.Exit(2)
}
client := openai.NewClient(apiKey)
resp, err := client.CreateChatCompletion(
context.Background(),
openai.ChatCompletionRequest{
Model: openai.GPT3Dot5Turbo,
Messages: []openai.ChatCompletionMessage{
{
Role: openai.ChatMessageRoleUser,
Content: `Please fix typos on the following command line and only return the fixed version as answer.
If given command is correct, just reply with the word "ZOMK", nothing else:
` + query,
},
},
},
)
if err != nil {
fmt.Printf("ChatCompletion error: %v\n", err)
os.Exit(1)
}
result := resp.Choices[0].Message.Content
// No newlines pls
trimmed := regexp.MustCompile(`[\t\r\n]+`).ReplaceAllString(strings.TrimSpace(result), "\n")
if trimmed == "ZOMK" {
os.Exit(3)
}
// Compare query with result
dmp := diffmatchpatch.New()
diffs := dmp.DiffMain(query, trimmed, false)
// Print both lines
fmt.Println(dmp.DiffPrettyText(diffs))
fmt.Println(trimmed)
os.Exit(0)
}