Vim tricks collection
The following is a bunch of various useful Vim tricks that I rarely see anyone else use.
- Completion
- Transpose two characters
- Visual put to exchange two snippets of text
- Put at current indent level
- Navigate by paragraphs
- Repeated changes across files using
argdo
- Use arrow keys for scrolling
- Different cursor shapes in GNOME Terminal
- Jedi-Vim configuration
- Flake8 plugin configuration
- Ale plugin configuration
- clang_complete configuration
- Replace raw Unicode character with named equivalent
- Insert Unicode character by name
Completion
:help
i_CTRL-N
i_CTRL-X_CTRL-L
In insert mode, press CTRL-N
to complete the current token using existing
tokens from open buffers, and press CTRL-X CTRL-L
to complete the current
line using existing lines in the file.
This can be very useful if you have a lot of } catch (IOException e) {
in
your code.
Transpose two characters
In Emacs, you have C-t
(transpose-chars
) which transposes the two
characters before the cursor,
for instance to turn normla
into normal
.
The equivalent keypress in Vim is xp
(or Xp
, depending on cursor position):
Delete a character and put it after the following character.
Visual put to exchange two snippets of text
:help
v_p
Occasionally you may want to exchange two snippets of text, for instance
swapping the first and third entry in the tuple (foo, bar, baz)
so it becomes
(baz, bar, foo)
.
When you press p
in Visual mode, you exchange the current visual selection
with the contents of the unnamed register.
This means the exchange can be achieved in the following way:
- Place the cursor at the
f
infoo
dw
to storefoo
in the unnamed register- Place the cursor at the
b
inbaz
(e.g.2W
) ve
to selectbaz
in visual modep
to exchange the two- Go back and put
baz
, e.g.F(p
.
In summary, dw
2W
ve
p
F(
p
.
Put at current indent level
:help
]p
]p
puts below current line at current indent level, and [p
puts above.
Navigate by paragraphs
:help
paragraph
To navigate between empty lines, use {
and }
.
Use empty lines accordingly in your code to ease navigation between logical
blocks.
To delete the current paragraph, use either {d}
or dap
(d
elete a
p
aragraph).
Very useful for reorganizing code.
Repeated changes across files using argdo
:help
arglist
In Vim, the arglist is the set of files specified on the command line when
you started Vim, and it can be reset to a new list using the :args
command.
To perform a command in all files in the arglist, use :argdo
.
Remember to :set autowrite
to automatically write the buffer before switching
to the next file.
For instance, to perform a global search and replace in all files matching *.txt
:
:set autowrite :args *.txt :argdo %s/FOO/bar/g
You can also insert a header guard in all C header files using the following:
:set autowrite :args *.h :argdo exec "norm ggO".expand("%") :argdo exec "norm gggUU:s/\\./_/g\" :argdo exec "norm ggI#ifndef " :argdo exec "norm ggyypR#define" :argdo exec "norm Go#endif"
Use arrow keys for scrolling
nmap <Down> 3<C-E> nmap <Up> 3<C-Y> vmap <Down> 3<C-E> vmap <Up> 3<C-Y> imap <Down> <C-O>3<C-E> imap <Up> <C-O>3<C-Y>
Different cursor shapes in GNOME Terminal
GNOME Terminal, xterm, and others, support the VT520 DECSCUSR escape codes for changing the cursor style. To mimic GVim and have a bar cursor in insert mode and underline cursor in replace mode:
let &t_SI="\<Esc>[5 q" let &t_SR="\<Esc>[3 q" let &t_EI="\<Esc>[0 q"
Jedi-Vim configuration
The default configuration of the Vim plugin for Jedi (awesome Python autocomplete/goto definition) adds a lot of unnecessary popups at unwanted times. A sane configuration is as follows:
let g:jedi#popup_on_dot = 0 let g:jedi#show_call_signatures = 2 let g:jedi#show_call_signatures_delay = 0 let g:jedi#auto_vim_configuration = 0 let g:jedi#smart_auto_mappings = 0 set noshowmode
Ale plugin configuration
The Ale plugin for Vim 8 runs Flake8 in the background. The default configuration runs Flake8 all the time, but I prefer to only run it on demand.
let g:ale_lint_on_enter = 0 let g:ale_lint_on_save = 0 let g:ale_lint_on_text_changed = 0 let g:ale_set_highlights = 1 let g:ale_set_loclist = 0 let g:ale_set_quickfix = 1 let g:ale_set_signs = 0 nnoremap <F5> :<C-u>call ale#Lint()<CR> nnoremap <Esc>u :<C-U>noh<Bar>call ale#highlight#SetHighlights(bufnr('%'), [])<CR> nnoremap <A-U> :<C-U>noh<Bar>call ale#highlight#SetHighlights(bufnr('%'), [])<CR>
clang_complete configuration
The default configuration of the clang_complete Vim plugin (awesome C++ autocomplete/goto definition) adds a lot of unnecessary popups at unwanted times. A sane configuration is as follows:
let g:clang_make_default_keymappings = 0 au FileType cpp nnoremap <buffer> <Leader>d :call g:ClangGotoDeclaration()<CR> au FileType cpp nnoremap <buffer> <Leader>g :call g:ClangFollowReference()<CR> let g:clang_auto_select = 2 let g:clang_complete_auto = 0 let g:clang_auto_user_options = "compile_commands.json"
Replace raw Unicode character with named equivalent
Run :Uniname
on one or more lines to replace non-ASCII characters
with named Unicode literals (or hexadecimal escapes in case of 8-bit control codes).
py3 <<EOF def uniname(ch): import unicodedata try: return '\\N{%s}' % unicodedata.name(ch) except ValueError: return repr(ch)[1:-1] EOF command! -range Uniname <line1>,<line2>py3do import re; return re.sub(r'[^\x20-\x7f]', lambda mo: uniname(mo.group()), line)
Insert Unicode character by name
Press CTRL-B
in Insert mode and type the name of a Unicode character,
e.g. SQUARE ROOT, to insert the given symbol at the cursor.
Completion is possible if you install font-unicode
from PyPI.
py3 <<EOF def unisyms(needle): import os, sqlite3, fontunicode.glyphlist db_filepath = os.path.join(os.path.dirname(fontunicode.glyphlist.__file__), 'unicode.db') con = sqlite3.connect(db_filepath, isolation_level=None) cur = con.cursor() cur.execute( """SELECT unilongname FROM Unicodes WHERE unilongname LIKE ?""", (needle + '%',)) return [result[0] for result in cur.fetchall()] EOF function! Unisyminputcomplete(ArgLead, CmdLine, CursorPos) return py3eval('unisyms(' . json_encode(a:CmdLine) . '[:' . a:CursorPos . '])') endfunction let g:unisyminputlast = '' function! Unisyminput() let g:unisyminputlast = input('', g:unisyminputlast, 'customlist,Unisyminputcomplete') return py3eval('"\N{' . g:unisyminputlast . '}"') endfunction inoremap <C-b> <C-r>=Unisyminput()<CR>