A lightweight, fast-starting Emacs-like terminal text editor written in pure Go.
goomacs provides a familiar Emacs keybinding experience for quick file editing without the overhead of a full Emacs installation. It is designed to be minimal, portable, and easy to use.
- Emacs keybindings -- Navigate and edit with standard Emacs key sequences
- Incremental search -- Forward and backward search with wraparound (C-s / C-r)
- Mark and region -- Set mark, select regions, kill/copy/yank (C-SPC, C-w, M-w, C-y)
- Kill ring -- Consecutive kills accumulate; yank pastes the last kill
- Undo -- Up to 100 levels of undo history (C-_ / C-/)
- Tab support -- Displays tabs with 8-column tab stops
- Multiple buffers -- Open and switch between multiple files (C-x b, C-x C-f, C-x C-b)
- Window splitting -- Split the screen vertically (C-x 2) or horizontally side-by-side (C-x 3) to view multiple buffers at once
- Syntax highlighting -- Automatic syntax coloring for source code files using Chroma (monokai theme, 256-color)
- M-x command palette -- Execute commands by name with tab completion (M-x)
- Comment/uncomment region -- Toggle comments on selected code with automatic language detection (30+ languages)
- Tab completion -- Filename and command name completion in prompts (Tab key)
- Find-grep -- Search across files with M-x find-grep and navigate results (RET, n/p, M-n/M-p)
- Goto line -- Jump to any line by number (C-l)
- Minimal dependencies -- Pure Go implementation using ANSI/VT100 escape sequences
Requires Go 1.24 or later.
go install github.com/ryogrid/goomacs@latestThis installs the goomacs binary to $GOPATH/bin (default: ~/go/bin). Make sure this directory is in your $PATH.
To build from source instead:
go build -o goomacs ../goomacs # Open with an empty *scratch* buffer
./goomacs filename.txt # Open a single file
./goomacs file1.go file2.go # Open multiple files (first is active)| Key | Action |
|---|---|
| C-f / Right | Forward one character |
| C-b / Left | Backward one character |
| C-n / Down | Next line |
| C-p / Up | Previous line |
| C-a | Beginning of line |
| C-e | End of line |
| M-< | Beginning of buffer |
| M-> | End of buffer |
| C-v | Scroll down one page |
| M-v | Scroll up one page |
| C-l | Goto line (prompts for line number) |
| Key | Action |
|---|---|
| C-h | Backspace (delete character before cursor) |
| C-d | Delete character at cursor |
| C-j | Newline (same as Enter) |
| C-k | Kill line (cut to end of line) |
| C-SPC | Set mark |
| C-w | Kill region (cut) |
| M-w | Copy region |
| C-y | Yank (paste) |
| C-_ / C-/ | Undo |
| C-g | Cancel / deactivate mark |
| Key | Action |
|---|---|
| C-s | Incremental search forward |
| C-r | Incremental search backward |
| Key | Action |
|---|---|
| C-x C-s | Save file |
| C-x C-f | Open file (find-file) |
| C-x b | Switch buffer by name |
| C-x C-b | List all open buffers |
| C-x k | Close (kill) buffer |
| C-x C-c | Quit (warns on unsaved changes) |
| Key | Action |
|---|---|
| C-x 2 | Split window vertically (top/bottom) |
| C-x 3 | Split window horizontally (side-by-side) |
| C-x o | Move focus to next window |
| C-x 0 | Close current window |
| C-x 1 | Close all other windows |
| Key | Action |
|---|---|
| M-x | Open command prompt (type command name, Tab to complete, Enter to execute) |
Available commands:
| Command | Description |
|---|---|
| comment-region | Comment out the selected region (requires active mark) |
| uncomment-region | Remove comments from the selected region |
| find-grep | Search across files using find/grep (results in grep buffer) |
| Key | Action |
|---|---|
| RET | Jump to source file and line |
| n | Next result |
| p | Previous result |
| M-n | Next file |
| M-p | Previous file |
| g | Refresh results |
| q | Close grep buffer |
Language detection is automatic (powered by go-enry). Supported languages include Go, Python, JavaScript, TypeScript, Rust, C, C++, Java, Ruby, Shell, HTML, CSS, SQL, Haskell, Lisp, and 15+ more. For unrecognized languages, # is used as the default comment prefix.
The status bar at the bottom of the screen shows:
- Filename (or
[No Name]for unsaved buffers) [Modified]indicator when the buffer has unsaved changes- Current line / total lines and column number (e.g.,
Line 42/100, Col 15)
goomacs/
├── main.go # Event loop, keybinding dispatch, and UI rendering
├── buffer.go # Buffer data structure and editing operations
├── grep.go # Find-grep command, grep output parser, *grep* buffer mode
├── grep_test.go # Grep parser unit tests
├── command.go # Command registry, M-x commands, comment/uncomment logic
├── highlight.go # Chroma-based syntax highlighting module
├── buffer_test.go # Buffer unit tests (69 tests)
├── main_test.go # Main package tests
├── go.mod # Go module definition
├── term/ # Pure Go terminal backend
│ ├── screen.go # Screen interface, Event types, Style, KeyCode constants
│ ├── terminal.go # Terminal implementation (raw mode, ANSI rendering, input parsing)
│ └── terminal_test.go # Terminal backend tests (26 tests)
├── e2e/ # End-to-end tests (tmux-based)
│ ├── harness.go # tmux session management and screen capture
│ ├── assertions.go # Screen assertion helpers and golden file support
│ ├── e2e_test.go # TestMain, test helpers, smoke test
│ ├── basic_test.go # Basic editing tests
│ ├── navigation_test.go # Cursor movement and scrolling tests
│ ├── search_test.go # Incremental search tests
│ ├── killyank_test.go # Kill, yank, and undo tests
│ ├── buffer_test.go # Buffer management tests
│ ├── window_test.go # Window splitting tests
│ ├── grep_test.go # Find-grep E2E tests
│ ├── highlight_test.go # Syntax highlighting smoke tests
│ └── testdata/ # Golden files for snapshot assertions
└── impl_docs/ # Implementation documentation
├── architecture.md # Architecture overview with diagrams
├── buffer.md # Buffer data structure documentation
├── terminal.md # Terminal backend documentation
└── event-loop.md # Event loop and rendering documentation
- github.com/alecthomas/chroma/v2 -- Syntax highlighting (lexers and themes)
- github.com/go-enry/go-enry/v2 -- Programming language detection for comment style lookup
- github.com/mattn/go-runewidth -- Unicode character width calculation (East Asian wide characters, etc.)
All terminal handling uses only the Go standard library (syscall, os, bufio, unicode/utf8, etc.) via ANSI/VT100 escape sequences.
go test ./...E2E tests use tmux to spawn goomacs in a pseudo-terminal, send keystrokes, and verify screen output. This catches rendering and interaction bugs that unit tests cannot.
Prerequisites:
# Install tmux (Ubuntu/Debian)
sudo apt-get install -y tmux
# Or on macOS
brew install tmuxRun E2E tests:
go test ./e2e/ -v -timeout 120sThe tests automatically build the goomacs binary before running. If tmux is not installed, the tests are skipped.
Update golden files (snapshot assertions):
UPDATE_GOLDEN=1 go test ./e2e/ -v -timeout 120sThis project is licensed under the MIT License. See LICENSE.txt for details.