# Gosh - a tiny educational shell in Go Gosh is a small, readable shell written in Go. It’s designed as an educational project: the code favors clarity over completeness so you can learn how a shell works by reading and modifying it. What you’ll find here: - A minimal interactive loop that reads input, parses it into a command, and executes it. - A simple builtin registry (e.g., `cd`, `exit`). - A executor that decides whether to run a builtin or spawn an external program. - A handful of small packages (parser, prompt, paths) that keep responsibilities focused and names unambiguous. Quick start ----------- Requirements: Go 1.25+ - Build: `go build ./cmd/gosh` - Run: `go run ./cmd/gosh` You should see a prompt like: `user@host ~/path > ` Type `exit` to quit or `cd` to change directories. ## How a shell works (general) At a high level, most shells follow the REPL loop (Read-eval-print): 1. Read - Display a prompt and read a line of input from the terminal (stdin). - Parse: Split the input into a program name and its arguments. Full shells also handle quoting, escaping, variable expansion, globbing, pipelines (`|`), redirections (`>`, `<`, `>>`), and subshells. This project intentionally keeps parsing simple (whitespace-separated tokens) to stay readable. 2. Eval (evaluate the input) - Decide what “the command” refers to: - Builtin: a command implemented inside the shell process (e.g., `cd`, which must change the current process’ working directory). - External: an executable resolved via `PATH` (e.g., `/usr/bin/ls`). 3. Print (execute and print output) - Builtins: run a function in the current process. - External: fork/exec (in Go: create an `exec.Cmd` and call `Run`), wiring stdin/stdout/stderr so output appears in your terminal. - Capture or propagate the exit status to use in conditionals and the next prompt. Beyond the basics (not all implemented here): - Redirections and pipes connect processes via file descriptors. - Job control manages foreground/background processes and signals (Ctrl‑C, Ctrl‑Z). - Shell scripting adds variables, conditionals, loops, and functions. ## Project architecture Executable - `cmd/gosh`: main program. REPL code (Read-eval-print loop) Core packages - `internal/runner`: command resolver and executor. Runs either a builtin or an external program. - `internal/parser`: turns raw input into a `command.Definition` (a simple `[]string`). - `internal/command`: helpers around command name/args. - `internal/builtins`: builtin registry and implementations (currently `cd`, `exit`). Supporting packages - `internal/prompt`: expands prompt variables like `%u` (user), `%h` (host), `%w` (cwd). - `internal/paths`: home-directory lookup, `~` expansion, and home abbreviation. ## Prompt format The prompt string is defined in `cmd/gosh/gosh.go` and supports: - `%u` → current user - `%h` → hostname - `%w` → working directory (**with** home abbreviated to `~`) - `%W` → working directory (**without** home abbreviated to `~`) ## Example session ``` $ go run ./cmd/gosh me@myhost ~ > pwd /home/me me@myhost ~ > cd /tmp me@myhost /tmp > ls ... me@myhost /tmp > exit 0 ``` ## Learning roadmap (ideas to extend) - Input - Support multi-line inputs. - Parsing - Quoting and escaping (single quotes, double quotes, backslash) - Environment variable expansion (`$HOME`, `${VAR}`) - Globbing (`*`, `?`, `[]`) - Execution - PATH resolution with helpful errors and `which`-like behavior - Redirections (`>`, `>>`, `<`) and pipelines (`|`) - Background jobs (`cmd &`) and job control (fg/bg, signals) - UX - Command history and line editing - Configurable prompts/themes ## Status This is intentionally minimal and focused on readability. If you experiment or extend it, consider adding tests close to the code you change (e.g., for `paths` and parsing behavior) to keep the learning loop tight.