1
0
Fork 0
mirror of https://gitlab.com/pnx/gosh synced 2026-06-16 07:04:57 +02:00
gosh/README.md
2025-10-27 02:03:02 +01:00

3.8 KiB
Raw Blame History

Gosh - a tiny educational shell in Go

Gosh is a small, readable shell written in Go. Its 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 youll 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.
  1. 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).
  1. 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 (CtrlC, CtrlZ).
  • 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.