"" My |vimrc|

" A |'textwidth'| of 79 is used throughout.

""" Comments

" Comments are written in Vim's help |notation|, see |help-writing|, which can
" be highlighted with
" https://git.rcrnstn.net/rcrnstn/vim-unobtrusive-comment.

" Section headings are not written in |notation|, but are instead indicated
" with multiple comment characters, which can form folds with
" https://git.rcrnstn.net/rcrnstn/vim-unobtrusive-fold.

""" Compatibility

" This vimrc should work with all configurations of Vim. Manually tested with:
" - Features: tiny, huge (Debian `apt-get install vim-{tiny,gtk3}`)
" - Encodings/Locales: C, UTF-8 (`LC_ALL=C{,.UFT-8}`)
" - Colors: 1, 2, 8, 16, 256, termguicolors (`--cmd "set t_Co=$colors"`)
" - Terminals: GUI, VTE, Linux, tmux with the correct `Ss` `terminal-override`
" - Platforms: Linux

""" Features

" |:version| says "tiny" features are always present and are therefore used in
" favor of more advanced features whenever possible. "Tiny" features include:
" - |+multi_byte|
" - |+mouse|
" - |+tag_binary|
" - |+user_commands|
" - |+autocmd|
" - |+localmap|
" Important features that are only present in "normal":
" - |+eval|

" Note that trying to set unsupported options is silently ignored, and so can
" be done without checking for support first (which is good, since that
" requires |+eval|). Everything between |:if| and |:endif| is also silently
" ignored if |+eval| is not available.

""" Encoding

" |'encoding'| is hard-coded to `utf-8`. However, only characters present in
" Code Page 437 should be used in the interface, to ensure font support on most
" terminals (in particular, the Linux console). See
" - https://en.wikipedia.org/wiki/Code_page_347
" - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/tty/vt/cp437.uni
" - `man showconsolefont`

""" Re-sourcing

" |setglobal| is used where appropriate so that buffer/window-local options are
" not overridden when re-sourcing.

" At the time of writing, |augroup| messes up the highlighting of |autocmd|s
" within it, so the `vimrc` group name is added to every |autocmd| instead (the
" addition of the group of course makes the highlighting misinterpret it as the
" `vimAutoEventList` and the events instead get the erroneous
" `VimAutoCmdSfxList`... file a bug?). This can be checked with `:g/autocmd`.

""" Mappings

" Don't make any built-in mappings do something completely different! Another
" Vimmer should never be surprised by what happens, unless it is pleasantly
" because the functionality is extended in useful and obvious ways. This
" includes mappings from popular plugins, for which the defaults should be kept
" as far as possible.

" |<Leader>| is hard-coded to <Space> so that mappings work without |+eval|.
" Setting |mapleader| to a different value after the mappings have been defined
" does not change the mappings, so it is not possible to "hot-swap" it for pair
" programming anyway.

"" Options
" TODO: Use |setglobal| for more things? Note that for options with a non-empty
" default local value, `setglobal` does nothing useful.

""" Reset
" set all&

""" Encoding
" Force Vim's internal encoding to a Unicode encoding.
set encoding=utf-8

""" Buffers
" Allow switching away from unsaved buffers.
set hidden

""" Clipboard
" Integrate with any graphical environment's clipboard.
set clipboard^=unnamedplus

""" Editing
set backspace=indent,eol,start
set virtualedit=block

""" Windows
" Put newly opened windows below and to the right.
set splitbelow
set splitright

""" Interface clutter
set noruler
set showcmd
set shortmess+=I
set guioptions=cf

""" Interface characters
" If |'t_Co'| is empty (or set to 1) the default behavior of |'fillchars'|
" `stl:`/`stlnc:` (`=`/`^`) will be used regardless of its setting. Other good
" choices for |'listchars'| `fold:` is ` ` and `tab:` is: `→ `, `――>`, `├──`,
" `──┤`, `├─┤`.
set list
set linebreak
set breakindent
set breakindentopt=sbr,shift:2
set fillchars=stl:_,stlnc:_,vert:│,fold:─,diff:\ |
set listchars=tab:├\ ┤,trail:•,extends:›,precedes:‹,nbsp:·
set showbreak=»\ |

""" Colors
if has('gui_running')
  set t_Co=16777216
endif
if 16 <= &t_Co && &t_Co <= 256
  set t_Co=16
endif

""" Title
set title
set titlestring=vim:%{fnamemodify(getcwd(),':~:t:s?^$?/?')}%(:%<%{pathshorten(expand('%:~:.'))}%)

""" Tabs
set expandtab
set shiftround
set shiftwidth=4
set softtabstop=-1

""" Mouse
set mouse=a

""" Command-line
set wildmenu
set wildmode=longest:full,full
set wildignore=_*,.git,.cache,.vagrant,.ansible,.npm,node_modules,pipx,snap
if has('patch-8.2.4325')
  " See http://ftp.vim.org/pub/vim/patches/8.2/8.2.4325.
  set wildoptions+=pum
endif

""" Search
set incsearch
set shortmess-=S

""" Timing
set lazyredraw
set notimeout
set ttimeout
set ttimeoutlen=100

""" Diffs
set diffopt+=vertical
set diffopt+=foldcolumn:0
if has('patch-8.1.0360')
  " See http://ftp.vim.org/pub/vim/patches/8.1/8.1.0360.
  set diffopt+=internal
  set diffopt+=algorithm:histogram
  set diffopt+=indent-heuristic
endif

""" Formatting
" See |auto-format|, |format-comments|, and |fo-table|.
set textwidth=79
" set colorcolumn=+1
set autoindent
set nojoinspaces
set formatoptions-=t
set formatoptions+=q
set formatoptions+=n
set formatoptions+=j
set nowrap

""" Comments
set commentstring=

""" Folds
set foldlevelstart=999
set foldtext=substitute(getline(v:foldstart),'\\t',repeat('\ ',&ts),'g').'\ '
if has('eval')
  set foldtext=unobtrusive_fold#text()
endif

""" Spelling
set spell
set spelllang=en_us
if has('eval')
  " Files downloaded from URL documented in |'thesaurus'|:
  " https://github.com/vim/vim/issues/629#issuecomment-443293282.
  let &thesaurus = split(&runtimepath, ',')[0] . '/thesaurus/en_us.txt'
endif

""" Views
set viewoptions-=options
set viewoptions+=slash
set viewoptions+=unix

"" Mappings

""" Escape
" Overwrites the default |i_CTRL-C|, |v_CTRL-C|. See
" https://vim.fandom.com/wiki/Avoid_the_escape_key.
inoremap <C-C> <Esc>
xnoremap <C-C> <Esc>

""" Windows
nnoremap <C-H> <C-W>h
nnoremap <C-J> <C-W>j
nnoremap <C-K> <C-W>k
nnoremap <C-L> <C-W>l
tnoremap <C-H> <C-W>h
tnoremap <C-J> <C-W>j
tnoremap <C-K> <C-W>k
tnoremap <C-L> <C-W>l

""" Buffers
nnoremap <Space>bb :ls<CR>:b<Space>
nnoremap <Space>bs :ls<CR>:sb<Space>
nnoremap <Space>bv :ls<CR>:vertical sb<Space>

""" `$MYVIMRC`
nnoremap <silent> <Space>ve :edit   $MYVIMRC<CR>
nnoremap <silent> <Space>vs :source $MYVIMRC<CR>

""" Help
nnoremap <silent> gK  :helpgrep \<<C-R><C-W>\><CR>
xnoremap <silent> gK y:helpgrep <C-R>"<CR>

""" Run

" File.
nnoremap <silent> <Space>% :!%:p:S<CR>
nnoremap <silent> <Space># :!#:p:S<CR>

" Command.
nnoremap <Space>! :new \| .!

""" Make
" TODO: |dispatch| provides default mappings, try to emulate them?
nnoremap <Space>m% :!make %:r:S<CR>
nnoremap <Space>m# :!make #:r:S<CR>
nnoremap <Space>mm :!make<CR>
nnoremap <Space>ma :!make all<CR>
nnoremap <Space>mt :!make test<CR>
nnoremap <Space>md :!make debug<CR>
if has('quickfix')
  nnoremap <Space>m% :silent make! %:r:S \| redraw!<CR>
  nnoremap <Space>m# :silent make! #:r:S \| redraw!<CR>
  nnoremap <Space>mm :silent make!       \| redraw!<CR>
  nnoremap <Space>ma :silent make! all   \| redraw!<CR>
  nnoremap <Space>mt :silent make! test  \| redraw!<CR>
endif
if has('terminal')
  nnoremap <Space>md :terminal make debug<CR>
endif

""" Improve default mappings

"""" Disable unconditional quit from Normal mode
" As warned about in |zz| these may be typed accidentally when Caps Lock is
" enabled and lose data. Redefining them is a bit hostile towards other users,
" but deemed worth it.
nnoremap <silent> ZZ :quit<CR>
nnoremap <silent> ZQ :quit<CR>

"""" Yank to end of line, not entire line
" As suggested in |Y|. Analogous with |D| does `d$` and |C| does `c$`.
nnoremap Y y$

"""" Don't include newline in Visual mode `$`.
xnoremap $ $h

"""" Visual mode paste doesn't clobber unnamed register
xnoremap p pgvy

"""" Visually select last pasted text
" TODO: Make a text object as well?
" Analogous with how |gv| visually selects last visually selected text. Default
" to always using ordinary Visual mode. Linewise and blockwise with |+eval|
" support.
nnoremap gp `[v`]
if has('eval')
  nnoremap <expr> gp '`[' . getregtype()[0] . '`]'
endif

"""" Restrict Visual mode substitutions to the selected text
xnoremap <Space>s :s/\%V

""" Mouse
" As suggested in |scroll-mouse-wheel|, scroll only one line.
noremap <MouseUp>   <C-E>
noremap <MouseDown> <C-Y>

" Toggle folds.
noremap <RightMouse> <LeftMouse>za

""" Command-line
" Take already written text into account when searching history.
cnoremap <C-P> <Up>
cnoremap <C-N> <Down>

""" Macros

" Repeat the macro in register `q` on current line, lines covered by visual
" selection, or line covered by text object.
nnoremap          QQ @q
xnoremap <silent> Q  :normal! @q<CR>
nnoremap <silent> Q  :set operatorfunc=<SID>Q<CR>g@
if has('eval')
  function! s:Q(...) abort
    '[,']normal! @q
  endfunction
endif

""" Diffs

" Current file.
nnoremap <silent> <Space>dd :w !diff --color -u %:S -<CR>

" Analogous with |dp| |do| in Normal mode.
nnoremap <silent> <Space>dpp :.diffput<CR>
nnoremap <silent> <Space>doo :.diffget<CR>
xnoremap <silent> <Space>dp  :diffput<CR>
xnoremap <silent> <Space>do  :diffget<CR>
nnoremap <silent> <Space>dp  :set operatorfunc=<SID>diffput<CR>g@
nnoremap <silent> <Space>do  :set operatorfunc=<SID>diffget<CR>g@
if has('eval')
  function! s:diffput(...) abort
    '[,']diffput
  endfunction
  function! s:diffget(...) abort
    '[,']diffget
  endfunction
endif

""" Formatting

" Format comment (only). NOTE that this requires a `gc` comment text object
" plugin.
nmap gQ gqgc
nmap gW gwgc

""" Folds

" Focus current fold.
nnoremap zV zMzv

" Focus next/previous fold. Overwrites default move to start/end of
" next/previous fold.
nnoremap zj zvm<zjzvm>gvzc'>zv
nnoremap zk zvzcVoVgkzvgkzvzcVoVzv

" Open/close nested folds recursively. Overwrites default open/close fold under
" cursor recursively.
nnoremap <silent> zO zvzczO
nnoremap <silent> zC zvzcV:foldclose!<CR>zvzc

""" Spelling

" Correct last misspelled word with first suggestion without moving the cursor.
" See also |compl-spelling|.
nnoremap z?               [s1z=<C-O>
inoremap <C-L> <C-G>u<Esc>[s1z=`]a<C-G>u

""" Visual mode operators

" Allows for visual selection of text objects that share a name with an
" operator.
nnoremap <silent> <Space>v     :set operatorfunc=<SID>v<CR>g@
nnoremap <silent> <Space>V     :set operatorfunc=<SID>V<CR>g@
nnoremap <silent> <Space><C-V> :set operatorfunc=<SID>CV<CR>g@
if has('eval')
  function! s:v(...) abort
    execute 'normal!' '`[v`]'
  endfunction
  function! s:V(...) abort
    execute 'normal!' '`[V`]'
  endfunction
  function! s:CV(...) abort
    execute 'normal!' "`[\<C-V>`]"
  endfunction
endif

"" Auto commands
" Make sure to not define any |autocmd|s before this!
augroup vimrc
  autocmd!
augroup END

""" Open the QuickFix/Location list window
" See
" - https://github.com/tpope/vim-dispatch/issues/145
" - https://github.com/tpope/vim-dispatch/issues/254
" - https://github.com/tpope/vim-dispatch/issues/310
" autocmd vimrc QuickFixCmdPost  *{make,{,vim}grep}* nested botright cwindow
" autocmd vimrc QuickFixCmdPost *l{make,{,vim}grep}* nested botright lwindow

""" Highlight all searches
" |'incsearch'| only highlights the first match.
autocmd vimrc CmdlineEnter /,\? let s:hlsearch =  &hlsearch | set hlsearch
autocmd vimrc CmdlineLeave /,\? let  &hlsearch = s:hlsearch

""" Save/load view
" As suggested in |:loadview|, load auto-saved view when opening buffer. Better
" than |last-position-jump|, |restore-cursor|.
autocmd vimrc BufWinEnter *
\ if !empty(expand('<afile>')) && empty(&buftype) |
\   loadview |
\ endif |
autocmd vimrc BufWinLeave *
\ if !empty(expand('<afile>')) && empty(&buftype) |
\   mkview |
\ endif |

"" Colors
" See |cterm-colors|, |gui-colors|. The greyscale hex values used for the GUI
" are CIELCHuv lightness 20, 60 and 80.

""" Defaults
" See |:hi-normal|, |:hi-normal-cterm|.

" Dark background and light foreground.
set background=dark
highlight! Normal guibg=#303030 guifg=#c6c6c6 ctermfg=White

""" Overrides

"""" Transparency
" Greyscale interface, dark red errors/warnings, light red spelling errors,
" bold white todos.

if !has('gui_running')
  autocmd vimrc VimEnter,ColorScheme,OptionSet *
  \ highlight! Normal guibg=NONE |
endif

" TODO: Look at all in |'highlight'|.
autocmd vimrc VimEnter,ColorScheme,OptionSet *
\ highlight! Normal           term=NONE cterm=NONE gui=NONE ctermbg=NONE |
\ highlight! LineNr           term=NONE cterm=NONE gui=NONE ctermbg=NONE guibg=NONE ctermfg=Grey     guifg=Grey     |
\ highlight! FoldColumn       term=NONE cterm=NONE gui=NONE ctermbg=NONE guibg=NONE ctermfg=Grey     guifg=Grey     |
\ highlight! SignColumn       term=NONE cterm=NONE gui=NONE ctermbg=NONE guibg=NONE ctermfg=Grey     guifg=Grey     |
\ highlight! VertSplit        term=NONE cterm=NONE gui=NONE ctermbg=NONE guibg=NONE ctermfg=Grey     guifg=Grey     |
\ highlight! StatusLine       term=NONE cterm=NONE gui=NONE ctermbg=NONE guibg=NONE ctermfg=White    guifg=White    |
\ highlight! StatusLineNC     term=NONE cterm=NONE gui=NONE ctermbg=NONE guibg=NONE ctermfg=Grey     guifg=Grey     |
\ highlight! StatusLineTerm   term=NONE cterm=NONE gui=NONE ctermbg=NONE guibg=NONE ctermfg=White    guifg=White    |
\ highlight! StatusLineTermNC term=NONE cterm=NONE gui=NONE ctermbg=NONE guibg=NONE ctermfg=Grey     guifg=Grey     |
\ highlight! TabLine          term=NONE cterm=NONE gui=NONE ctermbg=NONE guibg=NONE ctermfg=Grey     guifg=Grey     |
\ highlight! TabLineFill      term=NONE cterm=NONE gui=NONE ctermbg=NONE guibg=NONE ctermfg=Grey     guifg=Grey     |
\ highlight! TabLineSel       term=NONE cterm=NONE gui=NONE ctermbg=NONE guibg=NONE ctermfg=White    guifg=White    |
\ highlight! EndOfBuffer      term=NONE cterm=NONE gui=NONE ctermbg=NONE guibg=NONE ctermfg=Black    guifg=Black    |
\ highlight! Error            term=NONE cterm=NONE gui=NONE ctermbg=NONE guibg=NONE ctermfg=DarkRed  guifg=Red      |
\ highlight! ErrorMsg         term=NONE cterm=NONE gui=NONE ctermbg=NONE guibg=NONE ctermfg=DarkRed  guifg=Red      |
\ highlight! WarningMsg       term=NONE cterm=NONE gui=NONE ctermbg=NONE guibg=NONE ctermfg=DarkRed  guifg=Red      |
\ highlight! SpellBad         term=NONE cterm=NONE gui=NONE ctermbg=NONE guibg=NONE ctermfg=LightRed guifg=LightRed |
\ highlight! SpellLocal       term=NONE cterm=NONE gui=NONE ctermbg=NONE guibg=NONE ctermfg=LightRed guifg=LightRed |
\ highlight! SpellRare        term=NONE cterm=NONE gui=NONE ctermbg=NONE guibg=NONE ctermfg=LightRed guifg=LightRed |
\ highlight! SpellCap         term=NONE cterm=NONE gui=NONE ctermbg=NONE guibg=NONE ctermfg=LightRed guifg=LightRed |
\ highlight! Todo             term=bold cterm=bold gui=NONE ctermbg=NONE guibg=NONE ctermfg=White    guifg=White    |

"""" Comments
autocmd vimrc VimEnter,ColorScheme,OptionSet *
\ highlight! Comment guifg=#919191 ctermfg=Grey

"""" Diffs
autocmd vimrc VimEnter,ColorScheme,OptionSet *
\ highlight! DiffAdd          term=NONE cterm=NONE gui=NONE ctermfg=Black guifg=Black ctermbg=DarkGreen  guibg=Green  |
\ highlight! DiffDelete       term=NONE cterm=NONE gui=NONE ctermfg=Black guifg=Black ctermbg=DarkRed    guibg=Red    |
\ highlight! DiffChange       term=NONE cterm=NONE gui=NONE ctermfg=Black guifg=Black ctermbg=DarkBlue   guibg=Blue   |
\ highlight! DiffText         term=NONE cterm=NONE gui=NONE ctermfg=Black guifg=Black ctermbg=DarkYellow guibg=Yellow |
\ highlight! diffAdded        term=NONE cterm=NONE gui=NONE ctermbg=NONE  guibg=NONE  ctermfg=DarkGreen  guifg=Green  |
\ highlight! diffRemoved      term=NONE cterm=NONE gui=NONE ctermbg=NONE  guibg=NONE  ctermfg=DarkRed    guifg=Red    |

"""" Folds
autocmd vimrc VimEnter,ColorScheme,OptionSet *
\ highlight! link Folded Comment |

"""" |'listchars'|
autocmd vimrc VimEnter,ColorScheme,OptionSet *
\ highlight! link SpecialKey Special |
\ highlight! link NonText    Special |

"""" Vim comments
autocmd vimrc VimEnter,ColorScheme,OptionSet *
\ highlight! link vimCommentString vimComment |
\ highlight! link vimCommentTitle  vimComment |

"" Plugins

if has('eval')

  """ GitAdd
  " https://git.rcrnstn.net/rcrnstn/vim-gitadd

  " Make sure to not enable |:syntax| and |:filetype| until all plugins that
  " interact with them have been added! See |:packadd|.
  command! -bar -bang -nargs=+ GitAdd call s:GitAdd(<q-bang>, <f-args>)
  function! s:GitAdd(bang, url, ...) abort
    let name = split(a:url, '/')[-1]
    let dir = split(&packpath, ',')[0] . '/pack/gitadd/opt/' . name
    if !isdirectory(dir)
      silent execute '!git clone --recurse-submodules' join(a:000) a:url dir
      if isdirectory(dir . '/doc')
        execute 'helptags' dir . '/doc'
      endif
    endif
    if empty(a:bang)
      execute 'packadd!' name
    endif
  endfunction

  """ File type

  """" Built-in `vim`

  " See |ft-vim-indent|.
  let g:vim_indent_cont = 0

  """" Built-in `sh`

  " See |ft-sh-syntax|.
  let g:is_posix = 1

  """" Built-in `man`

  " See |ft-man-plugin|.
  let g:ft_man_folding_enable = 1
  runtime ftplugin/man.vim
  setglobal keywordprg=:Man

  """" `sheerun/vim-polyglot`
  GitAdd https://github.com/sheerun/vim-polyglot

  let g:vim_markdown_no_default_key_mappings = 1

  let g:polyglot_disabled = [
  \   'sensible',
  \   'autoindent',
  \ ]

  """" `tpope/vim-sleuth`
  GitAdd https://github.com/tpope/vim-sleuth

  """" `tpope/vim-apathy`
  GitAdd https://github.com/tpope/vim-apathy

  """" `tpope/vim-scriptease`
  GitAdd https://github.com/tpope/vim-scriptease

  """" `jyscao/vim-greprtpscr`
  GitAdd https://github.com/jyscao/vim-greprtpscr

  """" `vimwiki/vimwiki`
  " GitAdd https://github.com/vimwiki/vimwiki

  " let g:vimwiki_list = [{
  " \   'path':   '~/notes/',
  " \   'syntax': 'markdown',
  " \   'ext':    '.md',
  " \ }]

  """ Normal mode

  """" Built-in `matchit`

  packadd! matchit

  """" `tpope/vim-unimpaired`
  GitAdd https://github.com/tpope/vim-unimpaired

  """" `tpope/vim-repeat`
  GitAdd https://github.com/tpope/vim-repeat

  """" `tpope/vim-characterize`
  GitAdd https://github.com/tpope/vim-characterize

  """" `haya14busa/vim-asterisk`
  GitAdd https://github.com/haya14busa/vim-asterisk

  " As suggested by |asterisk-key-mappings|, except the mappings that don't
  " move the cursor set |'hlsearch'|.
  map            * <Plug>(asterisk-*)
  map            # <Plug>(asterisk-#)
  map           g* <Plug>(asterisk-g*)
  map           g# <Plug>(asterisk-g#)
  map <silent>  z* <Plug>(asterisk-z*): set hlsearch<CR>
  map <silent>  z# <Plug>(asterisk-z#): set hlsearch<CR>
  map <silent> zg* <Plug>(asterisk-gz*):set hlsearch<CR>
  map <silent> zg# <Plug>(asterisk-gz#):set hlsearch<CR>

  """" `AndrewRadev/splitjoin.vim`
  GitAdd https://github.com/AndrewRadev/splitjoin.vim

  """" `AndrewRadev/switch.vim`
  GitAdd https://github.com/AndrewRadev/switch.vim

  let g:switch_custom_definitions = [{
  \   '\<0\>': '1',
  \   '\<1\>': '0',
  \   '\(\w*\)TRUE\(\w*\)': '\1FALSE\2',
  \   '\(\w*\)True\(\w*\)': '\1False\2',
  \   '\(\w*\)true\(\w*\)': '\1false\2',
  \   '\(\w*\)FALSE\(\w*\)': '\1TRUE\2',
  \   '\(\w*\)False\(\w*\)': '\1True\2',
  \   '\(\w*\)false\(\w*\)': '\1true\2',
  \ }]

  """ Insert mode

  """" `tpope/vim-endwise`
  GitAdd https://github.com/tpope/vim-endwise

  """" `jiangmiao/auto-pairs`
  GitAdd https://github.com/jiangmiao/auto-pairs

  " Don't jump around too much. See |autopairs-options|.
  let g:AutoPairsCenterLine = 0
  let g:AutoPairsMultilineClose = 0

  """ Command-line mode

  """" `tpope/vim-rsi`
  GitAdd https://github.com/tpope/vim-rsi

  """" `tpope/vim-abolish`
  GitAdd https://github.com/tpope/vim-abolish

  """ Operators

  """" `tpope/vim-surround`
  GitAdd https://github.com/tpope/vim-surround

  """" `tpope/vim-commentary`
  GitAdd https://github.com/tpope/vim-commentary

  """" `tommcdo/vim-lion`
  GitAdd https://github.com/tommcdo/vim-lion

  let g:lion_squeeze_spaces = 1

  """" `tommcdo/vim-nowchangethat`
  GitAdd https://github.com/tommcdo/vim-nowchangethat

  """ Motions / text objects
  " TODO: Check that none of the later ones are not already defined by
  " `targets.vim`.

  """" `wellle/targets.vim`
  GitAdd https://github.com/wellle/targets.vim

  """" `bkad/CamelCaseMotion`
  GitAdd https://github.com/bkad/CamelCaseMotion

  let g:camelcasemotion_key = '<Space>'

  """" `tommcdo/vim-exchange`
  GitAdd https://github.com/tommcdo/vim-exchange

  """" `qstrahl/vim-dentures`
  GitAdd https://github.com/qstrahl/vim-dentures

  """" `kana/vim-textobj-user`
  GitAdd https://github.com/kana/vim-textobj-user

  " All later plugins in the "Motions / text objects" category depend on this
  " plugin. See https://github.com/kana/vim-textobj-user/wiki.

  """" `kana/vim-textobj-entire`
  GitAdd https://github.com/kana/vim-textobj-entire

  """" `kana/vim-textobj-line`
  GitAdd https://github.com/kana/vim-textobj-line

  " As suggested in |textobj-line-default-key-mappings|, except `{a,i}l` is
  " taken by `targets` "last", so we use uppercase `{a,i}L`.
  let g:textobj_line_no_default_key_mappings = 1
  omap aL <Plug>(textobj-line-a)
  omap iL <Plug>(textobj-line-i)
  xmap aL <Plug>(textobj-line-a)
  xmap iL <Plug>(textobj-line-i)

  """" `kana/vim-textobj-fold`
  GitAdd https://github.com/kana/vim-textobj-fold

  """" `kana/vim-textobj-syntax`
  GitAdd https://github.com/kana/vim-textobj-syntax

  """" `kana/vim-textobj-function`
  GitAdd https://github.com/kana/vim-textobj-function

  """" `idbrii/textobj-word-column.vim`
  GitAdd https://github.com/idbrii/textobj-word-column.vim

  """" `adriaanzon/vim-textobj-matchit`
  GitAdd https://github.com/adriaanzon/vim-textobj-matchit

  """" `rhysd/vim-textobj-continuous-line`
  GitAdd https://github.com/rhysd/vim-textobj-continuous-line

  """" `rsrchboy/vim-textobj-heredocs`
  GitAdd https://github.com/rsrchboy/vim-textobj-heredocs

  """ Colors

  """" `gruvbox-community/gruvbox`
  GitAdd https://github.com/gruvbox-community/gruvbox

  let g:gruvbox_contrast_dark = 'hard'
  let g:gruvbox_invert_selection = 0

  " Earlier settings indicate whether we want a color scheme not based on
  " terminal colors. '|termguicolors|' is reset further down if not supported.
  if &t_Co >= 256
    set termguicolors
    colorscheme gruvbox
  endif

  """ Windows

  """" `moll/vim-bbye`
  GitAdd https://github.com/moll/vim-bbye

  """ Folds

  """" `rcrnstn/vim-unobtrusive-fold`
  GitAdd https://git.rcrnstn.net/rcrnstn/vim-unobtrusive-fold

  """ Undo

  """" `mbbill/undotree`
  GitAdd https://github.com/mbbill/undotree

  nnoremap <silent> <Space>u :UndotreeToggle<CR>

  " let g:undotree_HighlightChangedText = 0
  " let g:undotree_DiffCommand = 'diff -u'

  """ QuickFix

  """" Built-in `cfilter`

  packadd! cfilter

  """ Modelines

  """" `ypcrts/securemodelines`
  GitAdd https://github.com/ypcrts/securemodelines

  """ Environment interaction

  """" Built-in `netrw`

  " Netrw versions (roughly) 162h to 170 break `gx`. Never download the remote
  " file to a temporary. See
  " - https://github.com/vim/vim/issues/1386
  " - https://github.com/vim/vim/issues/4738
  " - https://github.com/vim/vim/pull/7188
  let g:netrw_nogx = 1
  nnoremap <silent> gx  :call netrw#BrowseX(netrw#GX(), 0)<CR>
  xnoremap <silent> gx y:call netrw#BrowseX(@",         0)<CR>

  """" `ctrlpvim/ctrlp.vim`
  GitAdd https://github.com/ctrlpvim/ctrlp.vim

  let g:ctrlp_working_path_mode = ''
  let g:ctrlp_match_current_file = 1
  let g:ctrlp_follow_symlinks = 2
  let g:ctrlp_show_hidden = 1
  let g:ctrlp_status_func = ''
  let g:ctrlp_line_prefix = ''
  let g:ctrlp_use_caching = 0
  let g:ctrlp_use_readdir = 0 " Respect 'wildignore'.
  let g:ctrlp_max_files = 0 " Default 10000.
  let g:ctrlp_max_depth = 40 " Default 40.
  " let g:ctrlp_user_command_async = 1
  if has('unix')
    " TODO: Set `grepprg` to something similar, that skips things in
    " 'wildignore'.
    " let g:ctrlp_user_command = 'find' .
    " \ (g:ctrlp_follow_symlinks ? ' -L' : '') .
    " \ ' %s' .
    " \ ' -maxdepth ' . g:ctrlp_max_depth .
    " \ ' \( -false' .
    " \ (g:ctrlp_show_hidden ? '' : ' -o -name ".*"') .
    " \ ' ' .
    " \ join(map(split(&wildignore, ','), '"-o -name " . shellescape(v:val)')) .
    " \ ' \) -prune -o' .
    " \ ' -type f' .
    " \ ' -exec grep -Il . {} +' .
    " \ ' 2> /dev/null' .
    " \ (g:ctrlp_max_files ? ' | head -n ' . g:ctrlp_max_files : '')
    " " \ ' \(' .
    " " \ (g:ctrlp_follow_symlinks == 2 ? ' -o -type l' : '') .
    " " \ ' \)' .
  endif

  """" `tpope/vim-fugitive`
  GitAdd https://github.com/tpope/vim-fugitive

  autocmd vimrc FileType fugitiveblame call fugitive#MapJumps()

  """" `tommcdo/vim-fugitive-blame-ext`
  GitAdd https://github.com/tommcdo/vim-fugitive-blame-ext

  """" `tpope/vim-dispatch`
  GitAdd https://github.com/tpope/vim-dispatch

  nnoremap <Space>m% :Make %:r:S<CR>
  nnoremap <Space>m# :Make #:r:S<CR>
  nnoremap <Space>mm :Make<CR>
  nnoremap <Space>ma :Make all<CR>
  nnoremap <Space>mt :Make test<CR>

  """" `tpope/vim-eunuch`
  GitAdd https://github.com/tpope/vim-eunuch

  """" `tpope/vim-projectionist`
  GitAdd https://github.com/tpope/vim-projectionist

  """ Debugging

  """" `puremourning/vimspector`
  " GitAdd https://github.com/puremourning/vimspector

  " Debug Adapter Protocol (DAP) client. See
  " https://microsoft.github.io/debug-adapter-protocol/.

  """" `vim-vdebug/vdebug`
  " GitAdd https://github.com/vim-vdebug/vdebug

  " Common DeBugGer Protocol (DBGP) client. See
  " https://en.wikipedia.org/wiki/DBGp.

endif " has('eval')

"" Syntax and file type
if has('eval')
  syntax enable
  filetype plugin indent on
endif

"" File type overrides

autocmd vimrc FileType vim
\ setlocal keywordprg=:help formatoptions-=r

autocmd vimrc FileType help
\ setlocal nolist

autocmd vimrc FileType man
\ setlocal nolist

autocmd vimrc FileType c,cpp
\ setlocal commentstring=//\ %s

" As suggested in |ft-syntax-omni|, use syntax completion if no other
" completion has been defined.
autocmd vimrc FileType *
\ if &omnifunc == '' |
\   setlocal omnifunc=syntaxcomplete#Complete |
\ endif |

" As suggested in |unobtrusive-fold-example|.
autocmd vimrc FileType *        UnobtrusiveFoldComment
autocmd vimrc FileType markdown UnobtrusiveFoldChar #

"" Terminal overrides
" See |terminal-options|.

""" Cursor
" See |termcap-cursor-shape|, `:helpgrep t_SH`, and "Parameterized Strings" in
" `terminfo(5)`.

if has('cursorshape')
  set noshowmode
  let &t_vi = ''
  let &t_ve = "\<Esc>[?25h"
  " if $TERM =~? '^xterm\(-\|$\)'
    " See
    " - https://vt100.net/docs/vt510-rm/DECSCUSR
    " - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
    let &t_EI = "\<Esc>[1 q"
    let &t_SI = "\<Esc>[5 q"
    let &t_SR = "\<Esc>[3 q"
    let &t_SH = "\<Esc>[%p1%d q"
  " endif
  if $TERM =~? '^linux\(-\|$\)'
    " See
    " - https://www.kernel.org/doc/Documentation/admin-guide/vga-softcursor.rst
    let &t_EI = "\<Esc>[?8c"
    let &t_SI = "\<Esc>[?2c"
    let &t_SR = "\<Esc>[?2c"
    let &t_SH = "\<Esc>[?%?%p1%{3}%<%t%{8}%e%{2}%;%dc"
  endif
endif

""" True-color
" See |xterm-true-color|.

if has('termguicolors')
  " See https://github.com/termstandard/colors#truecolor-detection.
  if empty($COLORTERM) && !has('vcon')
    set notermguicolors
  endif
  " These are the defaults if `$TERM` is `xterm`.
  let &t_8f = "\<Esc>[38;2;%lu;%lu;%lum"
  let &t_8b = "\<Esc>[48;2;%lu;%lu;%lum"
  " Terminal window does not have transparent background when 'termguicolors'
  " is used. See http://ftp.vim.org/pub/vim/patches/8.2/8.2.3516.
  if !has('patch-8.2.3516')
    let s:termguicolors = &termguicolors
    autocmd vimrc TerminalOpen,WinEnter *
    \ let s:newtermguicolors =
    \   s:termguicolors &&
    \   empty(filter(range(1, bufnr('$')),
    \     'getbufvar(v:val, "&buftype") ==# "terminal"'
    \   )) |
    \ if s:newtermguicolors != &termguicolors |
    \   execute 'set' (s:newtermguicolors ? '' : 'no') . 'termguicolors' |
    \ endif |
  endif
endif