Vim, tmux and the Keybindings
The core concept of Vim is learning an alternative perception of text. You start seeing lines, sentences, paragraphs and such more innately. It will make you much faster when you start mastering Vim. You will never have to touch mouse to do even the most complex text manipulation. Also, it's not about the Vim software per se, but the mindset, keybindings and macros.
Vim was designed to be used on an English keyboard layout. You might have a bad time learning it if e.g. {
, ;
and /
are hard to press on your language. I highly encourage you to learn and use English layout if this becomes an issue. An alternative is to change the default configuration.
I recommend sticking with the default keybindings as much as possible. This will keep you productive on all environments and tools that use support Vim navigation e.g. various IDEs and remote terminals.
When you feel like navigating to a specific point takes more than a couple of key presses, Google the alternative. It shouldn't take many key presses to e.g. move to end of line or jump backwards three words. Use Google if you feel slow.
Practice makes perfect. It's best to go cold-turkey when learning Vim, just use it with all your text editors and IDEs. I encourage even disabling the normal navigation during the learning period.
// Sublime Text keybinding settings
// Not disabling up or down as those are used e.g. with autocompletion and menus.
{ "keys": ["left"], "command": "noop" },
{ "keys": ["right"], "command": "noop" },
{ "keys": ["pageup"], "command": "noop" },
{ "keys": ["pagedown"], "command": "noop" },
{ "keys": ["home"], "command": "noop" },
{ "keys": ["end"], "command": "noop" },
The default Sublime Text Vim emulation is total garbage. NeoVintageous is a decent alternative, not feature complete but most of it is in there.
I encourage to also install a Vim Chrome/Firefox plugin. Vimium is an excellent one. Main that I use is f
to quick jump to links and hjkl
for navigation. You can also use /
+ type a word + Enter
+ Enter
to navigate but that won't work on non-text links and in some popovers.
hjkl
to scrolldu
to jump down and upJK
to switch tabsxX
close/reopen tabvV
enter visual modes to copyy
or pastep
o
search and open a tab, an URL or a bookmark
I've switched Ctrl
(^) and Alt
around on all my devices. I have weak pinky fingers so pressing anything on the corner of the keyboard is draining during even short sessions. So I use my thumb for most of the modifiers. Surprisingly, this also makes many keybindings easier to press e.g. tmux
default prefix ^b
.
The Basics
I recommend turning off any "automatching" or "smart insert" of {}
, ""
etc. The feature that automatically adds a matching symbol when you type the first.
Vim has multiple editor modes:
- normal mode, for navigating around
- insert mode, for writing text
- visual mode, for verifying what you are selecting
- command-line mode, for running meta commands like
:w
to save the file - and many other modes, but those are not as essential
Undoing things is one of the most common actions: u
to undo, ^r
to redo.
If you press ^s
by accident to save, you can get back with ^q
. Explained simply, this freezes the rendering.
It is important to learn all the ways you get to typing in insert mode:
Key | Memory Rule | Where it Moves Before Insert Mode? |
---|---|---|
i | insert | in current position |
I | INSERT | at the beginning of the line |
a | append | move one character forward |
A | APPEND | at the end of the line |
o | open | start a new line under this one |
O | OPEN | start a new line above this one |
c | change | selective change discussed later |
C | CHANGE | delete and edit the rest of the line |
You can exit to normal mode with Esc
, ^[
or ^c
.
In Vim, you think in text objects.
- "character", "line" and "file" are self-explanatory
- "word" is a group of configurable characters;
a-z
,A-Z
,0-9
and_
by default - "WORD" is a group of characters other than whitespace like
<space>
or\n
- "sentence" is a word group separated by
.
/!
/?
followed by a whitespace - "paragraph" is a sentence group separated by a blank line
- custom text objects are created on the fly e.g.
$
(from here to beginning of line)
You think "I want to change this word" or "I want delete next 3 paragraphs". Not in individual characters or in abstract logical blocks as you'd normally do.
You navigate between various text objects using "motions".
Motion | Memory Rule | Description |
---|---|---|
space | - | move one character right |
enter | - | move one line down |
hjkl | - | move one character left/down/up/right |
w / W | word | next beginning of a word/WORD |
e / E | ending | next ending of a word/WORD |
b / B | back | previous beginning of a word/WORD |
+ / - | + to line count | beginning of the next/previous line |
^ / $ | same as regex | beginning/ending of the current line |
gg | start good game | beginning of the first line in file |
G | GO END IT | beginning of the last line in the file |
( / ) | - | previous/next sentence |
{ / } | - | previous/next paragraph |
fx / Fx | find | next/previous occurrence of x |
tx / Tx | 'till | before next/after previous occurrence of x |
; / , | - | repeat last fFtT forward/backward |
/ | - | starts a search to get position of the first match |
You prefix motions with "counts" and then they are triggered multiple times. For example, 2w
means "two words forward" and "5-"/"5k" both mean "5 lines up". Some motions make little sense without a count, e.g.|
goes to that column on the current line, defaults to first character or whitespace.
Your turn motions into text objects with a
/ i
prefixes. Used when in visual mode or after an operator to select the specified text object under the cursor without having to go to the beginning of the referenced text object. Without the a
/ i
prefix, the motion partially selects the given text object depending where the cursor is currently.
Notation | Memory Rule | Selects What? |
---|---|---|
iw | in word | words |
aw | around word | words and the trailing space |
iW | in WORD | WORDS |
aW | around WORD | WORDS and the trailing space |
is | in sentence | sentences |
as | around sentence | sentences and the trailing space |
ip | in paragraph | paragraphs |
ap | around paragraph | paragraphs and the trailing line |
i( / i) | in () | everything between () |
a( / a) | around () | everything between () and them |
i[ / i] | in [] | everything between [] |
a[ / a] | around [] | everything between [] and them |
i{ / i} | in {} | everything between {} |
a{ / a} | around {} | everything between {} and them |
i< / i> | in <> | everything between <> |
a< / a> | around <> | everything between <> and them |
i" | in double quotes | everything between "" |
a" | around double quotes | everything between "" and them |
i' | in single quotes | everything between '' |
a' | around single quotes | everything between '' and them |
i` | in back quotes | everything between `` |
a` | around back quotes | everything between `` and them |
The most essential operation are:
Operation | Memory Rule | Does What on the Selection? |
---|---|---|
d | delete | delete (also acts as cut if using default p paste |
c | change | delete and enter insert mode |
y | yank | copies to registry (like a clipboard) |
> | to right | shift right one indention level |
< | to left | shift left one indention level |
J | JOIN | joins the line with the next line separated by a space |
Most operators use the form:
{OPERATOR}{OPTIONAL_NUMBER}{MOTION_OR_OBJECT}
d4j = delete 4 lines down
dw = delete characters until beginning of then next word
caW = yank all of this WORD
ci" = change everything between the closest double quote pair
>ap = indent the all of this paragraph
<{ = indent paragraph up to this point
Some operations are eager and won't wait for a motion. You can frequently use v
to first select where to apply it though.
Operation | Memory Rule | What It Does? |
---|---|---|
~ | up-and-down | toggle uppercase and lowercase |
r | replace | after press, wait for input to replace at cursor |
x | exterminate | delete character at cursor |
X | EX-exterminate | delete character right before cursor |
s | substitute | delete character at cursor and enter insert mode |
There are shortcuts to work on the whole current line: dd
, yy
, cc
, >>
, <<
.
Many basic operations have uppercase variant which selects the rest of the line: D
, Y
, C
.
While in insert mode, you can use ^x^f
to explore file paths; relative or absolute. This is especially useful when writing configuration files that point to files.
=> i and type
/home/ruksi/D
=> ^x^f gives a list to choose from, enter to select =>
/home/ruksi/Downloads
Paste
You paste registry contents (aka. clipboards) using p
and P
:
Key | Memory Rule | From Where and Where To? |
---|---|---|
p | paste | paste your "-registry (default clipboard) below |
P | PASTE | paste your "-registry above |
"0p | paste yank | paste a specific registry 0; which is the last yank |
By default d
, c
, x
, y
, p
etc. operate on default register named "
. If you want to y
, d
and then p
something, you can refer to yank register 0
yy
dd
p => pastes what was delete-copied with d
"0p => pastes what was copied with y
""p => pastes what was delete-copied with d
Command-line Mode :
You enter command-line mode with :
.
Here are some basic commands:
:help
enter help manual:w
save file:wq
save and exit:q!
quit without savinge:
= open another file:s/text/replacement/g
replace all occurrences of "text on this line:%s/text/replacement/gc
replace all occurrences of "text" in file, with confirmation
Here are some a bit more exotic commands as extra tips:
v<SELECT_LINES>:sort
= sort selected lines:b#
= back to the file selection when you open a directory e.g.vim .
You can use :r !
REPL to run an actual shell command and capture the output. !
is generic filtering through external program.
Hello
=> :r !uname
Hello
Linux
Marks
ma
marks the cursor position as "a"`a
is a reference to the marked position "a"'a
is a reference to the line that has the mark "a"`.
is a reference to the last place that had a change:marks
lists all available marks
Visual mode selection is simply maintaining marks <
and >
. You rarely need to know this though.
Jumps
TODO: maybe list all jump motions here?
^o
jumps to an older position in jump history^i
jumps to a newer position in jump history:jumps
shows jump history
Macros
Macros allow recording and repeating a process:
q<letter><commands>q
records a macro e.g.qwv2B~q
changes two previous words casing<number>@<letter>
plays the macro<number>
times@@
replays the last macro
Macros allow you to "write shorthand and expand it" :
one 1
two 2
three 3
four 4
=> anywhere on the first line qwI'<Esc>Ea':<Esc>A,<Esc>+q3@w =>
'one': 1,
'two': 2,
'three': 3,
'four': 4,
Using f
, t
and /
as parts of a macro is really powerful.
The most common macros I do are on the format:
^ = go to the start of this line
qq = start recording macro "q"
<do something>
<Esc> = go back to the normal mode
+ = go to the first
q = stop recording the macro
Customization
Vim configuration is located at $HOME/.vimrc
. I don't use it for anything though.
vim .vimrc
Keybinding Table
^
means the Control key, symbol written with Shift + 6 by default.!
means not used at the moment, but must be implemented. (TODO)?
means not used at the moment, but should be utilized.-
means not used at the moment, and could be utilized in the context.x
means not used and other contexts forbid the usage."
means "leftwise ditto", the same as left cell.
Contexts:
Terminal
lists what the keybinding does in terminal, most are defaults.Vim
lists what the keybinding does in Vim by default, as I don't change themText
lists what it does in Sublime Text.IDE
lists what it does in JetBrains IDEs like WebStorm, PyCharm, etc.
Function Keys
F10
= Enter Presenter ModeF11
= Enter Full Screen ModeF12
= Enter Distract Free Mode
Press F11
and F12
when focusing on programming. Navigate between files with ^]
(go to usage/source), ^k
(open file) and ^K
(open file browser). Check version control status with ^backtick
Minimize all tool windows with ^M
.
Ctrl
Keybindings
Bind | Terminal | Vim | SublimeText | IDE |
---|---|---|---|---|
^` | - | - | show_panel.console | Show Local Changes |
^1 | ? | ? | switch to tab 1 | Select Tab #1 etc. |
^q | XON , the only use is to unfreeze terminal if you pressed ^s | XON | - | - |
^w | x | control viewports | close | Editor Tabs >Close |
^e | go to end of line | scroll line down | " | " |
^r | history search | redo | " | " |
^t | swap two previous character (useless) | jump to previous tag or indent editing line | new_file | File > New |
^y | paste after ^u or ^k | scroll line up | " | " |
^u | cut command up to cursor | scroll page up | " | " |
^i | - | jump to newer position | " | " |
^o | after ^r search, leave for edit, same as arrow keys | jump to older position | " | " |
^p | after ^r search, go to previous command | general "previous" | ! | same as Vim |
^[ | - | Esc alternative | Back | Back |
^] | - | jump to definition | goto_definition | Navigate > Declaration or Usages |
^a | go to start of line | increment number | increment number | increment number |
^s | XOFF , disabling the screen from refreshing; revert with ^q | XOFF | save | File > Save All |
^d | End of Transmission control character EOT, closes app | scroll half-page down | " | " |
^f | Right alternative | ? (default is alt. scroll but I use ^d ) | native search | native search |
^g | cancel ^r search like Esc (useless) | ? (show filename) | " | " |
^h | Backspace control character BS | h alternative | ? | ? |
^j | Line Feed control character LF, or "\n" | j alternative | " | " |
^k | cut command after cursor | ? | go_to_file | Navigate > File... |
^l | Form Feed | ? | ? | ? |
^; | Generate... | Generate... | Generate... | Generate... |
^' | Refactor This... | Refactor This... | Refactor This... | Refactor This... |
^\ | send SIGQUIT signal to the current application | SIGQUIT | ? | Refactor This... |
^Enter | s | v | context_menu | Other > Show Context Actions |
^z | stop the current application (SIGTSTP ); use fg , jobs and kill %1 to manage it | x | ? | ? |
^x | ? | decrement number | decrement number | decrement number |
^c | send SIGINT | send SIGINT | - | - |
^v | verbatim insert, e.g. ^vEnter to type ^M on terminal | select visual block | select visual block | select visual block |
^b | tmux prefix | " (default is alt. scroll but I use ^u ) | - | "split" prefix |
^n | after ^r search, go to next command | select next occurrence of the selected word | " | " |
^m | Carriage Return | Carriage Return | Carriage Return | Carriage Return |
^, | - | - | - | Unwrap/Remove |
^. | - | - | - | Surround With |
^/ | - | - | comment lines | comment lines |
^PgUp | sends ~5 | sends ~5 , changes 5 character casings | prev_view | Select Previous Tab |
^PgDw | sends ;~5 | also changes 5 character casings | next_view | Select Next Tab |
Some general notes of worth:
- I use
^f
for native search solely because the default Chrome search is so powerful for mouseless navigation. None of the half a dozen Vim Chrome plugins I have tried can easily pick arbitrary text to click (they might not always be links or buttons.) With Chrome search it's just^f
, type, enter, enter, enter, escape, enter to click an element. - I know that
^q
/^s
combo could be re-utilized with a little terminal configuration soXOFF/XON
is not considered, but I'll keep that as an extra leeway if I run out of bindings.
Ctrl+Shift
Keybindings
Bind | Terminal | Vim | SublimeText | IDE |
---|---|---|---|---|
^Q | - | - | - | - |
^W | - | - | - | Editor Tabs > Close All |
^E | - | - | - | Reformat Code |
^R | - | - | run selected markdown code block | Run > Run... |
^T | - | - | reopen_last_file | Reopen Closed Tab |
^Y | - | - | - | - |
^U | type Unicode | type Unicode | type Unicode | type Unicode |
^I | - | - | - | Inspect Code |
^O | - | - | - | Optimize Imports |
^P | - | - | - | Open Recent |
^{ | - | - | Forward | Forward |
^} | - | - | - | - |
^A | - | - | command palette | Find Action... |
^S | - | - | prompt_save_as | Copy As... |
^D | - | - | Toggle Breakpoint | Toggle Breakpoint |
^F | Find in View | " | find_in_files | Find in Files |
^G | - | - | - | - |
^H | - | - | - | Git Show History |
^J | - | - | - | - |
^K | - | - | focus_file_on_sidebar | Select in Project View |
^L | - | - | - | Locate Duplicates |
^: | - | - | - | - |
^" | - | - | - | - |
^| | - | - | - | - |
^> | - | - | - | - |
^Z | - | - | - | - |
^X | - | - | - | - |
^C | copy to OS clipboard | copy to OS clipboard | copy to OS clipboard | copy to OS clipboard |
^V | paste from OS clipboard | paste from OS clipboard | paste from OS clipboard | paste from OS clipboard |
^B | - | - | - | - |
^N | - | - | - | - |
^M | - | - | - | Hide All Tool Windows |
^< | - | - | - | - |
^> | - | - | - | - |
^? | - | - | block comment | block comment |
Alt
Keybindings
I don't use Alt
too much for single modifier keybindings as many applications on all Windows, Mac and Linux have Alt+<character
navigation so it all depends on context. But there are a couple.
Global Keybindings
I leave Super
(Windows key, system key, the thing between Ctrl
and Alt
) for the most global keybindings that I can use across all applications whenever.
Super
by itself should show application/file search e.g. to open PyCharm fast.Super+w
to close the active application.Super+e
to open the file browser, sometimes you just want to peek around.Super+d
to minimize all applications, showing the desktop.Super+Up
to maximize applicationSuper+Down
to bring the application to the original sizeSuper+Left
to move application to the left side of the screen.Super+Right
to move application to the right side of the screen,Super+<number>
to switch virtual desktops.Ctrl+Esc
brings up Todoist, a TODO task application.Ctrl+Shift+4
is to take a screenshot, the same as I use in MacOS.- I use
Alt+Tab
rebound to^Tab
as I've switched those modifiers around. Alt+Shift
= change keyboard layout (I code in English, type in Finnish and others)Ctrl+Shift+c
is OS copy,Ctrl+Shift+v
is OS paste if I need something outside of Vim clipboard.- Obviously why you can't use default
Ctrl+c
is because that is the default terminal interrupt signal. Ctrl+Insert
withShift+Insert
is another common default but that doesn't work at all while working the mouse, which is the thing you are doing when getting text outside of Vim.
- Obviously why you can't use default
Customizing Chrome
cVim
Install cVim
and use the following settings to make it feel even more like Vim:
set smoothscroll
let barposition = "bottom"
map } scrollPageDown
map { scrollPageUp
map <C-d> scrollPageDown
map <C-u> scrollPageUp
Now typing :help
brings you more info about cVim
.
Shortkeys
Install Shortkeys
to customize default Chrome keybindings that overlap with others.
ctrl+shift+c
,Copy
,Run JavaScript
,document.execCommand('copy')