██████╗ ██╗███╗   ███╗
  ██╔════╝ ██║████╗ ████║
  ██║  ███╗██║██╔████╔██║
  ██║   ██║██║██║╚██╔╝██║
  ╚██████╔╝██║██║ ╚═╝ ██║
   ╚═════╝ ╚═╝╚═╝     ╚═╝
  

Go + Vim = Gim

A blazingly fast, terminal-based text editor with vim-style keybindings

FeaturesInstallationKeybindingsArchitectureRoadmap

Go Version BubbleTea Lipgloss License

--- ## ✨ What is Gim? **Gim** is a modern, lightweight text editor written in Go that brings the power of vim-style modal editing to your terminal. Built on the excellent [Charm](https://charm.sh) stack, it combines the speed of Go with the elegance of functional UI patterns. ``` ┌──────────────────────────────────────────────────────────────┐ │ Why Gim? │ ├──────────────────────────────────────────────────────────────┤ │ 🚀 Fast - Native Go performance │ │ 🎨 Beautiful - Lipgloss-powered terminal styling │ │ 🧠 Vim-like - Modal editing for efficiency │ │ 🧪 Well-tested - Comprehensive integration test suite │ │ 📦 Single binary - No dependencies, just run │ └──────────────────────────────────────────────────────────────┘ ``` --- ## Trade Offs #### Undo Tree vs. Undo Stack While the undo tree method that vim uses is powerful, I rarely find myself using it. A stack terminal-based approach is more natural to "non-vim" users and much simpler to implement. Implementing a feature similar to Vims undo tree would many times longer than a simple stack. --- ## TODO List - Ops like change, and substitute and such should add to paste reg - Delete op should also add to paste reg --- ## 🎯 Features ### 🎭 Six Editor Modes | Mode | Key | Description | |------|-----|-------------| | **Normal** | `Esc` | Navigate and command - your home base | | **Insert** | `i/a/o` | Type and create | | **Visual** | `v` | Select characters | | **Visual Line** | `V` | Select whole lines | | **Visual Block** | `Ctrl+V` | Select rectangular regions | | **Command** | `:` | Execute commands *(coming soon)* | ### ⌨️ Full Motion System ``` gg ↑ b ←── · ──→ w/e ↓ G 0 ──────── $ │ _ │ └──┴───────┘ line ``` - **Character motions**: `h` `j` `k` `l` - The classics - **Word motions**: `w` `e` `b` - Jump by word boundaries - **Line motions**: `0` `$` `_` - Start, end, first non-whitespace - **File motions**: `gg` `G` - Top and bottom of file ### 🔧 Powerful Operators | Operator | Action | Examples | |----------|--------|----------| | `d` | Delete | `dd` `dw` `d$` `dG` | | `x` | Delete char | `x` `3x` | *Operators compose with motions and counts!* ``` 3 d 2w ↓ ↓ ↓ count op motion = Delete 6 words (3 × 2) ``` ### 🎪 Visual Mode Magic Select text visually, then operate on it: ``` ┌─────────────────────────────────┐ │ Hello, [world! How] are you? │ ← v + motion + d │ Hello, are you? │ ← Result └─────────────────────────────────┘ ┌─────────────────────────────────┐ │ [Line one ] │ │ [Line two ] │ ← V + j + d │ [Line three ] │ │ │ ← All lines deleted └─────────────────────────────────┘ ``` ### 🔢 Count Everything Prefix any command with a number: | Input | Action | |-------|--------| | `5j` | Move down 5 lines | | `3dd` | Delete 3 lines | | `10i=Esc` | Insert `==========` | | `2d3w` | Delete 6 words | ### 🪟 Smart Scrolling - Automatic viewport following - `scrollOff` margin keeps context visible - Smooth cursor tracking --- ## 📦 Installation ### From Source ```bash # Clone the repository git clone https://git.gophernest.net/azpect/TextEditor.git cd TextEditor # Build go build -o gim ./cmd/gim # Run ./gim [filename] ``` ### Quick Run ```bash go run ./cmd/gim [filename] ``` --- ## ⌨️ Keybindings ### Normal Mode
🧭 Navigation | Key | Action | |-----|--------| | `h` | Move left | | `j` | Move down | | `k` | Move up | | `l` | Move right | | `w` | Next word start | | `e` | Next word end | | `b` | Previous word start | | `0` | Line start | | `$` | Line end | | `_` | First non-whitespace | | `gg` | File start | | `G` | File end |
✏️ Entering Insert Mode | Key | Action | |-----|--------| | `i` | Insert before cursor | | `a` | Insert after cursor | | `I` | Insert at line start | | `A` | Insert at line end | | `o` | Open line below | | `O` | Open line above |
🗑️ Deletion | Key | Action | |-----|--------| | `x` | Delete character | | `dd` | Delete line | | `d{motion}` | Delete to motion | | `D` | Delete to end of line |
👁️ Visual Mode | Key | Action | |-----|--------| | `v` | Character visual | | `V` | Line visual | | `Ctrl+V` | Block visual |
### Insert Mode | Key | Action | |-----|--------| | `Esc` | Return to normal | | `Backspace` | Delete previous char | | `Delete` | Delete next char | | `Ctrl+W` | Delete previous word | | `Tab` | Insert tab (2 spaces) | | `Enter` | New line | | `↑↓←→` | Navigate | ### Visual Mode All normal mode navigation keys work, plus: | Key | Action | |-----|--------| | `d` | Delete selection | | `Esc` | Return to normal | --- ## 🏗️ Architecture Gim follows a clean, modular architecture inspired by the Elm Architecture (Model-Update-View): ``` ┌─────────────────────────────────────────────────────────────┐ │ cmd/gim/ │ │ Entry Point │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ internal/editor/ │ │ Model • Update • View • Style │ └─────────────────────────────────────────────────────────────┘ │ │ │ ▼ ▼ ▼ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ internal/input/ │ │ internal/motion/│ │internal/operator│ │ Handler │ │ h j k l w e │ │ d (delete) │ │ Keymap │ │ b 0 $ gg G │ │ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ │ └───────────────────┴────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ internal/action/ │ │ Action • Motion • Operator • Position │ │ (Core Interfaces) │ └─────────────────────────────────────────────────────────────┘ ``` ### Key Design Patterns - **🔌 Interface-based**: Actions/motions use a `Model` interface, enabling clean testing - **🎭 State Machine**: Input handler manages mode transitions and pending operations - **📐 Motion Types**: Linewise vs Charwise motions for proper operator behavior - **🔄 Composition**: Operators compose with motions (e.g., `d` + `w` = delete word) --- ## 🧪 Testing Gim has comprehensive integration tests using the `teatest` library: ```bash # Run all tests go test ./... # Run with verbose output go test -v ./internal/editor/ # Run specific test go test -v -run TestDeleteOperator ./internal/editor/ ``` **Test Coverage Areas:** - ✅ Basic motions (hjkl) - ✅ Jump motions (gg, G, 0, $, _) - ✅ Word motions (w, e, b) - ✅ Delete operator with all motions - ✅ Insert mode (all entry points, recording, replay) - ✅ Visual mode (all three types) - ✅ Scrolling behavior --- ## 🗺️ Roadmap ### ✅ Implemented - [x] Modal editing (Normal, Insert, Visual, Visual Line, Visual Block) - [x] Basic motions (hjkl, word motions, line motions) - [x] Delete operator with motion composition - [x] Count prefixes for all commands - [x] Insert mode with recording/replay - [x] Visual selection with operators - [x] Smart scrolling with scrollOff - [x] Relative line numbers ### 🚧 In Progress - [ ] Command mode (`:` commands) - [ ] File I/O (save/load) ### 🔮 Future - [ ] **Operators**: `y` (yank), `c` (change), `p` (paste) - [ ] **Motions**: `f`/`F`/`t`/`T` (find char), `/`/`?` (search), `{`/`}` (paragraph) - [ ] **Features**: - Undo/redo system - Multiple buffers/tabs - Syntax highlighting - Configuration file - Clipboard integration - Macros (`q` recording) - Marks (`m` and `'`) - Registers (`"`) - Text objects (`iw`, `a"`, etc.) - Plugins system --- ## 🎨 Built With

BubbleTea

- **[BubbleTea](https://github.com/charmbracelet/bubbletea)** - The fun, functional TUI framework - **[Lipgloss](https://github.com/charmbracelet/lipgloss)** - Style definitions for terminal apps - **[Go](https://go.dev)** - The language that makes it all possible --- ## 🤝 Contributing Contributions are welcome! Whether it's: - 🐛 Bug fixes - ✨ New features - 📖 Documentation improvements - 🧪 Test coverage Feel free to open issues and pull requests! --- ## 📜 License This project is open source. See [LICENSE](LICENSE) for details. ---

Made with 💜 and lots of ☕

"Because sometimes you just want to build your own vim"