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
finfoo dwto storefooin the unnamed register- Place the cursor at the
binbaz(e.g.2W) veto selectbazin visual modepto exchange the two- Go back and put
baz, e.g.F(p.
In summary, dw2WvepF(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 (delete a
paragraph).
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>