vim, git, aws and other three-letter words

Software Development Notes

Vim Features Overview

About

This is my overview of some of the Vim features created as a part of learning about these features.

The Vim config is here: https://github.com/serebrov/vimrc (careful, here be dragons).

Essential resources:

Normal mode - dot to repeat the last command

. (dot) - repeat the last normal-mode command, automatic mini-macro.

Normal mode operators, motions and text objects

Operators

[operator]{motion} - apply :h operator to the text defined by motion.

For example: >G - shift everything until the end of file to the right (> - shift right operator, G - end of file motion), gg=G - format the whole file (gg - jump to the top, = - format operator, G - end of file motion).

Operators:

  • c - change
  • d - delete
  • y - yank into register (does not change the text)
  • J - join lines, gJ - join lines without adding a space between them
  • ~ - swap case (only if 'tildeop' is set)
  • g~ - swap case, visual mode ~
  • gu - make lowercase, visual mode u
  • gU - make uppercase, visual mode U
  • ! - filter through an external program
  • = - text indenting, using equalprg or internal function
  • gq - text formatting, using formatexpr or formatprg or internal function
  • g? - ROT13 encoding
  • > - shift right (in visual mode >, in normal mode >>)
  • < - shift left (in visual mode <, in normal mode <<)
  • zf - define a fold
  • g@ - call function set with the 'operatorfunc' option

More info: how to define your own operator, :h :map-operator, how to define your own motion, :h omap-info.

Motions

Horizontal (left-right) motions

Imagine we have the following line in the buffer where * is the cursor position:


    Pudding—Alice: Alice—Pudding.
┆   ┆     ┆*┆            ┆      ┆  ┆
┆   ┆     ┆ ┆            ┆      ┆  ┆
0   ^     h l      gm    25|    g_ $

With h / l we can move one character left or right (it can also take count, 5h moves 5 characters to the left).

0 jumps to line start and so on. ^ jumps to the first non-space character (so the first P). g_ jumps to the last non-space and $ to the end of the line (assuming that we have some spaces at the end in the example above).

The [count]| moves to the specified column (25 in this case, which is the second P).

When the line is wrapped, g^ moves to the start of the screen line. The gm depends on the window width and moves to the center of the screen line.

Jump to the character: f / t, F / T

f jumps forward to the character given after it, so fc jumps to the next c.

t jumps forward "till" the character (stops just before it).

F and T do the same backwards.


Pudding-Alice: Alice-Pudding.
 |    *    |        |
 Fu        fc       tP
 TP

Words and WORDs

"Word"s are sequences of letters, digits and underscores (can be configured with 'iskeyword') and "WORD"s are any non-blank characters.

We can use the following motions (the cursor is at the * position):

Words and WORDs

    ┌┈┈┈┈┈┈┈┈┐ ┌┈┈┈┈┈┈┈┐ ┌┈┈┈┈┈┈┐ ┌┈┈┈┈┈┈┈┈┐ - WORDs
    ┌┈┈┈┈┈┐┌┈┐ ┌┈┈┈┐┌┈┈┐ ┌┈┈┈┐┌┈┐ ┌┈┈┈┈┈┐┌┈┐ - words
    Pudding--- Alice:::: Alice--- Pudding...
    ┆      ┆   *    ┆    ┆
    ┆      ┆        w    W ┈┈┈┈┈┈ next word / WORD
    ┆      ┆
    B      b - prev word / WORD

    Pudding--- Alice:::: Alice--- Pudding...
             ┆     ┆   ┆ *   ┆  ┆
             ┆     ┆   ┆     e  E ┈┈┈┈┈┈ end of the word / WORD
             ┆     ┆   ┆
             ┆     ┆   ge/gE ┈┈┈┈┈┈┈┈┈┈┈  end of the prev word / WORD
             ┆     ┆
             2gE   2ge ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈  two words / WORDs back

Vertical (up-down) motions

Vertical motions (the cursor is at *):

Up-down motions ...                     ┈┈┈ gg
...
But the Red Queen looked sulky,
and growled                             ┈┈┈ k - line up, `-` - up and move to the start
'Pudding—Alice: Alice—Pudding.     *
Remove the pudding!'                    ┈┈┈ j - line down, `+` - down and move to the start

and the waiters took it away so quickly ┈┈┈ :+3   - range is a motion, c:+2, d:107
that Alice couldn't return its bow.     ┈┈┈ /bow  - search is a motion, c/bow
...
...                                     ┈┈┈ G

Note that : (which lets you run a command from the Vim command line) can be used as a motion: d:call search('f') will delete until the next 'f' found by the search() function.

There is also [count]_ motion which moves count-1 lines down and jumps to the start of the line. It is like a ^ motion, but with count. If there is no count or count=1 it moves to the current line start, with count > 1 moves down and jumps to the start.

The [N]% jumps to the N% of the file, :[range]go[to] [count] and [count]go jump to the count byte in the file.

Text object motions / various motions

Matching pair () {} []      - % - move to the matching pair, make sure to enable the
              /**/            matchit.vim (standard plugin), ":h matchit.txt"
              <tag></tag>     "matching" things can be html tags, if/else statements
              if/else/endif   and you don't have to be at the pair item for % to work
              etc             for example, in "my text (something)", you can use % when
                              cursor is at the start of the line.

A next / prev sentence.     - ) / ( - [count] sentences, like y3) - yank 3 sentences

A paragraph of text.        - } / { - [count] paragraphs

Unmatched (                 - [( / ]( - prev/next unmatched (
Unmatched {                 - [{ / ]{ - prev/next unmatched {
Unmatched #if / #else       - [# / ]# - prev/next unmatched #if / #else

A method of the class       - [m / ]m, and [M / ]M move to the end of the method

A block comment /*  */      - [*, [/ / ]*, ]/ - prev / next comment mark

[n] lines from the top      - [n]H
[n] lines from the bottom   - [n]L
Middle line                 - M

A section                   - ]] / [[ - [count] sections, see ":h section",
                              can be redefined by filetype plugins, like move between
                              classes / methods in python.
End of the section          - ][ / [] - [count] end of section

Each of them can be used as an operator target.

For example c% - change until the matching pair:

if (x and y or something(b, c))
               *
               |
               c%        - from here it will find the parens pair around "b, c"
                           and will jump to the end paren

if (x and y or ▓)        - as a result, we are changing the whole "something(b, c)"
                           with just one motion

link_to("text", my_p(sing("one"), plu(fn("two"))))
                  *   A                                B
                  |
                  c%   --- from here will change until B
                  %c%  --- will change the A-B, including brackets
                  %ci( --- here will change inside the A-B

See also Vim's life-changing c%.

Text object selection

Text objects allow specifying which part of the text we want to operate on.

There are usually "around" objects which include surrounding elements (such as "a(" includes the surrounding parens) and "inner" objects which only include what's inside (such as "i(" that only selects text inside the parens).

A simple way to try text objects is to use them with the "v" (visual mode) motion. For example, "vaw" will select the "around word" and "viw" will select the "inner word".

word, word_two          - aw / iw (regular / inner "word" text object)
WORD, word--%4-         - aW / iW ("WORD" object)

'string'                - a' / i'
"string"                - a" / i"
`string`                - a` / i`

A sentence.             - as / is

A paragraph of
text. It also has a
text object.            - ap / ip

[ block ]               - a[, a] / i[, i]
( block )               - a(, a), ab / i(, i), ib
< block >               - a<, a> / i<, i>
{ block }               - a{, a}, aB / i{, i}, iB
<tag>value</tag>        - at / it

Plugins that add more text objects: wellle/targets.vim, indent object, column object.

The quotes text objects (a', a", etc) look forward if the cursor is not inside the quoted string. For example, if cursor is on the * position in text [*] text 'quote', the ya' will yank (copy) the quoted word. The wellle/targets.vim makes other text objects also look forward (and then also backward if there is no object forward).

Inner text objects (iw, iB, etc) do not include the surrounding marks. For words this is trailing space, for blocks - brackets.

"aw" vs "iw" vs "w"

    ┌┈┈┈┈┈┈┐   - yaw - yank word with trailing space - "Pudding "
    ┌┈┈┈┈┈┐    - yiw - yank only word - "Pudding"
    Pudding Alice

Note: motions like yw and yaw do the same and yank the word with the trailing space (same for daw, caw, etc), but it will be a bit different in visual mode. The vaw will also select the first letter of the next word (because w actually moves to there). It works in a similar way for other objects, like sentences. See also :h exclusive.

Motions and operators

There are 3 types of the effects of operators: characterwise, linewise, blockwise.

And *wise can be varied by operator and motion:

  • dw - characterwise - delete a word
  • >j - linewise - indent 2 lines
  • dj - linewise - delete 2 lines

It is possible to force *wise with the following keys:

  • v - characterwise
  • V - linewise
  • <C-v> - blockwise

Usage: {operator}{*wise-specifier}{motion}, see :h o_v:

  • dvj - characterwise
  • dVj - linewise
  • d<C-v>j - blockwise

See also: operator, the true power of Vim.

Marks

:h mark-motions.

  • a-z - local marks (inside the buffer), reset when buffer is deleted
  • A-Z - global (across files)
  • 0-9 - automatically set from .viminfo, '0 - cursor position on last exit from Vim, '1 - previous exit, and so on, see :h viminfo-file-marks

Set the mark with m{a-zA-Z}.

Jump to the mark:

  • '{a-z} `{a-z} - jump to mark in the current buffer, with ' - to the first non-blank char of the mark line, with ` - to the exact mark location
  • '{A-Z0-9} `{A-Z0-9} - jump to mark in the file (may be another file, not a motion in this case)

Jump to the mark is a motion (can be used with operators).

List of marks - :marks.

Delete marks with :delm:

:delm a - delete mark `a`
:delm a b or :delm ab - delete marks `a` and `b`
:delm p-z - delete all marks from `p` to `z`
:delm! - delete all marks for the current buffer (only a-z, not A-Z and 0-9)

Normal mode - jump list and change list

Jump list is a very powerful way to navigate files in Vim. It is similar to the browser back / forward navigation button. After you use a motion or a command like gf to open another file, you can use C-o to go back and C-i to go forward again.

The change list lets you move across edits in a similar way.

Jump list

  • <C-O> / <C-I> - move back / forward in the jump list, :jumps
  • '' / `` - jump to the previous place you jumped here from
  • gf - open file under cursor
  • gd / gD - local / global variable definition
  • C-] - jump to the tag
  • C-^ - switch between two recent files
  • [num]<C-^> - switch to 'num' file (see file numbers in :buffers)

Change list

  • g; / g, - move back / forward the change list, view the list :changes
  • gi - jump to last edit and start the insert mode (uses '^ mark)
  • '. - jump to last edit position

Special marks

Vim also provides a set of special marks that can be used to quickly jump around:

'[ `[ / '] `]   - first / last char of last changed / yanked text
'< `<  / '> `>  - first / last char of last visual selected text
''  ``          - previous jump position
'" `"           - position before exiting the buffer (useful when you reopen it)
'^ `^           - last insert mode position
'. `.           - last edit position
[' [` / ]' ]`   - [count] previous / next lowercase mark

Insert and command mode: editing shortcuts

Some shortcuts that are useful in the command and insert mode:

  • <C-H> - delete previous character
  • <C-W> - delete previous word
  • <C-U> - delete current line, this is often used in mappings to clear the command line, for example to remove the automatic '<,'> when there is a visual selection

Insert mode: editing shortcuts

And some editing shortcuts for the insert mode (everything can be done by switching to normal mode, changing the text and switching back to insert, but it may be faster to do a small edit operation while staying in the insert mode):

  • <C-T> / <C-D> - indent / un-indent, useful for markdown lists
  • <C-Y> / <C-E> - insert char above / below the cursor
  • <C-A> / <C-X> (normal mode) - increment/decrement number under the cursor
  • g<C-A> in visual mode - sequentially increment values in a column
1                1                1
1 -- select --> |1| -- g<C-A> --> 2
1               |1|               3

This one is special as it does switch to the normal mode, but only for one command:

  • <C-O> - execute normal command and get back to insert mode

:h insert.txt

Insert and command mode: insert from the register

<C-R><r> inserts the text from the register.

Examples:

  • <C-R>0 (zero) - paste yanked text
  • <C-R>" - paste the text from the unnamed register

If we have "Hello" in the a register and "World" in the b, we can insert them like this: "ap"bp from normal mode.

But it is easy to do from the insert mode <C-R>a<C-R>b and change will be repeatable with dot.

See also: Vim: The useful Ctrl-R

Insert and command mode: calculate the expression and insert the result

<C-R>= - prompt for the expression and insert it

<C-R>=3*0.65  -- will insert 1.95

Insert mode: insert the last inserted text

<C-A> - Insert the last text added in the insert mode.

Example:

"some_text(...)
ct(new_text"      - change "some_text" to "new_text" till the (

"some_text, ...   - now we need to do the same change, but till the comma
ct,<C-A>          - we enter the new command `ct,` and then use Ctrl-A to insert new_text

There is also <C-@> to insert the last inserted text and stop the insert mode.

Insert mode autocompletion

Completion shortcuts for the insert mode:

  • <C-N> / <C-P> - generic completion, :h i_CTRL-N
  • <C-X><C-O> - omni-completion, :h compl-omni
  • <C-X><C-L> - lines
  • <C-X><C-F> - file names, based on :pwd
  • <C-X><C-]> - tags
  • <C-X><C-K> - dictionary
  • <C-X><C-N> - keywords in current file
  • there are more, see :h ins-completion

Work with autocomplete menu:

  • <C-N> / <C-P> - use the next / prev match from the word list
  • <C-Y> - accept the currently selected match (yes)
  • <C-E> - revert to the originally typed text (exit from autocompletion)
  • <BS> (and <C-H>) - delete one character from current match
  • <C-L> - add one character from current match

Open the popup without selecting the first item: <C-N><C-P> (will actually select the first item and then un-select it).

Insert mode: complete whole lines

Complete whole lines with <C-X><C-L>:

  • type some text, do <C-X><C-L>
  • if there are a few suggestions - type a bit more and <C-L>
  • now you are at the end of the line, and complete mode is still active
  • press <C-X><C-L> a few more times to get more lines which follow the line you've got

See also: Let Vim Do the Typing.

Similarly it is possible to complete sentences word-by-word with <C-X><C-P>.

Command line window

The command line window is a larger view of the command line.

It is very useful to edit long commands, or search patterns because we can use the normal mode for editing (the normal command line, : only has insert mode).

  • q: - opens a command-line window.
  • q/ - opens a search history window.

From the command line / search prompt - press <C-F> to switch to the command-line window.

So don't re-map the q:! (as people often map it to nop because they accidentally open the command line window meaning to do :q).

If you often invoke it accidentally, you probably have a problem with entering :q correctly. In this case either remap the :q to something else (for example, to <Leader>q) or type it like this:

  • left pinky - Shift
  • right pinky - :
  • left pinky - q

(there is no chance to type it backwards this way).

Visual mode

In normal mode v, V, <C-V> start the char-, line-, block-wise visual mode. Same keys in visual mode switch between char/line/block modes.

In normal mode gv re-selects the last visual selection (very useful).

In visual mode:

  • o - move to other end of the selection (also very useful when you need to adjust the selection on the other end of the visual block)
  • gv - switch current and previous visual selection
  • c - change the selection (can re-paste after the change with <C-R>", convenient for wrapping)
  • d - delete the selection
  • r - replace each character in the selection with entered character

In the visual block mode:

  • O - move to other corner on the same line
  • $ - select until the end of line, will work for all lines even if the length is different
  • A / I - append / prepend the block with entered text

Visual block + $ - selects a non-rectangular block. Then use A to append to the end of lines. This is a very handy operation that often saves a lot of time.

Alternative: do A on one line, then select a block and repeat with :'<,'>normal ..

Select function body (between { and }): vaBV - select "a block" and then change the selection mode to line-wise. To select 2 levels up - v2aBV (when inside other {} block inside function) or vaBaB (repeat aB to move to the next block). A mapping to work from any level inside the function: :map t ? function <CR>f{vaBV (search backwards for function, move to the { and then do vaBV).

Show full file name and stats

  • <C-G> - normal mode, show current file name and path and cursor position
  • g<C-G> - show file stats (number of columns, lines, words, bytes)

Calculator: expression register

In insert mode, Ctrl-R= will prompt for the expression and insert the result into the document.

It can also be convenient to have the expression in the document, then copy it and insert when prompted. The insert operation will be in command-line mode and we can do it using Ctrl-R" (in cmd mode, Ctrl-R inserts the given register value).

For example:

Document:
5+5*2       | ^ v $ y       - go to start, select until end, copy
5+5*2=      | A = Ctrl-R =  - append, enter =, Ctrl-R = to invoke prompt

Command line:
=           | Ctrl-R "      - insert the copied expression
=5+5*2      | Enter

Document:
5+5*2=15

cos(1.57)=7.963267e-4

See :help i_CTRL-R_=, :help c_CTRL-R, :help registers.

Digraphs and special chars

  • <C-K>{char1}{char2} - insert a digraph (normal mode)
  • digraph table
  • <C-V><key> - insert the key literally (like <C-V><Tab> always inserts a tab, regardless of 'expandtab' option).
  • <C-V>{code} - insert the unicode char literally by decimal code
  • <C-V>u{code} - insert by hex code
  • ga - show ascii value of char under cursor
  • g8 - show utf-8 byte sequence for char under cursor

:dig - show digraphs

Manage Files

Some commands to manage files from Vim command line:

  • set path.,**= - set path to recursively look through the sub-directories.
  • :find **/filename or :e **/filename - search for the file and open it.
  • :find **/filename<TAB> - display the list of matching files and move through them
  • :saveas new_name - make a copy with new_name and switch to that copy
  • :saveas Ctrl-R % - will insert the current file name, useful if new file name is similar to the current file name (also the following can be useful to edit the new name in the command-line window)
  • :w new_name - make a copy, but don't switch to it
  • :drop file_name - open file or jump to already opened version
  • :set switchbuf + useopen= + :sbuffer path/to/file - with 'useopen' option will also search for already open buffer and jump to it (also affects quickfix)
  • :hardcopy - print the file

The 'tpope/vim-eunuch' adds more commands to manage files (like Remove, Move, Chmod, Find, SudoWrite, and others).

Netrw

Netrw is the standard Vim file manager:

  • <F1> - open netrw help (use <C-^> to get back)
  • - - go to the parent dir, <CR> - open a file
  • R - rename file
  • d - create dir
  • mf - mark file, mF - unmark file, mu - unmark all files, qF - mark quickfix files
  • :MF pattern - mark files by pattern, mr - query for pattern and mark files
  • mt - mark target dir (or :MP dir), mark files, mc - copy files (mm - move)
  • mg - vimgrep marked, mz - compress / decompress, mx - apply shell command, md - diff, mp - print
  • qf - file info
  • <del>, D - delete file or dir (marked files if there are any, visual selection if any)
  • gh - hide / unhide dot files
  • i - switch view mode (thin / long / wide / tree)
  • s - sorting style
  • p - preview the file
  • x - view the file with an associated program (gx in any buffer)
  • X - execute the file
  • mb - bookmark the directory, gb - go to bookmarked dir, qb - list bookmarks and history
  • :Ex */pattern - search in current dir
  • :Ex **/pattern - search in current dir and sub-directories
  • :Ex **//pattern - search in dir and sub-dirs inside files with vimgrep

Easter Eggs

  • :help 42
  • :help!
  • :help holy-grail
  • :help UserGettingBored
  • :help quotes
  • :Ni!
  • :set rightleft (revert with :set norightleft or :set rightleft!)
  • :help map-modes (see comment below the table about :nunmap)
  • :help showmatch (read the note)
  • :help bar

Tags: vim