ruk·si

Vim, tmux and the Keybindings

Updated at 2022-04-22 07:01

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 scroll
  • du to jump down and up
  • JK to switch tabs
  • xX close/reopen tab
  • vV enter visual modes to copy y or paste p
  • 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:

KeyMemory RuleWhere it Moves Before Insert Mode?
iinsertin current position
IINSERTat the beginning of the line
aappendmove one character forward
AAPPENDat the end of the line
oopenstart a new line under this one
OOPENstart a new line above this one
cchangeselective change discussed later
CCHANGEdelete 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".

MotionMemory RuleDescription
space-move one character right
enter-move one line down
hjkl-move one character left/down/up/right
w / Wwordnext beginning of a word/WORD
e / Eendingnext ending of a word/WORD
b / Bbackprevious beginning of a word/WORD
+ / -+ to line countbeginning of the next/previous line
^ / $same as regexbeginning/ending of the current line
ggstart good gamebeginning of the first line in file
GGO END ITbeginning of the last line in the file
( / )-previous/next sentence
{ / }-previous/next paragraph
fx / Fxfindnext/previous occurrence of x
tx / Tx'tillbefore 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.

NotationMemory RuleSelects What?
iwin wordwords
awaround wordwords and the trailing space
iWin WORDWORDS
aWaround WORDWORDS and the trailing space
isin sentencesentences
asaround sentencesentences and the trailing space
ipin paragraphparagraphs
aparound paragraphparagraphs 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 quoteseverything between ""
a"around double quoteseverything between "" and them
i'in single quoteseverything between ''
a'around single quoteseverything between '' and them
i`in back quoteseverything between ``
a`around back quoteseverything between `` and them

The most essential operation are:

OperationMemory RuleDoes What on the Selection?
ddeletedelete (also acts as cut if using default p paste
cchangedelete and enter insert mode
yyankcopies to registry (like a clipboard)
>to rightshift right one indention level
<to leftshift left one indention level
JJOINjoins 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.

OperationMemory RuleWhat It Does?
~up-and-downtoggle uppercase and lowercase
rreplaceafter press, wait for input to replace at cursor
xexterminatedelete character at cursor
XEX-exterminatedelete character right before cursor
ssubstitutedelete 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:

KeyMemory RuleFrom Where and Where To?
ppastepaste your "-registry (default clipboard) below
PPASTEpaste your "-registry above
"0ppaste yankpaste 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 saving
  • e: = 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 them
  • Text lists what it does in Sublime Text.
  • IDE lists what it does in JetBrains IDEs like WebStorm, PyCharm, etc.

Function Keys

  • F10 = Enter Presenter Mode
  • F11 = Enter Full Screen Mode
  • F12 = 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

BindTerminalVimSublimeTextIDE
^`--show_panel.consoleShow Local Changes
^1??switch to tab 1Select Tab #1 etc.
^qXON, the only use is to unfreeze terminal if you pressed ^sXON--
^wxcontrol viewportscloseEditor Tabs >Close
^ego to end of linescroll line down""
^rhistory searchredo""
^tswap two previous character (useless)jump to previous tag or indent editing linenew_fileFile > New
^ypaste after ^u or ^kscroll line up""
^ucut command up to cursorscroll page up""
^i-jump to newer position""
^oafter ^r search, leave for edit, same as arrow keysjump to older position""
^pafter ^r search, go to previous commandgeneral "previous"!same as Vim
^[-Esc alternativeBackBack
^]-jump to definitiongoto_definitionNavigate > Declaration or Usages
^ago to start of lineincrement numberincrement numberincrement number
^sXOFF, disabling the screen from refreshing; revert with ^qXOFFsaveFile > Save All
^dEnd of Transmission control character EOT, closes appscroll half-page down""
^fRight alternative? (default is alt. scroll but I use ^d)native searchnative search
^gcancel ^r search like Esc (useless)? (show filename)""
^hBackspace control character BSh alternative??
^jLine Feed control character LF, or "\n"j alternative""
^kcut command after cursor?go_to_fileNavigate > File...
^lForm Feed???
^;Generate...Generate...Generate...Generate...
^'Refactor This...Refactor This...Refactor This...Refactor This...
^\send SIGQUIT signal to the current applicationSIGQUIT?Refactor This...
^Entersvcontext_menuOther > Show Context Actions
^zstop the current application (SIGTSTP); use fg, jobs and kill %1 to manage itx??
^x?decrement numberdecrement numberdecrement number
^csend SIGINTsend SIGINT--
^vverbatim insert, e.g. ^vEnter to type ^M on terminalselect visual blockselect visual blockselect visual block
^btmux prefix" (default is alt. scroll but I use ^u)-"split" prefix
^nafter ^r search, go to next commandselect next occurrence of the selected word""
^mCarriage ReturnCarriage ReturnCarriage ReturnCarriage Return
^,---Unwrap/Remove
^.---Surround With
^/--comment linescomment lines
^PgUpsends ~5sends ~5, changes 5 character casingsprev_viewSelect Previous Tab
^PgDwsends ;~5also changes 5 character casingsnext_viewSelect 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 so XOFF/XON is not considered, but I'll keep that as an extra leeway if I run out of bindings.

Ctrl+Shift Keybindings

BindTerminalVimSublimeTextIDE
^Q----
^W---Editor Tabs > Close All
^E---Reformat Code
^R--run selected markdown code blockRun > Run...
^T--reopen_last_fileReopen Closed Tab
^Y----
^Utype Unicodetype Unicodetype Unicodetype Unicode
^I---Inspect Code
^O---Optimize Imports
^P---Open Recent
^{--ForwardForward
^}----
^A--command paletteFind Action...
^S--prompt_save_asCopy As...
^D--Toggle BreakpointToggle Breakpoint
^FFind in View"find_in_filesFind in Files
^G----
^H---Git Show History
^J----
^K--focus_file_on_sidebarSelect in Project View
^L---Locate Duplicates
^:----
^"----
^|----
^>----
^Z----
^X----
^Ccopy to OS clipboardcopy to OS clipboardcopy to OS clipboardcopy to OS clipboard
^Vpaste from OS clipboardpaste from OS clipboardpaste from OS clipboardpaste from OS clipboard
^B----
^N----
^M---Hide All Tool Windows
^<----
^>----
^?--block commentblock 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 application
  • Super+Down to bring the application to the original size
  • Super+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 with Shift+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.

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')