https://github.com/excelano/ved
The verbose ed — a drop-in compatible ed clone with friendly errors, written in pure-stdlib Rust
https://github.com/excelano/ved
Last synced: about 1 month ago
JSON representation
The verbose ed — a drop-in compatible ed clone with friendly errors, written in pure-stdlib Rust
- Host: GitHub
- URL: https://github.com/excelano/ved
- Owner: excelano
- License: mit
- Created: 2026-04-12T22:05:06.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-05-25T14:31:03.000Z (about 1 month ago)
- Last Synced: 2026-05-25T16:29:21.178Z (about 1 month ago)
- Language: Rust
- Homepage: https://excelano.github.io/ved/
- Size: 73.2 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# ved — the verbose ed
A drop-in compatible clone of [ed](https://www.gnu.org/software/ed/), the original Unix line editor, written in pure-stdlib Rust. ved adds friendly error messages, command confirmations, long-form command aliases, and a built-in help reference while preserving strict compatibility so any script written for real ed runs against ved unchanged.
**Full tutorial:** [https://excelano.github.io/ved/](https://excelano.github.io/ved/)
## Why
ed's one-character error messages and silent operations make it notoriously hard to learn. ved keeps ed's interface and behavior but tells you what happened: `deleted 3 lines (2-4)` instead of silence, `? no match` instead of `?`, and `help` prints a command reference without leaving the editor. If you already know ed, ved works exactly the same. If you're learning, ved explains what's going on.
## Install
The fastest path on Linux or macOS is the prebuilt-binary installer:
```sh
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/excelano/ved/releases/latest/download/ved-installer.sh | sh
```
On Windows, in PowerShell:
```powershell
powershell -ExecutionPolicy ByPass -c "irm https://github.com/excelano/ved/releases/latest/download/ved-installer.ps1 | iex"
```
The installer downloads the right tarball for your platform from the GitHub release, verifies its checksum, and drops the binary into `~/.cargo/bin` (or the equivalent on Windows). If `ved` isn't found on your `PATH` after installation, ensure `~/.cargo/bin` is on it. Releases also ship raw tarballs (`ved-*.tar.xz` / `.zip`) for manual installation.
To uninstall, remove the binary: `rm ~/.cargo/bin/ved`. ved stores nothing else on disk.
### Debian and Ubuntu
Install from the [Excelano apt repository](https://excelano.com/apt/), so `apt upgrade` keeps it current:
```sh
curl -fsSL https://excelano.com/apt/setup.sh | sudo sh
sudo apt install ved
```
The apt package is currently amd64 only; arm64 ships with the next release. On arm64, use the prebuilt installer above.
## Build from source
ved requires only a Rust toolchain (1.85+ for edition 2024). No external crates, no C dependencies, no runtime.
```sh
cd ved
cargo build --release
```
The binary is at `target/release/ved`. To install system-wide:
```sh
make build # build as your user (needs cargo)
sudo make install # copy binary to /usr/local/bin
sudo make install PREFIX=/usr # or specify a different prefix
```
To run without installing:
```sh
cargo run -- -p '* '
```
The `--` separates cargo's flags from ved's. `-p '* '` sets the command prompt (ed has no prompt by default).
## Quick start
```
$ ved myfile.txt # open a file
135 # ved prints the byte count
* ,p # print all lines
Hello world
This is a test file
* 1s/Hello/Goodbye/ # substitute on line 1
Goodbye world
* g/test/n # print lines matching "test" with numbers
2 This is a test file
* w # write back to the file
37
* q # quit
```
## Commands
| Command | Long form | Description |
|---|---|---|
| `[.]a` | `append` | Append text after the addressed line (end with `.`) |
| `[.]i` | `insert` | Insert text before the addressed line (end with `.`) |
| `[.,.]c` | `change` | Replace the addressed lines with new text (end with `.`) |
| `[.,.]d` | `delete` | Delete the addressed lines |
| `[.,.]p` | `print` | Print the addressed lines |
| `[.,.]n` | `number` | Print with line numbers |
| `[.,.]s/re/new/[g]` | | Substitute: replace regex matches in addressed lines |
| `[.,.]g/re/cmd` | | Global: run a command on every line matching a regex |
| `[.,.]v/re/cmd` | | Inverse global: run a command on lines NOT matching |
| `[.,.]w [file]` | | Write the addressed lines (default: all) to a file |
| `e [file]` | | Edit: replace the buffer with a file's contents |
| `r [file]` | | Read: append a file's contents after the addressed line |
| `q` | `quit` | Quit (warns on unsaved changes; repeat to force) |
| `Q` | | Quit unconditionally |
| `H` | `help` | Print the command reference |
## Addresses
Addresses specify which lines a command operates on. Most commands default to the current line (`.`).
| Address | Meaning |
|---|---|
| `5` | Line 5 |
| `.` | Current line |
| `$` | Last line |
| `+3` / `-1` | Relative to current line |
| `,` | All lines (shorthand for `1,$`) |
| `;` | Current line to end (shorthand for `.,$`) |
| `2,7` | Lines 2 through 7 |
## Regular expressions
ved implements POSIX Basic Regular Expressions (BRE) with a hand-written engine. No external regex library.
| Syntax | Meaning |
|---|---|
| `.` | Any single character |
| `*` | Zero or more of the preceding element |
| `^` / `$` | Start / end of line anchors |
| `[abc]` | Character class: matches a, b, or c |
| `[^abc]` | Negated class: matches anything except a, b, c |
| `[a-z]` | Range: matches any lowercase letter |
| `\(...\)` | Capturing group |
| `\1` ... `\9` | Backreference to captured group |
In replacement strings: `&` expands to the whole match, `\1`-`\9` expand to captured groups, `\&` is a literal ampersand.
## Implementation
2,006 lines of Rust across four modules, zero dependencies, 76 tests.
| Module | Lines | Purpose |
|---|---|---|
| `main.rs` | 753 | REPL, command dispatch, substitute/global/write/read |
| `bre.rs` | 929 | BRE regex engine: compiler, matcher, replacement expander |
| `address.rs` | 208 | Address parser and resolver |
| `buffer.rs` | 116 | Line buffer with current-line tracking |
The BRE engine started as a translation of Rob Pike's ~30-line recursive matcher from "The Practice of Programming," then grew bottom-up through a compile step (inspired by Ken Thompson's original ed), bracket expressions, capturing groups, and backreferences. The full history is in the git log.
## License
MIT. See [LICENSE](LICENSE).