A minimal, lightweight text editor built from scratch in C, inspired by Vim's modal editing philosophy. Clive runs directly in your terminal and provides a distraction-free editing experience with just the essentials.
Clive is a terminal-based text editor that implements core Vim-like functionality without the complexity of a full-featured editor. It operates in raw terminal mode, giving you direct control over every keystroke and screen update. The name "Clive" is a play on "C Live" - a live editor written in C.
This project was born from a desire to understand how text editors work at a fundamental level. By building Clive, I learned:
- How terminal control works through escape sequences and raw mode
- The intricacies of cursor positioning and screen rendering
- Modal editing patterns and state management
- File I/O operations and buffer management
- Low-level input handling and keyboard event processing
Building a text editor from scratch strips away all abstractions and forces you to think about every detail - from how backspace works to how lines are stored in memory. It's an exercise in understanding the tools we use every day.
- Normal Mode: Navigate and manipulate text with single-key commands
- Insert Mode: Type and edit text naturally
- Command Mode: Execute editor commands like save and quit
- Open and edit existing files or create new ones
- Line-based text buffer supporting up to 1000 lines
- Multiple cursor movement options (arrow keys and Vim-style hjkl)
- Line numbers displayed alongside your text
- Status bar showing filename, modification status, and cursor position
- Unsaved changes indicator to prevent accidental data loss
- Clipboard support for copying and pasting lines
- Bidirectional text search with pattern matching
- Quick line navigation (jump to start/end of line)
hor←- Move cursor leftjor↓- Move cursor downkor↑- Move cursor uplor→- Move cursor right0- Jump to beginning of line$- Jump to end of line
i- Enter insert mode at cursor positiono- Open a new line below current line and enter insert modeO- Open a new line above current line and enter insert modex- Delete character under cursord- Delete current line
y- Yank (copy) current line to clipboardp- Put (paste) clipboard content below current line
/- Search forward (type search term and press Enter)?- Search backward (type search term and press Enter)n- Jump to next search match (forward)N- Jump to previous search match (backward)
:- Enter command mode
Esc- Return to normal modeEnter- Create new line at cursor positionBackspace- Delete character before cursorh/j/k/lor Arrow keys - Navigate while editing- Any printable character - Insert at cursor
:w- Save current file:w filename- Save as new filename:wq- Save and quit:q- Quit (blocked if unsaved changes exist):q!- Force quit without saving
/searchterm- Search forward for "searchterm"?searchterm- Search backward for "searchterm"
Esc- Cancel command and return to normal modeBackspace- Delete character in command buffer
- GCC or any C compiler
- Unix-like operating system (Linux, macOS, WSL)
- Terminal emulator
gcc -o clive clive.c -Wall -WextraOr use the provided Makefile:
make# Create new file or edit existing
./clive filename.txt
# Start with empty buffer
./clive| Command | Action | Example Use Case |
|---|---|---|
h |
Move left | Navigate character by character |
j |
Move down | Navigate line by line |
k |
Move up | Navigate line by line |
l |
Move right | Navigate character by character |
←↓↑→ |
Arrow key movement | Alternative to hjkl |
0 |
Jump to line start | Quick navigation to beginning |
$ |
Jump to line end | Quick navigation to end |
i |
Enter insert mode | Start typing at cursor |
o |
Open line below | Add new line and start typing |
O |
Open line above | Insert line before current |
x |
Delete character | Remove single character |
d |
Delete line | Remove entire line |
y |
Yank (copy) line | Copy line to clipboard |
p |
Put (paste) line | Paste clipboard below |
/text |
Search forward | Find "text" going down |
?text |
Search backward | Find "text" going up |
n |
Next match | Jump to next search result |
N |
Previous match | Jump to previous search result |
: |
Command mode | Execute editor commands |
| Command | Action |
|---|---|
Esc |
Exit to normal mode |
Enter |
New line at cursor |
Backspace |
Delete previous character |
Arrow keys |
Navigate while inserting |
h/j/k/l |
Navigate while inserting |
| Any character | Insert at cursor position |
| Command | Action | Notes |
|---|---|---|
:w |
Write (save) file | Requires filename |
:w filename |
Save as filename | Sets new filename |
:q |
Quit editor | Blocked if unsaved changes |
:q! |
Force quit | Discards unsaved changes |
:wq |
Write and quit | Save then exit |
/pattern |
Search forward | Moves cursor to match |
?pattern |
Search backward | Moves cursor to match |
Esc |
Cancel command | Return to normal mode |
- Start in normal mode - you cannot type immediately
- Press
ito enter insert mode and start typing - Press
Escto return to normal mode from any other mode - Use
:wfrequently to save your work - The status bar shows
[+]when you have unsaved changes - Line numbers help you track your position in the file
- Use
h,j,k,lfor Vim-style navigation or arrow keys if you prefer - Search with
/for forward search or?for backward search - After searching, use
nto jump to next match orNfor previous match - Copy a line with
yand paste it below withp - Delete entire lines quickly with
d - Use
0and$to jump to line boundaries instantly
./clive myfile.txt # Open file
i # Enter insert mode
# Type your content
Esc # Return to normal mode
:w # Save
:q # Quit/searchterm # Find text forward
n # Jump to next occurrence
i # Enter insert mode to edit
# Make your changes
Esc # Back to normal mode
n # Continue to next matchy # Yank (copy) current line
j # Move down
p # Paste below current line
d # Delete a line you don't need0 # Jump to start of line
$ # Jump to end of line
k k k # Move up 3 lines
j j # Move down 2 lines- Maximum 1000 lines per file
- Maximum 256 characters per line
- No syntax highlighting
- No undo/redo functionality
- Clipboard only holds one line at a time
- No visual selection mode
- No multi-line copy/paste operations
- No split windows or tabs
- No configuration file
- Search wraps around but doesn't indicate when it does
- Undo/Redo: Implement a command history stack to reverse changes
- Search and Replace: Add
:s/old/new/command for text substitution - Visual Mode: Select and manipulate blocks of text (v, V commands)
- Multi-line Clipboard: Copy and paste multiple lines (dd, yy with counts)
- Search Wrap Indicator: Show message when search wraps around file
- Regex Search: Support regular expressions in search patterns
- Syntax Highlighting: Color coding for common programming languages
- Multiple Buffers: Edit multiple files in one session
- Configuration: Read settings from a .cliverc file
- Better Error Messages: Display helpful messages in the status bar
- Word Movement: Jump by words (w, b, e) instead of characters
- Jump to Line: Go to specific line number (:123)
- Auto-indentation: Maintain indentation on new lines
- Line Wrapping: Handle lines longer than terminal width
- Mouse Support: Click to position cursor
- Split Windows: View multiple files side by side
- Macros: Record and replay command sequences
- Plugin System: Extend functionality without modifying core
- UTF-8 Support: Handle international characters properly
- Incremental Search: Highlight matches as you type
- Dynamic Buffer: Remove line count and length limits
- Efficient Rendering: Only redraw changed portions of screen
- Gap Buffer: More efficient text insertion and deletion
- Crash Recovery: Auto-save and recover from unexpected exits
- Memory Optimization: Handle large files without loading entirely into RAM
Clive uses POSIX terminal control to achieve raw mode input handling. It disables canonical mode, echo, and signal generation to capture every keystroke. Screen updates are performed using ANSI escape sequences for cursor positioning and screen clearing.
The editor maintains a simple array-based buffer where each line is a fixed-size character array. While not the most memory-efficient approach, it keeps the implementation straightforward and easy to understand.
This is a learning project, but suggestions and improvements are welcome. The code prioritizes readability and educational value over performance optimization.
Free to use, modify, and learn from. No warranties provided.