diff --git a/go.mod b/go.mod index 5b1f0e6..3e5b3b6 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,10 @@ require ( github.com/wadey/go-rounding v1.1.0 ) -require github.com/joho/godotenv v1.5.1 // indirect +require ( + github.com/chzyer/readline v1.5.1 // indirect + github.com/joho/godotenv v1.5.1 // indirect +) require ( github.com/gabriel-vasile/mimetype v1.4.2 diff --git a/go.sum b/go.sum index f627422..c410aa0 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,7 @@ +github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= +github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= +github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= +github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= @@ -19,6 +23,7 @@ golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/src/input.go b/src/input.go index 3d336e1..8b72371 100644 --- a/src/input.go +++ b/src/input.go @@ -1,23 +1,36 @@ package main import ( - "bufio" "fmt" + "log" "os" + "github.com/chzyer/readline" "golang.org/x/term" ) -func input(args ...any) string { +var tempFilePath = os.TempDir() + "/argon_input_history.tmp" + +func input(args ...any) (string, error) { output := []any{} for i := 0; i < len(args); i++ { output = append(output, anyToArgon(args[i], false, true, 3, 0, true, 0)) } - fmt.Print(output...) - scanner := bufio.NewScanner(os.Stdin) - scanner.Scan() - input := scanner.Text() - return input + message := fmt.Sprint(output...) + rl, err := readline.NewEx(&readline.Config{ + Prompt: message, + HistoryFile: tempFilePath, + HistorySearchFold: true, + }) + if err != nil { + log.Fatalf("Failed to create readline instance: %v", err) + } + defer rl.Close() + line, err := rl.Readline() + if err != nil { // io.EOF or other error + return "", err + } + return line, nil } func getPassword(args ...any) (string, error) { @@ -25,38 +38,21 @@ func getPassword(args ...any) (string, error) { for i := 0; i < len(args); i++ { output = append(output, anyToArgon(args[i], false, true, 3, 0, true, 0)) } - fmt.Print(output...) - password := []byte{} - - oldState, err := term.MakeRaw(int(os.Stdin.Fd())) + message := fmt.Sprint(output...) + rl, err := readline.NewEx(&readline.Config{ + Prompt: message, + MaskRune: '*', + EnableMask: true, + }) if err != nil { - panic(err) + log.Fatalf("Failed to create readline instance: %v", err) } - defer term.Restore(int(os.Stdin.Fd()), oldState) - - for { - char := make([]byte, 1) - _, err := os.Stdin.Read(char) - if err != nil { - return "", err - } - if char[0] == 3 || char[0] == 4 { - return "", fmt.Errorf("keyboard interupt") - } else if char[0] == '\r' || char[0] == '\n' { - fmt.Println() - break - } else if char[0] == '\b' || char[0] == 127 { - if len(password) > 0 { - password = password[:len(password)-1] - fmt.Print("\b \b") - } - } else { - password = append(password, char[0]) - fmt.Print("*") - } + defer rl.Close() + line, err := rl.Readline() + if err != nil { // io.EOF or other error + return "", err } - fmt.Print("\r") - return string(password), nil + return line, nil } func pause() { diff --git a/src/shell.go b/src/shell.go index 50e7dac..4a7302d 100644 --- a/src/shell.go +++ b/src/shell.go @@ -3,22 +3,11 @@ package main import ( "fmt" "os" - "os/signal" "strings" ) func shell(global ArObject) { stack := stack{global, newscope()} - c := make(chan os.Signal, 1) - signal.Notify(c, os.Interrupt) - go func() { - for sig := range c { - if sig == os.Interrupt { - fmt.Println("\x1b[0m\n\x1b[32;240mBye :)\x1b[0m") - os.Exit(0) - } - } - }() fmt.Print("\x1b[32;240mWelcome to the Argon v3!\x1b[0m\n\n") for { indent := 0 @@ -27,7 +16,12 @@ func shell(global ArObject) { textBefore := ">>>" for i := 1; indent > 0 || (previous != indent && indent >= 0) || i == 1; i++ { indentStr := strings.Repeat(" ", indent) - code := indentStr + input("\x1b[38;240m"+textBefore+indentStr+" \x1b[0m\x1b[1;240m") + inp, err := input("\x1b[38;240m" + textBefore + indentStr + " \x1b[0m\x1b[1;240m") + if err != nil { + fmt.Println("\x1b[0m\n\x1b[32;240mBye :)\x1b[0m") + os.Exit(0) + } + code := indentStr + inp fmt.Print("\x1b[0m") totranslate = append(totranslate, UNPARSEcode{code, code, i, ""}) trimmed := strings.TrimSpace(code) diff --git a/src/term-class.go b/src/term-class.go index 3fde0bf..4dcaf5c 100644 --- a/src/term-class.go +++ b/src/term-class.go @@ -140,7 +140,15 @@ var ArInput = Map( return ArString(resp), ArErr{} }}, "__call__": builtinFunc{"input", func(args ...any) (any, ArErr) { - return input(args...), ArErr{} + inp, err := input(args...) + if err != nil { + return nil, ArErr{ + TYPE: "Runtime Error", + message: err.Error(), + EXISTS: true, + } + } + return ArString(inp), ArErr{} }}, "pause": builtinFunc{"pause", func(args ...any) (any, ArErr) { pause()