225 lines
4.2 KiB
Go
225 lines
4.2 KiB
Go
package main
|
||
|
||
import (
|
||
"fmt"
|
||
"gosh/cmd"
|
||
"gosh/types"
|
||
"gosh/utils"
|
||
"os"
|
||
"os/exec"
|
||
"path/filepath"
|
||
"strings"
|
||
|
||
"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 := strings.Fields(cmdStr)
|
||
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:]) {
|
||
fmt.Println("Unknown command:", parts[0])
|
||
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
|
||
}
|
||
}
|
||
}
|