Compare commits

..

18 Commits

Author SHA1 Message Date
Tobias P.L Wennberg
2a594eac1d Fix merge 2025-01-14 13:31:39 +01:00
Lo
9bbaae1d11 fixade autocomplete 2025-01-14 13:22:09 +01:00
Tobias P.L Wennberg
ed3067a9a0 Better input, now with ctrl 2025-01-14 10:39:22 +01:00
Tobias P.L Wennberg
ada7fa9d9e fix cursor 2025-01-14 09:24:56 +01:00
Tobias P.L Wennberg
3f1b876f68 Fix merge with autocomplete, still a few quirks 2025-01-14 09:15:35 +01:00
b071d3dd78 implemened cursor control and better escape char handling 2025-01-14 09:04:38 +01:00
Tobias P.L Wennberg
78fb97a860 Nvim works! 2025-01-14 09:02:59 +01:00
Tobias P.L Wennberg
e37798dd82 merge conflict 2025-01-13 18:05:13 +01:00
Tobias P.L Wennberg
a227e3e106 remove api key 2025-01-13 18:03:45 +01:00
markstad
94425a8c94 brainrot har implementerats 2025-01-13 17:58:00 +01:00
Lo
2f6f75b3a4 Mindre fixar med auto slut 2025-01-13 17:46:40 +01:00
Tobias P.L Wennberg
0216b72d65 Accidentally disabled tab-complete 2025-01-13 17:12:54 +01:00
Tobias P.L Wennberg
35af0423a7 merge flodman 2025-01-13 17:04:15 +01:00
Tobias P.L Wennberg
3c166dda98 Merge branch 'Flodman' 2025-01-13 17:02:51 +01:00
In_the_Thick_of_It
e6e223b6a7 implemented some brainrot for y'all :):):):):):) 2025-01-13 16:59:09 +01:00
Tobias P.L Wennberg
d4757c154b Fix 2025-01-13 15:45:26 +01:00
Tobias P.L Wennberg
45cf77ed2a Merge fix 2025-01-13 15:39:04 +01:00
Lo
45f50a95ce History auto komplett :D 2025-01-13 15:28:58 +01:00
11 changed files with 586 additions and 49 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
./api/api.go

6
api/api.go Normal file
View File

@ -0,0 +1,6 @@
package api
func Api() string {
apiString := "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"
return apiString
}

View File

@ -0,0 +1,42 @@
package brainrot
import (
"bbash/api"
"bbash/environment"
"bbash/input_parser"
"context"
"fmt"
"os"
"path/filepath"
"github.com/openai/openai-go"
"github.com/openai/openai-go/option"
)
func Brainrot(in input_parser.Input, env *environment.Env) {
file := filepath.Join(env.Path, in.Args_raw)
bytea_str, err := os.ReadFile(file)
//Skicka string(bytea_str)
if err != nil {
fmt.Print(fmt.Sprintf("L Rizz", err.Error()))
return
}
//Send to chatgpt
client := openai.NewClient(
option.WithAPIKey(api.Api()), // defaults to os.LookupEnv("OPENAI_API_KEY")
)
prompt := fmt.Sprintf("Rewrite the text I will provide you to brainrot. Make sure to use some of the words skibidi gyatt rizz only in ohio duke dennis did you pray today livvy dunne rizzing up baby gronk sussy imposter pibby glitch in real life sigma alpha omega male grindset andrew tate goon cave freddy fazbear colleen ballinger smurf cat vs strawberry elephant blud dawg shmlawg ishowspeed a whole bunch of turbulence ambatukam bro really thinks he's carti literally hitting the griddy the ocky way kai cenat fanum tax garten of banban no edging in class not the mosquito again bussing axel in harlem whopper whopper whopper whopper 1 2 buckle my shoe goofy ahh aiden ross sin city monday left me broken quirked up white boy busting it down sexual style goated with the sauce john pork grimace shake kiki do you love me huggy wuggy nathaniel b lightskin stare biggest bird omar the referee amogus uncanny wholesome reddit chungus keanu reeves pizza tower zesty poggers kumalala savesta quandale dingle glizzy rose toy ankha zone thug shaker morbin time dj khaled sisyphus oceangate shadow wizard money gang ayo the pizza here PLUH nair butthole waxing t-pose ugandan knuckles family guy funny moments compilation with subway surfers gameplay at the bottom nickeh30 ratio uwu delulu opium bird cg5 mewing fortnite battle pass all my fellas gta 6 backrooms gigachad based cringe kino redpilled no nut november pokénut november foot fetish F in the chat i love lean looksmaxxing gassy social credit bing chilling xbox live mrbeast kid named finger better caul saul i am a surgeon hit or miss i guess they never miss huh i like ya cut g ice spice gooning fr we go gym kevin james josh hutcherson coffin of andy and leyley metal pipe falling. Rewrite this text: %s", string(bytea_str))
chatCompletion, err := client.Chat.Completions.New(context.TODO(), openai.ChatCompletionNewParams{
Messages: openai.F([]openai.ChatCompletionMessageParamUnion{
openai.UserMessage(prompt),
}),
Model: openai.F(openai.ChatModelGPT4oMini),
})
if err != nil {
panic(err.Error())
}
fmt.Print(chatCompletion.Choices[0].Message.Content)
}

View File

@ -1,6 +1,7 @@
package command
import (
"bbash/command/brainrot"
"bbash/command/cat"
"bbash/command/cd"
"bbash/command/cp"
@ -15,6 +16,7 @@ import (
"bbash/command/rm"
"bbash/command/tail"
"bbash/command/touch"
"bbash/command/whereareyou"
"bbash/environment"
"bbash/input_parser"
"fmt"
@ -34,12 +36,12 @@ func Init(env *environment.Env) {
func Run_command(in input_parser.Input, env *environment.Env) {
switch in.Instruction {
case "fritiofcommand":
fritiofcommand.Fritiof(in, env)
case "pwd":
pwd.Pwd(in, env)
case "echo":
echo.Echo(in, env)
case "fritiof", "fritiofcommand":
fritiofcommand.Fritiof(in, env)
case "ls":
ls.Ls(in, env)
case "cd":
@ -62,6 +64,10 @@ func Run_command(in input_parser.Input, env *environment.Env) {
help.Help(in, env)
case "tail":
tail.Tail(in, env)
case "whereareyou":
whereareyou.Whereareyou(in, env)
case "brainrot":
brainrot.Brainrot(in, env)
default:
if !run_by_path(in, env) {
fmt.Println(fmt.Sprintf("No such command! (%s)", in.Instruction))
@ -76,8 +82,13 @@ func run_by_path(in input_parser.Input, env *environment.Env) bool {
return false
}
cmd := exec.Command(instr, strings.Fields(in.Args_raw)...)
output, _ := cmd.CombinedOutput()
print(string(output))
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
if err := cmd.Run(); err != nil {
fmt.Println(err.Error())
}
//output, _ := cmd.CombinedOutput()
//print(string(output))
return true
}

View File

@ -0,0 +1,11 @@
package whereareyou
import (
"bbash/environment"
"bbash/input_parser"
"fmt"
)
func Whereareyou(in input_parser.Input, env *environment.Env) {
fmt.Println("You're in the thick of it everybody knows!")
}

5
go.mod
View File

@ -3,6 +3,11 @@ module bbash
go 1.23.4
require (
github.com/openai/openai-go v0.1.0-alpha.44 // indirect
github.com/tidwall/gjson v1.18.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tidwall/sjson v1.2.5 // indirect
golang.org/x/sys v0.29.0 // indirect
golang.org/x/term v0.28.0 // indirect
)

12
go.sum
View File

@ -1,3 +1,15 @@
github.com/openai/openai-go v0.1.0-alpha.44 h1:p0OZp+sGEBcKlCIjEWIO5+R3cZEz34C3iw/MM5gAHoo=
github.com/openai/openai-go v0.1.0-alpha.44/go.mod h1:3SdE6BffOX9HPEQv8IL/fi3LYZ5TUpRYaqGQZbyk11A=
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=

View File

@ -1,24 +1,41 @@
package input_parser
import (
"bbash/environment"
"os"
"strings"
)
var commandsTab []string
var prevInput string
var tabIndex int
var skipCurrent bool
func AutoComplete(input string) string {
func AutoComplete(input string, env environment.Env) string {
rawInput := input
inputLength := len(input)
if inputLength == 0 {
return input
}
if tabIndex+2 > len(commandsTab) {
tabIndex = -1
if prevInput == input {
if skipCurrent {
return input
}
if prevInput == input {
tabIndex = tabIndex + 1
if len(commandsTab) == 0 && tabIndex > 0 {
return input
}
if tabIndex > len(commandsTab)-1 {
tabIndex = 0
}
prevInput = commandsTab[tabIndex]
return commandsTab[tabIndex]
}
@ -26,11 +43,15 @@ func AutoComplete(input string) string {
prevInput = input
tabIndex = 0
currentCommands := []string{
var flagsDictionary []string
baseCommands := []string{
"cat",
"cd",
"cp",
"echo",
"exit",
"fritiofcommand",
"head",
"help",
"ls",
@ -40,31 +61,270 @@ func AutoComplete(input string) string {
"rm",
"tail",
"touch",
"whereareyou",
}
var paths []string
fs, err := os.ReadDir(env.Path)
if err != nil {
// fmt.Print(fmt.Sprintf("Error opening directory %s", env.Path))
}
for _, f := range fs {
// if (f.Name()[0] == '.') && !(slices.Contains(in.Flags, "a")) {
// continue
// } // allows for hidden directories
// fmt.Print(f.Name())
// fmt.Println()
paths = append(paths, f.Name())
}
skipCurrent = false
acceptAll := false
var autoCompleteCommands []string
indexField0 := ""
var currentIndexFields int
var nextAutoCompleteCommands []string
noMoreFlags := false
for indexFields, currentField := range strings.Fields(input) {
// print("noMoreFlags", noMoreFlags)
currentIndexFields = indexFields
if currentIndexFields == 0 {
autoCompleteCommands = baseCommands
indexField0 = currentField
// println("len(strings.Fields(input))", len(strings.Fields(input)))
// println("input[1:]k", input[len(input)-1:], "khej")
if len(strings.Fields(input)) == 1 && input[len(input)-1:] == " " {
currentIndexFields += 1
// println("den hittade mellanslag :D")
acceptAll = true
}
}
if currentIndexFields > 0 {
// autoCompleteCommands = baseFunctions
// println("currentField 1 :D", currentField)
switch indexField0 {
case "fritiofcommand":
skipCurrent = true
case "pwd":
skipCurrent = true
case "echo":
skipCurrent = true
case "ls":
autoCompleteCommands = paths
flagsDictionary = []string{
"-a", "-help",
}
case "cd":
autoCompleteCommands = paths
case "man":
autoCompleteCommands = baseCommands
case "cat":
autoCompleteCommands = paths
case "head":
autoCompleteCommands = paths
flagsDictionary = []string{
"-n", "-help",
}
case "touch":
autoCompleteCommands = paths
case "rm":
autoCompleteCommands = paths
case "cp":
autoCompleteCommands = paths
nextAutoCompleteCommands = paths
case "mv":
autoCompleteCommands = paths
nextAutoCompleteCommands = paths
case "help":
skipCurrent = true
case "tail":
autoCompleteCommands = paths
flagsDictionary = []string{
"-n", "-help",
}
case "whereareyou":
skipCurrent = true
default:
skipCurrent = true
}
if skipCurrent {
return rawInput
}
if currentIndexFields == 1 {
// print("currentFieldhär om den har - :D", currentField)
if strings.ContainsAny(currentField, "-") {
noMoreFlags = true
}
}
if len(strings.Fields(input)) == 2 && input[len(input)-1:] == " " {
// currentIndexFields += 1
// println("den hittade mellanslag 2 :D")
acceptAll = true
autoCompleteCommands = nil
if noMoreFlags {
skipCurrent = true
return rawInput
}
}
}
if currentIndexFields > 2 {
skipCurrent = true
return rawInput
}
if currentIndexFields == 2 && noMoreFlags {
skipCurrent = true
return rawInput
}
if len(strings.Fields(input)) == 2 && input[len(input)-1:] == "-" {
autoCompleteCommands = flagsDictionary
}
if currentIndexFields > 0 && len(autoCompleteCommands) == 0 || currentIndexFields > 0 && strings.ContainsAny(rawInput, "-") {
// println("currentIdexFields är 2!!")
// if len(flagsDictionary) == 0 {
// skipCurrent = true
// return rawInput
// }
// } else {
// println("input", input, "test", input[len(input)-1:], "slut")
// if input[len(input)-1:] == " " {
// println("acceptAll")
// acceptAll = true
// }
// }
// println("currentField 2 :D", currentField)
autoCompleteCommands = nextAutoCompleteCommands
// println("nextAutoCompleteCommands", nextAutoCompleteCommands)
// println("autoCompleteCommands", autoCompleteCommands)
if len(nextAutoCompleteCommands) == 0 {
// println("currentField 100 :D", currentField)
// if strings.ContainsAny(rawInput, "-") {
autoCompleteCommands = flagsDictionary
// print("autoCompleteCommands", autoCompleteCommands)
// if currentIndexFields == 1 {
// noMoreFlags = true
// }
// } else {
// if len(autoCompleteCommands) == 0 {
// skipCurrent = true
// return rawInput
// }
// break
}
}
if currentIndexFields > 0 {
input = currentField
}
// println("loop", indexFields)
// if strings.ContainsAny(currentField, "-") {
// }
}
// println("autoCompleteCOmmands", autoCompleteCommands)
// println("autoCompleteCOmmands", autoCompleteCommands[0])
if autoCompleteCommands == nil {
skipCurrent = true
return rawInput
}
var commandsWorking []string
for _, currentCommand := range currentCommands {
// println(commandsWorking)
if len(currentCommand) < inputLength {
inputLength = len(input)
aLength := 0
foundAutoComplete := false
for _, currentCommand := range autoCompleteCommands {
// println("currentCommand")
// println(currentCommand)
if len(currentCommand) < inputLength && !acceptAll {
continue
}
if !acceptAll {
currentCommandWithoutEnd := currentCommand[:inputLength]
if currentCommandWithoutEnd != input {
continue
}
commandsWorking = append(commandsWorking, currentCommand)
}
foundAutoComplete = true
aLength = len(currentCommand) - len(input)
aLength = len(currentCommand) - aLength
// println("aLength")
// println(aLength)
// println("currentCommand")
// println(currentCommand)
// println("rawInput")
// println(rawInput)
if acceptAll {
commandsWorking = append(commandsWorking, rawInput+currentCommand)
} else {
commandsWorking = append(commandsWorking, rawInput+currentCommand[aLength:])
}
}
if !foundAutoComplete {
skipCurrent = true
return rawInput
}
// println("commandsWorking")
// println(commandsWorking[0])
// println(commandsWorking[1])
commandsTab = commandsWorking
if len(commandsTab) == 0 {
return input
}
prevInput = commandsTab[0]
return commandsTab[0]
removedStart := commandsTab[0]
// removedStart := commandsTab[0][inputLength:]
prevInput = removedStart
return prevInput
}

View File

@ -0,0 +1,55 @@
package input_parser
import "bbash/environment"
func AutoCompleteHistory(input string, env environment.Env) string {
inputLength := len(input)
if inputLength == 0 {
return ""
}
// tabIndex = 0
// currentCommands := []string{
// "cat",
// "cd",
// "cp",
// "echo",
// "head",
// "help",
// "ls",
// "man",
// "mv",
// "pwd",
// "rm",
// "tail",
// "touch",
// }
historyWorking := ""
for _, currentHistory := range env.History[:len(env.History)-1] {
// println("currentHistory", currentHistory)
if len(currentHistory) < inputLength {
continue
}
currentCommandWithoutEnd := currentHistory[:inputLength]
if currentCommandWithoutEnd != input {
continue
}
historyWorking = currentHistory
}
if len(historyWorking) != 0 {
historyWorking = historyWorking[inputLength:]
}
return historyWorking
}

View File

@ -0,0 +1,105 @@
package input_parser
import (
"bbash/environment"
"bufio"
"fmt"
"strings"
)
func Escape_handler(reader *bufio.Reader, history_index int, input string, env environment.Env, cursor int) (string, int, int) {
next_rune, _, _ := reader.ReadRune()
if next_rune == 59 {
}
if next_rune != 91 { // not "["
return "", history_index, cursor
}
next_rune, _, _ = reader.ReadRune()
switch next_rune {
case 65: //A
if history_index > 0 {
history_index--
input = env.History[history_index]
cursor = len(input)
}
case 66: //B
if history_index < len(env.History)-1 {
history_index++
input = env.History[history_index]
}
if history_index == len(env.History)-1 {
input = ""
cursor = 0
}
cursor = len(input)
case 68: //D
if cursor > 0 {
cursor--
}
case 67: //C
if prevGhostString != "" {
input = input + prevGhostString
cursor = len(input)
}
if cursor < len(input) {
cursor++
}
case 49:
cursor = ctrl(reader, input, cursor)
return input, history_index, cursor
}
return input, history_index, cursor
}
func ctrl(reader *bufio.Reader, input string, cursor int) int {
next_rune, _, err := reader.ReadRune()
if err != nil {
fmt.Println(err.Error())
return cursor
}
if next_rune != 59 {
return cursor
}
next_rune, _, err = reader.ReadRune()
if err != nil {
fmt.Println(err.Error())
return cursor
}
if next_rune != 53 {
return cursor
}
next_rune, _, err = reader.ReadRune()
if err != nil {
fmt.Println(err.Error())
return cursor
}
switch next_rune {
case 68: // ctrl left
input_at := input[:cursor]
last_index := strings.LastIndex(input_at, " ")
if last_index == -1 {
cursor = 0
} else {
input_at = input_at[:last_index]
cursor = len(input_at)
}
case 67: // ctrl right
input_next := input[cursor:]
next_trimmed := strings.TrimLeft(input_next, " ")
last_index := strings.Index(next_trimmed, " ")
if last_index == -1 {
cursor = len(input)
} else {
cursor = cursor + last_index + (len(input_next) - len(next_trimmed))
}
}
return cursor
}

View File

@ -10,6 +10,8 @@ import (
"golang.org/x/term"
)
var prevGhostString string
type Input struct {
// The instruction a.k.a first argument
Instruction string
@ -22,9 +24,9 @@ type Input struct {
func Parse(env *environment.Env) Input {
input := input_str(env)
return parse(input)
return Parse_input(input)
}
func parse(input string) Input {
func Parse_input(input string) Input {
split := strings.Split(strings.TrimSpace(string(input)), " ")
instruction := strings.TrimSpace(split[0])
@ -75,6 +77,8 @@ func input_str(env *environment.Env) string {
history_index := len(env.History) // not -1 since we start at the new one
env.History = append(env.History, input)
cursor := 0
env.History[len(env.History)-1] = input
fmt.Print("\r\033[K")
fmt.Print(env.Path)
@ -82,6 +86,12 @@ func input_str(env *environment.Env) string {
fmt.Print(input)
for {
if cursor > len(input) {
cursor = len(input)
}
if cursor < 0 {
cursor = 0
}
r_rune, _, err := reader.ReadRune()
if err != nil {
fmt.Print(fmt.Sprintf("Error reading user input: %s", err.Error()))
@ -89,50 +99,69 @@ func input_str(env *environment.Env) string {
switch r_rune {
case 3: // ^C
fmt.Println("^C")
cursor = 0
input = ""
case 4: // ^D
input = "exit"
goto loop_exit
case 27: // UPP
if r, _, _ := reader.ReadRune(); r != 91 {
break
}
case 66: // DOWN
if history_index < len(env.History)-2 {
history_index++
input = env.History[history_index]
case 8: // <CTR><BACKSPACE>
input_at := input[:cursor]
input_after := input[cursor:]
last_index := strings.LastIndex(input_at, " ")
if last_index == -1 {
input_at = ""
cursor = 0
} else {
history_index = len(env.History) - 1
input = ""
if r, _, _ := reader.ReadRune(); r == 65 { // UPP
if history_index > 0 {
history_index--
input = env.History[history_index]
}
}
if r, _, _ := reader.ReadRune(); r != 66 { //DOWN
if history_index < len(env.History)-1 {
history_index++
input = env.History[history_index]
} else {
input = ""
}
}
input_at = input_at[:last_index]
cursor = len(input_at)
}
input = input_at+input_after
case 9: // TAB
input = AutoComplete(input, *env)
cursor = len(input)
case 27: // Escape
input, history_index, cursor = Escape_handler(reader, history_index, input, *env, cursor)
case 127: //packspace
input_at := input[:cursor]
input_after := input[cursor:]
if len(input) > 0 {
input = input[:len(input)-1]
input_at = input_at[:len(input_at)-1]
cursor--
}
input=input_at+input_after
case 13: // Enter
goto loop_exit
default:
input = input + string(r_rune)
input_at := input[:cursor]
input_after := input[cursor:]
input_at += string(r_rune)
input = input_at+input_after
cursor++
}
ghost_input := AutoCompleteHistory(input, *env)
env.History[len(env.History)-1] = input
fmt.Print("\r\033[K")
fmt.Print("\r")
fmt.Print(env.Path)
fmt.Print(" > \033[K")
fmt.Print(input)
fmt.Print("\033[2m", ghost_input, "\033[0m")
prevGhostString = ""
backwardSteps := len(ghost_input)
if backwardSteps != 0 {
fmt.Printf("\033[%dD", backwardSteps)
prevGhostString = ghost_input
}
fmt.Print("\r")
fmt.Print(env.Path)
fmt.Print(" > ")
fmt.Print(input)
for i := 0; i < cursor; i++ {
fmt.Print("\033[C")
}
}
loop_exit:
term.Restore(int(std_fd), term_restore)