diff --git a/command/echo/echo.go b/command/echo/echo.go index 88bc8b7..7639f63 100644 --- a/command/echo/echo.go +++ b/command/echo/echo.go @@ -8,5 +8,4 @@ import ( func Echo(in input_parser.Input, _ *environment.Env) { fmt.Print(in.Args_raw) - // fungerar inte om råttan åt din kod } diff --git a/environment/environment.go b/environment/environment.go index baf8916..e9d43ef 100644 --- a/environment/environment.go +++ b/environment/environment.go @@ -10,6 +10,9 @@ type Env struct { Path string Env map[string]string + + // History where each command gets append to the end + History []string } func Get_env() Env { @@ -17,14 +20,21 @@ func Get_env() Env { if err != nil { log.Fatal(err.Error()) } + return Env{ + Path: pwd, + Env: inherit_environment(), + History: get_history(), + } +} +func inherit_environment() map[string] string{ env := make(map[string]string) for _, s_env := range os.Environ() { split := strings.Split(s_env, "=") env[split[0]] = split[1] } - return Env{ - Path: pwd, - Env: env, - } - + return env +} +func get_history() []string { + var x []string + return x } diff --git a/go.mod b/go.mod index e370850..06b5da9 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,8 @@ module bbash go 1.23.4 + +require ( + golang.org/x/sys v0.29.0 // indirect + golang.org/x/term v0.28.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..f05f63b --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +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= +golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= diff --git a/input_parser/input_parser.go b/input_parser/input_parser.go index 80069ce..7905846 100644 --- a/input_parser/input_parser.go +++ b/input_parser/input_parser.go @@ -1,10 +1,13 @@ package input_parser import ( + "bbash/environment" "bufio" - "log" + "fmt" "os" "strings" + + "golang.org/x/term" ) type Input struct { @@ -17,16 +20,21 @@ type Input struct { Flags []string } -func Parse() Input { - input := input_str() +func Parse(env *environment.Env) Input { + input := input_str(env) return parse(input) } func parse(input string) Input { split := strings.Split(string(input), " ") instruction := strings.TrimSpace(split[0]) + + args_raw := "" + if len(split) > 1 { + args_raw = split[1] + } + var flags []string var args []string - for _, arg := range split[1:] { if arg[0:2] == "--" { var result = strings.TrimSpace(arg) @@ -47,13 +55,69 @@ func parse(input string) Input { Instruction: instruction, Args: args, Flags: flags, + Args_raw: args_raw, } } -func input_str() string { - reader := bufio.NewReader(os.Stdin) - input, err := reader.ReadString('\n') +func input_str(env *environment.Env) string { + std_fd := os.Stdin.Fd() + term_restore, err := term.MakeRaw(int(std_fd)) if err != nil { - log.Fatal(err.Error()) + fmt.Println(fmt.Sprintf("Error opening terminal: %s", err.Error())) + panic(err.Error()) } + reader := bufio.NewReader(os.Stdin) + var input string + history_index := len(env.History) // not -1 since we start at the new one + env.History = append(env.History, input) + + env.History[len(env.History)-1] = input + fmt.Print("\r\033[K") + fmt.Print(env.Path) + fmt.Print(" > ") + fmt.Print(input) + + for { + r_rune, _, err := reader.ReadRune() + if err != nil { + fmt.Print(fmt.Sprintf("Error reading user input: ", err.Error())) + } + switch r_rune { + case 3: // ^C + input = "" + case 4: // ^D + input = "exit" + goto loop_exit + case 65: // UPP + if history_index > 0 { + history_index-- + input = env.History[history_index] + } + case 66: // DOWN + if history_index < len(env.History)-1 { + history_index++ + input = env.History[history_index] + } else { + input = "" + } + case 67: // LEFT + case 68: // RIGHT + case 127: //packspace + if len(input) > 0 { + input = input[:len(input)-1] + } + case 13: // Enter + goto loop_exit + default: + input = input + string(r_rune) + } + env.History[len(env.History)-1] = input + fmt.Print("\r\033[K") + fmt.Print(env.Path) + fmt.Print(" > ") + fmt.Print(input) + } + loop_exit: + term.Restore(int(std_fd), term_restore) + fmt.Println() return input } diff --git a/input_parser/test_test.go b/input_parser/test_test.go index 0e723dc..72c0110 100644 --- a/input_parser/test_test.go +++ b/input_parser/test_test.go @@ -1,6 +1,7 @@ package input_parser import ( + "bbash/environment" "fmt" "testing" ) @@ -11,3 +12,9 @@ func TestParse(t *testing.T) { fmt.Println(test.Args) fmt.Println(test.Flags) } + +func TestInput(t *testing.T) { + + input := input_str(&environment.Env{}) + fmt.Println(input) +} diff --git a/main.go b/main.go index 0f4688a..1424f8c 100644 --- a/main.go +++ b/main.go @@ -13,8 +13,10 @@ func main() { command.Init(&env) for { - fmt.Print(fmt.Sprintf("%s > ", env.Path)) - in_parsed := input_parser.Parse() + in_parsed := input_parser.Parse(&env) + if in_parsed.Instruction == "exit" { + break + } command.Run_command(in_parsed, &env) fmt.Println() }