nvim
Vanilla nvim, no plugin manager — everything here is a built-in.
Modes
i- insert mode (bar cursor, typing = text)
A- insert at end of current line
a- insert after cursor
o / O- open new line below / above, enter insert mode
Esc- back to normal mode (block cursor, keys = commands)
u- undo last change
Ctrl-r- redo (undo the undo)
Quitting / saving
:w- save
:q- quit (fails if unsaved changes)
:q!- quit without saving (escape hatch)
:wq- save and quit
:x- save and quit only if there were changes
File paths
:e <path>- open a file (replaces current buffer)
:tabnew <path>- open a file in a new tab
:sp <path>- open a file in a horizontal split
:vsp <path>- open a file in a vertical split
Relative paths (:e practice.py) resolve against nvim's cwd, not your last-opened file or your shell prompt's visible dir — check with :pwd.
Motions
/pattern + n/N- search forward, next/previous match
?pattern- search backward
200G or :200- jump to line 200
gg / G- jump to first / last line
0 / $- start / end of current line
w / b- jump forward / backward one word
dd- delete current line
dw- delete word
d$- delete to end of line
yy- yank (copy) current line
p / P- paste after / before cursor
Registers
"ayy- yank current line into register
a
"ap- paste register
a's contents
Named registers a–z persist until overwritten; unnamed register " holds the most recent yank/delete regardless of a named register.
Macros
qa ... q- record keystrokes into register
a, stop recording
@a- replay macro
a once
14@a- replay macro
a 14 times
@@- replay the last-used macro again
Search / replace
:%s/old/new/g- replace every match, whole file (
% = whole file, g = all matches per line)
:s/old/new/g- same, but current line only
:%s/old/new/gc- same as the whole-file version, but confirm each match first
Windows / splits
:sp- split horizontally (new split on top)
:vsp- split vertically (new split on left)
Ctrl-w h/j/k/l- move focus to the split left/down/up/right
Ctrl-w w- cycle focus to the next split
Ctrl-w q- close the current split
Ctrl-w =- resize all splits to equal size
Tabs
:tabnew <path>- open a file in a new tab
gt / gT- next / previous tab
:tabclose- close current tab
LSP (Python via pyright)
Requires pyright on PATH (npm install -g pyright) — auto-attaches to any .py buffer via init.lua's FileType python autocmd. No plugin manager needed; this is nvim's built-in vim.lsp client (0.10+).
gd- go to definition (jumps to where a symbol is actually defined)
K- hover (type info / docstring for whatever's under the cursor)
<leader>e- show the diagnostic under the cursor in a floating window (leader = space)
]d / [d- jump to next / previous diagnostic in the buffer
Scope boundary
Pyright catches type/reference errors it can see in the code itself (typo'd method names, wrong argument types). It does NOT catch logic bugs like "no caller actually passes this parameter" — that requires tracing actual call sites, a different and harder problem than type-checking a single file.
netrw (file browser)
Built into nvim — no plugin required. Not a persistent sidebar; each command opens a full directory listing that replaces or splits your current buffer.
:Ex- open netrw in the current window (replaces buffer, like
:e but browsable)
:Vex- open netrw in a vertical split (like
:vsp)
:Sex- open netrw in a horizontal split (like
:sp)
Enter (on a file)- open it in the netrw window
%- create a new file at the current netrw location
d- create a new directory
D- delete the file/directory under the cursor (confirms first)
R- rename the file/directory under the cursor
No persistent panel and no git-status-in-tree — for that, a plugin (nvim-tree, neo-tree, oil.nvim) is required, out of scope for this vanilla-nvim setup.
Mode indicator (Warp/tmux specific)
Cursor SHAPE is the real signal: thin bar = insert mode, solid block = normal mode. The text status line at the bottom does not show a mode name in this setup — go by cursor shape, not status-line text.