See also: recommended vim plugins

Below are some useful snippets from my vimrc. I didn't include specific options, but you can read my full vimrc if you are interested in those, too.

Prevent compatibility issues with plugins when using fish-shell

" vim likes a Bourne compatible shell
if has('unix')
  if executable('zsh')
    set shell=zsh
  elseif executable('bash')
    set shell=bash
  else
    set shell=sh
  endif
  let g:is_posix=1  " Better syntax highlighting - :h ft-sh-syntax
endif

Indent / dedent selected blocks like IDEs

" Keep selection after visually indenting
vnoremap < <gv
vnoremap > >gv

Make n always search down and N always search up

This means you don't have to worry about n and N switching directions when you search with / vs ?

" Keep search matches in the middle of the window
" Make n always search down and N always search up
noremap <expr> n 'Nn'[v:searchforward].'zzzv'
noremap <expr> N 'nN'[v:searchforward].'zzzv'

Write current file as root

For when you forget or don't want to sudo

" Write current file as root (also provided by vim-eunuch with :SudoWrite)
cnoremap w!! w !sudo tee > /dev/null %

Copy the file and line number to the clipboard

" Copy filename:linenumber to clipboard
nnoremap <leader>yy :let @+=expand('%:t') . ':' . line(".")<CR>

Automatically create missing parent directories when saving new file

augroup vimrc_auto_mkdir
  " https://stackoverflow.com/a/42872275
  autocmd!
  autocmd BufWritePre * call s:auto_mkdir(expand('<afile>:p:h'), v:cmdbang)
  function! s:auto_mkdir(dir, force)
    if !isdirectory(a:dir)
          \   && (a:force
          \       || input("'" . a:dir . "' does not exist. Create? [y/N] ") =~? '^y\%[es]$')
      call mkdir(iconv(a:dir, &encoding, &termencoding), 'p')
    endif
  endfunction
augroup END

Smart home key

" Smart home key
noremap <expr> <silent> <Home> xor(col('.') == match(getline('.'),'\S')+1, getline('.')=~'^\s*$' && col('.') == strlen(getline('.'))) ? '0' : '^'
inoremap <silent> <Home> <C-O><Home>
" 0 is also smart home
map 0 <Home>
" Move the original 0 functionality to ^ since the new 0 replaces ^
noremap ^ 0

Clear search result highlights with ^c

" Clear search highlights with ^c
"nnoremap <silent> <C-c> :nohlsearch<CR><silent><C-c>
"nnoremap <silent> <C-L> :nohlsearch<C-R>=has('diff')?'<Bar>diffupdate':''<CR><CR><C-L>
nnoremap <silent> <C-c> :nohlsearch<C-R>=has('diff')?'<Bar>diffupdate':''<CR><CR><silent><C-c>

Reopen files to previous position

if has('autocmd')
  " Specific autocmds can only be reverted if they are grouped. Revert with:
  " ":augroup reopen_to_last_position | autocmd! | augroup END"

  " If defaults.vim was loaded, clear conflicting vimStartup
  augroup vimStartup
    autocmd!
  augroup END
  augroup reopen_to_last_position
    autocmd!
    " Jump to the last cursor position when reopening a file
    " Don't do it when the position is invalid, when inside an event handler
    " (happens when dropping a file on gvim) and for a commit message (it's
    " likely a different one than last time).
    " If it doesn't work, check permissions on ~/.viminfo
    autocmd BufReadPost *
      \ if line("'\"") > 1 && line("'\"") <= line("$") && &ft !=# 'gitcommit' |
      \   exe 'normal! g`"' |
      \ endif
    " fold expand doesn't always work in BufReadPost
    autocmd BufWinEnter * normal! zv
  augroup END
endif