Coming from Vim
bi keeps vim’s grammar — counts, operators, motions, text objects, ., :s, :g, ranges — so your fingers already know most of it. This page is the rest: what bi does differently, what it adds, and what is not there yet.
Keys that mean something else
| Key | In vim | In bi |
|---|---|---|
s |
cl spelled shorter |
jump: type a few characters, press the letter next to the match (lesson) — cl still works |
S |
cc spelled shorter |
select by structure: a letter at both ends of every tree-sitter scope around the cursor (lesson) — cc still works |
ga |
print the character’s code | :alt — open the alternate file: .h beside .c, _test.go beside .go |
gA |
— | :valt — the alternate file in a vertical split |
gf |
edit the file name under the cursor | the fuzzy file picker over the whole project |
gb |
— | the buffer switcher, most recently shown first |
gh |
select mode | in the file tree: show dotfiles |
K |
man the word |
what the language server knows about the cursor |
"p "P |
paste from register p |
open the picker over every capture, then paste |
"n |
register n |
the named space: capture first, name it after with :yname |
"* |
the primary selection | a spelling of "+ — the system clipboard |
Tab |
same byte as Ctrl-I |
the same — so it is jump-forward, and never buffer-next |
Space |
l |
l until a <leader> binding claims it; bi ships <leader><leader> for code actions |
- |
line up, first non-blank | out of the file into the file tree |
Shift-↓ Shift-↑ |
scroll a page | move the line or the selected block one row |
Ctrl-N |
next line | add a cursor at the next occurrence (in insert mode: next completion) |
Ctrl-X |
subtract from a number | skip this occurrence while adding cursors |
Registers are a ring
Vim asks you to choose one of 36 slots at yank time, which is the moment you
least know whether something is worth keeping. bi captures every y, d, c
and x into a ring 4096 deep and moves the choice to paste time, where
"p opens a picker that can search it. Plain p still pastes the newest
capture.
"a–"z slots and no numbered "1–"9 delete registers. Named registers exist, but you name a capture after taking it: "nyy, then :yname x. "np picks among the names.The clipboard is explicit: nothing is mirrored to it, because exporting
every dd to the desktop is a surprise that cannot be undone. "+y sends
over OSC 52, so it works over SSH too.
Search
- Smartcase by default. An all-lowercase pattern ignores case; a capital anywhere makes it exact.
- No highlight by default, as in vim —
:hlsturns it on,:nohoff. - The footer becomes the search while you are searching: the pattern, and
[3/17]— which match you are on out of how many. - No regular expressions in
/or:syet.:find~and:replace~, the project-wide pair, do take a regex. &repeats the last:swith its flags, where vim drops them.
Windows and buffers
:spopens below and:vsto the right, and focus moves into the new window. Vim does the opposite, which makes focus look like it did not move.:qcloses the window and never asks about unsaved changes — the buffer stays in the list.:bddeletes a buffer and is the one that asks.Ctrl-W fputs a letter in every window; press it to go there.:resizetakes ratios::resize 1:2divides a split one to two.- No tab pages, and no moving windows around (
Ctrl-W xrH J K L).
Options
:set number {n}is one option with a value:0off,-1relative,1every line,5every fifth.:set nuand:set rnudo not exist.- Options are spelled
:set name value(:set number=5works too) and resolve per file: bi’s defaults, then your[options], the filetype’s rules, the project’s.editorconfig, and finally:set. - The config is TOML at
~/.config/bi/config.toml, and it is a patch over the compiled-in defaults, not a replacement. There is no vimscript, no Lua and no plugin system.
Editing details
:wtrims: trailing whitespace, blank lines at either end, and a missing final newline — as its own undo step. Markdown keeps its two-space line breaks. Turn any of it off per project in.editorconfigor config.:retabrewrites leading whitespace only; a tab inside a string is content.:gruns a fixed set of sub-commands —d,s,&,m,case,retab,normal— so:g/x/qcannot close the editor.c,IandAin a block show the text on every row as you type, not when you pressEsc. The file ends up the same.- Visual
pputs what it replaced on the ring, so select-pswaps two things;Pleaves the ring alone. - A new line in insert mode that you leave empty loses its indent on
Esc. Tabin insert mode moves to the next indent stop instead of inserting a fixed width;Shift-Tabgoes back.- Undo is a tree: undoing and typing keeps the old branch. Nothing reaches
those branches yet (
g-,g+,:earlier). - Every
:command that takes a line range takes'vtoo — the selection itself, rectangle included. Pressing:in visual mode prefills it.
What bi adds
Things you would install plugins for in Neovim, already in the binary:
tree-sitter with twenty grammars, a language server client with completion
and code actions, surround (ys ds cs), comments (gc), multiple
cursors, label jumps, pickers, a file tree with copy/move/rename, git signs,
project find and replace with a preview, indent guides,
TODO highlighting, colour swatches, .editorconfig, encodings and CRLF kept
byte-identical, images in terminals that speak the kitty protocol, and text
tools like :sort, :align, :case, :base64e, :uuid4 and :jsonfmt.
The Learn section walks through all of it with screenshots.
Not there yet
- Macros (
q,@) and marks (m{a},`{a}). gn,HML,zzztzb,Ctrl-FCtrl-B.- Regular expressions in
/and:s. - Persistent undo, and reaching abandoned undo branches.
- Folding, tab pages, and tree-sitter injections (a code fence in markdown stays plain).
- Git beyond signs and a numstat — no hunks, staging or blame.