Vim
post by lsusr · 2021-04-07T06:35:59.268Z · LW · GW · 57 commentsContents
Movement Editing Text Objects Insert Mode Miscellaneous edit commands The Undo Tree Macros Visual mode Find and Replace Enter and exit Cheatsheet None 57 comments
Vim is a terminal-based editor optimized for speed. Keys are hotkeys by default. Vim does not even use Ctrl
for most of them. Maneuvering via hotkeys is so efficient mouse input is often disabled by default.
This guide focuses on the features I use most frequently. It has nothing about with native Vim windows because I use i3 or Spacemacs instead. If you feel I left out a valuable feature then please let me know about it in the comments.
Movement
The simplest way to move is via the hjkl
keys.
key | action |
---|---|
h | moves the cursor one character left |
j | moves the cursor one line down |
k | moves the cursor one line up |
l | moves the cursor one character right |
The hl
keys operate within a single line. Pressing h
at the start of a line does nothing. Pressing l
at the end of a line does nothing. By line I mean a string of characters ending with a carriage return. The fact that a long paragraph appears to wrap around on your screen is irrelevant.
The jk
keys move the cursor down and up a single line. If the cursor is in the 3rd column of the 6th line then pressing j
moves the cursor to the 3th column of the 7th line.
Most commands can be prefixed with a number. 4h
moves the cursor left 4 characters. 101j
moves the cursor down 101 lines.
A sequence of nonempty lines is called a paragraph. The {}
keys move the cursor forward and back by paragraphs.
key | action |
---|---|
} | moves the curser forward one paragraph |
{ | moves the curser backward one paragraph |
There are two kinds of "words" in Vim. A word is a sequence of alphanumeric characters. A Word is a sequence of non-whitespace characters. The wbe
keys move the cursor around words. The WBE
keys move the cursor around Words.
key | action |
---|---|
w | moves the cursor forward to the next start of a word |
e | moves the cursor forward to the next end of a word |
b | moves the cursor backward to the next start of a word |
W | moves the cursor forward to the next start of a Word |
E | moves the cursor forward to the next end of a Word |
B | moves the cursor backward to the next start of a Word |
The #*
keys move the cursor forward and backward to the next "idenfitier". If the cursor hovers over the word "marmot" then pressing *
will move the cursor forward to the next instance of the word "marmot" and pressing #
will move the cursor backward to the previous instance of the word "marmot".
key | action |
---|---|
# | moves the cursor backward to the previous identifier |
* | moves the cursor forward to the previous identifier |
The f
key takes a character as an argument and moves the cursor forward to that character. For example, fa
moves the cursor forward to the next instance of a
. The f
key operates within a line. It will never take the cursor to another line. The F
command is like f
except it searches backward. The t
and T
commands are like f
and F
exvcept they move the cursor one fewer character.
The ;
command repeats the most recent fFtT
command. The ,
command is like ;
except backwards. If you use an F
command followed by a ,
then the double-backwardsness will cancel itself out.
key | action |
---|---|
f<char> | moves forward to <char> |
F<char> | moves backward to <char> |
t<char> | moves forward to the character before <char> |
T<char> | moves backward to the character after <char> |
; | repeats the previous fFtT command |
, | repeats the previous fFtT command except reversed |
The 0^$
keys move the cursor to the beginning and end of a line.
key | action |
---|---|
0 | moves the cursor to the beginning of the line |
^ | moves the cursor to the beginning of the line, excluding whitespace |
+ | moves the cursor to the beginning of the next line, excluding whitespace |
$ | moves the cursor to the end of the line |
The HLM
keys move the cursor around relative to the viewing window itself.
key | action |
---|---|
H | moves the cursor the the start of the first visible line |
M | moves the cursor the the start of the middle visible line |
L | moves the cursor the the start of the last visible line |
You can move the viewing window itself with z
and Ctrl
keys.
key | action |
---|---|
Ctrl-e | moves the viewing window down one visual line |
Ctrl-y | moves the viewing window up one visual line |
Ctrl-f | moves the viewing window forward by one viewing window |
Ctrl-b | moves the viewing window backward by one viewing window |
Ctrl-d | moves the viewing window forward by half of one viewing window |
Ctrl-u | moves the viewing window backward by half of one viewing window |
zz | moves the viewing window to position the cursor in the middle |
zt | moves the viewing window to position the cursor at the top |
zb | moves the viewing window to position the cursor at the bottom |
You can move the cursor itself up and down visible lines with the g
prefix.
key | action |
---|---|
gj | moves the cursor down one visual line |
gk | moves the cursor up one visual line |
The g
key can also go to a particular line.
key | action |
---|---|
gg | jumps the cursor to the beginning of the buffer[1] |
G | jumps the cursor to the end of the buffer |
<num>gg | jumps the cursor to the specified line |
<num>G | '' |
The |
key is like g
except for columns.
key | action |
---|---|
<num>| | moves the cursor to the <num>th column within a line |
The /
key performs search. You type /
then the string you are searching for and then press Enter
. The ?nN
keys are analogous to F;n
.
key | action |
---|---|
/ | initiates a search |
? | initiates a backwards search |
n | repeats the previous search |
N | repeats the previous search except reversed |
The ()
characters move forward and backward one sentence.
key | action |
---|---|
) | moves forward to the next start of a sentence |
( | moves backward to the next start of a sentence |
The []
characters move the cursor forward and backward to a variety of things. My favorite uses of []
is to go forward and backward to matching parenthesis. For example, ])
moves forward to the next unmatched closing parenthesis. It is indispensable when writing Lisp. Inner quotes and tags behave similarly to parentheticals.
key | action |
---|---|
]) | move forward to matching parenthesis |
]( | '' |
[) | move backward to matching parenthesis |
[( | '' |
[[ | jump to function start |
]] | jump to function end |
You can (invisibly) mark places in your buffer to return to later. You can set one mark per letter. Lowercase letters a-z are buffer-specific e.g. each buffer can have its own "a" mark. Uppercase letters A-Z are global e.g. only one buffer at a time can have an "A" mark.
key | action |
---|---|
m<a-z> | create a buffer-specific mark |
m<A-Z> | create a global mark |
'<mark> | jump to the beginning of the line with mark <mark> |
`<mark> | jump to mark <mark> |
Some marks are populated automatically. Of the automatic marks, I only use ''
. You can find the others here.
mark | meaning |
---|---|
'' | jump to last jump point |
Editing
Now that you know how to move, we can edit some text. Most of the time you edit text you should use the dyp
keys.
d
stands for delete, which is similar to "cut".y
stands for yank, which is similar to "copy".p
stands for put, which is similar to "paste".
The d
key operates on text objects and movement commands. For example dtA
deletes everything up to (but not including) the next "A" on the current line.
Every delete operation operates on characters or lines. dtA
operates on characters and thus behaves similarly to other editors. A delete operation which operates on lines deletes an integer number of lines. Delete operations which operate on lines delete the current line and the destination line. Thus, dj
deletes the current line and the next line.
y
is identical to d
except it leaves your buffer unchanged.
delete or yank key | action |
---|---|
d<char> | deletes every character from the starting character up to (and including) the destination character |
d<line> | deletes every line from the starting line up to (and including) the destination line |
dd | deletes the current line |
y<char> | yanks every character from the starting character up to (and including) the destination character |
y<line> | yanks every line from the starting line up to (and including) the destination line |
yy | yanks the current line |
p
puts the selection before the cursor. P
puts the selection after the cursor. "Before" and "after" refer to characters or lines depending on whether you deleted/yanked characters or lines.
key | action |
---|---|
p | put after the cursor |
P | put before the cursor |
By default, p
and P
will put the last text you deleted or yanked. You can save text into registers by prefixing "<register>
before your delete or yank command. For example, "add
deletes the current line and saves it into register "a".
There is one register for each letter a-z. If you use a capital letter then your delete or yank command will append to the register instead of overwriting it. You can put from a register by prefixing your p
or P
command with the register. For example, "ap"
will put from register "a".
You can find a list of special registers here.
Text Objects
Remember how I said you could follow d
and y
with a movement command or a text object? Remember from earlier the concept of "words" and "paragraphs"? Here we put them together into a simple grammar.
da
deletes a text object.
key | action |
---|---|
daw | delete a word |
daW | delete a Word |
das | delete a sentence |
dap | delete a paragraph |
da( | delete a parenthetical |
da) | '' |
yaw | yank a word |
yaW | yank a Word |
yas | yank a sentence |
yap | yank a paragraph |
ya( | yank a parenthetical |
ya) | '' |
You can replace the a
with an i
to delete an inner word, an inner paragraph, etcetera. An inner text object is just like the regular text object except it does not include any surrounding delimiters. In the case of a parenthetical, the "inner parenthetical" does not include the outside parenthesis. For words/sentences/paragraphs, the delimiter is whitespace.
key | action |
---|---|
diw | delete inner word |
diW | delete inner Word |
dis | delete inner sentence |
dip | delete inner paragraph |
di( | delete inner parenthetical |
di) | '' |
yiw | yank inner word |
yiW | yank inner Word |
yis | yank inner sentence |
yip | yank inner paragraph |
yi( | yank inner parenthetical |
yi) | '' |
Other text objects include '"[]{}<>
. They all do what you would expect them to do. t
refers to an HTML-like tag.
Insert Mode
You cannot write everything by yanking and putting pieces of existing text together. Sometimes you have to insert text into a document. Several different keys drop you into insert mode.
key | action |
---|---|
i | inserts text before the cursor |
a | inserts text after the cursor |
I | inserts text at the beginning of the line |
A | inserts text at the end of the line |
o | creates a newline below the current line and inserts text there |
O | creates a newline above the current line and inserts text there |
s | deletes the current character and inserts text |
S | deletes the current line and inserts text |
You can exit insert mode by pressing Escape
but it is faster to remap your CapsLock
key to Ctrl
and then exit insert mode with Ctrl-[
. Some hotkeys are valid only while in insert mode.
insert mode key | action |
---|---|
Escape | exits insert mode |
Ctrl-[ | '' |
Ctrl-F | moves cursor forward one character |
Ctrl-b | moves cursor backward one character |
Ctrl-w | deletes one word backward (without saving it to a register) |
The c
key is like d
except it drops you into insert mode afterward.
key | action |
---|---|
c<movement> | clear text |
c<text_object> | clear text |
After you exit insert mode, the whole insertion counts as a single edit. So if you type ci(
followed by an insertion then the entire replacement of text inside the parenthetical counts as a single edit. You can repeat an edit with the .
operator.
key | action |
---|---|
. | repeat previous edit |
The .
key might be the most important key in all of Vim. Generally-speaking, the more you use the .
operator the better you are at Vim.
Miscellaneous edit commands
key | action |
---|---|
x | delete the character under the cursor |
X | delete the character before the cursor |
~ | toggle capitalization and move the cursor forward one character |
r<char> | replace a single character |
The Undo Tree
u
and Ctrl-r
operate like the undo and redo stack you are familiar with.
key | action |
---|---|
u | undo last edit |
Ctrl-r | redo next edit |
If you undo a long series of edits and then mistakenly make an edit you can undo the damage with g+
and g-
which traverse the nodes of the tree in chronological and reverse-chronological order.
key | action |
---|---|
g+ | traverse undo tree in chronological order |
g- | traverse undo tree in reverse chronological order |
Macros
A macro is a series of keystrokes. Macros are good for automating repetitive tasks, especially editing structured text.
To define a macro, start by pressing the q
key. Then pick a letter a-z at which to save the macro. Then execute the macro manually. When you are done typing the macro, press q
again.
Once you have a macro defined, you can press @
followed by the macro's letter to execute the macro.
key | action |
---|---|
q | define a macro |
@<a-z> | execute a macro |
@@ | execute previous macro |
Macros are well-behaved. If a macro modifies a line and then goes down one line and you tell Vim to execute the macro 1000 times but your buffer only has 700 lines then Vim will stop when it gets to the end of your buffer.
Visual mode
Visual modes are similar to highlighting. Visual modes have their uses, but it is usually faster to avoid them.
key | action |
---|---|
v | enter visual mode |
V | enter visual line mode |
Ctrl-v | enter visual rectangle mode |
Find and Replace
You can find and replace all the instances of a string by typing :%s/
followed by the original string followed by /
followed by the replacement string followed by Enter…assuming you did not type any escape sequences. Find and replace is a complex subject I will not delve into here even though I do use it.
Enter and exit
You can enter Vim by typing vim
into your terminal followed by the file you would like to create or edit. You can exit vim by typing :
followed by a quit command.
command | action |
---|---|
:q | exit if no changes are pending |
:q! | force an exit even if changes are pending |
:w | write to disk |
:wq | write to disk and then exit |
Typing ZZ
does the same thing as the :wq
command.
Cheatsheet
If you are not from a Unix back then the term "buffer" may be unfamiliar. Just translate "buffer" to "file" or "document" in your head even though, technically, a buffer is more general than a document. ↩︎
57 comments
Comments sorted by top scores.
comment by ChristianKl · 2021-04-07T18:24:25.155Z · LW(p) · GW(p)
Why do you believe that you are actually faster with Vim? I used Vim quite a while a bit and it usually still requires thinking to use it. I haven't seen any evidence that Vim actually makes programs faster that goes beyond programmers feeling faster. Do you have evidence for that, either through measuring your own performance or through another source?
Replies from: John_Maxwell_IV, SatvikBeri, gilch, glagidse, SatvikBeri, Alexei↑ comment by John_Maxwell (John_Maxwell_IV) · 2021-04-07T23:34:54.998Z · LW(p) · GW(p)
After practicing Vim for a few months, I timed myself doing the Vim tutorial (vimtutor on the command line) using both Vim with the commands recommended in the tutorial, and a click-and-type editor. The click-and-type editor was significantly faster. Nowadays I just use Vim for the macros, if I want to do a particular operation repeatedly on a file.
I think if you get in the habit of double-clicking to select words and triple-clicking to select lines (triple-click and drag to select blocks of code), click-and-type editors can be pretty fast.
Replies from: SatvikBeri↑ comment by SatvikBeri · 2021-04-07T23:42:41.719Z · LW(p) · GW(p)
This is a great experiment, I'll try it out too. I also have pretty decent habits for non-vim editing so it'll be interesting to see.
Replies from: SatvikBeri↑ comment by SatvikBeri · 2021-04-08T01:01:19.049Z · LW(p) · GW(p)
I did :Tutor on neovim and only did commands that actually involved editing text, it took 5:46.
Now trying in Sublime Text. Edit: 8:38 in Sublime, without vim mode – a big difference! It felt like it was mostly uniform, but one area where I was significantly slower was search and replace, because I couldn't figure out how to go backwards easily.
Replies from: John_Maxwell_IV↑ comment by John_Maxwell (John_Maxwell_IV) · 2021-04-08T22:47:49.001Z · LW(p) · GW(p)
Interesting, thanks for sharing.
I couldn't figure out how to go backwards easily.
Command-shift-g right?
Replies from: SatvikBeri↑ comment by SatvikBeri · 2021-04-09T15:45:35.952Z · LW(p) · GW(p)
I ended up using cmd+shift+i which opens the find/replace panel with the default set to backwards.
↑ comment by SatvikBeri · 2021-04-08T13:35:55.409Z · LW(p) · GW(p)
So, one of the arguments you've made at several points is that we should expect Vim to be slower because it has more choices. This seems incorrect to me, even a simple editor like Sublime Text has about a thousand keyboard shortcuts, which are mostly ad-hoc and need to be memorized separately. In contrast Vim has a small, (mostly) composable language. I just counted lsusr's post, and it has fewer than 30 distinct components – most of the text is showing different ways to combine them.
The other thing to consider is that most programmers will use at least a dozen editors/IDEs in their careers. I have 5 open on my laptop right now, and it's not because I want to! Vim provides a unified set of key bindings among practically every editor, which normally have very different ways of doing things.
So that's on the order of a 10x-100x order of magnitude reduction in vocabulary size, which should at least make you consider the idea that Vim has lower latency.
Replies from: ChristianKl, ChristianKl↑ comment by ChristianKl · 2021-04-08T15:21:54.169Z · LW(p) · GW(p)
The issue is not just more choices but more choices to achieve the same result. In programming languages Python achieved a large user-base through being easy to use with it's core principles like "there should be one obvious way to do things".
I have 5 open on my laptop right now, and it's not because I want to! Vim provides a unified set of key bindings among practically every editor, which normally have very different ways of doing things.
The problem is that it's not dependable when you can use the Vim shortcuts within user editors. If I use IdeaVim in IntelliJ I can use "*y to copy a lot of things to the clipboard but not for example the text in hover popups for which I actually need Crtl+c and where I lose the ability to copy the text when I let Vim overwrite the existing shortcut.
↑ comment by ChristianKl · 2021-04-09T15:28:39.328Z · LW(p) · GW(p)
Let's think about an example. I want to move my cursor.
I might be in a situation when 3W, lllllllllllllllllllllllllllllllll, / with something else $b are all valid moves to get at my target location for the cursor.
This has probably something like 3-5 seconds latency because I not only have to think about where my cursor should go about also about the way to get there.
On the other hand without VIM, having a proper keyboard that makes arrow keys easy to reach I might have a latency of maybe 700 milliseconds.
VIM frequently costs mental processing capacity because I have to model my code in my head in concepts like words (for w and b) that I wouldn't otherwise.
Replies from: SatvikBeri, gilch↑ comment by SatvikBeri · 2021-04-09T16:13:39.535Z · LW(p) · GW(p)
If you're using non-modal editing, in that example you could press Alt+rightarrow three times, use cmd+f, the end key (and back one word), or cmd+righarrow (and back one word). That's not even counting shortcuts specific to another IDE or editor. Why, in your mental model, does the non-modal version feel like fewer choices? I suspect it's just familiarity – you've settled on some options you use the most, rather than trying to calculate the optimum fewest keystrokes each time.
Have you ever seen an experienced vim user? 3-5 seconds latency is completely unrealistic. It sounds to me like you're describing the experience of being someone who's a beginner at vim and spent half their life into non-modal editing, and in that case, of course you're going to be much faster with the second. And to be fair, vim is extremely beginner-unfriendly in ways that are bad and could be fixed without harming experts – kakoune(https://kakoune.org/) is similar but vastly better designed for learning.
As a side note, this is my last post in this conversation. I feel like we have mostly been repeating the same points and going nowhere.
↑ comment by gilch · 2021-04-09T17:48:13.279Z · LW(p) · GW(p)
The choices become much more obvious with experience. Waiting 3-5 seconds is completely unrealistic once you know what you are doing. I'd fall back to using the mouse well before 3 seconds, unless I'm in a remote terminal or something that doesn't support it, in which case I'd use /
/ ?
and n
.
You could theoretically target any character in the file using only Space to advance the cursor and gg
to go back to the start (well, depending on your settings). But nobody even thinks to do it this way (because it's stupid), so it doesn't seem to drain any mental resources not thinking about it.
Similarly, experienced vimmers don't use hjkl
very much. lllllllllllllllllllllllllllllllll
is just not something that occurs to you when you think of (and act on) better options first. If you have to use an arrow key more than a few times in a row, you're doing something wrong. (I mean, sometimes I use j
s to scroll down as I'm reading, but I'm not going for speed in that case.) By the time you get to about 4-5 keystrokes, you're better off searching with /
/ ?
.
Similarly, if you have to hit w
more than a few times, you're probably doing something wrong. It's usually not something that even occurs to me.
I mostly jump around within a line by using f
/F
and ;
/,
. It's faster than going by word with w
or by character with h
/l
. One still has to pick a character or two to target, and for longer jumps, one learns to avoid common characters like vowels, and learn to prefer rarer characters like punctuation. This is just a fast heuristic, I'm not mentally counting character statistics for my current line.
↑ comment by ChristianKl · 2021-04-09T18:45:12.817Z · LW(p) · GW(p)
Similarly, if you have to hit
w
more than a few times, you're probably doing something wrong.
Do you mean that for both doing "4w" and "wwww"?
Replies from: gilch↑ comment by gilch · 2021-04-10T02:01:16.951Z · LW(p) · GW(p)
Yes? I mean, other vimmers might feel differently, but I basically don't use counts like that. Counting to move the cursor is too much effort, especially if you're counting higher than 2-3. It's not worth the time it takes.
ww
is the same number of keystrokes as 2w
. I might use the latter if I needed a single motion operator to repeat later with .
, like c2w
, but ww
or even www
would be easier most of the time. Past that, we're getting to the 4-5 keystrokes where /
is better, and you can probably do it in two to three keystrokes with f
-something (;
) as easily as www
.
So rather than counting how many words to get from here to there to find the right number to enter before the w
, I'm just looking at the there and hit f
, plus whatever character I'm looking at getting to, or a less common one adjacent to it. If the cursor doesn't quite get there, you can ;
a few times. If you overshoot, use ,
to reverse.
↑ comment by gilch · 2021-04-07T19:56:55.646Z · LW(p) · GW(p)
I've done pair programming with devs who don't know vim, and remember on multiple occasions watching the other dev try to make an edit while thinking that I'd be done by now if I was the one typing.
Most of the time, what I do with vim is at the level of habit and "muscle memory". I don't have to think about it. If I'm programming a macro or writing a regex, sure, I have to think. But the motion commands just happen now.
↑ comment by glagidse · 2021-04-08T10:22:21.835Z · LW(p) · GW(p)
For me, Vim isn't about speed, it's about staying focused. If I have to move my hand between the keyboard and the mouse every time I want to move the cursor, I lose a little bit of focus. Vim solves this issue by not having to move the placement of your hands. Of course a pointing stick also solves most of these issues.
↑ comment by SatvikBeri · 2021-04-07T21:12:06.147Z · LW(p) · GW(p)
As far as I know there's almost no measurement of productivity of developer tools. Without data, I think there are two main categories in which editor features, including keyboard shortcuts, can make you more productive:
- By making difficult tasks medium to easy
- By making ~10s tasks take ~1s
An example of the first would be automatically syncing your code to a remote development instance. An example of the first would be adding a comma to the end of several lines at once using a macro. IDEs tend to focus on 1, text editors tend to focus on 2.
In general, I think it's very likely that the first case makes you more productive. What about the second?
My recollection is that in studies of how humans respond to feedback, there are large differences between even relatively short periods of latency. Something like vim gives you hundreds of these (learning another editor's keyboard shortcuts very well probably does too.) I can point to dozens of little things that are easier with vim, conversely, nothing is harder because you can always just drop into insert mode.
I agree that this isn't nearly as convincing as actual studies would be, but constructing a reasonable study on this seems pretty difficult.
Replies from: ChristianKl↑ comment by ChristianKl · 2021-04-07T22:32:08.195Z · LW(p) · GW(p)
My recollection is that in studies of how humans respond to feedback, there are large differences between even relatively short periods of latency.
I would expect using VIM to increase latency. While you are going to press fewer keys you are likely going to take slightly longer to press the keys as using any key is more complex.
I can point to dozens of little things that are easier with vim, conversely, nothing is harder because you can always just drop into insert mode.
There's the paradox of choice and having more choices to accomplish a task costs mental resources. Vim forces me to spent cognitive resources to chose between different alternatives of how to accomplish a task.
All the professional UX people seem to advocate making interfaces as simple as possible.
Replies from: gilch, SatvikBeri↑ comment by gilch · 2021-04-08T04:51:31.801Z · LW(p) · GW(p)
There's the paradox of choice and having more choices to accomplish a task costs mental resources.
As your vocabulary has grown, has your speech slowed down? Is it faster to look at the keyboard and type with one finger, or touch-type with all ten? Have you ever played fighting video games? Is someone who knows more moves at a disadvantage? It might depend on how much they've practiced them!
More conscious choices slow me down, it's true, but once it's ingrained at the level of habit, you can do it almost as fast as you can think it, just like speaking or typing or playing a fighting game. Learning to do it in the first place is slower, but like learning to touch-type, try to get it right before you try to get it fast.
When I touch-type words, I don't think in terms of individual letters. I don't move that way either. There are clusters of keystrokes that happen frequently in English text. My other fingers have already started moving to the next letters before I've finished pressing the first one. Vim's motion commands end up feeling the same way. It's just like typing words.
New vimmer: I need to swap a line with the next one. I should cut it and paste it after. What was the command for that again? D? Uh. Visual mode! hhhhhhhhhhhhhhhhhv
. Um. k
? no. j
. l
. $
. d
. Down? j
. p
! What? Uh, undo! u
! Up? k
! p
! Why isn't this working? u
! $
! i
! Enter. Aw screw it! Backspace! Right-arrow, Enter, p
! Backspace! Escape, p
! Phew!
Intermediate vimmer: I could select the whole line with V
and cut with d
or do a cut-motion with ^D
. 0D
is a little easier to reach than ^D
though. Or dd
. The dd
is easiest. Am I still in insert mode? Escape, Escape. dd
! Down? Oh, already there. Paste-below with p
. p
! Done.
Experience vimmer: swap-linesddp
done.
I'm not even thinking in terms of select-copy-paste steps here. ddp
is a muscle macro in its own right, just like a common word or a practiced fighting-game move.
↑ comment by ChristianKl · 2021-04-08T10:16:35.804Z · LW(p) · GW(p)
Is it faster to look at the keyboard and type with one finger, or touch-type with all ten?
Touch typing doesn't increase the amount of choices if you do it properly. If you learn touch typing properly there's a single finger that's responsible for a single key.
As your vocabulary has grown, has your speech slowed down?
That's a bad comparison because as my vocabulary grew I also get better got speaking.
In cross language comparisons more choices, do slow down speakers. Speakers of a language with fewer phomenes are faster at speaking a single phoneme then speakers of a language with more different phonemes.
↑ comment by SatvikBeri · 2021-04-07T22:49:40.651Z · LW(p) · GW(p)
I would expect using VIM to increase latency. While you are going to press fewer keys you are likely going to take slightly longer to press the keys as using any key is more complex.
This really isn't my experience. Once you've practiced something enough that it becomes a habit, the latency is significantly lower. Anecdotally, I've pretty consistently seen people who're used to vim accomplish text editing tasks much faster than people who aren't, unless the latter is an expert in keyboard shortcuts of another editor such as emacs.
There's the paradox of choice and having more choices to accomplish a task costs mental resources. Vim forces me to spent cognitive resources to chose between different alternatives of how to accomplish a task.
All the professional UX people seem to advocate making interfaces as simple as possible.
You want simple interfaces for beginners. Interfaces popular among professionals tend to be pretty complex, see e.g. Bloomberg Terminal or Photoshop or even Microsoft Excel.
Replies from: ChristianKl↑ comment by ChristianKl · 2021-04-08T09:52:15.280Z · LW(p) · GW(p)
This really isn't my experience. Once you've practiced something enough that it becomes a habit, the latency is significantly lower.
How much experience do you have with measuring the latency of things to know what takes 400ms and what takes 700ms?
Anecdotally, I've pretty consistently seen people who're used to vim accomplish text editing tasks much faster than people who aren't, unless the latter is an expert in keyboard shortcuts of another editor such as emacs.
Even if total time for the task is reduced the latency for starting the task might still be higher.
↑ comment by Alexei · 2021-04-07T20:28:32.508Z · LW(p) · GW(p)
I think about ~1year into using vim, I thought the same thing: I’m doing the same thing, just with more quicker steps, so it feels faster. But after that I persisted and now it’s actually faster. Part of it is expanding your repertoire and memorizing it (where you don’t have to think about it at all). Also vim editor by itself I still find very clunky, but using vim shortcuts in something like PyCharm is $$$!
Replies from: ChristianKl↑ comment by ChristianKl · 2021-04-07T20:43:34.104Z · LW(p) · GW(p)
But after that I persisted and now it’s actually faster.
How do you know?
Replies from: Alexei↑ comment by Alexei · 2021-04-08T01:32:44.166Z · LW(p) · GW(p)
For any given thing you want to do imagine what it would take to do it without Vim and it’s just more & usually more awkward key strokes.
I’d say the only place where I still use mouse is to jump to a completely random place in code.
Replies from: gilch, ChristianKl↑ comment by ChristianKl · 2021-04-08T10:13:54.340Z · LW(p) · GW(p)
For any given thing you want to do imagine what it would take to do it without Vim
This reminds me of the person with whom I was arguing about what takes how long on Anki and who was saying that his own judgement of what takes how long is superior to the Anki statistics where I know how the code works and which actually measures the time correctly.
Human imagination is not good at estimating what tasks have how much latency.
comment by ConCave · 2021-04-07T17:27:40.837Z · LW(p) · GW(p)
For people who are newer to vim, I think that reviewing lists like this is useful, but the main thing to realize is that there's always a clever, easy way of doing things in vim. If you're having some text-editing problem, and having to do lots of repetitive work, there will be a way of reducing that using vim. Then, when you have a problem and you are interested in sharpening your saw for a bit and you have the necessary free time, you can look up the clever way to do things.
Looking at VimGolf (https://www.vimgolf.com/) can also help make a link in your mind between useful shortcuts (like the ones listed in this post) and problems that can be solved easily with those shortcuts. For me at least, that makes it easier to recall the shortcuts when they would be useful.
comment by gianlucatruda · 2021-04-07T10:43:16.454Z · LW(p) · GW(p)
This is a superb overview! I've used Vim for about 2 years now, but I still learned a bunch of things from this post that I didn't pick up from other cheatsheets or articles.
My 2-cents: Vim itself is powerful as an editor, but I always missed some IDE features. What I've come to realise is that the real power of Vim is not the editor, but the keybindings. I installed the Vim extension in VSCode some time ago and have loved the hybrid workflow. Since then, I've been gradually incorporating Vim keybindings into all the tools I use for text — like Overleaf for writing papers in LaTeX and Zettlr for writing notes in Markdown. I still use Vim itself for small scripts and quickly editing files. It's so powerful being able to go between applications and never have to think about what your fingers are doing to transform ideas into output.
One thing I still haven't quite figured out is in-browser text entry. So far, I haven't liked the solutions I've found, but it's something I'm looking into for the future. Writing this comment without my usual keybindings is... slow.
Replies from: ConCave, lsusr↑ comment by ConCave · 2021-04-07T17:24:15.209Z · LW(p) · GW(p)
I have to agree with this. Having one set of keybindings that you can take with you to most editors is something that really adds to the value of learning vim. I learned Sublime Text's shortcuts, then IntelliJ's shortcuts, which required a separate retraining. Learning vim required retraining again, but now I can bring that effort with me to new editing environments.
Replies from: lsusr↑ comment by lsusr · 2021-04-07T17:43:24.265Z · LW(p) · GW(p)
In addition, some old Unix utilities like less
use a subset of Vim keybindings by default.
↑ comment by gianlucatruda · 2021-04-08T15:53:47.756Z · LW(p) · GW(p)
Yes! Even many websites and web apps implement some Vim standards. Particularly \
for search.
↑ comment by lsusr · 2021-04-07T17:41:54.257Z · LW(p) · GW(p)
I'm in the same boat. I do most of my text editing in Spacemacs with Vim keybindings. Please let me know if you figure out a good in-browser text entry solution.
Replies from: gilch↑ comment by gilch · 2021-04-07T19:51:23.631Z · LW(p) · GW(p)
I have an AutoHotKey script that copies any highlighted text, pops up a gVim window with that text, and then I can save it back into the clipboard with :wq. I works on any plain text field in any app that respects the C-c copy-selection shortcut. I'm sure someone with your skills could put together something similar. I think I had a variant that would also C-a to select all and then C-v after I closed gVim.
I also have a more involved AHK script that does a subset of vim commands in any normal text field while I hold down the tab button. Getting the f
command to work was a bit of a trick. I kind of stopped using it once I got a Lenovo with a TrackPoint, but if anyone is interested I could try to dig it up and put in on GitHub or something.
↑ comment by Sunny from QAD (Evan Rysdam) · 2021-04-07T23:35:08.170Z · LW(p) · GW(p)
It's funny that this came up on LessWrong around this time, as I've just recently been thinking about how to get vim-like behavior out of arbitrary text boxes. Except I also have the additional problem that I'm somewhat unsatisfied with vim. I've been trying to put together my own editor with an "API first" mentality, so that I might be able to, I don't know, eventually produce some kind of GTK widget that acts like my editor by default. Or something. And then maybe it'll be easy to make a variant of, say, Thunderbird, in which the email-editing text box is one of those instead of a normal text box.
(If you're curious, I have two complaints about vim. (1) It's a little bloated, what with being able to open a terminal inside of the editor and using a presumably baked-in variant of sed to do find-and-replace rather than making you go through a generic "run such-and-such program on such-and-such text selection" command if you want the fancy sed stuff. And (2) its commands are slightly irregular, like how d/foo deletes everything up to what the cursor would land on if you just typed /foo but how dfi deletes everything up to and including what the cursor would land on if you just typed fi.)
Replies from: gilch↑ comment by gilch · 2021-04-08T03:41:44.560Z · LW(p) · GW(p)
Vim is far from optimal, but it's very customizable, which makes it easy to paper over the more obvious cracks.
For alternative ideas, the Canon Cat had a pretty well-designed interface for text editing, which Jef Raskin described in The Humane Interface, which has influenced my thinking about UI design. It's still not as fast as Vim, but much easier to learn. The 80% solution for the 20% effort maybe. If you want to try it out, it's old enough that you can emulate it in your browser, although I had to download MAME to get all the keybindings working.
comment by beriukay · 2021-04-07T16:37:58.547Z · LW(p) · GW(p)
Hey, this was a great write-up! Quite comprehensive, and definitely showcases more of the functionality than I normally use.
Another useful trick is that you can increment and decrement numbers. In normal mode, making sure your cursor is on the same line and before or on the chosen number, press ctrl a
to increase by one, or ctrl x
decrease by one. You can combine this with a prefix (just like above with jumping lines), so 56 ctrl a
will increase the next number on that line by 56. This is most useful with integers, not so great with decimals.
Edit: formatting.
comment by Multicore (KaynanK) · 2021-06-06T21:22:00.843Z · LW(p) · GW(p)
A couple months after reading this post, I am now getting a big burst of dopamine every time I use the . key in vim.
(Even though it's just on the level of "Insert/replace the same text in multiple places")
comment by tchauvin (timot.cool) · 2021-04-08T22:01:06.905Z · LW(p) · GW(p)
In my opinion, the 4 killer features of vim beyond moving around and basic editing are:
- macros
- the
s
command used with regular expressions - the
g
command (see e.g. Power of g) - the ability to run text through any Unix utility (Vim and the shell)
If you know your Unix utilities (I often use awk
inside of vim; it's also great outside of it), your regular expressions, and these features, you can sculpt any text as you wish. What I mean is that you can take the output of pretty much anything, in a messed up format, and transform it into the content and format you want. This is supposed to be inspiring but I'm not sure how good a job I'm doing.
Also, if anyone's interested, here are my current vim Anki cards. I use Anki for keyboard shortcuts which are supposed to be muscle memory, AMA
comment by Zolmeister · 2021-04-07T18:02:59.583Z · LW(p) · GW(p)
Some highlights from my .vimrc
" Prevent data loss
set undofile
" Flush to disk every character (Note: disk intensive, e.g. makes large copy-pastes slow)
set updatecount=1
" Directory browsing usability
let g:netrw_liststyle = 3 " tree list view
let g:netrw_banner = 0
" Copy for X11
vnoremap <C-c> "cy <Bar> :call system('xclip -selection clipboard', @c)<CR><CR>
Also worth checking out CoC (language server)
comment by WrongPlanet · 2022-04-17T11:12:09.070Z · LW(p) · GW(p)
There is a typo: "idenfitier" instead of "identifier"
comment by Crackatook (peterson-yook-1) · 2021-11-10T01:13:58.065Z · LW(p) · GW(p)
Hi, I downloaded vim for the first time, after reading your post. It is fascinating program, and learning about it is another interesting experience. Now, I have three things to ask you.
- Why didn't you write about [ESC] and [i] keys to turn on and off the [vim mode]? I had no idea but just messing with it, before I can activate these cool shortcuts. Hahaha
- I write stuff and save constantly. In Vim, whenever I save, it creates another file ~[filename], over and over again. How do we organize files for vim?
- Lastly, how do we paste outside texts to the vim? :p didn't work.
I just dumped you all these questions, sorry about that, but I appreciate your help much.
Replies from: lsusr↑ comment by lsusr · 2021-11-10T03:43:35.199Z · LW(p) · GW(p)
- Escape is too far from homerow compared to
Ctrl+[
. It's better to useCtrl+[
. I wrote about thei
key in the "Insert Mode" section. - I'm not sure I understand the question. I take it you mean you save various versions of the same file? For version control, I use Git.
- If you're using Vim via the terminal, you can often paste via
Ctrl+Shift+v
.
↑ comment by Crackatook (peterson-yook-1) · 2021-11-11T01:39:45.401Z · LW(p) · GW(p)
O I like these keys. Thank you
I'm not sure I understand the question.
Each time I save progress, vim creates another file. At the end, I have multiple files in addition to the original one. But it seems like it is not supposed to work that way?
Replies from: lsusr↑ comment by lsusr · 2021-11-11T02:10:15.580Z · LW(p) · GW(p)
It shouldn't be that way at all. The normal way to save progress while you're editing a file is to type :w
followed by the Enter key. If you do this, Vim should write (or overwrite) the file on disk, resulting in a maximum of one file. (I'm ignoring the hidden temporary file.)
comment by krg · 2021-09-08T02:25:55.950Z · LW(p) · GW(p)
Nice, I've only used VIM for a year so far, and now I'm stuck with it and happy.
Are these typos?
<num>gg - jumps the cursor to the beginning of the buffer
And the results for p
and P
being "before" and "after" are switched, at least I believe so. For me p
pastes after, and P
pastes before.
comment by David Gross (David_Gross) · 2021-04-08T05:10:41.342Z · LW(p) · GW(p)
You can exit insert mode by pressing
Escape
but it is faster to remap yourCapsLock
key toCtrl
and then exit insert mode withCtrl-[
.
I don't get how that's faster.
Replies from: gilch, lsusrcomment by paragonal · 2021-04-07T23:10:33.154Z · LW(p) · GW(p)
A question for the people who use vim keybindings in IDEs: how do you deal with keybindings for IDE tasks which are not part of vim (like using the debugger, refactoring, code completion, etc.)? The last time I tried to use vim bindings in an IDE there were quite some overlaps with these so I found myself coming up with compromise systems which didn't work that well because they weren't coherent.
Replies from: gilch, SatvikBeri↑ comment by gilch · 2021-04-08T03:50:02.487Z · LW(p) · GW(p)
At least for PyCharm, this was somewhat easier on macOS than on Windows, since you have control
, option
, command
and shift
, instead of just Ctrl
, Alt
, and Shift
(well, and the Win
key, but the OS reserves too many bindings there.) On macOS, The IDE uses command
for most things, while Vim usually uses control
when it needs a modifier at all. On Windows they both want to use Ctrl
, so it's more difficult to configure all the bindings.
↑ comment by SatvikBeri · 2021-04-07T23:17:00.132Z · LW(p) · GW(p)
Some IDEs are just very accommodating about this, e.g. PyCharm. So that's great.
Some of them aren't, like VS Code. For those, I just manually reconfigure the clashing key bindings. It's annoying, but it only takes ~15 minutes total.
Replies from: paragonal↑ comment by paragonal · 2021-04-07T23:36:01.307Z · LW(p) · GW(p)
Thanks for your answer. Part of the problem might have been that I wasn't that proficient with vim. When I reconfigured the clashing key bindings of the IDE I sometimes unknowingly overwrote a vim command which turned out to be useful later on. So I had to reconfigure numerous times which annoyed me so much that I abandoned the approach at the time.
comment by theme_arrow · 2021-04-07T07:59:54.594Z · LW(p) · GW(p)
Thanks for this writeup. Could you share a bit more about how you got into using Vim and why you've found it to improve speed so much? I occasionally need to use vi when there's nothing else installed on a system, but the clunkiness and high barrier to entry has never made me tempted to use Vim as my primary editor.
Replies from: lsusr↑ comment by lsusr · 2021-04-07T17:54:27.832Z · LW(p) · GW(p)
Keyboard shortcuts are faster than the mouse. Keys accessible from homerow are faster than distant keys like the arrow keys. Keyboard shortcuts you can combine are more powerful than standalone keyboard shortcuts. As gianlucatruda mentioned [LW(p) · GW(p)], the important thing is Vim keybindings, not the editor itself. You can get a similar speed boost by installing Vim keybindings on your favorite editor.
I learned Vim very early in my programming career because I knew the upfront investment would pay itself over many times—and it has. Vim has paid my initial investment back many times over purely in terms of time saved. But speed does not just help me save time editing files. It also helps me think faster because my memory is volatile. For every time interval there is a chance I will forget a critical piece of information. My volatile memory puts a limit on how complex of a task I can handle. If my think-decide-act cycles iterate faster, I can complete more complicated tasks before my volatile memory expires.