diff --git a/README.md b/README.md index 2428964..91f315e 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,129 @@ # shed -A shell program written in Rust for Unix based operating systems. This is mostly a pet project, still largely a work in progress, though it is being designed with end-users in mind. Will add more to this readme as features are implemented. + +A Unix shell written in Rust. The name is a nod to the two oldest Unix utilities — `sh` and `ed` — reflecting the shell's emphasis on a capable built-in line editor alongside standard shell functionality. + +## Features + +### Line Editor + +shed includes a built-in vim emulator as its line editor, written from scratch — not a readline wrapper or external library. It aims to provide a more precise vim editing experience at the shell prompt. + +- **Normal mode** — motions (`w`, `b`, `e`, `f`, `t`, `%`, `0`, `$`, etc.), verbs (`d`, `c`, `y`, `p`, `r`, `x`, `~`, etc.), text objects (`iw`, `aw`, `i"`, `a{`, `is`, etc.), registers, `.` repeat, `;`/`,` repeat, and counts +- **Insert mode** — insert, append, replace, with Ctrl+W word deletion and undo/redo +- **Visual mode** — character-wise selection with operator support +- **Real-time syntax highlighting** — commands, keywords, strings, variables, redirections, and operators are colored as you type +- **Tab completion** — context-aware completion for commands, file paths, and variables + +### Prompt + +The prompt string supports escape sequences for dynamic content: + +| Escape | Description | +|--------|-------------| +| `\u` | Username | +| `\h`, `\H` | Hostname (short / full) | +| `\w`, `\W` | Working directory (full / basename, truncation configurable via `shopt`) | +| `\$` | `$` for normal users, `#` for root | +| `\t`, `\T` | Last command runtime (milliseconds / human-readable) | +| `\s` | Shell name | +| `\e[...` | ANSI escape sequences for colors and styling | +| `\!name` | Execute a shell function and embed its output | + +The `\!` escape is particularly useful — it lets you embed the output of any shell function directly in your prompt. Define a function that prints something, then reference it in your prompt string: + +```sh +gitbranch() { git branch --show-current 2>/dev/null; } +export PS1='\u@\h \W \!gitbranch \$ ' +``` + +Additionally, `echo` now has a `-p` flag that expands prompt escape sequences, similar to how the `-e` flag expands conventional escape sequences. + +### Shell Language + +shed's scripting language contains all of the essentials. + +- **Control flow** — `if`/`elif`/`else`, `for`, `while`, `until`, `case` with pattern matching and fallthrough +- **Functions** — user-defined with local variable scoping, recursion depth limits, and `return` +- **Pipes and redirections** — `|`, `|&` (pipe stderr), `<`, `>`, `>>`, `<<` (heredoc), `<<<` (herestring), fd duplication (`2>&1`) +- **Process substitution** — `<(...)` and `>(...)` +- **Command substitution** — `$(...)` and backticks +- **Arithmetic expansion** — `$((...))` with `+`, `-`, `*`, `/`, `%`, `**` +- **Parameter expansion** — `${var}`, `${var:-default}`, `${var:=default}`, `${var:+alt}`, `${var:?err}`, `${#var}`, `${var#pattern}`, `${var%pattern}`, `${var/pat/rep}` +- **Brace expansion** — `{a,b,c}`, `{1..10}`, `{1..10..2}` +- **Glob expansion** — `*`, `?`, `[...]` with optional dotglob +- **Tilde expansion** — `~` and `~user` +- **Logical operators** — `&&`, `||`, `&` (background) +- **Test expressions** — `[[ ... ]]` with file tests, string comparison, arithmetic comparison, and regex matching +- **Subshells** — `(...)` for isolated execution +- **Variable attributes** — `export`, `local`, `readonly` + +### Job Control + +- Background execution with `&` +- Suspend foreground jobs with Ctrl+Z +- `fg`, `bg`, `jobs`, `disown` with flags (`-l`, `-p`, `-r`, `-s`, `-h`, `-a`) +- Process group management and proper signal forwarding + +### Builtins + +`echo`, `cd`, `pwd`, `read`, `export`, `local`, `readonly`, `unset`, `source`, `eval`, `exec`, `shift`, `alias`, `unalias`, `trap`, `jobs`, `fg`, `bg`, `disown`, `pushd`, `popd`, `dirs`, `shopt`, `builtin`, `command`, `return`, `break`, `continue`, `exit`, `true`, `false`, `:` + +### Configuration + +Shell options are managed through `shopt`: + +```sh +shopt core.autocd=true # cd by typing a directory path +shopt core.dotglob=true # include hidden files in globs +shopt prompt.highlight=false # toggle syntax highlighting +shopt prompt.edit_mode=vi # editor mode +shopt core.max_hist=5000 # history size +``` + +The rc file is loaded from `~/.shedrc` on startup. + +## Building + +### Cargo + +Requires Rust (edition 2024). + +```sh +cargo build --release +``` + +The binary will be at `target/release/shed`. + +### Nix + +A flake is provided with a NixOS module and a Home Manager module. + +```sh +# Build and run directly +nix run github:km-clay/shed + +# Or add to your flake inputs +inputs.shed.url = "github:km-clay/shed"; +``` + +To use the NixOS module: + +```nix +# flake.nix outputs +nixosConfigurations.myhost = nixpkgs.lib.nixosSystem { + modules = [ + shed.nixosModules.shed + # ... + ]; +}; +``` + +Or with Home Manager: + +```nix +imports = [ shed.homeModules.shed ]; +``` + +## Status + +`shed` is experimental software and is currently under active development. It covers most day-to-day interactive shell usage and a good portion of POSIX shell scripting, but it is not yet fully POSIX-compliant.