Files and windows¶
Reading and writing¶
:w write
:w other.py write somewhere else, and edit that from now on
:q quit — refuses if the buffer has unsaved changes
:q! quit anyway
:wq :x write and quit
ZZ the same, without the colon
:q with a split open closes the window, as vim's does. Only the last window closing leaves the editor.
Several files at once¶
A buffer is a file that is open. A window is a rectangle looking at one. They are different things, and the difference is most of what this page is about.
:e path open a file
:e read this one again off the disk
:e! …discarding what you changed
:ls list the buffers (:buffers, :files)
:bn the next buffer (:bnext)
:bp the one before (:bprev, :bN)
:b name the buffer whose name matches (:buffer)
A file already open comes back as the buffer it is, never as a second copy: two buffers on one file would each hold half the undo history, and whichever was written last would quietly throw the other's work away.
Switching buffers keeps your registers and macros (those belong to the session) and leaves the undo history with the buffer it came from.
Splits¶
:sp [path] a window above this one (:split, :new)
:vsp [path] a window beside it (:vsplit, :vs, :vnew)
:clo close this window (:close)
:on close every other one (:only)
Then Ctrl+W and one of:
w |
the next window in reading order, wrapping |
h j k l |
left, down, up, right (arrows work too) |
s v |
split this one, horizontally or vertically |
c q |
close it |
o |
close every other one |
Two windows on one buffer share the text and keep their own cursors, so :sp lets you read two parts of one file at once.
The layout is a grid, not a tree: :sp adds a row across the full width, :vsp adds a window to the row it is in. Nobody who splits one way at a time can tell the difference.
The file picker¶
Ctrl+P, or :find, is a fuzzy picker over the project. Type a few letters of the path and press Enter; it opens in the current window. The characters that matched are underlined, so you can see why something ranked where it did.
It searches from the same project root :grep uses, and skips the same build output. The walk is pruned as it goes, so it reads the project without reading its virtualenv.
The system clipboard¶
This is a subprocess away (pbcopy on macOS, wl-copy or xclip on Linux), so it cannot happen inside a keystroke. The keymap records what was asked for and the session performs it. You will not notice, except that a machine with none of those programs installed says so.
Encodings and line endings¶
Three things are decided when a file is read and then honoured for the life of the buffer: how the bytes were decoded, what the line endings were, and whether the last line had one.
A latin-1 file with CRLF endings and no trailing newline is written back as exactly that. Getting any of this wrong turns "open a file and save it" into a diff of the whole file, which is the worst bug a text editor can have: it is silent, it is in every file you touch, and version control reports it as your work.
UTF-8 is tried first and latin-1 is the fallback, because every byte sequence is valid latin-1. A file it is wrong about still round-trips byte for byte. A byte-order mark is detected, never guessed at.
You can override any of it:
:set ff=unix write LF endings (fileformat)
:set ff=dos write CRLF
:set ff say which it is now
:set eol end the file with a newline
:set noeol do not
:set encoding=utf-8
.editorconfig sets the first two for you where it says so (see settings).
Crash recovery¶
Every few seconds, each modified buffer is copied under $XDG_DATA_HOME/turbovi/recover/. If the editor dies, the copy is still there.
Opening a file with a recovery copy newer than it says so:
vi has no dialog for this, and a buffer silently replaced by a recovery copy is worse than one that tells you the copy is there. Writing the file clears the copy, because a buffer that matches its file has nothing to recover.