"" My |vimrc|

" TODO: Supply chain attacks are getting more common. We should use (mandate?)
" commit hashes in `GitAdd`. Also, make sure to use a command format that
" ignores tag/branch names (those can be named to look like hashes and are
" mutable).

" TODO: Do we want to try to integrate with Debian? There seems to be at least
" two ways vim-related files are installed:
" - Purely auxilliary files as part of some other package: Files are installed
"   to `/usr/share/vim/addons` which are referenced by files installed to
"   `/usr/share/vim/registry`. `vim-addons` from the `vim-addon-manager` can be
"   used to (presumably) symlink them into a path that is listed in
"   'runtimepath'.
" - As a standalone `vim-${addon}` package: Files are installed to
"   `/usr/share/vim-${addon}`, presumably symlinked into a `start` or `opt`
"   'packpath' during package installation.
"   <https://vim-team.pages.debian.net/vim/> and the `dh_vim-addon` man page in
"   the `dh-vim-addon` package contains some further details.

""" Formatting

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

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

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

""" Compatibility

" TODO: Test with `nvi`, a "bug-for-bug compatible" clone of the original BSD
" `vi`.
" TODO: Test with `VIM_POSIX=1 "$vim"` (for different `$vim`s?). See
" |$VIM_POSIX|.

" This vimrc should work with all configurations of Vim. Manually tested with:
" - Versions: TODO: Whatever some old {Debian,Ubuntu,Fedora} ships.
" - Features: small, huge (Debian `apt-get install vim-{tiny,gtk3}`)
" - Locales: C, UTF-8 (`LC_ALL=C{,.UFT-8}`)
" - Colors: 1, 2, 8, 16, 256, termguicolors (`--cmd "set {t_Co=$colors,tgc}"`)
" - UI: TUI, GUI (`{,g}vim`)
" - Terminals: GUI, VTE, Linux, tmux with the correct `Ss` `terminal-override`
" - Platforms: Unix-like

" TODO: `man setfont` says:
" > Note: if a font has more than 256 glyphs, only 8 out of 16 colors can be
" > used simultaneously. It can make console perception worse (loss of
" > intensity and even some colors).
" The default font on my system has 512 glyphs (`showconsolefont -v`).

" TODO: `man setfont` says, in section "CONSOLE MAPS":
" > Several mappings are involved in the path from user program output to
" > console display.
" Might be worth reading up on that. If I already did, document.

""" Features

" |:version| says "tiny" features are always present and are therefore used in
" favor other features whenever possible. "Tiny" features include:
" - |+multi_byte|
" - |+mouse|
" - |+tag_binary|
" - |+user_commands|
" - |+autocmd|
" - |+localmap|

" Note that trying to set (run-time, but not compile-time) 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. See
" |no-eval-feature|.

""" 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, via `CHARMAP` in
" `/etc/default/console-setup`). See
" - <https://en.wikipedia.org/wiki/Code_page_437>
" - <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.

" A `vimrc` |augroup| is cleared and used for all |autocmd|s. 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` highlighting... 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
" surprised 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. Worse, for options with
" only a (buffer or window) local value, `setglobal` does nothing, literally.
" Is that a problem, should we even set local values here? Maybe identifying
" them and getting rid of them is a good idea?

" TODO: Maybe source |defaults.vim|? Probably not, but add some documentation?

" TODO: Look at |:options| and maybe follow the same grouping?

" NOTE that |OptionSet| was added in
" <http://ftp.vim.org/pub/vim/patches/8.1/8.1.0081> and may not be available.

""" Reset
setglobal 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

""" Modeline
set nomodeline

""" Navigation
set nostartofline
" <http://ftp.vim.org/pub/vim/patches/9.0/9.0.0640>: Cannot scroll by screen
" line if a line wraps. Add the 'smoothscroll' option.
if has('patch-9.0.0640')
  set smoothscroll
endif

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

""" Interface
set showcmd
set noruler
set laststatus=1
set showtabline=1
set shortmess+=I
set guioptions=cf " console dialogs, foreground (no fork())
set numberwidth=1

""" 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: `→ `, `――>`, `├──`,
" `──┤`, `├─┤`.
" TODO: `:help 'fillchars'` says "for `stl` and `stlnc` only single-byte values
" are supported". Test the current (non-ASCII) values against older versions of
" Vim. See also <http://ftp.vim.org/pub/vim/patches/8.2/8.2.2569>.
" TODO: If Vim cannot tell appart |hl-StatusLine| and |hl-StatusLineNC| (e.g.
" because |hl-StatusLine| is a |hl-link|), (ordinary) spaces and `fillchars`
" `stl` characters for the statusline of the focused window will be replaced
" with `^`. Note that this includes the single character under the `fillchars`
" `vert`, which cannot be set with |'statusline'|.
set linespace=-1
set list
set linebreak
set breakindent
set breakindentopt=sbr,shift:2
set showbreak=» 
set fillchars=stl:─,stlnc:─,vert:│,fold:─,diff: 
" set fillchars=stl:_,stlnc:_,vert:│,fold:─,diff: 
set listchars=tab:├─,trail:•,extends:›,precedes:‹,nbsp:·
" <http://ftp.vim.org/pub/vim/patches/8.1/8.1.0759>: Showing two characters for
" tab is limited. Allow for a third character for "tab:" in 'listchars'.
if has('patch-8.1.0759')
  " ab	c
  " set listchars+=tab:├\ ┤
  set listchars+=tab:│\ │
endif
" TODO: `%f` still shows `[No Name]`, is there a way to remove that?
set statusline=%(%f\ %)
if has('eval')
  " TODO: This works poorly with plugins that have windows with their own
  " statusbar, e.g. |undotree.txt|.
  " set statusline=%(%{expand('%:.s?^/??')}\ %)
  " `fillchar_status` function in `src/screen.c:4649` of Vim source.
  " TODO: Try to use some other non-standard space? Search for "\<SPACE\>" in
  " |digraphs|.
  " set fillchars+=stl:\ ,stlnc: 
  set fillchars+=stl: ,stlnc: 
  " set fillchars+=stl:┘,stlnc:┘
  " TODO: Standardize on global functions? Or |autoload|s (but that would break
  " our "single file" policy)?
  " function! s:statusline() abort
  function! Statusline() abort
    " TODO: Make this expansion relative to the window-local cwd? Also do other
    " substitutions, like `$HOME` to `~`, the expanded `$VIMRUMTIME` to the
    " string `$VIMRUNTIME`, etc. We used to have `s?^/??`, why?
    " TODO: Harmonize with `titlestring`.
    let l:title = !empty(&l:buftype) ? &l:buftype : expand('%:~:.')
    if &l:buftype =~# 'help\|terminal'
      let l:title .= ':' . expand('%:t')
    elseif &l:buftype ==# 'quickfix' && exists('w:quickfix_title')
      let l:title .= ':' . w:quickfix_title
    endif
    if !empty(l:title)
      let l:title .= ' '
    endif
    " NOTE: `matchstr` looks for the _first_ match.
    " TODO: This is slow. Cache the `matchstr` result?
    let l:fill = matchstr(&fillchars, '\(^\|,\)stl:\zs[^,]*')
    let l:pad  = winwidth(0) - strwidth(l:title)
    return l:title . repeat(l:fill, l:pad)
  endfunction
  " <http://ftp.vim.org/pub/vim/patches/8.2/8.2.1347>: Cannot easily get the
  " script ID. Support expand('<SID>').
  " if has('patch-8.2.1347')
  "   let &statusline = '%{'.expandcmd('<SID>statusline()').'}'
  " else
    let &statusline = '%{Statusline()}'
  "   function! g:Statusline() abort
  "     return s:statusline()
  "   endfunction
  " endif
endif

""" Colors
" May be overritten later by Vim for terminals with |t_RB|.
set background=dark
set guioptions+=d
if &t_Co > 16
  set t_Co=16
  " <https://github.com/neovim/neovim/issues/11974#issuecomment-1658464993>
  if has('nvim')
    lua ffi = require "ffi" ffi.cdef "int t_colors" ffi.C.t_colors = 16
  endif
endif
set notermguicolors
" <https://github.com/termstandard/colors#truecolor-detection>
if empty($COLORTERM) && !has('vcon')
  set notermguicolors
endif
if has('gui_running')
  set termguicolors
endif

""" Bell
set belloff=error

""" Title
set title
" set titlestring=vi:%{fnamemodify(getcwd(),':~:t:s?^$?/?')}%(:%<%{pathshorten(expand('%:.:s?^/??'))}%)
" TODO: Break out into `Title()` function and harmonize with `statusline`.
set titlestring=vi:%{fnamemodify(getcwd(),':~:t:s?^$?/?')}%(:%<%{expand('%:.:s?^/??')}%)
set titleold=

""" Tabs
" When reading files written by others, assume default `tabstop=8`.
" When Writing files, use 4 space indents.
set shiftwidth=4
set shiftround
set softtabstop=-1
set expandtab

""" Mouse
set mouse=a

""" Command-line
set wildmenu
set wildmode=longest:full,full
" See also |'suffixes'|.
set wildignore+=_*
set wildignore+=.git
set wildignore+=UPSTREAMS,FORKS
" Relative to `$HOME`.
set wildignore+=*/.vim/pack,*/.config/vim/pack,*/.config/nvim/pack
set wildignore+=*/.cache,
set wildignore+=*/.mozilla/firefox
set wildignore+=*/.local/lib,*/.local/share/man
set wildignore+=*/.vagrant,*/.ansible
set wildignore+=*/.local/pipx,__pycache__,.venv,*.egg-info
set wildignore+=*/.cargo
set wildignore+=*/.npm,node_modules
set wildignore+=*/.local/share/tldr
set wildignore+=*/snap
set wildignore+=*/.wine/dosdevices,*/.wine/drive_*
" <http://ftp.vim.org/pub/vim/patches/8.2/8.2.4325>: 'wildmenu' only shows few
" matches. Add the "pum" option: use a popup menu to show the matches.
if has('patch-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
" <http://ftp.vim.org/pub/vim/patches/8.1/8.1.0360>: Using an external diff
" program is slow and inflexible. Include the xdiff library. Use it by default.
if has('patch-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 winwidth=80
" set colorcolumn=+1
set autoindent
set nojoinspaces
" Don't autowrap text, enable comment formatting with |gq|, recognize lists,
" remove comment leader when joining.
set formatoptions-=t
" set formatoptions+=q " TODO: This is the default?
set formatoptions+=n
set formatoptions+=j
set nowrap " See also |breakindent|, |breakindentopt|, |showbreak| set above.
" A custom 'formatprg' produces nicer results but is harder to replicate for
" others and places undue burden on documentation contributors. Having simple
" format rules is more important than slightly prettier formatting.
" TODO: At least make the expressions valid (we're lacking spaces, no?).
" if executable('par')
"   let &formatprg = join(['par', 'T'.&tabstop, 'w'.&textwidth, 'e'])
"   let &formatprg = join(['par', 'T'.&tabstop, 'w'.&textwidth, 'e', 'j'])
" elseif executable('fmt')
"   let &formatprg = 'fmt' . '-w' . &textwidth '-g' . &textwidth
" endif

""" Comments
" set commentstring=#%s

""" Folds
set foldlevelstart=999
set foldtext=substitute(getline(v:foldstart),'\\t',repeat('\ ',&ts),'g').'\ '

""" Spelling
" set spell
set spelllang=en_us
set thesaurus=~/.vim/thesaurus/en_us.txt
" TODO: We can probably do something better/cleaner for the thesaurus on our
" own. In particular, publicly available, clearly licensed, version controlled,
" code to generate the vim thesaurus from primary sources.
" The current `~/.vim/thesaurus/en_us.txt` is downloaded from the URL
" documented in |'thesaurus'|:
" <https://github.com/vim/vim/issues/629#issuecomment-443293282>. This zip file
" contains a patch to <https://www.openoffice.org/lingucomponent/MyThes-1.zip>
" and the results of running the patched code on the included files, as well as
" the licenses. `MyThes-1.zip` is linked from
" <https://www.openoffice.org/lingucomponent/thesaurus.html> and seems to be
" some version of <https://github.com/hunspell/mythes>. MyThes states in its
" readme that it is based on WordNet 2.0. However, the latest version as of
" this writing is 3.1. When generating a Vim version, it helps to have a
" visualization to guide the heuristics that will probably be needed. Searching
" <https://wordnet.princeton.edu/related-projects> for "thesaurus" gives
" several projects. <https://wordvis.com> looks good (try e.g. "completion").
" Another search hit,
" <https://www2.seas.gwu.edu/~simhaweb/software/jword/index.html>, states that
" "WordNet's vocabulary is smaller than other "word" databases", so we might
" want to use other sources as well, e.g. Roget's Thesaurus.
"
" WordNet
" - <https://wordnet.princeton.edu/download/current-version>
" - <https://wordnetcode.princeton.edu/wn3.1.dict.tar.gz>
" Data hosted on Project Gutenberg
" - <https://www.gutenberg.org/ebooks/3202>  (2002) Moby Thesaurus List
" - <https://www.gutenberg.org/ebooks/10681> (2004) Roget's Thesaurus of English Words and Phrases
" - <https://www.gutenberg.org/ebooks/22>    (1991) Roget's Thesaurus
" - <https://www.gutenberg.org/ebooks/38390> (2011) A Dictionary of English Synonymes [...]
" - <https://www.gutenberg.org/ebooks/51155> (2016) A Complete Dictionary of Synonyms and Antonyms
" For Swedish, there is
" - <https://folkets-lexikon.csc.kth.se/synlex.html>
" - <https://spraakbanken.gu.se/en/resources/saldo>

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

""" Files
set swapfile
set writebackup
set backupcopy=yes
set undofile
set directory=~/.cache/vim/swap//
set backupdir=~/.cache/vim/backup//
set undodir=~/.cache/vim/undo//
set viewdir=~/.cache/vim/view//
set viminfofile=~/.cache/vim/viminfo
if has('nvim')
  set shadafile=
endif

""" Conceal
set conceallevel=2
set concealcursor=nc

""" Platform
set shellslash

""" External tools
" Not POSIX: `-H` (suggested in 'grepprg'), `-I`.
set grepprg=grep\ -nHI

""" Quickfix
set switchbuf=useopen

"" Mappings
" TODO: Categorize into map modes. Use the nonspecific |:map| (|mapmode-nvo|)
" and |:map!| (|mapmode-ic|) more often?

""" 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

""" Clear and redraw
" <C-L> is overridden above, so use a <Leader> mapping.
nnoremap <Space><C-L> <C-L>

""" Movement
" Up down dispaly lines (unless a count is given).
nnoremap <expr> j v:count ? 'j' : 'gj'
nnoremap <expr> k v:count ? 'k' : 'gk'

" End of pair opened at end of current line.
" TODO: These are overridden by `matchit`.
nnoremap <silent> g% :<C-U>norm!  $%<CR>
onoremap <silent> g% :<C-U>norm!  $%<CR>
xnoremap <silent> g% :<C-U>norm! v$%<CR>

""" Scrolling
" Put paragraph containing cursor line at the top of the window.
" TODO: Preserve jump list somehow?
nnoremap zg {jzt<C-O>

""" Visual mode repeat
" See also `vim-visualrepeat`.
xnoremap . :normal! .<CR>

""" Clipboard
" Yank file and line number of cursor.
nnoremap <silent> <Space>yy :let @+ = expand('%:p') . ':' . line('.')<CR>

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

""" Keyword
" nnoremap K :silent execute "normal! K" \| redraw!<CR>
" nnoremap <silent> K :terminal ++close <C-R>=&keywordprg<CR> <cword><CR>
" TODO: vnoremap
" TODO: `set keywordprg=:help`

""" Help
" TODO: Make this filetype dependent? Could use |:grep| or |fugitive|'s
" |:Ggrep|. On the other hand, there are other built-in mappings that does
" keyword search in a codebase.
" TODO: Here we use `g` as prefix. Do we do that in other places? Should we not
" use <Leader> (i.e. <Space>)?
nnoremap <silent> gK  :helpgrep \<<C-R><C-W>\><CR>
xnoremap <silent> gK y:helpgrep <C-R>"<CR>

""" Run
" TODO: Standardize where the output goes.

" File (with output in pager).
nnoremap <silent> <Space><Space>% :!%:p:S \| less -FR<CR>
nnoremap <silent> <Space><Space># :!#:p:S \| less -FR<CR>

" Command (with output in new window).
nnoremap <Space><Space>! :new \| .!

""" Quickfix

"""" Toggle Quickfix window
" TODO: Do similar for location list?
" TODO: Make the |botright| global with some |autocmd|?
nnoremap <expr> <Space><Space>q
\ empty(filter(range(1,winnr('$')),'getwinvar(v:val,"&buftype")==#"quickfix"'))
\ ? ':botright copen<CR>'
\ : ':botright cclose<CR>'

""" Make
" TODO: |dispatch| provides default mappings, try to emulate them?
" TODO: Should these be <silent> as well?
" TODO: Use the |terminal-debugger| instead of a make target?
nnoremap <Space><Space>m% :!make %:r:S \| less -FR<CR>
nnoremap <Space><Space>m# :!make #:r:S \| less -FR<CR>
nnoremap <Space><Space>mm :!make       \| less -FR<CR>
nnoremap <Space><Space>ma :!make all   \| less -FR<CR>
nnoremap <Space><Space>mt :!make test  \| less -FR<CR>
nnoremap <Space><Space>md :!make debug \| less -FR<CR>
if has('quickfix')
  nnoremap <Space><Space>m% :silent make! %:r:S \| redraw!<CR>
  nnoremap <Space><Space>m# :silent make! #:r:S \| redraw!<CR>
  nnoremap <Space><Space>mm :silent make!       \| redraw!<CR>
  nnoremap <Space><Space>ma :silent make! all   \| redraw!<CR>
  nnoremap <Space><Space>mt :silent make! test  \| redraw!<CR>
endif
if has('terminal')
  nnoremap <Space><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 put that doesn't clobber unnamed register
" See also <http://ftp.vim.org/pub/vim/patches/8.2/8.2.4242>.
xnoremap P pgvy

""" Visual mode

"""" Visually select last pasted text
" TODO: Make a text object as well?
" TODO: I use this relatively often, but it clobbers the built in |gp|. I never
" use that, but it seems useful, so maybe I should? Find another natural
" mapping?
" 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

"""" Visual movement
xnoremap <C-h> hoho
xnoremap <C-j> jojo
xnoremap <C-k> koko
xnoremap <C-l> lolo

""" Scrolling
" Arrow keys scroll. Useful when 'mouse' is empty and the terminal sends arrow
" keys when scrolling with the mouse.
noremap <Up>    <C-Y>
noremap <Down>  <C-E>
noremap <Left>  zh
noremap <Right> zl

""" Mouse
" As suggested in |scroll-mouse-wheel|, scroll only one line.
noremap <ScrollWheelUp>     <C-Y>
noremap <ScrollWheelDown>   <C-E>
noremap <C-ScrollWheelUp>   zh
noremap <C-ScrollWheelDown> zl
noremap <ScrollWheelLeft>   zh
noremap <ScrollWheelRight>  zl

" Toggle folds.
noremap <RightMouse>   <LeftMouse>za
noremap <2-RightMouse> <LeftMouse>za
noremap <3-RightMouse> <LeftMouse>za
noremap <4-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.
" Se also |:DiffOrig|.
" TODO: Use a buffer?
" <https://gist.github.com/romainl/7198a63faffdadd741e4ae81ae6dd9e6>
nnoremap <silent> <Space><Space>dd :w !
\ diff -u --color=always %:S -
\ \| tail -n +3
\ \| less -FR
\ <CR>
nnoremap <silent> <Space><Space>dw :w !
\ diff -u %:S -
\ \| tail -n +3
\ \| wdiff -d -n
\   -w "$([ "$(tput colors)" -ge 16 ] && tput setaf  9 \|\| { tput bold; tput setaf 1; })"
\   -y "$([ "$(tput colors)" -ge 16 ] && tput setaf 10 \|\| { tput bold; tput setaf 2; })"
\   -x "$([ "$(tput colors)" -ge 16 ] && tput setaf 15 \|\| { tput bold; tput setaf 7; })"
\   -z "$([ "$(tput colors)" -ge 16 ] && tput setaf 15 \|\| { tput bold; tput setaf 7; })"
\ \| less -FR
\ <CR>
" Requires `vim-fugitive`.
nmap <silent> <Space><Space>dg :Gdiffsplit<CR>

" Analogous with |dp| |do| in Normal mode.
" TODO: Is adding a `diffupdate` at the end useful?
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.
" TODO: |c_CTRL-R_=| requires |+eval|?
nnoremap <silent> zj m<zjzvm>gvzc'>zv
nnoremap <silent> zk zvzckVzvV:<C-R>=prevnonblank(line('.'))<CR><CR>zvzcVoVzv

" 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

""" Normalize date to ISO 8601
" See |:visual_example|.
" See also |abolish-coercion|.
" This is hacky but works without |+eval|.
xnoremap crd <Esc>`>a<CR><Esc>`<i<CR><Esc>!!date +'\%Y-\%m-\%d' -f -<CR>kJJ

""" Go to string in file under cursor

" The built-in |gF|, and related |CTRL-W_F|, |CTRL-W_gF|, commands extend |gf|
" by also parsing trailing `:{lineno}` (specifically, any non-filename
" character optionally surrounded by whitespace, or the literal string
" ` line `, followed by a decimal number). This corresponds to common output of
" compilers/interpreters/linters. It also happens to roughly correspond to
" _one_ of the common (or, for [POSIX.1-2017][], allowed) outputs of `ctags`.
" It does not however allow the _other_ format: search strings. Let's fix that.
"
" Search strings are very useful when you're not sure what version of the file
" someone else might have, so it's hard to give an accurate line number, but
" the chance is high that a search string will yield the correct location. It
" also conveys more information to someone not wanting to _follow_ the
" reference right now than a line number would.
"
" Vim actually allows _any_ Ex command in tag files (subject to |'exrc'| and
" |'secure'|, see |tag-security|), not just line numbers and search strings,
" see |tags-file-format|. The mapping below only accepts what amounts to
" possibly anchored non-regex search strings, for three reasons: 1) security,
" 2) implementation simplicity, 3) it is what [POSIX.1-2017][] `ctags` / `ex` /
" `vi` supports.
"
" It is important that we lean on the built-in mappings as much as possible
" since they include functionality based on <count>, |'isfname'|, |'path'|,
" |'suffixesadd'|, and |'includeexpr'|, special handling of escaped spaces and
" trailing punctuation, as well as home directory and environment variable
" expansion (|expandcmd|) that would be hard to re-implement, see |gf|. Note
" that the built-in mappings only trigger when the cursor is on or before the
" _filename_, not on the address. |gF| falls back to |gf| functionality without
" giving an error message if a traling line number can't be found, which we
" mimic.
"
" [POSIX.1-2017]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ctags.html#tag_20_27_12

" TODO: Also support `file:line:col`?

if has('eval')
  nnoremap gF      :<C-U>call <SID>gf("gF")<CR>
  nnoremap <C-W>F  :<C-U>call <SID>gf("\<lt>C-W>F")<CR>
  nnoremap <C-W>gF :<C-U>call <SID>gf("\<lt>C-W>gF")<CR>
  function! s:gf(cmd) abort
    let back   = '\\\\'
    let fwd    = '\\\/'
    let dollar = '\$\/\@!'
    let other  = '[^\/$]'
    let chr    = '\%(' . join([back, fwd, dollar, other], '\|') . '\)'
    let str    = '\(' . chr . '\+\)'
    let start  = '\(\^\?\)'
    let end    = '\(\$\?\)'
    let addr   = '\/' . start . str . end . '\/'
    let after  = '\%>' . (col('.')-1) . 'c'
    let file   = '[[:fname:]]'
    let sep    = '[[:space:]]*[^[:fname:][:digit:]/][[:space:]]*'
    let pat    = '\m' . after . file . sep . addr
    let match  = matchlist(getline('.'), pat)
    execute 'normal!' (v:count1 . a:cmd)
    if !empty(match)
      let start = match[1]
      let str   = match[2]
      let end   = match[3]
      let pat   = '\C' . '\m' . start . '\V' . str . '\m' . end
      call cursor(1, 1)
      if search(pat, 'c') == 0
        echo "Could not find search string:" (start . str . end)
      endif
    endif
  endfunction
endif

"" Commands

""" Fill quickfix with output from system command
" TODO: |<q-args>| does not seem to escape quotes, so things like `Cexpr echo
" 'hello'` does not work. Probably passing it to a function so that we get a
" argument variable to call |shellescape| on is required?
" TODO: How does this compare to |dispatch|?
command! -bang -complete=shellcmd -nargs=+ Cexpr
\ execute (empty(<q-bang>)?'cexpr':'cgetexpr') 'system(expandcmd(' escape(<q-args>, "'") '))'

""" Run `git ls` and preview commits on cursor move
" Requires `vim-fugitive` and a `ls`/`lsa` Git alias.
command! -bar Gls
\ Git ls |
\ execute 'nmap <silent> <buffer> j j:silent vert Gpedit <cword><CR><C-W>=' |
\ execute 'nmap <silent> <buffer> k k:silent vert Gpedit <cword><CR><C-W>=' |
\ execute 'autocmd vimrc BufUnload <buffer> pclose' |
command! -bar Glsa
\ Git lsa |
\ execute 'nmap <silent> <buffer> j j:silent vert Gpedit <cword><CR><C-W>=' |
\ execute 'nmap <silent> <buffer> k k:silent vert Gpedit <cword><CR><C-W>=' |
\ execute 'autocmd vimrc BufUnload <buffer> pclose' |

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

""" Hacks for options that Vim likes to reset

" `$VIMRUNTIME/colors/default.vim`
autocmd vimrc OptionSet background set background=dark

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

""" Don't show extra things in special buffers
" TODO: This needs to be moved to after the plugins for it to work in e.g.
" fugitive?
if !has('nvim')
  autocmd vimrc BufReadPost,TerminalWinOpen *
  \ if !empty(&buftype) |
  \   silent setlocal nolist nospell |
  \ endif
endif

""" QuickFix/Location list

"""" Open 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>
" TODO: Maybe this can be fixed by switching back to the previous window after
" opening the quickfix window? Make sure to only switch to the previous if we
" actually opened the window.
" autocmd vimrc QuickFixCmdPost [^l]* nested botright cwindow
" autocmd vimrc QuickFixCmdPost   l*  nested botright lwindow
" autocmd vimrc QuickFixCmdPost  {{make,{,vim}grep{,add}},c{,get,add}{expr,file,buffer}} nested botright cwindow
" autocmd vimrc QuickFixCmdPost {l{make,{,vim}grep{,add}},l{,get,add}{expr,file,buffer}} nested botright lwindow

"""" Conceal column numbers
autocmd vimrc BufReadPost quickfix
\ setlocal conceallevel=2 concealcursor=nvic nonumber |
\ syntax match qfColumnNr / col \d\+/ containedin=qfLineNr transparent conceal |

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

"" Colors
" See |cterm-colors|, |gui-colors|.

silent !. ~/.shrc.d/color.sh
" redraw!

" TODO: Document that |autocmd| is available in "tiny" (i.e. always) but
" |+syntax| requires "normal", so doing it the way we're doing it makes sure it
" works everywhere. This is especially important for interface highlights
" (|listchars|).

" TODO: This is getting ridiculous. |:syntax-on| suggests we can just use
" |:highlight| outside any |autocmd|s and it will work. Look into this.

" TODO: Support `has('gui_running')` and |'termguicolors'|. Look into e.g.
" |g:terminal_ansi_colors|.

""" General
" Transparent background, grayscale interface. Sensible errors/warnings,
" spellchecking, diffs, comments, and todos. See |:hi-normal| and
" |:hi-normal-cterm|.

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

" TODO: Look at all in |'highlight'| (in particular |hl-Search|) and |highlight-default|.
" TODO: This could be done by setting |'highlight'| instead of monkying around
" with highlight groups. Unclear if better.
" TODO: For all chromatic colors, use `Light*`.
" TODO: Remove all `White` except `Normal` from this list and link them to `Normal`?
" TODO: Remove all `Gray` except `Comment` from this list and link them to `Comment`?
" NOTE: When |hl-StatusLine| is a |:hi-link| Vim cannot determine if it's equal
" to |hl-StatusLineNC| and uses "^^^". Same for `StatusLineTerm{,NC}`. See
" `src/drawscreen.c:550` (at the bottom of the funtion `win_redr_status`) in
" the Vim source.
" TODO: Since the Linux console cannot use `DarkGray` as a background, consider
" using any other `Dark*` color (e.g. `DarkYellow`) as (non-`reverse`) `Visual`
" `ctermbg` with `ctermfg=NONE`. NOTE: This requires that we standardize on
" `__color_set_uniform_diff_low`. `__color_set_uniform_diff_high` works (in
" fact is required) for `cterm=reverse ctermfg=NONE ctermbg=NONE`.
" TODO: Why do we need the `term=NONE`? Is this tested ever? Is it used in
" `vim.tiny`?

" TODO: Vim requests the background color from the terinal with the escape
" sequence |t_RB| and sets |'background'| when it gets the response
" (|v:termrbgresp|). That response may come after |vimrc| has completed, so if
" you want to do |:colorscheme| do it in a `autocmd vimrc OptionSet
" background`.

" autocmd vimrc ColorScheme * nested
" \ highlight Normal font='Monospace Regular 10'

" \ set background=dark | runtime syntax/syncolor.vim |
autocmd vimrc ColorScheme * nested
\ highlight Normal           term=NONE   cterm=NONE   gui=NONE              ctermbg=NONE        ctermfg=White      |
\ highlight Comment          term=NONE   cterm=NONE   gui=NONE   guibg=NONE ctermbg=NONE        ctermfg=DarkGray   |
\ highlight Todo             term=NONE   cterm=NONE   gui=NONE   guibg=NONE ctermbg=NONE        ctermfg=White      |
\ highlight Error            term=NONE   cterm=NONE   gui=NONE   guibg=NONE ctermbg=NONE        ctermfg=LightRed   |
\ highlight SpellBad         term=NONE   cterm=NONE   gui=NONE   guibg=NONE ctermbg=NONE        ctermfg=LightRed   |
\ highlight SpellOther       term=NONE   cterm=NONE   gui=NONE   guibg=NONE ctermbg=NONE        ctermfg=LightRed   |
\ highlight Visual           term=NONE   cterm=NONE   gui=NONE              ctermbg=LightGray   ctermfg=NONE       |
\ highlight Search           term=NONE   cterm=NONE   gui=NONE              ctermbg=DarkYellow  ctermfg=NONE       |
\ highlight DiffAdd          term=NONE   cterm=NONE   gui=NONE              ctermbg=DarkGreen   ctermfg=NONE       |
\ highlight DiffDelete       term=NONE   cterm=NONE   gui=NONE              ctermbg=DarkRed     ctermfg=NONE       |
\ highlight DiffChange       term=NONE   cterm=NONE   gui=NONE              ctermbg=DarkBlue    ctermfg=NONE       |
\ highlight DiffText         term=NONE   cterm=NONE   gui=NONE              ctermbg=DarkYellow  ctermfg=NONE       |
\ highlight diffAdded        term=NONE   cterm=NONE   gui=NONE   guibg=NONE ctermbg=NONE        ctermfg=LightGreen |
\ highlight diffRemoved      term=NONE   cterm=NONE   gui=NONE   guibg=NONE ctermbg=NONE        ctermfg=LightRed   |
\ highlight StatusLine       term=NONE   cterm=NONE   gui=NONE              ctermbg=NONE        ctermfg=White      |
\ highlight StatusLineTerm   term=NONE   cterm=NONE   gui=NONE              ctermbg=NONE        ctermfg=White      |
\ highlight StatusLineNC     term=NONE   cterm=NONE   gui=NONE   guibg=NONE ctermbg=NONE        ctermfg=DarkGray   |
\ highlight StatusLineTermNC term=NONE   cterm=NONE   gui=NONE   guibg=NONE ctermbg=NONE        ctermfg=DarkGray   |
\ highlight Ignore           term=NONE   cterm=NONE   gui=NONE   guibg=NONE ctermbg=NONE        ctermfg=Black      |
" \ highlight DiffAdd          term=NONE   cterm=NONE   gui=NONE              ctermbg=LightGreen  ctermfg=Black      |
" \ highlight DiffDelete       term=NONE   cterm=NONE   gui=NONE              ctermbg=LightRed    ctermfg=Black      |
" \ highlight DiffChange       term=NONE   cterm=NONE   gui=NONE              ctermbg=LightBlue   ctermfg=Black      |
" \ highlight DiffText         term=NONE   cterm=NONE   gui=NONE              ctermbg=LightYellow ctermfg=Black      |

""" No bold
" Remove all `cterm=bold` set by default in `$VIMRUNTIME/syntax/syncolor.vim`.
" The Linux virtual console does typically not have a bold font.
autocmd vimrc ColorScheme * nested
\ highlight Identifier cterm=NONE ctermfg=LightCyan |

""" Debug
autocmd vimrc ColorScheme * nested
\ highlight debugPC         term=reverse cterm=NONE gui=NONE guibg=DarkBlue ctermbg=DarkBlue guifg=NONE     ctermfg=NONE     |
\ highlight debugBreakpoint term=NONE    cterm=NONE gui=NONE guibg=NONE     ctermbg=NONE     guifg=LightRed ctermfg=LightRed |

" set highlight-=s:StatusLine
" set highlight-=S:StatusLineNC
" set highlight-=z:StatusLineTerm
" set highlight-=Z:StatusLineTermNC
" set highlight+=s:Normal,z:Normal,S:Comment,Z:Comment

autocmd vimrc ColorScheme * nested
\ highlight! link TabLineSel     Normal |
\ highlight! link ToolbarButton  Comment |
" \ highlight! link StatusLine     Normal |
" \ highlight! link StatusLineTerm Normal |

""" Interface
autocmd vimrc ColorScheme * nested
\ highlight! link TabLine          Comment |
\ highlight! link TabLineFill      Comment |
\ highlight! link ToolbarLine      Comment |
\ highlight! link VertSplit        Comment |
\ highlight! link LineNr           Comment |
\ highlight! link Folded           Comment |
\ highlight! link FoldColumn       Comment |
\ highlight! link SignColumn       Comment |
" \ highlight! link StatusLineNC     Comment |
" \ highlight! link StatusLineTermNC Comment |

""" Errors/warnings
autocmd vimrc ColorScheme * nested
\ highlight! link ErrorMsg   Error |
\ highlight! link WarningMsg Error |

""" Spell
autocmd vimrc ColorScheme * nested
\ highlight! link SpellCap   SpellOther |
\ highlight! link SpellRare  SpellOther |
\ highlight! link SpellLocal SpellOther |

""" Visual
autocmd vimrc ColorScheme * nested
\ highlight! link VisualNOS    Visual |
\ highlight! link ColorColumn  Visual |
\ highlight! link CursorColumn Visual |
\ highlight! link CursorLine   Visual |
\ highlight! link CursorLineNr Visual |

""" Popup menu
" See |'showbreak'|, |'listchars'| `extends` `precedes` `eol`.
autocmd vimrc ColorScheme * nested
\ highlight Pmenu     ctermbg=LightGray ctermfg=DarkGray |
\ highlight PmenuSel  ctermbg=LightGray ctermfg=White    |
\ highlight PmenuSbar ctermbg=DarkGray                   |

""" Non-document characters
" See |'showbreak'|, |'listchars'| `extends` `precedes` `eol`.
autocmd vimrc ColorScheme * nested
\ highlight! link NonText     Special |
\ highlight! link EndOfBuffer Ignore  |

""" Document non-printables characters
" See |'listchars'| `tab`, `space`, `trail`, `nbsp`.
autocmd vimrc ColorScheme * nested
\ highlight! link SpecialKey Comment |

""" Document concealed characters
" See |'listchars'| `conceal`.
autocmd vimrc ColorScheme * nested
\ highlight! link Conceal Ignore |

""" Vim comments
autocmd vimrc ColorScheme * nested
\ highlight! link vimCommentString vimComment |
\ highlight! link vimCommentTitle  vimComment |

""" Apply
" TODO: Move `syntax enable` to someplace before this?
" TODO: `doautocmd vimrc ColorScheme` worked for everything except when using
" Vim as `$MANPAGER`. Not sure if this is a problem with `vimrc` or
" `.vim/ftplugin/man.vim`. We don't always `has('eval')` though.
" echom &background
" if has('eval')
"   colorscheme default
" endif
" echom &background
doautocmd vimrc ColorScheme
" autocmd vimrc VimEnter  *               nested doautocmd vimrc ColorScheme
" autocmd vimrc OptionSet background,t_Co nested doautocmd vimrc ColorScheme

"" 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

  " TODO: Should be easy to create a |'foldexpr'| that's better than the
  " built-in `foldmethod=indent`.
  " function s:manfold() abort
  "   foldlevel()
  " endfunction

  " We're using our own |:ManHelp| instead.
  " runtime ftplugin/man.vim
  " setglobal keywordprg=:Man

  """" Built-in `asm`

  " See |ft-asm-syntax|.
  let g:filetype_i = 'asm'

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

  """" `preservim/vim-markdown`
  GitAdd https://github.com/preservim/vim-markdown

  let g:vim_markdown_no_default_key_mappings = 1
  let g:vim_markdown_toc_autofit = 1
  let g:vim_markdown_math = 1
  let g:vim_markdown_frontmatter = 1
  let g:vim_markdown_no_extensions_in_markdown = 1

  " " Defaults.
  " " |vim-markdown-fenced-code-block-languages|
  " let g:vim_markdown_fenced_languages = [
  " \   "c++=cpp",
  " \   "viml=vim",
  " \   "bash=sh",
  " \   "ini=dosini",
  " \ ]
  " " Additions.
  " call add(g:vim_markdown_fenced_languages, [
  " \   "diff",
  " \ ])


  " <https://github.com/preservim/vim-markdown/issues/232>
  " let g:vim_markdown_new_list_item_indent = 0
  " let g:vim_markdown_auto_insert_bullets = 0

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

  " Roughly as recommended in the readme.
  " autocmd vimrc BufNewFile,BufFilePre,BufRead *.md set filetype=markdown.pandoc

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

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

  """" `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',
  " \ }]

  """" `mhinz/vim-rfc`
  GitAdd https://github.com/mhinz/vim-rfc

  """" `HiPhish/info.vim`
  GitAdd https://gitlab.com/HiPhish/info.vim

  """ Normal mode

  """" Built-in `matchit`

  packadd! matchit

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

  " <https://github.com/tpope/vim-unimpaired/issues?q=conceal>
  " <https://github.com/tpope/vim-unimpaired/issues/105>
  " <https://github.com/tpope/vim-unimpaired/pull/152>
  nnoremap yoe :setlocal conceallevel=<C-R>=&conceallevel == 0 ? 2 : 0<CR><CR>
  nnoremap [oe :setlocal conceallevel=<C-R>=&conceallevel == 0 ? 0 : &conceallevel - 1<CR><CR>
  nnoremap ]oe :setlocal conceallevel=<C-R>=&conceallevel == 2 ? 2 : &conceallevel + 1<CR><CR>

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

  """" `inkarkat/vim-visualrepeat`
  " NOTE: Requires <https://github.com/inkarkat/vim-ingo-library>
  GitAdd https://github.com/inkarkat/vim-visualrepeat

  """" `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> gz* <Plug>(asterisk-gz*):set hlsearch<CR>
  map <silent> gz# <Plug>(asterisk-gz#):set hlsearch<CR>

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

  " TODO: According to |splitjoin_align| this requires either of the Tabular or
  " Align plugins. We currently prefer vim-lion. Create a pull request?
  " let g:splitjoin_align = 1

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

  let g:switch_custom_definitions = [{
  \   '\<0\>': '1',
  \   '\<1\>': '0',
  \   '\<OFF\>': 'ON',
  \   '\<Off\>': 'On',
  \   '\<off\>': 'on',
  \   '\<ON\>': 'OFF',
  \   '\<On\>': 'Off',
  \   '\<on\>': 'off',
  \   '\<NO\>': 'YES',
  \   '\<No\>': 'Yes',
  \   '\<no\>': 'yes',
  \   '\<YES\>': 'NO',
  \   '\<Yes\>': 'No',
  \   '\<yes\>': 'no',
  \   '\(\w*\)FALSE\(\w*\)': '\1TRUE\2',
  \   '\(\w*\)False\(\w*\)': '\1True\2',
  \   '\(\w*\)false\(\w*\)': '\1true\2',
  \   '\(\w*\)TRUE\(\w*\)': '\1FALSE\2',
  \   '\(\w*\)True\(\w*\)': '\1False\2',
  \   '\(\w*\)true\(\w*\)': '\1false\2',
  \   '\<\(set *\)no\([a-z]\+\)\>=\@!': '\1\2',
  \   '\<\(set *\)\([a-z]\+\)\>=\@!':   '\1no\2',
  \ }]

  """" `terryma/vim-smooth-scroll`
  " GitAdd https://github.com/terryma/vim-smooth-scroll

  " Kind of useful when pair programming to give some indication of navigation,
  " mostly annoying when not.

  " Roughly as suggested in the readme.
  " noremap <silent> <C-U> :call smooth_scroll#up(  &scroll*1, 20, &scroll/4)<CR>
  " noremap <silent> <C-D> :call smooth_scroll#down(&scroll*1, 20, &scroll/4)<CR>
  " noremap <silent> <C-B> :call smooth_scroll#up(  &scroll*2, 20, &scroll/2)<CR>
  " noremap <silent> <C-F> :call smooth_scroll#down(&scroll*2, 20, &scroll/2)<CR>

  """ Insert mode

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

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

  " TODO: Look at "Swedish Character Conflict" in the documentation.

  " Disable meta mappings.
  let g:AutoPairsShortcutToggle     = ''
  let g:AutoPairsShortcutFastWrap   = ''
  let g:AutoPairsShortcutJump       = ''
  let g:AutoPairsShortcutBackInsert = ''

  " 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

  " `targets` just pairs up quotes from the beginning of line, which is often
  " not what we want (especially in shell scripts).
  xnoremap i" i"
  xnoremap i' i'
  xnoremap i` i`
  onoremap i" i"
  onoremap i' i'
  onoremap i` i`

  """" `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`
  " TODO: I'm not happy with this, replace.
  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`
  " TODO: This is a stopgap untill we make a Vim colorscheme from
  " <https://notes/rcrnstn/colors.md>.
  GitAdd https://github.com/gruvbox-community/gruvbox

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

  autocmd vimrc OptionSet termguicolors nested
  \ execute 'colorscheme' &termguicolors ? 'gruvbox' : 'default' |

  doautocmd OptionSet termguicolors

  """ 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

  " As suggested in |unobtrusive_fold#text()|.
  set foldtext=unobtrusive_fold#text()

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

  let g:vim_markdown_folding_disabled = 1

  """ Undo

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

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

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

  """ QuickFix

  """" Built-in `cfilter`
  packadd! cfilter

  """" `romainl/vim-qf`
  " GitAdd https://github.com/romainl/vim-qf

  " let g:qf_mapping_ack_style = 1
  " let g:qf_shorten_path = 1

  " TODO: Check if this causes problems, see the "Open the QuickFix/Location
  " list window" section.
  " let g:qf_auto_open_quickfix = 0

  """ Spell

  """" `inkarkat/vim-SpellCheck`
  " NOTE: Requires <https://github.com/inkarkat/vim-ingo-library>
  " GitAdd https://github.com/inkarkat/vim-SpellCheck

  """ Modelines

  """" `ypcrts/securemodelines`
  " GitAdd https://github.com/ypcrts/securemodelines
  " TODO: Last updated 2019 as of writing, can we be sure is this really more
  " secure than the built-in sandbox? Besides, we don't use modelines much
  " anyway.

  " let g:secure_modelines_verbose = 1

  """ Environment interaction

  """" Built-in `netrw`

  let g:netrw_home = '~/.cache/vim/netrw'
  let g:netrw_banner = 0

  " 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>

  """" `bogado/file-line`
  GitAdd https://github.com/bogado/file-line

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

  " <https://github.com/kien/ctrlp.vim/issues/337>
  " <https://github.com/ctrlpvim/ctrlp.vim/pull/316>
  " <https://github.com/ctrlpvim/ctrlp.vim/issues/450>
  " NOTE: Highly dependent on non-documented ctrlp internals.
  function! s:ctrlp_syntax() abort
    execute 'autocmd vimrc OptionSet cursorline'
    \  'if winnr() == ' winnr() ' && &cursorline |'
    \  '  set nocursorline |'
    \  'endif |'
    syntax     region CtrlPLine      start="^"   end="$"
    syntax     region CtrlPLineSel   start="\%#" end="$"
    highlight! link   CtrlPLine      Comment
    highlight! link   CtrlPLineSel   Normal
    " TODO: `&term ==# 'linux'` does not do `underline`.
    highlight         CtrlPPrtCursor term=underline cterm=underline
  endfunction
  " We need to define the `Syntax` `autocmd` after `ctrlp` has been loaded, but
  " also when we reload the `vimrc`.
  " TODO: This still does not work when reloading the `vimrc`.
  autocmd vimrc VimEnter *
  \ autocmd vimrc Syntax ctrlp call s:ctrlp_syntax()
  autocmd vimrc Syntax ctrlp call s:ctrlp_syntax()

  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_match_window = 'max:20' " Default 'max:10'
  " let g:ctrlp_user_command_async = 1
  if has('unix')
    " TODO: Set `grepprg` to something similar, that skips things in
    " 'wildignore'.
    let s:wildignore      = split(&wildignore, ',')
    let s:wildignore_name = filter(copy(s:wildignore), '!count(v:val, "/")')
    let s:wildignore_path = filter(copy(s:wildignore), ' count(v:val, "/")')

    let g:ctrlp_user_command =
    \ 'find' .
    \ (!g:ctrlp_follow_symlinks ? '' : ' -L') .
    \ ' %s' .
    \ ' -mount' .
    \ ' -maxdepth ' . g:ctrlp_max_depth .
    \ ' \( -false' .
    \ (g:ctrlp_show_hidden ? '' : ' -o -name ".*"') .
    \ ' ' . join(map(s:wildignore_name, '"-o -name " . shellescape(v:val)')) .
    \ ' ' . join(map(s:wildignore_path, '"-o -path " . shellescape(v:val)')) .
    \ ' \) -prune -o' .
    \ ' -type f -print' .
    \ ' 2> /dev/null' .
    \ (!g:ctrlp_max_files ? '' : ' | head -n ' . g:ctrlp_max_files)


    " \ ' -type d -exec test -d {}/.git \; -prune -o' .
    " \ ' -exec grep -Il . {} +' .
    " \ ' \(' .
    " \ (g:ctrlp_follow_symlinks == 2 ? ' -o -type l' : '') .
    " \ ' \)' .

    " function! s:ctrl_find_prefix(prefix, list) abort
    "   return map(copy(a:list), '["' . a:prefix . '", shellescape(v:val)]')
    " endfunction
    " function! s:ctrl_find_join(join, list) abort
    "   return ['\('] + eval(join(a:list, '+["' . a:join . '"]+')) + ['\)']
    " endfunction
    " let g:ctrlp_user_command = join(
    " \   ['find', (!g:ctrlp_follow_symlinks ? '' : '-L'), '%s'] +
    " \   ['-maxdepth', g:ctrlp_max_depth] +
    " \   s:ctrl_find_join('-o',
    " \     s:ctrl_find_prefix('-name', g:ctrlp_show_hidden ? [] : ['.*']) +
    " \     s:ctrl_find_prefix('-name', s:wildignore_name) +
    " \     s:ctrl_find_prefix('-path', s:wildignore_path)
    " \   ) + ['-prune', '-o'] +
    " \   ['-type', 'f', '-print'] +
    " \   ['2>', '/dev/null'] +
    " \   (!g:ctrlp_max_files ? [] : ['|', 'head', '-n', g:ctrlp_max_files])
    " \ )

  endif

  """" `mhinz/vim-tree`
  " GitAdd https://github.com/mhinz/vim-tree

  " As suggesteed in the readme.
  " autocmd vimrc FileType tree
  " \ setlocal foldmethod=expr

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

  autocmd vimrc FileType fugitiveblame call fugitive#MapJumps()

  " http://vimcasts.org/episodes/fugitive-vim-browsing-the-git-object-database/
  " TODO: Do we want `bufhidden=wipe`?
  autocmd vimrc BufReadPost fugitive://* setlocal bufhidden=delete

  " TODO: Add some `git log -L` (see man page) mapping.

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

  """" `iberianpig/tig-explorer.vim`
  " GitAdd https://github.com/iberianpig/tig-explorer.vim

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

  " https://github.com/tpope/vim-dispatch/issues/203
  function! s:focus_start_set() abort
    if get(b:, 'start_local', 1)
      let b:start_local = get(b:, 'start')
    endif
    let b:start = s:start
  endfunction
  function! s:focus_start_unset() abort
    if type(get(b:, 'start_local')) == type('')
      let b:start = b:start_local
    else
      unlet! b:start
    endif
    unlet! b:start_local
  endfunction
  function! s:focus_start(bang, command) abort
    if !empty(a:command)
      let s:start = a:command
      augroup vimrc_dispatch_start
        autocmd!
      augroup END
      silent bufdo call s:focus_start_set()
      augroup vimrc_dispatch_start
        autocmd BufEnter * call s:focus_start_set()
      augroup END
      echo 'Set global default to :Start' s:start
    elseif a:bang
      unlet! s:start
      augroup vimrc_dispatch_start
        autocmd!
      augroup END
      silent bufdo call s:focus_start_unset()
      if type(get(b:, 'start')) == type('')
        echo 'Reverted default to :Start' b:start
      else
        echo 'Reverted default to :Start'
      endif
    else
      if type(get(s:, 'start')) == type('')
        echo 'Global focus is :Start' s:start
      elseif type(get(b:, 'start')) == type('')
        echo 'Buffer default is :Start' b:start
      else
        echo 'Global default is :Start'
      endif
    endif
  endfunction
  command! -bang -nargs=* -range=-1 -complete=customlist,dispatch#command_complete FocusStart
  \ call s:focus_start(<bang>0, <q-args>)

  " TODO: Put this in a QuickFix section?

  " TODO: Stick to the default mappings.
  nnoremap <Space><Space>m% :Make %:r:S<CR>
  nnoremap <Space><Space>m# :Make #:r:S<CR>
  nnoremap <Space><Space>mm :Make<CR>
  nnoremap <Space><Space>ma :Make all<CR>
  nnoremap <Space><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

  """" Built-in `termdebug`
  " See |terminal-debug|.

  packadd! termdebug
  " TODO: Add mappings.
  " TODO: Remove |:Winbar|.
  " TODO: Do some |termdebug-customizing|, especially |termdebug_shortcuts|.
  " TODO: Add some signs? ■♦←↑→↓›»•·
  " let g:termdebug_popup = 0

  nnoremap <Space>dd :Termdebug

  nnoremap <Space>db :Break<CR>
  nnoremap <Space>dB :Clear<CR>
  nnoremap <Space>di :Step<CR>
  nnoremap <Space>do :Over<CR>
  nnoremap <Space>df :Finish<CR>
  nnoremap <Space>dr :Run<CR>
  nnoremap <Space>da :Arguments<CR>
  nnoremap <Space>ds :Stop<CR>
  nnoremap <Space>dc :Continue<CR>
  " nnoremap <Space>de :Evaluate<CR>

  " nnoremap <Space>dg :Gdb<CR>
  " nnoremap <Space>ds :Source<CR>
  " nnoremap <Space>da :Asm<CR>

  " nnoremap <Space>dw :Winbar<CR>

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

  " Debug Adapter Protocol (DAP) client. See
  " - <https://microsoft.github.io/debug-adapter-protocol/>
  " - <https://sourceware.org/gdb/current/onlinedocs/gdb.html/Debugger-Adapter-Protocol.html>

  " <https://github.com/mfussenegger/nvim-dap/wiki/Debug-Adapter-installation>

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

  " Supports PHP, Python, Ruby, Perl, Tcl and NodeJS.

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

endif " has('eval')

"" Syntax and file type
if has('gui_running')
  " See |'background'|.
  " TODO: Causes the GUI cursor to be misplaced?
  " gui
endif
if has('eval')
  filetype plugin indent on
  syntax enable
endif

"" File type detection
" See |new-filetype|.

if has('eval')

  autocmd! filetypedetect BufRead,BufNewFile *.Xresources setf xdefaults
  autocmd! filetypedetect BufRead,BufNewFile *.gdb*init   setf gdb
  autocmd! filetypedetect BufRead,BufNewFile *.asy        setf cpp
  autocmd! filetypedetect BufRead,BufNewFile *.gvpr       setf c

endif

"" Language specific |help|

if has('eval')
  function! s:help(cmd, arg, filetype) abort
    for i in range(len(a:cmd))
      let a:cmd[i] = join(
      \   map(split(a:cmd[i], '%s', 1), 'shellescape(v:val)'),
      \   shellescape(a:arg)
      \ )
    endfor
    silent help
    silent let old_shellredir = &shellredir
    silent let &shellredir    = '>'
    silent setlocal buftype=nofile bufhidden=delete noswapfile
    silent setlocal noreadonly modifiable
    silent execute 'file' a:arg
    silent keepjumps normal! ggdG
    silent execute 'read' '!' join(a:cmd)
    silent keepjumps normal! ggdd
    silent execute 'setlocal' 'filetype=' . a:filetype
    silent setlocal readonly nomodifiable nomodified
    silent setlocal buftype=help
    silent let &shellredir = old_shellredir
  endfunction
endif

command! -nargs=1 -complete=shellcmd ManHelp
\ call s:help(['man', '%s'], <q-args>, 'man')

command! -nargs=1 PythonHelp
\ call s:help(['python3', '-m', 'pydoc', '%s'], <q-args>, 'python')

command! -nargs=1 OctaveHelp
\ call s:help(['octave', '--eval', 'help("%s")'], <q-args>, 'octave')

" TODO: Would be cool to define one for `filetype` `gitconfig` that does
" `ManHelp git-config` and then `/^ {7}\zs` whith the first two components of
" setion words and `<cowrd>`.

"" File type overrides

autocmd vimrc FileType *
\ setlocal keywordprg=:ManHelp |

" TODO: This needs work. We globally override `fillchars` `stl`/`stlnc` and
" `statusline` but don't take into account file type plugins setting their own
" `statusline`.
" TODO: `w:quickfix_title` is not always defined (e.g. when openging the
" quickfix list when it has not been populated). Guard the printing in some
" way?
autocmd vimrc FileType qf
\ setlocal statusline=%{Statusline()} |
autocmd vimrc FileType help
\ setlocal statusline=%{Statusline()} |

autocmd vimrc FileType vim
\ setlocal keywordprg=:help |

autocmd vimrc FileType sh
\ setlocal shiftwidth=2 |

autocmd vimrc FileType c,cpp,glsl
\ setlocal commentstring=//\ %s |
\ setlocal matchpairs=(:),{:},[:],<:> |
\ setlocal cinkeys-=0# cinoptions=L0,l1,g0,N-s,E-s,t0,c0,C1,(s,u0,W1s,m1,j1,J1,N999,*999 |
\ setlocal path=.,**/include,**/src,/usr/include,/usr/local/include,/usr/include/c++/11 |

autocmd vimrc FileType man
\ setlocal nolist nospell |
\ execute 'nnoremap <buffer> <Space>/ /^ \{4,\}\(--\S\+\, \)\?\zs-' |

autocmd vimrc FileType dot
\ setlocal commentstring=//\ %s |

autocmd vimrc FileType gitcommit
\ setlocal nolist spell |

autocmd vimrc FileType markdown
\ setlocal spell complete+=kspell |
" \ setlocal formatoptions-=q |

autocmd vimrc FileType python
\ setlocal keywordprg=:PythonHelp |

autocmd vimrc FileType octave
\ setlocal keywordprg=:OctaveHelp |

" Don't insert comment leader after |i_<CR>|, |o|, or |O|.
autocmd vimrc FileType *
\ setlocal formatoptions-=r formatoptions-=o |

" 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 |

" TODO: Add a match for `\<TODO\>` (and `\<NOTE\>`?) unconditionally for all
" file types.

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

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

if has('cursorshape')
  set noshowmode
  " Cursor visible/invisible
  " On Linux the following is the default, which messes with our cursor
  " shape:
  " - `t_ve = "\033[?25h\033[?0c"`
  " - `t_vi = "\033[?25l\033[?1c"`
  " See
  " - <https://vt100.net/docs/vt510-rm/DECTCEM>
  " - `console_codes(4)`
  let &t_ve = "\033[?25h"
  let &t_vi = "\033[?25l"
  " if $TERM =~? '^xterm\(-\|$\)'
    " See
    " - <https://vt100.net/docs/vt510-rm/DECSCUSR>
    " - `:helpgrep t_SH`
    let &t_EI = "\033[1 q"
    let &t_SI = "\033[5 q"
    let &t_SR = "\033[3 q"
    let &t_SH = "\033[%p1%d q"
  " endif
  if $TERM =~? '^linux\(-\|$\)'
    " See
    " - <https://www.kernel.org/doc/Documentation/admin-guide/vga-softcursor.rst>
    " - `console_codes(4)`
    let &t_EI = "\033[?6c"
    let &t_SI = "\033[?2c"
    let &t_SR = "\033[?2c"
    let &t_SH = "\033[?%?%p1%{3}%<%t%{6}%e%{2}%;%dc"
  endif
endif

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

if has('termguicolors') && !has('nvim')
  " These are the defaults if `$TERM` is `xterm`.
  let &t_8f = "\033[38;2;%lu;%lu;%lum"
  let &t_8b = "\033[48;2;%lu;%lu;%lum"
  " <http://ftp.vim.org/pub/vim/patches/8.2/8.2.3516>: Terminal window does not
  " have transparent background when 'termguicolors' is used. Fix the
  " background color.
  if !has('patch-8.2.3516')
    let s:termguicolors = &termguicolors
    autocmd vimrc OptionSet termguicolors
    \ 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