Compare commits

...

20 Commits

Author SHA1 Message Date
asrul10
d11017d792 Merge pull request #12 from asrul10/feat/read-file
feat: read file and add to prompt
2024-02-08 12:00:21 +07:00
asrul10
1c4113d0c2 feat: read file and add to prompt 2024-02-08 11:57:25 +07:00
asrul10
00b2ea6614 Merge pull request #10 from asrul10/feat/copy-clipboard
(feat) Copy to clipboard
2023-12-19 10:12:35 +07:00
asrul10
9538b0fed5 feat: copy to clipboard 2023-12-19 10:09:26 +07:00
asrul10
5141cb69a3 update 2023-12-19 09:30:22 +07:00
asrul10
ae90ef6cfb Merge pull request #8 from asrul10/feature/regenerate-gpt
Add a feature to regenerate the result and some minor improvements
2023-04-09 10:56:43 +07:00
asrul10
7f81b1942b style: update version 2023-04-09 10:54:35 +07:00
asrul10
dafcaaff0f docs: update example result 2023-04-09 10:53:11 +07:00
asrul10
fbb68d2a28 feat: add regenerate options 2023-04-09 10:51:26 +07:00
asrul10
2d6fef23aa chore: set default options to (N)o execute 2023-04-09 10:33:53 +07:00
asrul10
432bfc61db feat: add example usage if there is no option 2023-04-09 10:30:13 +07:00
asrul10
0e50c8ec04 feat: remove borders to make it easy to copy 2023-04-09 10:25:50 +07:00
asrul10
148e1d9420 fix: box result 2023-03-25 22:26:38 +07:00
asrul10
952eee1a29 docs: fix link 2023-03-12 16:20:23 +07:00
asrul10
c2619a2864 docs: add executable link 2023-03-12 16:13:01 +07:00
asrul10
b1166a724d Merge pull request #1 from asrul10/workflow
Add github actions for release
2023-03-12 16:04:27 +07:00
asrul10
c6b1474117 chore: add github actions 2023-03-12 16:01:18 +07:00
asrul10
b04f7016b8 fix: remove precompiled file 2023-03-12 14:36:12 +07:00
asrul10
4f52b5bbad docs: add LICENSE 2023-03-12 06:48:21 +07:00
asrul10
dce4360043 fix: blocking loading when input api key 2023-03-12 06:27:03 +07:00
11 changed files with 209 additions and 61 deletions

31
.github/workflows/release.yaml vendored Normal file
View File

@@ -0,0 +1,31 @@
name: basebuild
on:
pull_request:
push:
jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: '>=1.18.0'
- name: Run tests
run: go test ./...
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v3
with:
distribution: goreleaser
version: latest
args: release --rm-dist
env:
GITHUB_TOKEN: ${{ secrets.TOKEN }}

2
.gitignore vendored
View File

@@ -8,4 +8,4 @@
go.work
*.log
lcg
dist/

33
.goreleaser.yaml Normal file
View File

@@ -0,0 +1,33 @@
archives:
- format: tar.gz
builds:
- binary: lcg
env:
- CGO_ENABLED=0
goarch:
- amd64
- arm64
- arm
goos:
- linux
- darwin
changelog:
filters:
exclude:
- '^docs:'
- '^test:'
sort: asc
checksum:
name_template: 'checksums.txt'
release:
draft: true
snapshot:
name_template: "{{ incpatch .Version }}-next"
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
# vim: set ts=2 sw=2 tw=0 fo=cnqoj

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 asrul10
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -11,23 +11,28 @@ Build from source
> ln -s ~/.linux-command-gpt/lcg ~/.local/bin
```
Or you can [download lcg executable file](https://github.com/asrul10/linux-command-gpt/releases)
### Example Usage
```bash
> lcg I want to extract file linux-command-gpt.tar.gz
> lcg I want to extract linux-command-gpt.tar.gz file
Completed in 0.92 seconds
┌────────────────────────────────────┐
tar -xvzf linux-command-gpt.tar.gz
└────────────────────────────────────┘
Are you sure you want to execute the command? (Y/n):
tar -xvzf linux-command-gpt.tar.gz
Do you want to (c)opy, (r)egenerate, or take (N)o action on the command? (c/r/N):
```
To use the "copy to clipboard" feature, you need to install either the `xclip` or `xsel` package.
### Options
```bash
> lcg [options]
--help output usage information
--version output the version number
--update-key update the API key
--delete-key delete the API key
--help -h output usage information
--version -v output the version number
--file -f read command from file
--update-key -u update the API key
--delete-key -d delete the API key
```

2
go.mod
View File

@@ -1,3 +1,5 @@
module github.com/asrul/linux-command-gpt
go 1.18
require github.com/atotto/clipboard v0.1.4

2
go.sum Normal file
View File

@@ -0,0 +1,2 @@
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=

View File

@@ -4,7 +4,7 @@ import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"io"
"net/http"
"os"
"path/filepath"
@@ -88,7 +88,7 @@ func (gpt3 *Gpt3) loadApiKey() bool {
if _, err := os.Stat(apiKeyFile); os.IsNotExist(err) {
return false
}
apiKey, err := ioutil.ReadFile(apiKeyFile)
apiKey, err := os.ReadFile(apiKeyFile)
if err != nil {
return false
}
@@ -144,7 +144,7 @@ func (gpt3 *Gpt3) Completions(ask string) string {
if err != nil {
panic(err)
}
req.Body = ioutil.NopCloser(bytes.NewBuffer(payloadJson))
req.Body = io.NopCloser(bytes.NewBuffer(payloadJson))
client := &http.Client{}
resp, err := client.Do(req)
@@ -153,7 +153,7 @@ func (gpt3 *Gpt3) Completions(ask string) string {
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}

Binary file not shown.

124
main.go
View File

@@ -4,12 +4,13 @@ import (
"fmt"
"math"
"os"
"os/exec"
"os/user"
"strings"
"time"
"github.com/asrul/linux-command-gpt/gpt"
"github.com/asrul/linux-command-gpt/reader"
"github.com/atotto/clipboard"
)
const (
@@ -26,14 +27,17 @@ const (
Usage: lcg [options]
--help output usage information
--version output the version number
--update-key update the API key
--delete-key delete the API key
--help -h output usage information
--version -v output the version number
--file -f read command from file
--update-key -u update the API key
--delete-key -d delete the API key
Example Usage: lcg I want to extract linux-command-gpt.tar.gz file
Example Usage: lcg --file /path/to/file.json I want to print object questions with jq
`
VERSION = "0.1.0"
VERSION = "0.2.1"
CMD_HELP = 100
CMD_VERSION = 101
CMD_UPDATE = 102
@@ -57,6 +61,37 @@ func handleCommand(cmd string) int {
return CMD_COMPLETION
}
func getCommand(gpt3 gpt.Gpt3, cmd string) (string, float64) {
gpt3.InitKey()
s := time.Now()
done := make(chan bool)
go func() {
loadingChars := []rune{'-', '\\', '|', '/'}
i := 0
for {
select {
case <-done:
fmt.Printf("\r")
return
default:
fmt.Printf("\rLoading %c", loadingChars[i])
i = (i + 1) % len(loadingChars)
time.Sleep(30 * time.Millisecond)
}
}
}()
r := gpt3.Completions(cmd)
done <- true
elapsed := time.Since(s).Seconds()
elapsed = math.Round(elapsed*100) / 100
if r == "" {
return "", elapsed
}
return r, elapsed
}
func main() {
currentUser, err := user.Current()
if err != nil {
@@ -65,9 +100,24 @@ func main() {
args := os.Args
cmd := ""
file := ""
if len(args) > 1 {
cmd = strings.Join(args[1:], " ")
start := 1
if args[1] == "--file" || args[1] == "-f" {
file = args[2]
start = 3
}
cmd = strings.Join(args[start:], " ")
}
if file != "" {
err := reader.FileToPrompt(&cmd, file)
if err != nil {
fmt.Println(err)
return
}
}
h := handleCommand(cmd)
if h == CMD_HELP {
@@ -98,51 +148,31 @@ func main() {
return
}
s := time.Now()
done := make(chan bool)
go func() {
loadingChars := []rune{'-', '\\', '|', '/'}
i := 0
for {
select {
case <-done:
fmt.Printf("\r")
return
default:
fmt.Printf("\rLoading %c", loadingChars[i])
i = (i + 1) % len(loadingChars)
time.Sleep(30 * time.Millisecond)
}
}
}()
c := "R"
r := ""
elapsed := 0.0
for c == "R" || c == "r" {
r, elapsed = getCommand(gpt3, cmd)
c = "N"
fmt.Printf("Completed in %v seconds\n\n", elapsed)
fmt.Println(r)
fmt.Print("\nDo you want to (c)opy, (r)egenerate, or take (N)o action on the command? (c/r/N): ")
fmt.Scanln(&c)
// No action
if c == "N" || c == "n" {
return
}
}
gpt3.InitKey()
r := gpt3.Completions(cmd)
done <- true
if r == "" {
return
}
c := "Y"
elapsed := time.Since(s).Seconds()
elapsed = math.Round(elapsed*100) / 100
fmt.Printf("Completed in %v seconds\n", elapsed)
fmt.Printf("┌%s┐\n", strings.Repeat("─", len(r)+2))
fmt.Printf("│ %s │\n", r)
fmt.Printf("└%s┘\n", strings.Repeat("─", len(r)+2))
fmt.Print("Are you sure you want to execute the command? (Y/n): ")
fmt.Scanln(&c)
if c != "Y" && c != "y" {
// Copy to clipboard
if c == "C" || c == "c" {
clipboard.WriteAll(r)
fmt.Println("\033[33mCopied to clipboard")
return
}
cmsplit := strings.Split(r, " ")
cm := exec.Command(cmsplit[0], cmsplit[1:]...)
out, err := cm.Output()
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println(string(out))
}

24
reader/file.go Normal file
View File

@@ -0,0 +1,24 @@
package reader
import (
"bufio"
"os"
)
func FileToPrompt(cmd *string, filePath string) error {
f, err := os.Open(filePath)
if err != nil {
return err
}
defer f.Close()
reader := bufio.NewReader(f)
*cmd = *cmd + "\nFile path: " + filePath + "\n"
for {
line, err := reader.ReadString('\n')
if err != nil {
break
}
*cmd = *cmd + "\n" + line
}
return nil
}