mirror of
https://gitlab.com/pnx/gosh
synced 2026-06-15 23:03:09 +02:00
106 lines
3.8 KiB
Markdown
106 lines
3.8 KiB
Markdown
# 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.
|