This commit is contained in:
JISAUAY 2025-06-24 16:02:09 -05:00
commit f6140a1fc3
11 changed files with 308 additions and 0 deletions

18
cmd/cat.go Normal file
View File

@ -0,0 +1,18 @@
package cmd
import (
"gosh/types"
"os"
"github.com/fatih/color"
)
func GoshCat(sh *types.Shell, filename string) types.CmdOutput {
data, err := os.ReadFile(filename)
red := color.New(color.FgRed).SprintFunc()
if err != nil {
return types.CmdOutput{Id: 1, Output: red(err)}
}
return types.CmdOutput{Id: 0, Output: string(data)}
}

22
cmd/cd.go Normal file
View File

@ -0,0 +1,22 @@
package cmd
import (
"os"
"gosh/types"
"github.com/fatih/color"
)
func GoshCd(sh *types.Shell, dir string) types.CmdOutput {
err := os.Chdir(dir)
red := color.New(color.FgRed).SprintFunc()
if err != nil {
return types.CmdOutput{Id: 1, Output: red(err)}
}
dir, _ = os.Getwd()
sh.Cd = dir
return types.CmdOutput{Id: 0, Output: ""}
}

7
cmd/clear.go Normal file
View File

@ -0,0 +1,7 @@
package cmd
import "fmt"
func GoshClear() {
fmt.Print("\033[H\033[2J")
}

60
cmd/grep.go Normal file
View File

@ -0,0 +1,60 @@
package cmd
import (
"gosh/types"
"regexp"
"strconv"
"strings"
"github.com/fatih/color"
)
func GoshGrep(sh *types.Shell, args map[string]string, input string, regex string) types.CmdOutput {
re := regexp.MustCompile(regex)
lines := strings.Split(input, "\n")
red := color.New(color.FgRed).SprintFunc()
value, ok := args["-C"]
var err error
context_lines := 0
if ok {
context_lines, err = strconv.Atoi(value)
if err != nil {
return types.CmdOutput{Id: 1, Output: red(err)}
}
context_lines++
}
var output strings.Builder
for i, line := range lines {
if re.MatchString(line) {
// Print behind
if context_lines != 0 {
for bi := i - context_lines; bi < i; bi++ {
if bi < 0 {
continue
} else {
output.WriteString(lines[bi] + "\n")
}
}
}
output.WriteString(line + "\n")
// Print after
if context_lines != 0 {
for ai := i + 1; ai < i+context_lines; ai++ {
if ai > len(lines)-1 {
continue
} else {
output.WriteString(lines[ai] + "\n")
}
}
}
}
}
return types.CmdOutput{Id: 0, Output: output.String()}
}

28
cmd/ls.go Normal file
View File

@ -0,0 +1,28 @@
package cmd
import (
"gosh/types"
"os"
"strings"
"github.com/fatih/color"
)
func GoshLs(sh *types.Shell) types.CmdOutput {
children, err := os.ReadDir(sh.Cd)
red := color.New(color.FgRed).SprintFunc()
if err != nil {
return types.CmdOutput{Id: 1, Output: red(err)}
}
var output strings.Builder
for _, child := range children {
if child.IsDir() {
output.WriteString(color.CyanString(child.Name()+"/") + "\n")
} else {
output.WriteString(child.Name() + "\n")
}
}
return types.CmdOutput{Id: 0, Output: output.String()}
}

9
cmd/pwd.go Normal file
View File

@ -0,0 +1,9 @@
package cmd
import (
"gosh/types"
)
func GoshPwd(sh *types.Shell) types.CmdOutput {
return types.CmdOutput{Id: 0, Output: sh.Cd}
}

10
go.mod Normal file
View File

@ -0,0 +1,10 @@
module gosh
go 1.21.5
require (
github.com/fatih/color v1.18.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
golang.org/x/sys v0.25.0 // indirect
)

11
go.sum Normal file
View File

@ -0,0 +1,11 @@
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=

126
main.go Normal file
View File

@ -0,0 +1,126 @@
package main
import (
"bufio"
"fmt"
"gosh/cmd"
"gosh/types"
"os"
"strings"
"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 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":
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()
default:
fmt.Println("Unknown command: ", parts[0])
return
}
}
gosh_print_output(prevOutput)
}
func main() {
reader := bufio.NewReader(os.Stdin)
c := color.New(color.FgCyan)
dir, _ := os.Getwd()
sh := types.Shell{Cd: dir}
var should_exit = false
for {
c.Print(sh.Cd)
fmt.Print("> ")
input, err := reader.ReadString('\n')
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
}
}
}

7
readme.md Normal file
View File

@ -0,0 +1,7 @@
# GoLSh
Go Lang Shell
## Commands
`cd`, `ls`, `pwd`, `grep`, `cat`, `clear`

10
types/shell.go Normal file
View File

@ -0,0 +1,10 @@
package types
type Shell struct {
Cd string
}
type CmdOutput struct {
Id int
Output string
}