TurboVI
A vi clone for the terminal: modes, counts, operators, registers, marks, macros, split windows and :s, in about three thousand lines of Python.
uv sync
uv run turbovi somefile.py
uv run turbovi one.py two.py # two buffers, :bn between them
uv run turbovi # a scratch buffer
:q to leave, :help for what is here.
What a vim user gets
The grammar, ["x] [count] operator [count] motion, over hjkl w b e W B E 0 ^ $ gg G { } f F t T %. Operators d c y > < with doubling (dd, yy, cc), text objects (iw aw i( a" i{), and x X D C s S r ~ J p P o O.
Modes: normal, insert, visual, visual-line and command.
Paging with <C-f> <C-b> <C-d> <C-u>, by the window rather than by a fixed number, and <C-e> / <C-y> to move the view without moving the cursor.
Search with / ? n N and match highlighting. Undo and redo with u and <C-r>. . repeats the last change, recorded as keystrokes the way vi does it, so a change that ends in insert mode replays whole.
:s with ranges (%, ., $, 1,5, .+1), the g, i and n flags, any non-alphanumeric delimiter, and & in the replacement. One u undoes the whole substitution.
Marks: ma puts one down, `a comes back to the character and 'a to the first non-blank of that line. Every jump leaves a mark, so `` returns from a G or a search. `:marks` lists them. They are not shifted when the text moves, which is the one place this is smaller than vi.
Macros: qa records into register a, q stops, @a plays, 3@a plays three times, @@ repeats the last. They share storage with the yank registers the way vi's do, so "ap pastes a macro as text and @a runs a yanked line. A macro that calls itself stops with a message rather than a stack that runs out.
Several files at once with :e :ls :bn :bp :b, split windows with :sp and :vsp, and <C-w> then w s v c o or h j k l to move between them. <C-p> and :find are a fuzzy picker over the project: type a few letters of the path and it opens in the current window.
The system clipboard on "+y and "+p, over OSC 52 and a local helper, so it crosses ssh.
Syntax colouring from the file's name. :set syntax=rust colours a file with no suffix, :set nosyntax stops. A search hit and a selection paint over the colouring, because finding something inside a comment has to be visible.
A file opens and saves as itself. The encoding, the line endings and whether the last line had a newline are read once and written back unchanged. A latin-1 file stays latin-1, a CRLF file stays CRLF, and a file with no trailing newline does not gain one.
Settings and recovery
Settings live in $XDG_CONFIG_HOME/turbovi/config, a file of ex commands the way a vimrc is:
set nu
set rnu
sp
A modified buffer is copied to $XDG_DATA_HOME/turbovi/recover/ every few seconds, keyed by a hash of its absolute path, and :recover puts it back after a crash without writing anything to disk. The recovery copy is dropped when the buffer is saved.
What it is not
Not a vim: no plugins, no scripting language, no :g, no folds, no tabs, no persistent undo across sessions yet.
Built on turbodesk
turbodesk is the immediate-mode terminal UI library underneath. This editor is the application on it that uses no widgets at all — views, events and hooks, nothing else — which is what proved the core carries a real application on its own. It lived in that repository as examples/vi/ until 2026-08-26; a smaller showcase version stays there.
Release files for turbovi 0.3.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| turbovi-0.3.2.tar.gz | 59.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| turbovi-0.3.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 127.8 kB
Release files / turbovi-0.3.2.tar.gz
| Download URL | turbovi-0.3.2.tar.gz |
|---|---|
| Size | 59.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d3965e47485750450607651c9b6807007fc4233613e1826a36eaf264416d5dda
|
|
BLAKE2b-256 checksum How to use checksums |
0a2351277379e25395403702dc04b4761f4cfd4f4795d43330679ca555b0ac89
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.30 {"installer":{"name":"uv","version":"0.11.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / turbovi-0.3.2-py3-none-any.whl
| Download URL | turbovi-0.3.2-py3-none-any.whl |
|---|---|
| Size | 68.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e806dcb6434eb44bd99c60993edeafc88d07203baf3f1234747f2becfb900f81
|
|
BLAKE2b-256 checksum How to use checksums |
cf187122853db08c785f450c06030d0632e7b4fe62045d7d0347b337fdabf4f3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.30 {"installer":{"name":"uv","version":"0.11.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|