From da0fd7ddafa3c17768471e4798e603eba302e8c1 Mon Sep 17 00:00:00 2001 From: nokotan Date: Thu, 22 Oct 2026 00:50:36 +0300 Subject: [PATCH] Fix terminal restore state and add set themes via local vars --- cmd/app/main.go | 29 ++++++++++++++-- config/config.go | 6 ---- executor/executor.go | 81 ++++++++++++++++++++++++++++++-------------- go.mod | 7 ++-- go.sum | 5 ++- 5 files changed, 91 insertions(+), 37 deletions(-) delete mode 100644 config/config.go diff --git a/cmd/app/main.go b/cmd/app/main.go index 0957699..463a8fa 100644 --- a/cmd/app/main.go +++ b/cmd/app/main.go @@ -2,21 +2,44 @@ package main import ( "fmt" + "os" + "strings" "nshell/executor" "nshell/suggestions" "github.com/c-bata/go-prompt" + "golang.org/x/term" ) +var oldStateTerminal *term.State + +func getColor(color string) prompt.Color { + color = strings.ToUpper(color) + switch color { + case "CYAN": + return prompt.Cyan + case "RED": + return prompt.Red + default: + return prompt.Green + } +} + func main() { + fd := int(os.Stdin.Fd()) + if state, err := term.GetState(fd); err == nil { + oldStateTerminal = state + } fmt.Println("Wellcome to noko-shell(nshell) :3") options := []prompt.Option{ - prompt.OptionPrefix("nshell ^^>"), - prompt.OptionPrefixTextColor(prompt.Cyan), + prompt.OptionLivePrefix(func() (string, bool) { + return executor.GetVariable("NSHELL_PREFIX_TEXT"), true + }), + prompt.OptionPrefixTextColor(getColor(executor.GetVariable("NSHELL_PREFIX_COLOR"))), } - p := prompt.New(executor.Exec, suggestions.Completer, options...) + p := prompt.New(executor.BuildExecutor(oldStateTerminal, &fd), suggestions.Completer, options...) p.Run() } diff --git a/config/config.go b/config/config.go deleted file mode 100644 index 4d5e572..0000000 --- a/config/config.go +++ /dev/null @@ -1,6 +0,0 @@ -// Package config current shell config -package config - -type Config struct { - UserLine string -} diff --git a/executor/executor.go b/executor/executor.go index 925f818..db902ea 100644 --- a/executor/executor.go +++ b/executor/executor.go @@ -6,40 +6,71 @@ import ( "os" "os/exec" "strings" + + "golang.org/x/term" ) -func Exec(line string) { - line = strings.TrimSpace(line) - if line == "" { - return - } +var localVars = make(map[string]string) - args := strings.Fields(line) - command := args[0] - commandArgs := args[1:] +func BuildExecutor(oldStateTerminal *term.State, fd *int) func(string) { + return func(line string) { + line = strings.TrimSpace(line) - if command == "exit" { - fmt.Println("Bye Bye my small deer :3") - os.Exit(0) - } + if strings.Contains(line, "=") && !strings.HasPrefix(line, "export ") { + parts := strings.SplitN(line, "=", 2) + key := strings.TrimSpace(parts[0]) + value := strings.TrimSpace(parts[1]) - if command == "cd" { - if len(commandArgs) < 1 { - fmt.Fprintln(os.Stderr, "cd: argument was skipped") + localVars[key] = value return } - if err := os.Chdir(commandArgs[0]); err != nil { - fmt.Fprintln(os.Stderr, err) + + line = os.Expand(line, GetVariable) + + if line == "" { + return } - return - } - cmd := exec.Command(command, commandArgs...) - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr + args := strings.Fields(line) + command := args[0] + commandArgs := args[1:] - if err := cmd.Run(); err != nil { - fmt.Fprintf(os.Stderr, "Execution error: %v\n", err) + if command == "exit" { + fmt.Println("Bye Bye my small deer :3") + if oldStateTerminal != nil { + _ = term.Restore(*fd, oldStateTerminal) + } + os.Exit(0) + } + + if command == "cd" { + if len(commandArgs) < 1 { + fmt.Fprintln(os.Stderr, "cd: argument was skipped") + return + } + if err := os.Chdir(commandArgs[0]); err != nil { + fmt.Fprintln(os.Stderr, err) + } + return + } + + cmd := exec.Command(command, commandArgs...) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + if err := cmd.Run(); err != nil { + fmt.Fprintf(os.Stderr, "Execution error: %v\n", err) + } } } + +func GetVariable(key string) string { + if val, exists := localVars[key]; exists { + return val + } + if val := os.Getenv(key); val != "" { + return val + } + return "" +} diff --git a/go.mod b/go.mod index 0f78cec..098b9ef 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,10 @@ module nshell go 1.27.2 -require github.com/c-bata/go-prompt v0.2.6 +require ( + github.com/c-bata/go-prompt v0.2.6 + golang.org/x/term v0.47.0 +) require ( github.com/mattn/go-colorable v0.1.7 // indirect @@ -10,5 +13,5 @@ require ( github.com/mattn/go-runewidth v0.0.9 // indirect github.com/mattn/go-tty v0.0.3 // indirect github.com/pkg/term v1.2.0-beta.2 // indirect - golang.org/x/sys v0.0.0-20200918174421-af09f7315aff // indirect + golang.org/x/sys v0.49.0 // indirect ) diff --git a/go.sum b/go.sum index 257cea7..f3b1511 100644 --- a/go.sum +++ b/go.sum @@ -21,5 +21,8 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200918174421-af09f7315aff h1:1CPUrky56AcgSpxz/KfgzQWzfG09u5YOL8MvPYBlrL8= golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.49.0 h1:XbzkgYJHdqh/8m2Uu0W/dQv8nktxx4BFHp1M0gROTXA= +golang.org/x/sys v0.49.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og= +golang.org/x/term v0.47.0 h1:cpyOwQkr2Nzxe2p6KnrTG7Ei2wtzjsuSjhpXXepZ/BM= +golang.org/x/term v0.47.0/go.mod h1:efAfAuG6RKABvg1ArGebRkvX6LXul14SM67o2e4mUCY=