GoLSh/main.go
2025-06-30 13:17:57 -05:00

242 lines
4.5 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"fmt"
"gosh/cmd"
"gosh/types"
"gosh/utils"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/anmitsu/go-shlex"
"github.com/chzyer/readline"
"github.com/fatih/color"
)
func gosh_print_output(cmdo types.CmdOutput) {
switch cmdo.Id {
case 0:
fmt.Printf(cmdo.Output)
case 1:
fmt.Printf("Error: %s\n", cmdo.Output)
}
}
func parse_flags(parts []string) (map[string]string, []string) {
flags := make(map[string]string)
args := []string{}
i := 0
for i < len(parts) {
if strings.HasPrefix(parts[i], "-") {
key := parts[i]
val := ""
if i+1 < len(parts) && !strings.HasPrefix(parts[i+1], "-") {
val = parts[i+1]
i++
}
flags[key] = val
} else {
args = append(args, parts[i])
}
i++
}
return flags, args
}
func process_golshscript(sh *types.Shell, file_path string) {
data, err := os.ReadFile(file_path)
if err != nil {
fmt.Println("Error: ", err)
return
}
lines := strings.Split(string(data), "\n")
for _, line := range lines {
gosh_process_input(sh, strings.TrimSpace(line))
}
}
func check_pathes(sh *types.Shell, name string, args []string) bool {
var output types.CmdOutput
program_found := false
// Check Python Pathes
for _, path := range sh.PyPaths {
children, err := os.ReadDir(path)
if err != nil {
color.Red("Error reading path.")
fmt.Println(err)
}
for _, child := range children {
child_name := strings.TrimSpace(child.Name())
if !child.IsDir() && child_name == name {
program_found = true
full_path := filepath.Join(path, child.Name())
path_args := append([]string{full_path}, args...)
comd := exec.Command("python3", path_args...)
out, err := comd.Output()
if err != nil {
fmt.Print("Error: ")
color.Red(err.Error())
}
output = types.CmdOutput{Id: 0, Output: string(out)}
}
}
}
if program_found {
gosh_print_output(output)
}
return program_found
}
func gosh_process_input(sh *types.Shell, input string) {
// Split by pipe and trim spaces
commands := strings.Split(input, "|")
var prevOutput types.CmdOutput
for _, cmdStr := range commands {
cmdStr = strings.TrimSpace(cmdStr)
parts, err := shlex.Split(cmdStr, false)
if err != nil {
fmt.Println(err)
}
if len(parts) == 0 {
continue
}
switch parts[0] {
case "pwd":
prevOutput = cmd.GoshPwd(sh)
case "cd":
if len(parts) < 2 {
fmt.Println("Usage: cd <dir>")
return
}
prevOutput = cmd.GoshCd(sh, parts[1])
case "ls":
if len(parts) > 1 {
prevOutput = cmd.GoshLs(sh, parts[1:]...)
} else {
prevOutput = cmd.GoshLs(sh)
}
case "cat":
if len(parts) < 2 {
fmt.Println("Usage: cat <path to file>")
return
}
prevOutput = cmd.GoshCat(sh, parts[1])
case "grep":
if len(parts) < 2 {
fmt.Println("Usage: grep <pattern>")
return
}
flags, args := parse_flags(parts)
// Feed previous output to grep
prevOutput = cmd.GoshGrep(sh, flags, prevOutput.Output, args[len(args)-1])
case "clear":
cmd.GoshClear()
case "apath":
if len(parts) < 2 {
fmt.Println(("Usage: apath <path/dir>"))
return
}
prevOutput = cmd.GolshPyapath(sh, parts[1])
default:
if !check_pathes(sh, parts[0], parts[1:]) {
comd := exec.Command(parts[0], parts[1:]...)
out, err := comd.CombinedOutput()
if err != nil {
fmt.Print("Error: ")
color.Red(err.Error())
return
}
fmt.Println(string(out))
return
}
}
}
gosh_print_output(prevOutput)
}
func main() {
dir, _ := os.Getwd()
// Init shell
sh := types.Shell{
Cd: dir,
PyPaths: []string{}}
// Check for and execute .golshrc
golshrc_path, _ := os.UserHomeDir()
golshrc_path = golshrc_path + "/.golshrc"
_, err := os.Stat(golshrc_path)
golshrc_exists := err == nil
if golshrc_exists {
process_golshscript(&sh, golshrc_path)
}
// Set up readline
rl, err := readline.NewEx(&readline.Config{
Prompt: sh.Cd + "> ",
AutoComplete: &utils.AutoCompleter{Sh: &sh},
InterruptPrompt: "^C",
EOFPrompt: "exit",
})
if err != nil {
panic(err)
}
defer rl.Close()
cd_path_color := color.New(color.FgBlue)
var should_exit = false
for {
rl.SetPrompt(cd_path_color.Sprint("GOLSH "+sh.Cd+"") + " ")
input, err := rl.Readline()
if err != nil {
fmt.Println("Error reading input: ", err)
}
input = strings.TrimSpace(input)
switch input {
case "exit":
should_exit = true
default:
gosh_process_input(&sh, input)
}
if should_exit {
break
}
}
}