vim/vimrc @ 417f91fae3c2

More
author Steve Losh <steve@stevelosh.com>
date Thu, 28 Mar 2024 16:06:55 -0400
parents 4673e928c08e
children 4e1d6d6873fe
" .vimrc
" Author: Steve Losh <steve@stevelosh.com>
" Source: https://hg.stevelosh.com/dotfiles/file/tip/vim/vimrc

" See also vimrc-minimal for the rest of this.

" Preamble ---------------------------------------------------------------- {{{
set shell=/bin/bash\ --login

filetype off
call pathogen#infect()
filetype plugin indent on
set nocompatible

" }}}
" Load Minimal ------------------------------------------------------------ {{{

source ~/.vimrc-minimal

" }}}
" Spelling ---------------------------------------------------------------- {{{
"
" There are three dictionaries I use for spellchecking:
"
"   /usr/share/dict/words
"   Basic stuff.
"
"   ~/.vim/custom-dictionary.utf-8.add
"   Custom words (like my name).  This is in my (version-controlled) dotfiles.
"
"   ~/.vim-local-dictionary.utf-8.add
"   More custom words.  This is *not* version controlled, so I can stick
"   work stuff in here without leaking internal names and shit.
"
" I also remap zG to add to the local dict (vanilla zG is useless anyway).
set dictionary=/usr/share/dict/words
set spellfile=~/.vim/custom-dictionary.utf-8.add,~/.vim-local-dictionary.utf-8.add
nnoremap zG 2zg

" }}}
" Color scheme ------------------------------------------------------------ {{{

set termguicolors
let g:badwolf_tabline = 2
let g:badwolf_html_link_underline = 0
colorscheme goodwolf

" Reload the colorscheme whenever we write the file.
augroup color_badwolf_dev
    au!
    au BufWritePost badwolf.vim color badwolf
    au BufWritePost goodwolf.vim color goodwolf
augroup END

" Highlight VCS conflict markers
match ErrorMsg '^\(<\|=\|>\)\{7\}\([^=].\+\)\?$'

nnoremap <leader>B :call GoodWolfToggleBoldStrings()<cr>

" }}}
" Convenience mappings ---------------------------------------------------- {{{

" Copying/pasting text to the system clipboard.
noremap  <leader>p "+p
vnoremap <leader>y "+y
nnoremap <leader>y VV"+y
nnoremap <leader>Y "+y

" Open
function Open(thing)
    call system(['open', a:thing])
endfunction

nnoremap <leader>o "zyiW:call Open(@z)<cr>
vnoremap <leader>o "zy:call Open(@z)<cr>

" Rebuild Ctags (mnemonic RC -> CR -> <cr>)
nnoremap <leader><cr> :silent !myctags >/dev/null 2>&1 &<cr>:redraw!<cr>

" Highlight Group(s)
nnoremap <F8> :echo "hi<" . synIDattr(synID(line("."),col("."),1),"name") . '> trans<'
                        \ . synIDattr(synID(line("."),col("."),0),"name") . "> lo<"
                        \ . synIDattr(synIDtrans(synID(line("."),col("."),1)),"name") . ">"<CR>

" Send visual selection to paste.stevelosh.com
vnoremap <leader>P :w !pb && open `pbpaste`<cr>

" }}}
" Quick editing ----------------------------------------------------------- {{{

nnoremap <leader>eb :vsplit ~/Dropbox/bitly.txt<cr>
nnoremap <leader>ed :vsplit ~/.vim/custom-dictionary.utf-8.add<cr>
nnoremap <leader>ef :vsplit ~/.config/fish/config.fish<cr>
nnoremap <leader>eg :vsplit ~/.gitconfig<cr>
nnoremap <leader>es :vsplit ~/.stumpwmrc<cr>
nnoremap <leader>eh :vsplit ~/.hgrc<cr>
nnoremap <leader>elw :vsplit ~/.lispwords<cr>
nnoremap <leader>em :vsplit ~/.mutt/muttrc<cr>
nnoremap <leader>ep :vsplit ~/.plan/README.markdown<cr>
nnoremap <leader>eln :vsplit ~/lab/README.markdown<cr>
nnoremap <leader>eq :vsplit ~/Dropbox/quotes.txt<cr>Gzz
nnoremap <leader>et :vsplit ~/.tmux.conf<cr>
nnoremap <leader>evf :vsplit ~/.vimrc<cr>
nnoremap <leader>evm :vsplit ~/.vimrc-minimal<cr>

" }}}
" Status Line ------------------------------------------------------------- {{{

function! StatusLineMode()
    let mode = mode()

    if mode == "n"
        call GoodWolfHL('GWStatusLineMode', 'coal', 'lime', 'bold')
        call GoodWolfHL('GWStatusLineModeX', 'lime', 'deepergravel')
        call GoodWolfHL('GWStatusLineModeY', 'lime', 'deepgravel')
        return "NORMAL"
    elseif mode == "no"
        call GoodWolfHL('GWStatusLineMode', 'coal', 'lime', 'bold')
        call GoodWolfHL('GWStatusLineModeX', 'lime', 'deepergravel')
        call GoodWolfHL('GWStatusLineModeY', 'lime', 'deepgravel')
        return "OPERATOR"
    elseif mode == "V" || mode == ""
        call GoodWolfHL('GWStatusLineMode', 'coal', 'dirtyblonde', 'bold')
        call GoodWolfHL('GWStatusLineModeX', 'dirtyblonde', 'deepergravel')
        call GoodWolfHL('GWStatusLineModeY', 'dirtyblonde', 'deepgravel')
        return "VISUAL"
    elseif mode == "s" || mode == "S" || mode == ""
        call GoodWolfHL('GWStatusLineMode', 'coal', 'dirtyblonde', 'bold')
        call GoodWolfHL('GWStatusLineModeX', 'dirtyblonde', 'deepergravel')
        call GoodWolfHL('GWStatusLineModeY', 'dirtyblonde', 'deepgravel')
        return "SELECT"
    elseif mode == "i"
        call GoodWolfHL('GWStatusLineMode', 'coal', 'tardis', 'bold')
        call GoodWolfHL('GWStatusLineModeX', 'tardis', 'deepergravel')
        call GoodWolfHL('GWStatusLineModeY', 'tardis', 'deepgravel')
        return "INSERT"
    elseif mode == "r" || mode == "Rv"
        call GoodWolfHL('GWStatusLineMode', 'coal', 'taffy', 'bold')
        call GoodWolfHL('GWStatusLineModeX', 'taffy', 'deepergravel')
        call GoodWolfHL('GWStatusLineModeY', 'taffy', 'deepgravel')
        return "REPLACE"
    elseif mode == "t"
        call GoodWolfHL('GWStatusLineMode', 'coal', 'tardis', 'bold')
        call GoodWolfHL('GWStatusLineModeX', 'tardis', 'deepergravel')
        call GoodWolfHL('GWStatusLineModeY', 'tardis', 'deepgravel')
        return "TERMINAL"
    else
        call GoodWolfHL('GWStatusLineMode', 'coal', 'lime', 'bold')
        call GoodWolfHL('GWStatusLineModeX', 'lime', 'deepergravel')
        call GoodWolfHL('GWStatusLineModeY', 'lime', 'deepgravel')
        return "OTHER"
    endif
endfunction

function! SetStatusLine(winnr)
    let s = ""

    if a:winnr == winnr()
        "let errors = SyntasticStatuslineFlag()
	let errors = ""

        let s .= "%#GWStatusLineMode#"
        let s .= " "
        let s .= "%{StatusLineMode()}"
        let s .= " "
        let s .= "%#GWStatusLineModeX#"
        let s .= " "

        if strlen(errors) != 0
            let s .= "%#Error#"
            let s .= errors
            let s .= "%#GWStatusLineModeX# "
        endif

        let s .= "%f"
        let s .= " %m%r%h%w"
        let s .= "%="

        let s .= " %y"
        let s .= " \[%{&fileencoding?&fileencoding:&encoding}/%{&fileformat}\] "

        let s .= "%#GWStatusLineModeY#"
        let s .= ""
        let s .= "%#GWStatusLineMode#"
        let s .= " %c:"
        let s .= "%l"        " Current line
        let s .= "/"
        let s .= "%L"        " Total lines
        let s .= " "
    else
        let s .= "%#StatusLineNC#"
        let s .= "%f"
        let s .= " %m%r%h%w"
        let s .= "%="
        let s .= " %y"
        let s .= " \[%{&fileencoding?&fileencoding:&encoding}/%{&fileformat}\] "
    endif

    return s
endfunction

function! RefreshStatusLine()
    for nr in range(1, winnr('$'))
        call setwinvar(nr, '&statusline', '%!SetStatusLine(' . nr . ')')
    endfor
endfunction

augroup statusline
  autocmd!
  autocmd VimEnter,WinEnter,BufWinEnter * call RefreshStatusLine()
augroup END

" set statusline+=%=

" }}}
" Filetype-specific ------------------------------------------------------- {{{

" April {{{

augroup ft_commonlisp_april " {{{
    au!

    au FileType lisp inoremap <buffer> <c-j>;  ⍝
    au FileType lisp inoremap <buffer> <c-j>i  ⍳
    au FileType lisp inoremap <buffer> <c-j>r  ⍴
    au FileType lisp inoremap <buffer> <c-j>e  ∊
    au FileType lisp inoremap <buffer> <c-j>_i ⍸
    au FileType lisp inoremap <buffer> <c-j>_, ⍪

    au FileType lisp inoremap <buffer> <c-j>1  ¨
    au FileType lisp inoremap <buffer> <c-j>F  ⍨
    au FileType lisp inoremap <buffer> <c-j>P  ⍣
    au FileType lisp inoremap <buffer> <c-j>R  ⍤

    au FileType lisp inoremap <buffer> <c-j>*  ×
    au FileType lisp inoremap <buffer> <c-j>/  ÷
    au FileType lisp inoremap <buffer> <c-j>0  ∘
    au FileType lisp inoremap <buffer> <c-j>-  ¯
    au FileType lisp inoremap <buffer> <c-j>l  ⍟

    au FileType lisp inoremap <buffer> <c-j>c  ⌈
    au FileType lisp inoremap <buffer> <c-j>f  ⌊

    au FileType lisp inoremap <buffer> <c-j><c-j> ←
    au FileType lisp inoremap <buffer> <c-j><  ←
    au FileType lisp inoremap <buffer> <c-j>>  →
    au FileType lisp inoremap <buffer> <c-j>^  ↑
    au FileType lisp inoremap <buffer> <c-j>v  ↓

    au FileType lisp inoremap <buffer> <c-j>d  ∆
    au FileType lisp inoremap <buffer> <c-j>D  ⍙

    au FileType lisp inoremap <buffer> <c-j>Gk ⍋
    au FileType lisp inoremap <buffer> <c-j>Gj ⍒

    au FileType lisp inoremap <buffer> <c-j>oo  ○
    au FileType lisp inoremap <buffer> <c-j>o\| ⌽
    au FileType lisp inoremap <buffer> <c-j>o\  ⍉
    au FileType lisp inoremap <buffer> <c-j>o-  ⊖

    au FileType lisp inoremap <buffer> <c-j>A  ∧
    au FileType lisp inoremap <buffer> <c-j>O  ∨

    au FileType lisp inoremap <buffer> <c-j>=< ≤
    au FileType lisp inoremap <buffer> <c-j>=< ≥
    au FileType lisp inoremap <buffer> <c-j>=/ ≠
    au FileType lisp inoremap <buffer> <c-j>=== ≡
    au FileType lisp inoremap <buffer> <c-j>==/ ≢

    au FileType lisp inoremap <buffer> <c-j>q  ⎕
    au FileType lisp inoremap <buffer> <c-j>Q  ⌷
    au FileType lisp inoremap <buffer> <c-j>t  ⊢

    au FileType lisp inoremap <buffer> <c-j>u  ∪
    au FileType lisp inoremap <buffer> <c-j>U  ∩
    au FileType lisp inoremap <buffer> <c-j>+  ⌿
    au FileType lisp inoremap <buffer> <c-j>[  ⊂
    au FileType lisp inoremap <buffer> <c-j>]  ⊃

    au FileType lisp inoremap <buffer> <c-j>a  ⍺
    au FileType lisp inoremap <buffer> <c-j>w  ⍵
    au FileType lisp inoremap <buffer> <c-j>z  ⍬
augroup END " }}}

" }}}
" Assembly {{{

augroup ft_asm
    au!
    au BufNewFile,BufRead *.s set filetype=arm64asm
    au FileType arm64asm setlocal noexpandtab shiftwidth=8 tabstop=8 softtabstop=8
augroup END

" }}}
" Bazel {{{

augroup ft_bazel
    au!
    au FileType bzl nnoremap <buffer> gi :Neoformat buildifier<cr>
augroup END

" }}}
" C {{{

augroup ft_c
    au!
    au FileType c setlocal foldmethod=marker foldmarker={,}
    au FileType c setlocal ts=8 sts=8 sw=8 noexpandtab
augroup END

" }}}
" C++ {{{

augroup ft_cpp
    au!
    au FileType cpp setlocal foldmethod=marker foldmarker={,}
    au FileType cpp setlocal ts=8 sts=8 sw=8 noexpandtab
augroup END

" }}}
" C# {{{

augroup ft_csharp
    au!
    au FileType cs setlocal foldmethod=marker foldmarker={,}
    au FileType cs setlocal foldtext=MyFoldText()
    au FileType cs nnoremap <buffer> gi mz=ap`z
    au FileType cs setlocal ts=4 sw=4 sts=4 noexpandtab
augroup END

" }}}
" Contacts {{{

augroup ft_contacts
    au!
    autocmd BufNewFile,BufRead .contacts setlocal ts=32
    autocmd BufNewFile,BufRead .contacts setlocal noexpandtab
augroup END

" }}}
" Common Lisp {{{

" Helper Functions {{{
function! HighlightLispRepl() "{{{
    " set syntax=lisp
    syn match replPrompt /\v^\[([a-z A-Z])+\] [-._a-zA-Z0-9]+\>/
    syn match replComment /\v^;.*/

    " syn match replResult /\v^#\<[^>]+\>$/
    hi def link replResult Debug
    hi def link replComment Comment
endfunction "}}}
function! MapLispReplKeys() "{{{
    nnoremap <buffer> <silent> <localleader>q :call QuickloadLispSystem()<cr>
    nnoremap <buffer> <silent> <localleader>Q :call QuickloadLispPrompt()<cr>
endfunction "}}}
function! InitializeLispRepl() "{{{
    call MapLispReplKeys()
    call HighlightLispRepl()
endfunction "}}}

function! OpenLispReplMakerlisp() "{{{
    NeoRepl makerlisp
endfunction "}}}
function! OpenLispReplMakerlispRaw() "{{{
    NeoRepl makerlisp-raw
endfunction "}}}

function! OpenLispReplSBCL() "{{{
    NeoRepl sbcl-vlime
endfunction "}}}
function! OpenLispReplSBCLRaw() "{{{
    NeoRepl sbcl-vlime-raw
endfunction "}}}

function! OpenLispReplCCL() "{{{
    NeoRepl ccl-vlime
endfunction "}}}
function! OpenLispReplECL() "{{{
    NeoRepl ecl-vlime
    call InitializeLispRepl()
endfunction "}}}
function! OpenLispReplABCL() "{{{
    NeoRepl abcl-vlime
    call InitializeLispRepl()
endfunction "}}}

function! SetLispWords() "{{{
    setlocal isk+=.

    if exists("b:did_set_lisp_words")
        return
    endif

    let b:did_set_lisp_words = 1

    setlocal lispwords+=block

    setlocal lispwords+=when-let
    setlocal lispwords+=test
    setlocal lispwords+=.let*
    setlocal lispwords+=define-compiler-macro

    " optima
    setlocal lispwords+=optima:match
    setlocal lispwords+=match,match*,defun-match,defun-match*
    setlocal lispwords+=ematch,ematch*,defun-ematch,defun-ematch*
    setlocal lispwords+=cmatch,cmatch*,defun-cmatch,defun-cmatch*

    " 1am
    setlocal lispwords+=test

    " sketch
    setlocal lispwords+=with-pen
    setlocal lispwords+=with-font

    " charms
    setlocal lispwords+=with-curses

    " bones
    setlocal lispwords+=rule

    " cl-arrows
    setlocal lispwords+=->
    setlocal lispwords+=->>
    setlocal lispwords+=-<>
    setlocal lispwords+=-<>>
    setlocal lispwords+=_

    " alexandria
    setlocal lispwords+=define-constant
    setlocal lispwords+=switch
    setlocal lispwords+=cswitch
    setlocal lispwords+=eswitch
    setlocal lispwords+=with-gensyms
    setlocal lispwords+=once-only

    " more shit
    setlocal lispwords+=define-test
    setlocal lispwords+=recursively
endfunction "}}}

function! SendLispForm() "{{{
    call SelectAndSendToNeoRepl("vab")
endfunction "}}}

function! SelectToplevelLispForm() "{{{
    execute "normal v\<Plug>(sexp_outer_top_list)"
endfunction "}}}
function! SelectLispExpression() "{{{
    execute "normal v\<Plug>(sexp_inner_element)"
endfunction "}}}

function! HyperspecLispExpression(vertical) "{{{
    let z = @z

    call SelectLispExpression()
    normal! gv"zy

    if a:vertical
        vnew
    else
        new
    endif

    set buftype=nofile

    call termopen('clhs ' . @z)

    normal! i

    let @z = z
endfunction "}}}

function! SendToplevelLispForm() "{{{
    let view = winsaveview()

    call SelectToplevelLispForm()
    call NeoReplSendSelection()

    call winrestview(view)
endfunction "}}}
function! IndentToplevelLispForm() "{{{
    let view = winsaveview()

    call SelectToplevelLispForm()
    execute "normal! gv="

    call winrestview(view)
endfunction "}}}

function! DisassembleLispSymbol() "{{{
    let old_z = @z

    normal! "zyiw
    call NeoReplSendRaw("(disassemble '" . @z . ")\n")

    let @z = old_z
endfunction "}}}

function! DuplicateLispForm() " {{{
    let old_z = @z

    " save our position
    normal! mz

    " yank the form into the z register and paste it out
    execute "normal v\<Plug>(sexp_outer_list)"
    normal! "zy
    normal! "zP

    " select the thing we just pasted, move to the right of it and insert the
    " line break
    execute "normal v\<Plug>(sexp_outer_list)\<esc>"
    execute "normal! a\<cr>\<esc>"

    " fix indentation
    call IndentToplevelLispForm()

    " jump back to our previous position and move to the next form,
    " to get to the correct final place
    normal! `z
    call SexpForward()

    let @z = old_z
endfunction " }}}

function! QuickloadLispSystem() " {{{
    let systems = split(system('ls -1 *.asd | grep -v test | cut -d. -f1 | uniq')) " its fine
    if len(systems) == 0
        echom "Could not find any .asd files..."
        return
    elseif len(systems) > 1
        echom "Found too many any .asd files..."
        return
    endif

    call NeoReplSendRaw("(ql:quickload :" . systems[0] . ")\n")
endfunction " }}}
function! QuickloadLispPrompt() " {{{
    call NeoReplSendRaw("(ql:quickload :" . input("? ") . ")\n")
endfunction " }}}

" }}}
" Folding {{{
let g:lisp_fold_extra = [ 
            \ 'macrolet>',
            \ 'test>',
            \ 'eval-when>',
            \ 'eval-dammit>',
            \ 'scratch>',
            \
            \ 'declaim',
            \
            \ 'macro-map'
            \ ]
" }}}

augroup ft_commonlisp " {{{
    au!

    au BufNewFile,BufRead *.asd,*.ros set filetype=lisp
    au BufNewFile,BufRead *.paren set filetype=lisp
    au BufNewFile,BufRead .abclrc set filetype=lisp
    au BufNewFile,BufRead .lisprc set filetype=lisp
    au BufNewFile,BufRead stumpwmrc set filetype=lisp
    au BufNewFile,BufRead .stumpwmrc set filetype=lisp
    au BufNewFile,BufRead .stumpwmrc.local set filetype=lisp

    au FileType lisp nnoremap <buffer> U :syntax sync fromstart<cr>:redraw!<cr>:call TurnOnLispFolding()<cr>

    au FileType lisp call SetLispWords()
    au FileType lisp call EnableParedit()
    au FileType lisp silent! call TurnOnLispFolding()

    au FileType lisp RainbowParenthesesActivate
    au syntax lisp RainbowParenthesesLoadRound

    " Force omnicompletion (vlime's)
    au FileType lisp inoremap <c-n> <c-x><c-o>

    " lol, vim ignores indentexpr if lisp is set
    " au FileType lisp setlocal nolisp
    au FileType lisp setlocal iskeyword+=!,?,%,-

    " stay with lispindent for now
    au FileType lisp setlocal lisp
    au FileType lisp setlocal equalprg=lispindent

    " Fix windows
    au FileType lisp nnoremap <buffer> <localleader>W <c-w>j<c-w>J<c-w>k<c-w>H

    " scratch buffer
    au FileType lisp nnoremap <buffer> <leader><tab> :e scratch.lisp<cr>

    " Open REPLs
    au FileType lisp nnoremap <buffer> <silent> <localleader>Os :call OpenLispReplSBCL()<cr>
    au FileType lisp nnoremap <buffer> <silent> <localleader>Oc :call OpenLispReplCCL()<cr>
    au FileType lisp nnoremap <buffer> <silent> <localleader>Oe :call OpenLispReplECL()<cr>
    au FileType lisp nnoremap <buffer> <silent> <localleader>Oa :call OpenLispReplABCL()<cr>
    au FileType lisp nnoremap <buffer> <silent> <localleader>Ors :call OpenLispReplSBCLRaw()<cr>

    " Misc mappings
    " au FileType lisp nnoremap <buffer> gi :call IndentToplevelLispForm()<cr>
    au FileType lisp nnoremap <buffer> <localleader>h :call HyperspecLispExpression(0)<cr>
    au FileType lisp nnoremap <buffer> <localleader>H :call HyperspecLispExpression(1)<cr>
    au FileType lisp nnoremap <buffer> <silent> <localleader>q :call QuickloadLispSystem()<cr>
    au FileType lisp nnoremap <buffer> <silent> <localleader>Q :call QuickloadLispPrompt()<cr>
    au FileType lisp nnoremap <buffer> [] :call DuplicateLispForm()<cr>
    au FileType lisp nnoremap <buffer> <localleader>( :call PareditToggle()<cr>
    ")
    au FileType lisp inoremap <buffer> <c-s> <c-o>:call vlime#plugin#SendToREPL(vlime#ui#CurTopExpr())<cr>

    " Navigate trees of sexps with arrows
    au FileType lisp call s:vim_sexp_mappings()
    au FileType lisp noremap <buffer> <left>  :<c-u>call SexpBack()<cr>
    au FileType lisp noremap <buffer> <right> :<c-u>call SexpForward()<cr>
    au FileType lisp noremap <buffer> <up>    :<c-u>call SexpUp()<cr>
    au FileType lisp noremap <buffer> <down>  :<c-u>call SexpDown()<cr>

    " Writing
    au FileType lisp noremap <buffer> <localleader>=  I; => <esc>
augroup END " }}}

" }}}
" Cram {{{

let cram_fold=1

augroup ft_cram
    au!

    au BufNewFile,BufRead *.t set filetype=cram
    au Syntax cram setlocal foldlevel=1
    au FileType cram nnoremap <buffer> <localleader>ee :e<cr>
augroup END

" }}}
" CSS and LessCSS {{{

augroup ft_css
    au!

    au BufNewFile,BufRead *.less setlocal filetype=less

    au Filetype less,css setlocal foldmethod=marker
    au Filetype less,css setlocal foldmarker={,}
    au Filetype less,css setlocal omnifunc=csscomplete#CompleteCSS
    au Filetype less,css setlocal iskeyword+=-

    " Use <localleader>S to sort properties.  Turns this:
    "
    "     p {
    "         width: 200px;
    "         height: 100px;
    "         background: red;
    "
    "         ...
    "     }
    "
    " into this:

    "     p {
    "         background: red;
    "         height: 100px;
    "         width: 200px;
    "
    "         ...
    "     }
    au BufNewFile,BufRead *.less,*.css nnoremap <buffer> <localleader>S ?{<CR>jV/\v^\s*\}?$<CR>k:sort<CR>:noh<CR>

    " Make {<cr> insert a pair of brackets in such a way that the cursor is correctly
    " positioned inside of them AND the following code doesn't get unfolded.
    au BufNewFile,BufRead *.less,*.css inoremap <buffer> {<cr> {}<left><cr><space><space><space><space>.<cr><esc>kA<bs>
augroup END

" }}}
" Diff {{{

" This is from https://github.com/sgeb/vim-diff-fold/ without the extra
" settings crap.  Just the folding expr.

function! DiffFoldLevel()
    let l:line=getline(v:lnum)

    if l:line =~# '^\(diff\|Index\)'     " file
        return '>1'
    elseif l:line =~# '^\(@@\|\d\)'  " hunk
        return '>2'
    elseif l:line =~# '^\*\*\* \d\+,\d\+ \*\*\*\*$' " context: file1
        return '>2'
    elseif l:line =~# '^--- \d\+,\d\+ ----$'     " context: file2
        return '>2'
    else
        return '='
    endif
endfunction

augroup ft_diff
    au!

    autocmd FileType diff setlocal foldmethod=expr
    autocmd FileType diff setlocal foldexpr=DiffFoldLevel()
augroup END

" }}}
" Django {{{

augroup ft_django
    au!

    au BufNewFile,BufRead urls.py           setlocal nowrap
    au BufNewFile,BufRead urls.py           normal! zR
    au BufNewFile,BufRead dashboard.py      normal! zR
    au BufNewFile,BufRead local_settings.py normal! zR

    au BufNewFile,BufRead admin.py     setlocal filetype=python.django
    au BufNewFile,BufRead urls.py      setlocal filetype=python.django
    au BufNewFile,BufRead models.py    setlocal filetype=python.django
    au BufNewFile,BufRead views.py     setlocal filetype=python.django
    au BufNewFile,BufRead settings.py  setlocal filetype=python.django
    au BufNewFile,BufRead settings.py  setlocal foldmethod=marker
    au BufNewFile,BufRead forms.py     setlocal filetype=python.django
    au BufNewFile,BufRead common_settings.py  setlocal filetype=python.django
    au BufNewFile,BufRead common_settings.py  setlocal foldmethod=marker
augroup END

" }}}
" DTrace {{{

augroup ft_dtrace
    au!

    autocmd BufNewFile,BufRead *.d set filetype=dtrace
augroup END

" }}}
" EQ {{{

augroup ft_eq
    au!

    autocmd BufNewFile,BufRead eqlog_*.txt set filetype=eq

    vnoremap <localleader>d ::w !~/src/dotfiles/bin/eq-dotcount<cr>
augroup END

" }}}
" Firefox {{{

augroup ft_firefox
    au!
    au BufRead,BufNewFile ~/Library/Caches/*.html setlocal buftype=nofile
augroup END

" }}}
" Fish {{{

function! SendFishParagraph() "{{{
    call SelectAndSendToNeoRepl("vip", 1)
endfunction "}}}

augroup ft_fish
    au!

    au BufNewFile,BufRead *.fish setlocal filetype=fish

    au FileType fish setlocal foldmethod=marker foldmarker={{{,}}}
    au FileType fish nnoremap <buffer> <localleader>e :call NeoReplSendCurrentLine()<cr>
    au FileType fish nnoremap <buffer> <localleader>E :call SendFishParagraph()<cr>
    au FileType fish nnoremap <buffer> <localleader>F :call NeoReplSendEntireFile(1)<cr>
    au FileType fish nnoremap <buffer> <localleader>c :call NeoReplSendRaw("clear")<cr>
augroup END

" }}}
" Git {{{

augroup ft_git
    au!

    au FileType gitcommit nnoremap <buffer> <localleader>j /On branch sjl<cr>f/l"zyt/gg0P:nohl<cr>$a <esc>a
augroup END

" }}}
" gnuplot {{{

function! OpenGnuplotRepl() "{{{
    NeoRepl gnuplot
    set syntax=gnuplot
    " syn match replPrompt /\v^\*/
    " hi def link replPrompt SpecialChar

    " syn match replResult /\v^#\<[^>]+\>$/
    " hi def link replResult Debug
endfunction "}}}

function! SendGNUPlotParagraph() "{{{
    call SelectAndSendToNeoRepl("^vip")
endfunction "}}}
function! SendGNUPlotBuffer() "{{{
    call SelectAndSendToNeoRepl("ggVG")
endfunction "}}}

augroup ft_gnuplot
    au!

    au BufNewFile,BufRead *.gp,.gnuplot setlocal filetype=gnuplot

    au FileType gnuplot nnoremap <buffer> <silent> <localleader>o :call OpenGnuplotRepl()<cr>

    au FileType gnuplot nnoremap <buffer> <silent> <localleader>e :call SendGNUPlotParagraph()<cr>

    au FileType gnuplot setlocal foldmethod=marker foldmarker={{{,}}}
augroup END

" }}}
" Go {{{

function! GetGoFold(lnum)
    let line = getline(a:lnum)
    let prev = getline(a:lnum-1)
    let next = getline(a:lnum+1)

    " Toplevel folds.
    if line =~# '\v^//'
        " Toplevel comments.
        if prev =~# '\v^//'
            return '1'
        else
            return '>1'
        endif
    elseif line =~# '\v^\S.*[{(`]$'
        " Things that open a toplevel block, e.g.:
        "     func foo () {
        return '>1'
    elseif line =~#'\v^[})`]$'
        " The close of a toplevel block, e.g.:
        "     }
        " This doesn't close the fold because we want to fold the space after it
        " later.
        return '1'
    elseif line == "" && next =~#'\v^//'
        " Blank line before a comment.  If the previous line is a comment, fold
        " it with that.  Otherwise don't fold it.  Example:
        "
        "     func x () {
        "             …
        "     }
        "                                         don't fold this one
        "     // foo ---------------------
        "                                         but DO fold this one into the header comment
        "     // some doc comment
        "     // with lines
        "     func y () …
        if prev =~#'\v^//'
            return '1'
        else
            return '0'
        endif
    elseif line == "" && prev =~#'\v^[})]$'
        " Blank line after the close of a toplevel block.  Fold it with the
        " block.
        return '<1'
    elseif line =~# '\v^\S'
        " Some other toplevel line, e.g.:
        "     import ...
        return '0'
    endif

    " Inner folds.
    if line =~# '\v^\s+//'
        " Inner comment.
        let p = prev =~# '\v^\s+//'
        let n = next =~# '\v^\s+//'
        if !n && !p
            " Single line comment, don't make a new fold.
            return '='
        elseif n && p
            " Middle of a multi-line comment, fold.
            return '2'
        elseif !p
            " Start of a multi-line comment.
            return '>2'
        elseif !n
            " End of a multi-line comment.
            return '<2'
        endif
    endif

    " Otherwise fold with previous.
    return '='
endfunction

func Eatchar(pat)
    let c = nr2char(getchar(0))
    return (c =~ a:pat) ? '' : c
endfunc

augroup ft_go
    au!

    au BufRead,BufNewFile go.mod set ft=go

    au FileType go setlocal shiftwidth=8
    au FileType go setlocal foldmethod=expr
    au FileType go setlocal foldexpr=GetGoFold(v:lnum)
    au FileType go nnoremap <buffer> <silent> M :GoDoc<cr>
    au FileType go nnoremap <buffer> <localleader>t :GoInfo<cr>
    au FileType go nnoremap <buffer> <localleader>h :GoDocBrowser<cr>
    au FileType go nnoremap <buffer> <localleader>c :GoBuild<cr>
    au FileType go nnoremap <buffer> <localleader>xc :GoCallers<cr>

    au FileType go inoremap <c-n> <c-x><c-o>

    " this language is incredible
    au FileType go iabbrev <buffer> enil if err != nil
    au FileType go iabbrev <buffer> rete return err
    au FileType go iabbrev <buffer> retne return nil, err
    au FileType go iabbrev <buffer> retse return "", err
    au FileType go iabbrev <buffer> retze return "", err

    au FileType go iabbrev <buffer> enilre if err != nil {<cr>return err<down>
    au FileType go iabbrev <buffer> enilrn if err != nil {<cr>return nil, err<down>
    au FileType go iabbrev <buffer> enilrs if err != nil {<cr>return "", err<down>
    au FileType go iabbrev <buffer> enilrz if err != nil {<cr>return 0, err<down>

    au FileType gohtmltmpl setlocal shiftwidth=4
augroup END

" }}}
" hgrc {{{

augroup ft_hgrc
    au!

    " s/hsl/ghs/
    au BufReadPost,BufNewFile hgrc nnoremap <buffer> <localleader>g yypciwgit<esc>wwcwghs<esc>f/f/asjl/<esc>A.git<esc>
augroup END

" }}}
" HTML, Django, Jinja, Dram, Go, Kill Me {{{

let g:html_indent_tags = ['p', 'li']

augroup ft_html
    au!

    au BufNewFile,BufRead *.html setlocal filetype=gohtmltmpl
    au BufNewFile,BufRead *.dram setlocal filetype=htmldjango

    au FileType html,jinja,htmldjango,gohtmltmpl setlocal foldmethod=manual

    " Use <localleader>f to fold the current tag.
    au FileType html,jinja,htmldjango,gohtmltmpl nnoremap <buffer> <localleader>f Vatzf

    " Use <localleader>t to fold the current templatetag.
    au FileType html,jinja,htmldjango nmap <buffer> <localleader>t viikojozf

    " Indent tag
    au FileType html,jinja,htmldjango,gohtmltmpl nnoremap <buffer> <localleader>= Vat=

    " Django tags
    au FileType jinja,htmldjango inoremap <buffer> <c-t> {%<space><space>%}<left><left><left>

    " Django variables
    au FileType jinja,htmldjango inoremap <buffer> <c-b> {{<space><space>}}<left><left><left>
augroup END

" }}}
" Java {{{

augroup ft_java
    au!

    au FileType java setlocal foldmethod=marker
    au FileType java setlocal foldmarker={,}
    au FileType java inoremap <c-n> <c-x><c-]>
augroup END

" }}}
" Javascript {{{

augroup ft_javascript
    au!

    au FileType javascript setlocal foldmethod=marker
    au FileType javascript setlocal foldmarker={,}

    " Make {<cr> insert a pair of brackets in such a way that the cursor is correctly
    " positioned inside of them AND the following code doesn't get unfolded.
    au Filetype javascript inoremap <buffer> {<cr> {}<left><cr><space><space><space><space>.<cr><esc>kA<bs>
    " }

    " Prettify a hunk of JSON with <localleader>p
    au FileType javascript nnoremap <buffer> <localleader>p ^vg_:!python -m json.tool<cr>
    au FileType javascript vnoremap <buffer> <localleader>p :!python -m json.tool<cr>
augroup END

" }}}
" JSON {{{

augroup ft_json
    au!

    au FileType json setlocal sw=4
augroup END

" }}}
" Latex {{{

let g:tex_flavor = 'latex'

augroup ft_latex
    au!

    au Filetype tex inoremap <buffer> <c-b> \begin{}<left>
    au Filetype tex nnoremap <buffer> <localleader>q :%s/[‘’]/'/<cr>
augroup END

" }}}
" Mail {{{

augroup ft_mail
    au!

    au Filetype mail setlocal spell
    au FileType mail setlocal textwidth=72
augroup END

" }}}
" Makefile {{{

augroup ft_make
    au!

    au Filetype make setlocal shiftwidth=8
    au Filetype make setlocal foldmethod=marker foldmarker={{{,}}}
augroup END

" }}}
" Makerlisp {{{

function! HighlightMakerlispRepl() "{{{
    setlocal nolist

    " set syntax=lisp
    syn match replPrompt /\v^\>/
    syn match replComment /\v^;.*/

    " syn match replResult /\v^#\<[^>]+\>$/
    hi def link replResult Debug
    hi def link replComment Comment
endfunction "}}}

function! OpenLispReplMakerlispRaw() "{{{
    NeoRepl makerlisp-raw
    call HighlightMakerlispRepl()
endfunction "}}}

augroup ft_makerlisp " {{{
    au!

    au BufNewFile,BufRead *.l set filetype=makerlisp
    au FileType makerlisp setlocal syntax=lisp sw=2

    au FileType makerlisp nnoremap <buffer> U :syntax sync fromstart<cr>:redraw!<cr>:call TurnOnLispFolding()<cr>
    au FileType makerlisp call SetLispWords()
    au FileType makerlisp call EnableParedit()
    au FileType makerlisp silent! call TurnOnLispFolding()
    au FileType makerlisp RainbowParenthesesActivate
    au FileType makerlisp setlocal iskeyword+=!,?,%,-
    au FileType makerlisp setlocal lisp
    au FileType makerlisp setlocal equalprg=lispindent

    " Open REPL
    au FileType makerlisp nnoremap <buffer> <silent> <localleader>Om :call OpenLispReplMakerlispRaw()<cr>

    " Misc mappings
    au FileType makerlisp nnoremap <buffer> gi :call IndentToplevelLispForm()<cr>
    au FileType makerlisp nnoremap <buffer> [] :call DuplicateLispForm()<cr>
    au FileType makerlisp nnoremap <buffer> <localleader>( :call PareditToggle()<cr>

    au FileType makerlisp nnoremap <buffer> <localleader>e :call SendToplevelLispForm()<cr>
    au FileType makerlisp nnoremap <buffer> <localleader>f :call NeoReplSendEntireFile()<cr>
    au FileType makerlisp nnoremap <buffer> <localleader>c :call NeoReplSendRaw("(cls)")<cr>

    ")
augroup END " }}}

" }}}
" Markdown {{{

augroup ft_markdown
    au!

    au BufNewFile,BufRead *.m*down setlocal filetype=markdown foldlevel=1

    au Filetype markdown setlocal spell

    " Linkify selected text inline to contents of pasteboard.
    au Filetype markdown vnoremap <buffer> <localleader>l <esc>`>a]<esc>`<i[<esc>`>lla()<esc>"+P

    " Use <localleader>1/2/3 to add headings.
    " au Filetype markdown nnoremap <buffer> <localleader>1 yypVr=:redraw<cr>
    " au Filetype markdown nnoremap <buffer> <localleader>2 yypVr-:redraw<cr>
    au Filetype markdown nnoremap <buffer> <localleader>1 mzI#<space><esc>`zll
    au Filetype markdown nnoremap <buffer> <localleader>2 mzI##<space><esc>`zlll
    au Filetype markdown nnoremap <buffer> <localleader>3 mzI###<space><esc>`zllll
    au Filetype markdown nnoremap <buffer> <localleader>4 mzI####<space><esc>`zlllll

    au Filetype markdown inoremap <buffer> <c-cr> <cr><esc>mz?^ *\*?e<cr>"zy0:noh<cr>`z"zpA* <esc>a
    au Filetype markdown inoremap <buffer> <s-c-cr> <cr><esc>mz?^ *\*?e<cr>"zy0:noh<cr>`z"zpA  * <esc>a
    au Filetype markdown inoremap <buffer> <s-tab> <esc>mz0xx`za
    au Filetype markdown inoremap <buffer> <c-tab> <esc>mzI  <esc>`zlla
augroup END

" }}}
" Martian {{{

augroup ft_martian
    au!

    au Filetype markdown inoremap <buffer> <c-n> <c-x><c-n>
augroup END

" }}}
" Mercurial {{{

augroup ft_mercurial
    au!

    au BufNewFile,BufRead *hg-editor-*.txt setlocal filetype=hgcommit
augroup END

" }}}
" Mutt {{{

augroup ft_muttrc
    au!

    au BufRead,BufNewFile *.muttrc set ft=muttrc

    au FileType muttrc setlocal foldmethod=marker foldmarker={{{,}}}
augroup END

" }}}
" NextFlow {{{

augroup ft_nextflow
    au!

    " au BufRead,BufNewFile *.nf set ft=groovy
augroup END

" }}}
" Nginx {{{

augroup ft_nginx
    au!

    au BufRead,BufNewFile nginx.conf                             set ft=nginx
    au BufRead,BufNewFile *.nginx.conf                           set ft=nginx

    au FileType nginx setlocal foldmethod=marker foldmarker={,}
augroup END

" }}}
" .plan {{{

function! PlanLinkPaste()
    execute "normal! gg}}O[]: \<esc>\"*p0"
    normal! a
endfunction

augroup ft_plan
    au!

    " au BufNewFile,BufRead ~/.plan/README.markdown nnoremap <buffer> <localleader>l :call PlanLinkPaste()<cr>
    au BufNewFile,BufRead *.markdown nnoremap <buffer> <localleader>d o##<esc>:r!date +\%Y-\%m-\%d<cr>kJ
augroup END

" }}}
" Postgresql {{{

augroup ft_postgres
    au!

    au BufNewFile,BufRead *.sql set filetype=pgsql
    au BufNewFile,BufRead *.pgsql set filetype=pgsql

    au FileType pgsql set foldmethod=marker foldmarker=\ $$,$$\ 
    au FileType pgsql set softtabstop=4 shiftwidth=4
    au FileType pgsql setlocal commentstring=--\ %s comments=:--

    " Set up some basic neorepl mappings.
    "
    " key  desc                   mnemonic
    " \o - connect neorepl        [o]pen repl
    " \l - send current line      [l]ine
    " \e - send current hunk      [e]val
    " \f - send entire file       [r]eload file
    " \c - send ctrl-l            [c]lear

    au FileType pgsql nnoremap <buffer> <silent> <localleader>o :call NeoReplOpenFish()<cr>
    au FileType pgsql nnoremap <buffer> <silent> <localleader>l :call NeoReplSendCurrentLine()<cr>
    au FileType pgsql nnoremap <buffer> <silent> <localleader>e :call NeoReplSendParagraph()<cr>
    au FileType pgsql nnoremap <buffer> <silent> <localleader>f :call NeoReplSendEntireFile()<cr>
    au FileType pgsql nnoremap <buffer> <silent> <localleader>c :call NeoReplSendRaw("")<cr>
    au FileType pgsql nnoremap <buffer> <silent> <localleader>q :call NeoReplSendRaw("q")<cr>
augroup END

" }}}
" Prolog {{{

augroup ft_prolog
    au!

    au BufNewFile,BufRead *.pl set filetype=prolog
augroup END

" }}}
" Python {{{

" Helper Functions {{{
let g:current_python_lsp_client = 0

function! PythonLSPConnect() "{{{
    if g:current_python_lsp_client == 0
        lua vim.lsp.start_client({cmd={"nc", "127.0.0.1", "9898"}})
        " TODO lol
        let g:current_python_lsp_client = 1
    endif
endfunction "}}}

function! PythonLSPAttach() "{{{
    call PythonLSPConnect()
    lua vim.lsp.buf_attach_client(0, 1)
    call PythonLSPMappings()
endfunction "}}}

function! PythonLSPSig() "{{{
    lua vim.lsp.buf.signature_help()
    return ""
endfunction "}}}

function! PythonLSPMappings() "{{{
    setlocal omnifunc=v:lua.vim.lsp.omnifunc
    inoremap <buffer> <c-n>    <c-x><c-o>
    nnoremap <buffer> <c-]>    :lua vim.lsp.buf.definition()<cr>
    nnoremap <buffer> M        :lua vim.lsp.buf.hover()<cr>
    inoremap <buffer> <c-m>    <c-r>=PythonLSPSig()<cr>
endfunction "}}}

" }}}

augroup ft_python
    au!

    au FileType python setlocal define=^\s*\\(def\\\\|class\\)
    au FileType python setlocal textwidth=88

    " Jesus tapdancing Christ, built-in Python syntax, you couldn't let me
    " override this in a normal way, could you?
    au FileType python if exists("python_space_error_highlight") | unlet python_space_error_highlight | endif

    au FileType python nnoremap <buffer> gi :Neoformat black<cr>zx

    au FileType python nnoremap <buffer> <localleader>cc :call PythonLSPAttach()<cr>
augroup END

" }}}
" QuickFix {{{

augroup ft_quickfix
    au!
    au Filetype qf setlocal colorcolumn=0 nolist nocursorline nowrap tw=0

    " vimscript is a joke
    au Filetype qf nnoremap <buffer> <cr> :execute "normal! \<lt>cr>"<cr>
augroup END

" }}}
" R {{{

let R_external_term = 'st -t "R REPL" --'
let R_args = ['--no-save', '--quiet']
let R_save_win_pos = 0
let R_arrange_windows = 0
let R_assign = 0
let R_clear_line = 1
let R_nvim_wd = 1
let R_user_maps_only = 1
let R_nvimpager = 'vertical'
let R_help_w = 81
let r_indent_ess_comments = 0
let r_indent_ess_compatible = 0
let r_indent_align_args = 0

function! s:customNvimRMappings()
   " Normal Mode
    nmap <buffer> <localleader>Or <Plug>RStart
    nmap <buffer> <localleader>Cr <Plug>RClose
    nmap <buffer> <localleader>c  <Plug>RClearConsole
    nmap <buffer> <localleader>h  <Plug>RHelp
    nmap <buffer> M               <Plug>RShowArgs
    nmap <buffer> <localleader>e  <Plug>RSendParagraph
    nmap <buffer> <localleader>w  mzviw<Plug>RSendSelection<esc>'z
    nmap <buffer> <localleader>W  mzviW<Plug>RSendSelection<esc>'z
    nmap <buffer> <localleader>S  <Plug>RSendLine
    nmap <buffer> <localleader>E  <Plug>RSendLine
    nmap <buffer> <localleader>f  <Plug>RSendFile
    nmap <buffer> <localleader>i  <Plug>RViewDFv
    nmap <buffer> <localleader>I  <Plug>RViewDFs
    nmap <buffer> gi              mzvip:Rformat<cr>'z

    inoremap <buffer> <c-n> <c-x><c-o>

    " Insert Mode
    inoremap <buffer> <c-.> <esc>A \|><cr>
    inoremap <buffer> <c-,> <-<space>
    inoremap <buffer> <c-'> <esc>A +<cr>

    " Visual Mode
    vmap <buffer> <localleader>e  <Plug>RSendSelection
    vmap <buffer> gi              :Rformat<cr>
endfunction

augroup ft_r
    au!

    autocmd filetype r setlocal shiftwidth=2
    autocmd filetype r call s:customNvimRMappings()
augroup END

" }}}
" Sh {{{

function! SendShellParagraph() "{{{
    call SelectAndSendToNeoRepl("vip", 1)
endfunction "}}}

augroup ft_sh
    au!

    au FileType sh nnoremap <buffer> <localleader>e :call NeoReplSendCurrentLine()<cr>
    au FileType sh nnoremap <buffer> <localleader>E :call SendShellParagraph()<cr>
    au FileType sh nnoremap <buffer> <localleader>F :call NeoReplSendEntireFile(1)<cr>
    au FileType sh nnoremap <buffer> <localleader>C :call NeoReplSendRaw("clear")<cr>
    au FileType sh nnoremap <buffer> <localleader>c :ShellCheck!<cr>
augroup END

" }}}
" Standard In {{{

augroup ft_stdin
    au!

    " Treat buffers from stdin (e.g.: echo foo | vim -) as scratch.
    au StdinReadPost * :set buftype=nofile
augroup END

" }}}
" Terminal {{{

augroup ft_terminal
    au!
    au TermOpen * setlocal scrolloff=0
augroup END

" }}}
" Terraform {{{

augroup ft_terraform
    au!

    au FileType terraform setlocal foldmethod=syntax
augroup END

" }}}
" Vagrant {{{

augroup ft_vagrant
    au!
    au BufRead,BufNewFile Vagrantfile set ft=ruby
augroup END

" }}}
" Vim {{{

augroup ft_vim
    au!

    au FileType vim setlocal foldmethod=marker keywordprg=:help
    au FileType help setlocal textwidth=78
    au BufWinEnter *.txt if &ft == 'help' | wincmd L | endif

    au FileType vim vnoremap <localleader>S y:@"<CR>
    au FileType vim nnoremap <localleader>S ^vg_y:execute @@<cr>:echo 'Sourced line.'<cr>

    au FileType vim inoremap <buffer> <c-n> <c-x><c-n>
augroup END

" }}}
" YAML {{{

augroup ft_yaml
    au!

    au FileType yaml set shiftwidth=2
augroup END

" }}}
" XML {{{

augroup ft_xml
    au!

    au FileType xml setlocal foldmethod=manual

    " Use <localleader>f to fold the current tag.
    au FileType xml nnoremap <buffer> <localleader>f Vatzf

    " Indent tag
    au FileType xml nnoremap <buffer> <localleader>= Vat=
augroup END

" }}}

" }}}
" Plugin settings --------------------------------------------------------- {{{

" Ack {{{

nnoremap <leader>a :Ack!<space>
let g:ackprg = 'ag --smart-case --nogroup --nocolor --column'

" }}}
" Boxdraw {{{

vmap <space> +O
vmap -. +>
vmap -, +<
vmap -6 +^
vmap -v +v
vmap -> ++>
vmap -< ++<
vmap -^ ++^
vmap -V ++v
vmap -- +-

" }}}
" Clam {{{

nnoremap ! :Clam<space>
vnoremap ! :ClamVisual<space>
let g:clam_autoreturn = 1
let g:clam_debug = 1
let g:clam_winwidth = 84

" }}}
" Commentary {{{

nmap <leader>c <Plug>CommentaryLine
xmap <leader>c <Plug>Commentary
nmap <leader>C gcip

augroup plugin_commentary
    au!
    au FileType htmldjango setlocal commentstring={#\ %s\ #}
    au FileType clojurescript setlocal commentstring=;\ %s
    au FileType lisp setlocal commentstring=;;\ %s
    au FileType makerlisp setlocal commentstring=;;\ %s
    au FileType puppet setlocal commentstring=#\ %s
    au FileType snakemake setlocal commentstring=#\ %s
    au FileType nginx setlocal commentstring=#\ %s
    au FileType fish setlocal commentstring=#\ %s
    au FileType gnuplot setlocal commentstring=#\ %s
    au FileType cs setlocal commentstring=//\ %s
    au FileType arduino setlocal commentstring=//\ %s
    au FileType pandabt setlocal commentstring=//\ %s
    au FileType nextflow setlocal commentstring=//\ %s
augroup END

" }}}
" Ctrl-P {{{

let g:ctrlp_dont_split = 'NERD_tree_2'
let g:ctrlp_jump_to_buffer = 0
let g:ctrlp_working_path_mode = 0
let g:ctrlp_match_window_reversed = 1
let g:ctrlp_split_window = 0
let g:ctrlp_max_height = 20
let g:ctrlp_extensions = ['tag']

let g:ctrlp_map = '<leader>,'
nnoremap <leader>. :CtrlPTag<cr>
nnoremap <leader>b :CtrlPBuffer<cr>
nnoremap <leader><lt> :CtrlP<space>

let g:ctrlp_prompt_mappings = {
\ 'PrtSelectMove("j")':   ['<c-j>', '<down>', '<s-tab>'],
\ 'PrtSelectMove("k")':   ['<c-k>', '<up>', '<tab>'],
\ 'PrtHistory(-1)':       ['<c-n>'],
\ 'PrtHistory(1)':        ['<c-p>'],
\ 'ToggleFocus()':        ['<c-tab>'],
\ }

let my_ctrlp_ffind_command = "ffind --semi-restricted --dir %s --type e -B -f"
let g:ctrlp_user_command = my_ctrlp_ffind_command

" }}}
" DelimitMate {{{

let delimitMate_excluded_ft = "clojure,lisp,makerlisp"
let delimitMate_expand_cr = 1

" }}}
" Fugitive {{{

nnoremap <leader>gd :Gdiff<cr>
nnoremap <leader>gs :Gstatus<cr>:15wincmd_<cr>:setlocal winfixheight<cr>
nnoremap <leader>gw :Gwrite<cr>
nnoremap <leader>ga :Gadd<cr>
nnoremap <leader>gb :Gblame<cr>
nnoremap <leader>gco :Gcheckout<cr>
nnoremap <leader>gci :Gcommit<cr>
nnoremap <leader>gm :Gmove<cr>
nnoremap <leader>gr :Gremove<cr>
nnoremap <leader>gpo :!git push origin<cr>
nnoremap <leader>gpu :!git push upstream<cr>
nnoremap <leader>gl :Clam git gll -100 \| stripcolor<cr>


augroup ft_fugitive
    au!

    au BufRead */.git/index setlocal nolist

    " tpope is back on his bullshit
    au FileType fugitive if expand('%:p') =~# '.*/.git/index' | nnoremap <buffer> K :q<cr> | endif
augroup END

" "Hub"
vnoremap <leader>H :Gbrowse<cr>
nnoremap <leader>H V:Gbrowse<cr>

" }}}
" Go {{{

let g:go_fmt_command = "gofmt"
let g:go_fmt_options = {
    \ 'gofmt': '-s',
    \ 'goimports': '',
    \ }
let g:go_fmt_experimental = 1
let g:go_fmt_autosave = 1
let g:go_imports_autosave = 1
let g:go_doc_keywordprg_enabled = 0
let g:go_def_mode = "godef"

let g:go_diagnostics_enabled = 0
let g:go_highlight_diagnostic_errors = 0
let g:go_highlight_diagnostic_warnings = 0

" }}}
" Gundo {{{

nnoremap <F5> :GundoToggle<CR>

let g:gundo_debug = 1
let g:gundo_preview_bottom = 1
let g:gundo_tree_statusline = "Gundo"
let g:gundo_preview_statusline = "Gundo Preview"

" }}}
" HTML5 {{{

let g:event_handler_attributes_complete = 0
let g:rdfa_attributes_complete = 0
let g:microdata_attributes_complete = 0
let g:atia_attributes_complete = 0

" }}}
" MiniYank {{{

" map p <Plug>(miniyank-autoput)
" map P <Plug>(miniyank-autoPut)
" nmap gp <Plug>(miniyank-cycle)
" nnoremap gP g-

" }}}
" NeoFormat {{{

nnoremap <f6> :Neoformat<cr>

let g:neoformat_snakemake_snakefmt = {
        \ 'exe': '/home/sjl/virtualenvs/snakemake/bin/snakefmt',
        \ 'args': [],
        \ 'replace': 1,
        \ 'stdin': 0,
        \ 'valid_exit_codes': [0]
        \ }

let g:neoformat_enabled_snakemake = ['snakefmt']

" }}}
" NeoRepl {{{

function! SelectAndSendToNeoRepl(selectionString, ...) "{{{
    let ignoreBlankLines = a:0 >= 1 ? a:1 : 0

    let view = winsaveview()

    execute "normal! " . a:selectionString . "\<esc>"
    call NeoReplSendSelection(ignoreBlankLines)

    call winrestview(view)
endfunction "}}}

function! NeoReplSendEntireFile(...) "{{{
    let ignoreBlankLines = a:0 >= 1 ? a:1 : 0

    call SelectAndSendToNeoRepl("ggVG", ignoreBlankLines)
endfunction "}}}

function! NeoReplSendCurrentLine() "{{{
    call SelectAndSendToNeoRepl("^vg_")
endfunction "}}}

function! NeoReplSendParagraph() "{{{
    call SelectAndSendToNeoRepl("^Vip")
endfunction "}}}

function! NeoReplOpenFish() "{{{
    NeoRepl fish
endfunction "}}}

" }}}
" NERD Tree {{{

noremap  <F2> :NERDTreeToggle<cr>
inoremap <F2> <esc>:NERDTreeToggle<cr>
noremap  <F14> :NERDTreeFind<cr>
inoremap <F14> <esc>:NERDTreeFind<cr>
noremap  <S-F2> :NERDTreeFind<cr>
inoremap <S-F2> <esc>:NERDTreeFind<cr>

augroup ps_nerdtree
    au!

    au Filetype nerdtree setlocal nolist
    au Filetype nerdtree nnoremap <buffer> H :vertical resize -10<cr>
    au Filetype nerdtree nnoremap <buffer> L :vertical resize +10<cr>
    " au Filetype nerdtree nnoremap <buffer> K :q<cr>
augroup END

let NERDTreeHighlightCursorline = 1
let NERDTreeIgnore = ['\~$', '.*\.pyc$', 'pip-log\.txt$', 'whoosh_index',
                    \ 'xapian_index', '.*.pid', 'monitor.py', '.*-fixtures-.*.json',
                    \ '.*\.o$', 'db.db', 'tags.bak', '.*\.pdf$', '.*\.mid$',
                    \ '^tags$',
                    \ '^.*\.meta$',
                    \ '^.*\.fasl$',
                    \ '^.*\.dx64fsl$',
                    \ '^.*\.lx64fsl$',
                    \ '.*\.bcf$', '.*\.blg$', '.*\.fdb_latexmk$', '.*\.bbl$', '.*\.aux$', '.*\.run.xml$', '.*\.fls$',
                    \ '.*\.midi$']

let NERDTreeMinimalUI = 1
let NERDTreeDirArrows = 1
let NERDChristmasTree = 1
let NERDTreeChDirMode = 2
let NERDTreeMapJumpFirstChild = 'gK'
let g:NERDTreeMinimalMenu = 1

" }}}
" Paredit {{{

let g:paredit_smartjump = 1
let g:paredit_shortmaps = 0
let g:paredit_electric_return = 0
let g:paredit_matchlines = 200

let g:paredit_disable_lisp = 1
let g:paredit_disable_clojure = 1

function! EnableParedit()
    call PareditInitBuffer()

    " Quit fucking with my split-line mapping, paredit.
    nunmap <buffer> S

    " Also quit fucking with my save file mapping.
    nunmap <buffer> s

    " Please just stop
    nunmap <buffer> <leader>W
    nunmap <buffer> <leader>O
    nunmap <buffer> <leader>S

    " Oh my god will you fuck off already
    " nnoremap <buffer> dp :diffput<cr>
    " nnoremap <buffer> do :diffobtain<cr>

    " Eat shit
    nunmap <buffer> [[
    nunmap <buffer> ]]

    " Better mappings
    noremap <buffer> () :<c-u>call PareditWrap("(", ")")<cr>
    noremap <buffer> )( :<c-u>call PareditSplice()<cr>
    noremap <buffer> (( :<c-u>call PareditMoveLeft()<cr>
    noremap <buffer> )) :<c-u>call PareditMoveRight()<cr>
    noremap <buffer> (j :<c-u>call PareditJoin()<cr>
    noremap <buffer> (s :<c-u>call PareditSplit()<cr>
    noremap <buffer> )j :<c-u>call PareditJoin()<cr>
    noremap <buffer> )s :<c-u>call PareditSplit()<cr>
    " ))
endfunction

" }}}
" Python-Mode {{{

let g:pymode_doc = 1
let g:pymode_doc_bind = 'M'
let g:pydoc = 'pydoc'
let g:pymode_syntax = 1
let g:pymode_syntax_all = 0
let g:pymode_syntax_builtin_objs = 1
let g:pymode_syntax_print_as_function = 0
let g:pymode_syntax_space_errors = 0
let g:pymode_run = 0
let g:pymode_lint = 0
let g:pymode_breakpoint = 0
let g:pymode_utils_whitespaces = 0
let g:pymode_virtualenv = 0
let g:pymode_folding = 0

let g:pymode_options_indent = 0
let g:pymode_options_fold = 0
let g:pymode_options_other = 0
let g:pymode_options = 0

let g:pymode_rope = 0
let g:pymode_rope_global_prefix = "<localleader>R"
let g:pymode_rope_local_prefix = "<localleader>r"
let g:pymode_rope_auto_project = 1
let g:pymode_rope_enable_autoimport = 0
let g:pymode_rope_autoimport_generate = 1
let g:pymode_rope_autoimport_underlineds = 0
let g:pymode_rope_codeassist_maxfixes = 10
let g:pymode_rope_sorted_completions = 1
let g:pymode_rope_extended_complete = 1
let g:pymode_rope_autoimport_modules = ["os", "shutil", "datetime"]
let g:pymode_rope_confirm_saving = 1
let g:pymode_rope_vim_completion = 1
let g:pymode_rope_guess_project = 1
let g:pymode_rope_goto_def_newwin = 0
let g:pymode_rope_always_show_complete_menu = 0

" }}}
" Rainbow Parentheses {{{

let g:rbpt_max = 1

" }}}
" Scratch {{{

command! ScratchToggle call ScratchToggle()

function! ScratchToggle()
    if exists("w:is_scratch_window")
        unlet w:is_scratch_window
        exec "q"
    else
        exec "normal! :Sscratch\<cr>\<C-W>L"
        let w:is_scratch_window = 1
    endif
endfunction

nnoremap <silent> <leader><tab> :ScratchToggle<cr>

" }}}
" Secure Modelines {{{

let g:secure_modelines_allowed_items = [
            \ "textwidth",   "tw",
            \ "foldmethod",  "fdm",
            \ "foldnextmax",  "fdn",
            \ "lispwords",  "lw",
            \ ]

" }}}
" Sexp {{{

function! s:vim_sexp_mappings() " {{{
    xmap <silent><buffer>   af   <Plug>(sexp_outer_list)
    omap <silent><buffer>   af   <Plug>(sexp_outer_list)
    xmap <silent><buffer>   if   <Plug>(sexp_inner_list)
    omap <silent><buffer>   if   <Plug>(sexp_inner_list)
    xmap <silent><buffer>   aF   <Plug>(sexp_outer_top_list)
    omap <silent><buffer>   aF   <Plug>(sexp_outer_top_list)
    xmap <silent><buffer>   iF   <Plug>(sexp_inner_top_list)
    omap <silent><buffer>   iF   <Plug>(sexp_inner_top_list)
    xmap <silent><buffer>   as   <Plug>(sexp_outer_string)
    omap <silent><buffer>   as   <Plug>(sexp_outer_string)
    xmap <silent><buffer>   is   <Plug>(sexp_inner_string)
    omap <silent><buffer>   is   <Plug>(sexp_inner_string)
    xmap <silent><buffer>   ae   <Plug>(sexp_outer_element)
    omap <silent><buffer>   ae   <Plug>(sexp_outer_element)
    xmap <silent><buffer>   ie   <Plug>(sexp_inner_element)
    omap <silent><buffer>   ie   <Plug>(sexp_inner_element)

    nmap <silent><buffer>   [[   <Plug>(sexp_swap_element_backward)
    xmap <silent><buffer>   [[   <Plug>(sexp_swap_element_backward)
    nmap <silent><buffer>   ]]   <Plug>(sexp_swap_element_forward)
    xmap <silent><buffer>   ]]   <Plug>(sexp_swap_element_forward)

    nmap <silent><buffer>   {    <Plug>(sexp_move_to_prev_top_element)
    xmap <silent><buffer>   {    <Plug>(sexp_move_to_prev_top_element)
    omap <silent><buffer>   {    <Plug>(sexp_move_to_prev_top_element)
    nmap <silent><buffer>   }    <Plug>(sexp_move_to_next_top_element)
    xmap <silent><buffer>   }    <Plug>(sexp_move_to_next_top_element)
    omap <silent><buffer>   }    <Plug>(sexp_move_to_next_top_element)

    " nmap <silent><buffer> (               <Plug>(sexp_move_to_prev_bracket)
    " xmap <silent><buffer> (               <Plug>(sexp_move_to_prev_bracket)
    " omap <silent><buffer> (               <Plug>(sexp_move_to_prev_bracket)
    " nmap <silent><buffer> )               <Plug>(sexp_move_to_next_bracket)
    " xmap <silent><buffer> )               <Plug>(sexp_move_to_next_bracket)
    " omap <silent><buffer> )               <Plug>(sexp_move_to_next_bracket)
    " nmap <silent><buffer> <M-b>           <Plug>(sexp_move_to_prev_element_head)
    " xmap <silent><buffer> <M-b>           <Plug>(sexp_move_to_prev_element_head)
    " omap <silent><buffer> <M-b>           <Plug>(sexp_move_to_prev_element_head)
    " nmap <silent><buffer> <M-w>           <Plug>(sexp_move_to_next_element_head)
    " xmap <silent><buffer> <M-w>           <Plug>(sexp_move_to_next_element_head)
    " omap <silent><buffer> <M-w>           <Plug>(sexp_move_to_next_element_head)
    " nmap <silent><buffer> g<M-e>          <Plug>(sexp_move_to_prev_element_tail)
    " xmap <silent><buffer> g<M-e>          <Plug>(sexp_move_to_prev_element_tail)
    " omap <silent><buffer> g<M-e>          <Plug>(sexp_move_to_prev_element_tail)
    " nmap <silent><buffer> <M-e>           <Plug>(sexp_move_to_next_element_tail)
    " xmap <silent><buffer> <M-e>           <Plug>(sexp_move_to_next_element_tail)
    " omap <silent><buffer> <M-e>           <Plug>(sexp_move_to_next_element_tail)
    " nmap <silent><buffer> [[              <Plug>(sexp_move_to_prev_top_element)
    " xmap <silent><buffer> [[              <Plug>(sexp_move_to_prev_top_element)
    " omap <silent><buffer> [[              <Plug>(sexp_move_to_prev_top_element)
    " nmap <silent><buffer> ]]              <Plug>(sexp_move_to_next_top_element)
    " xmap <silent><buffer> ]]              <Plug>(sexp_move_to_next_top_element)
    " omap <silent><buffer> ]]              <Plug>(sexp_move_to_next_top_element)
    " nmap <silent><buffer> [e              <Plug>(sexp_select_prev_element)
    " xmap <silent><buffer> [e              <Plug>(sexp_select_prev_element)
    " omap <silent><buffer> [e              <Plug>(sexp_select_prev_element)
    " nmap <silent><buffer> ]e              <Plug>(sexp_select_next_element)
    " xmap <silent><buffer> ]e              <Plug>(sexp_select_next_element)
    " omap <silent><buffer> ]e              <Plug>(sexp_select_next_element)
    " nmap <silent><buffer> ==              <Plug>(sexp_indent)
    " nmap <silent><buffer> =-              <Plug>(sexp_indent_top)
    " nmap <silent><buffer> <LocalLeader>i  <Plug>(sexp_round_head_wrap_list)
    " xmap <silent><buffer> <LocalLeader>i  <Plug>(sexp_round_head_wrap_list)
    " nmap <silent><buffer> <LocalLeader>I  <Plug>(sexp_round_tail_wrap_list)
    " xmap <silent><buffer> <LocalLeader>I  <Plug>(sexp_round_tail_wrap_list)
    " nmap <silent><buffer> <LocalLeader>[  <Plug>(sexp_square_head_wrap_list)
    " xmap <silent><buffer> <LocalLeader>[  <Plug>(sexp_square_head_wrap_list)
    " nmap <silent><buffer> <LocalLeader>]  <Plug>(sexp_square_tail_wrap_list)
    " xmap <silent><buffer> <LocalLeader>]  <Plug>(sexp_square_tail_wrap_list)
    " nmap <silent><buffer> <LocalLeader>{  <Plug>(sexp_curly_head_wrap_list)
    " xmap <silent><buffer> <LocalLeader>{  <Plug>(sexp_curly_head_wrap_list)
    " nmap <silent><buffer> <LocalLeader>}  <Plug>(sexp_curly_tail_wrap_list)
    " xmap <silent><buffer> <LocalLeader>}  <Plug>(sexp_curly_tail_wrap_list)
    " nmap <silent><buffer> <LocalLeader>w  <Plug>(sexp_round_head_wrap_element)
    " xmap <silent><buffer> <LocalLeader>w  <Plug>(sexp_round_head_wrap_element)
    " nmap <silent><buffer> <LocalLeader>W  <Plug>(sexp_round_tail_wrap_element)
    " xmap <silent><buffer> <LocalLeader>W  <Plug>(sexp_round_tail_wrap_element)
    " nmap <silent><buffer> <LocalLeader>e[ <Plug>(sexp_square_head_wrap_element)
    " xmap <silent><buffer> <LocalLeader>e[ <Plug>(sexp_square_head_wrap_element)
    " nmap <silent><buffer> <LocalLeader>e] <Plug>(sexp_square_tail_wrap_element)
    " xmap <silent><buffer> <LocalLeader>e] <Plug>(sexp_square_tail_wrap_element)
    " nmap <silent><buffer> <LocalLeader>e{ <Plug>(sexp_curly_head_wrap_element)
    " xmap <silent><buffer> <LocalLeader>e{ <Plug>(sexp_curly_head_wrap_element)
    " nmap <silent><buffer> <LocalLeader>e} <Plug>(sexp_curly_tail_wrap_element)
    " xmap <silent><buffer> <LocalLeader>e} <Plug>(sexp_curly_tail_wrap_element)
    " nmap <silent><buffer> <LocalLeader>h  <Plug>(sexp_insert_at_list_head)
    " nmap <silent><buffer> <LocalLeader>l  <Plug>(sexp_insert_at_list_tail)
    " nmap <silent><buffer> <LocalLeader>@  <Plug>(sexp_splice_list)
    " nmap <silent><buffer> <LocalLeader>o  <Plug>(sexp_raise_list)
    " xmap <silent><buffer> <LocalLeader>o  <Plug>(sexp_raise_list)
    " nmap <silent><buffer> <LocalLeader>O  <Plug>(sexp_raise_element)
    " xmap <silent><buffer> <LocalLeader>O  <Plug>(sexp_raise_element)
    " nmap <silent><buffer> <M-k>           <Plug>(sexp_swap_list_backward)
    " xmap <silent><buffer> <M-k>           <Plug>(sexp_swap_list_backward)
    " nmap <silent><buffer> <M-j>           <Plug>(sexp_swap_list_forward)
    " xmap <silent><buffer> <M-j>           <Plug>(sexp_swap_list_forward)
    " nmap <silent><buffer> <M-S-j>         <Plug>(sexp_emit_head_element)
    " xmap <silent><buffer> <M-S-j>         <Plug>(sexp_emit_head_element)
    " nmap <silent><buffer> <M-S-k>         <Plug>(sexp_emit_tail_element)
    " xmap <silent><buffer> <M-S-k>         <Plug>(sexp_emit_tail_element)
    " nmap <silent><buffer> <M-S-h>         <Plug>(sexp_capture_prev_element)
    " xmap <silent><buffer> <M-S-h>         <Plug>(sexp_capture_prev_element)
    " nmap <silent><buffer> <M-S-l>         <Plug>(sexp_capture_next_element)
    " xmap <silent><buffer> <M-S-l>         <Plug>(sexp_capture_next_element)
    " imap <silent><buffer> <BS>            <Plug>(sexp_insert_backspace)
    " imap <silent><buffer> "               <Plug>(sexp_insert_double_quote)
    " imap <silent><buffer> (               <Plug>(sexp_insert_opening_round)
    " imap <silent><buffer> )               <Plug>(sexp_insert_closing_round)
    " imap <silent><buffer> [               <Plug>(sexp_insert_opening_square)
    " imap <silent><buffer> ]               <Plug>(sexp_insert_closing_square)
    " imap <silent><buffer> {               <Plug>(sexp_insert_opening_curly)
    " imap <silent><buffer> }               <Plug>(sexp_insert_closing_curly)
endfunction " }}}

let g:sexp_filetypes = ''
let g:sexp_mappings = {}
let g:sexp_insert_after_wrap = 0
let g:sexp_enable_insert_mode_mappings = 0

" wew lads
function! SexpUp()
    execute "normal \<Plug>(sexp_move_to_prev_bracket)"
    execute "normal! v"
    execute "normal \<Plug>(sexp_inner_element)"
    execute "normal! o\<esc>"
endfunction

function! SexpDown()
    execute "normal! v"
    execute "normal \<Plug>(sexp_inner_element)"
    execute "normal! \<esc>v"
    execute "normal \<Plug>(sexp_inner_list)"
    execute "normal! o\<esc>"
endfunction

function! SexpForward()
    execute "normal \<Plug>(sexp_move_to_next_element_head)"
endfunction

function! SexpBack()
    execute "normal \<Plug>(sexp_move_to_prev_element_head)"
endfunction

" }}}
" Splice {{{

let g:splice_prefix = "-"

let g:splice_initial_mode = "grid"

let g:splice_initial_layout_grid = 0
let g:splice_initial_layout_loupe = 0
let g:splice_initial_layout_compare = 0
let g:splice_initial_layout_path = 0

let g:splice_initial_diff_grid = 1
let g:splice_initial_diff_loupe = 0
let g:splice_initial_diff_compare = 1
let g:splice_initial_diff_path = 0

let g:splice_initial_scrollbind_grid = 0
let g:splice_initial_scrollbind_loupe = 0
let g:splice_initial_scrollbind_compare = 0
let g:splice_initial_scrollbind_path = 0

let g:splice_wrap = "nowrap"

" }}}
" Targets {{{

let g:targets_pairs = '()b {}B []r <>'

" }}}
" Ultisnips {{{

let g:UltiSnipsExpandTrigger       = '<Tab>'
let g:UltiSnipsJumpForwardTrigger  = '<Tab>'
let g:UltiSnipsJumpBackwardTrigger = '<S-Tab>'

let g:UltiSnipsSnippetDirectories=[$HOME.'/.vim/ultisnips-bullshit']

" }}}
" Vlime {{{


" \ "xref": {
"     \ "pos": "float",
"     \ "size": 5,
"     \ "vertical": v:false
" \ },
let g:vlime_window_settings = {
        \ "sldb": {
            \ "pos": "belowright",
            \ "vertical": v:false
        \ },
        \ "xref": {
            \ "pos": "belowright",
            \ "vertical": v:false
        \ },
        \ "repl": {
            \ "pos": "belowright",
            \ "vertical": v:false
        \ },
        \ "inspector": {
            \ "pos": "belowright",
            \ "vertical": v:false
        \ },
        \ "arglist": {
            \ "pos": "topleft",
            \ "size": 2,
            \ "vertical": v:false
        \ }
    \ }

let g:vlime_compiler_policy = {
            \ "DEBUG": 2,
            \ "SAFETY": 3,
            \ "SPEED": 1
            \ }

let g:vlime_contribs = [
            \ "SWANK-ASDF",
            \ "SWANK-PACKAGE-FU",
            \ "SWANK-PRESENTATIONS",
            \ "SWANK-FANCY-INSPECTOR",
            \ "SWANK-C-P-C",
            \ "SWANK-ARGLISTS",
            \ "SWANK-REPL",
            \ "SWANK-FUZZY",
            \ "SWANK-TRACE-DIALOG"
            \ ]

" let g:vlime_indent_keywords = {"defsystem": 1}

function! CleanVlimeWindows()
    call vlime#plugin#CloseWindow("preview")
    call vlime#plugin#CloseWindow("notes")
    call vlime#plugin#CloseWindow("xref")
    wincmd =
endfunction

function! MapVlimeKeys()
    nnoremap <silent> <buffer> <c-]> :call vlime#plugin#FindDefinition(vlime#ui#CurAtom())<cr>
    nnoremap <silent> <buffer> -     :call CleanVlimeWindows()<cr>
endfunction

augroup CustomVlimeInputBuffer
    autocmd!
    " autocmd FileType vlime_input inoremap <silent> <buffer> <tab> <c-r>=VlimeKey("tab")<cr>
    "
    autocmd FileType vlime_input setlocal omnifunc=vlime#plugin#CompleteFunc
    autocmd FileType vlime_input setlocal indentexpr=vlime#plugin#CalcCurIndent()
    autocmd FileType vlime_input inoremap <c-n> <c-x><c-o>
augroup end

augroup LocalVlime
    autocmd!

    " Settings
    au FileType vlime_sldb setlocal nowrap foldmethod=indent shiftwidth=8 tabstop=8
    au FileType vlime_repl setlocal nowrap winfixheight

    " Keys for Lisp files
    au FileType lisp nnoremap <buffer> <localleader>e :call vlime#plugin#Compile(vlime#ui#CurTopExpr(v:true))<cr>
    au FileType lisp nnoremap <buffer> <localleader>f :w<cr>:call vlime#plugin#CompileFile(expand("%:p"))<cr>
    au FileType lisp nnoremap <buffer> <localleader>S :call vlime#plugin#SendToREPL(vlime#ui#CurTopExpr())<cr>
    au FileType lisp nnoremap <buffer> <localleader>i :call vlime#plugin#Inspect(vlime#ui#CurExprOrAtom())<cr>
    au FileType lisp nnoremap <buffer> <nowait> <localleader>I :call vlime#plugin#Inspect()<cr>
    au FileType lisp nnoremap <buffer> M :call vlime#plugin#DocumentationSymbol(vlime#ui#CurAtom())<cr>
    au FileType lisp nnoremap <buffer> gi :call IndentToplevelLispForm()<cr>
    au FileType lisp vnoremap <buffer> gi =
    au FileType lisp setlocal indentexpr=vlime#plugin#CalcCurIndent()

    " Keys for the REPL
    au FileType vlime_repl      nnoremap <buffer> i :call vlime#ui#repl#InspectCurREPLPresentation()<cr>
    au FileType vlime_repl      nnoremap <buffer> <2-LeftMouse> :call vlime#ui#repl#InspectCurREPLPresentation()<cr>

    " Keys for the Inspector
    au FileType vlime_inspector nnoremap <buffer> <2-LeftMouse> :call vlime#ui#inspector#InspectorSelect()<cr>

    " Keys for the Preview
    au FileType vlime_preview nnoremap <buffer> <localleader>p :call vlime#plugin#SetPackage()<cr>
    au FileType vlime_preview nnoremap <buffer> <localleader>m1 :call vlime#plugin#ExpandMacro(vlime#ui#CurExpr(), "one")<cr>

    " Universal keys, for all kinds of Vlime windows
    au FileType lisp,vlime_repl,vlime_inspector,vlime_sldb,vlime_notes,vlime_xref,vlime_preview call MapVlimeKeys()

    " Fix <cr>
    au FileType lisp            inoremap <buffer> <cr> <cr><c-r>=vlime#plugin#VlimeKey("cr")<cr>
    au FileType vlime_xref      nnoremap <buffer> <cr> :call vlime#ui#xref#OpenCurXref()<cr>
    au FileType vlime_notes     nnoremap <buffer> <cr> :call vlime#ui#compiler_notes#OpenCurNote()<cr>
    au FileType vlime_sldb      nnoremap <buffer> <cr> :call vlime#ui#sldb#ChooseCurRestart()<cr>
    au FileType vlime_inspector nnoremap <buffer> <cr> :call vlime#ui#inspector#InspectorSelect()<cr>

    " Fix d
    au FileType vlime_sldb      nnoremap <buffer> <nowait> d :call vlime#ui#sldb#ShowFrameDetails()<cr>

    " Fix s
    au FileType vlime_sldb      nnoremap <buffer> <nowait> s :call vlime#ui#sldb#StepCurOrLastFrame("step")<cr>

    " Fix p
    au FileType vlime_inspector nnoremap <buffer> p :call vlime#ui#inspector#InspectorPop()<cr>
augroup end

" }}}
" Windowswap {{{

let g:windowswap_map_keys = 0 "prevent default bindings
nnoremap <silent> <c-w><c-w> :call WindowSwap#EasyWindowSwap()<CR>

" }}}

" }}}
" Mini-plugins ------------------------------------------------------------ {{{
" Stuff that should probably be broken out into plugins, but hasn't proved to be
" worth the time to do so just yet.

" HTTP Statuses {{{

function! HTTPStatuses()
    call termopen('w3m /home/sjl/Dropbox/docs/httpstatuses/httpstatuses.com/index.html')
endfunc

command! HTTPStatuses call HTTPStatuses()

" }}}
" Synstack {{{

" Show the stack of syntax hilighting classes affecting whatever is under the
" cursor.
function! SynStack()
  echo join(map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")'), " > ")
endfunc

nnoremap <F7> :call SynStack()<CR>

" }}}
" Diffwhite Toggle {{{

set diffopt-=iwhite
let g:diffwhitespaceon = 0
function! ToggleDiffWhitespace()
    if g:diffwhitespaceon
        set diffopt-=iwhite
        let g:diffwhitespaceon = 0
    else
        set diffopt+=iwhite
        let g:diffwhitespaceon = 1
    endif
    diffupdate
endfunc

" TODO: Figure out the diffexpr shit necessary to make this buffer-local.
" nnoremap <leader>W :call ToggleDiffWhitespace()<CR>

" }}}
" Virtualedit Toggle {{{

set virtualedit=block
let g:virtualeditallon = 0

function! ToggleVirtualEdit()
    if g:virtualeditallon
        set virtualedit=block
        let g:virtualeditallon = 0
    else
        set virtualedit=all
        let g:virtualeditallon = 1
    endif
endfunc

nnoremap <leader>V :call ToggleVirtualEdit()<cr>

" }}}
" Error Toggles {{{

command! ErrorsToggle call ErrorsToggle()
function! ErrorsToggle() " {{{
  if exists("w:is_error_window")
    unlet w:is_error_window
    exec "q"
  else
    exec "Errors"
    lopen
    let w:is_error_window = 1
  endif
endfunction " }}}

command! LocationToggle call LocationToggle()
function! LocationToggle() " {{{
  if exists("w:is_location_window")
    unlet w:is_location_window
    exec "q"
  else
    lopen
    let w:is_location_window = 1
  endif
endfunction " }}}

command! -bang -nargs=? QFixToggle call QFixToggle(<bang>0)
function! QFixToggle(forced) " {{{
  if exists("g:qfix_win") && a:forced == 0
    cclose
    unlet g:qfix_win
  else
    copen 10
    let g:qfix_win = bufnr("$")
  endif
endfunction " }}}

" nmap <silent> <f3> :ErrorsToggle<cr>
nmap <silent> <f4> :QFixToggle<cr>
nmap <silent> <f3> :LocationToggle<cr>

" }}}
" Hg (Mercurial) {{{
"
" \hc - hg commit
" \hd - hg diff
" \hs - hg status
"
" \hpd - hg push default
" \hpu - hg push upstream
" \hpg - hg push git
" \hpp - push everything lol
"
" \hB - hg blame (current file)
" \hD - hg diff (current file)
"
" \h<space> - raw hg commands

nnoremap <leader>hc :!hg commit<cr>

nnoremap <leader>hpd :!hg push default<cr>
nnoremap <leader>hpu :!hg push upstream<cr>
nnoremap <leader>hpg :!hg push git<cr>
nnoremap <leader>hpa :!hg paths -q \| xargs -n1 hg push<cr>

function! s:HgDiff() " {{{
    diffthis

    let fn = expand('%:p')
    let ft = &ft

    wincmd v
    edit __hgdiff_orig__

    setlocal buftype=nofile

    normal ggdG
    execute "silent r!hg cat --rev . " . fn
    normal ggdd

    execute "setlocal ft=" . ft

    diffthis
    diffupdate
endfunction " }}}
command! -nargs=0 HgDiff call s:HgDiff()

" Diff the current file
nnoremap <leader>hD :HgDiff<cr>

" Diff the entire repo
nnoremap <leader>hd :wa<cr>:Clam hg diff<cr>:set ft=diff nowrap foldlevel=1<cr>gg

function! s:HgBlame() " {{{
    let fn = expand('%:p')

    wincmd v
    wincmd h
    edit __hgblame__
    vertical resize 28

    setlocal scrollbind winfixwidth nolist nowrap nonumber buftype=nofile ft=none

    normal ggdG
    execute "silent r!hg blame -undq " . fn
    normal ggdd
    execute ':%s/\v:.*$//'

    wincmd l
    setlocal scrollbind
    syncbind
endfunction " }}}
command! -nargs=0 HgBlame call s:HgBlame()
nnoremap <leader>hB :HgBlame<cr>

function! s:HgStatus() " {{{
    Clam hg status
endfunction " }}}
command! -nargs=0 HgStatus call s:HgStatus()
nnoremap <leader>hs :HgStatus<cr>

" Bare hg commands
nnoremap <leader>h<space> :!hg<space>

" }}}
" Ack motions {{{

" Motions to Ack for things.  Works with pretty much everything, including:
"
"   w, W, e, E, b, B, t*, f*, i*, a*, and custom text objects
"
" Awesome.
"
" Note: If the text covered by a motion contains a newline it won't work.  Ack
" searches line-by-line.

nnoremap <silent> <leader>A :set opfunc=<SID>AckMotion<CR>g@
xnoremap <silent> <bs> :<C-U>call <SID>AckMotion(visualmode())<CR>

" nnoremap <leader>A :Ack! '\b<c-r><c-w>\b'<cr>
" nnoremap <bs> :Ack! '\b<c-r><c-w>\b'<cr>

" With C-R C-W, according to the help: "With CTRL-W the part of the word that
" was already typed is not inserted again."  Because we're using \b to ack for
" word boundaries, the command string looks like `:Ack! '\b` at this point, and
" so if the word we're on happens to start with a lowercase b (e.g. "bonkers")
" it will be skipped, and we'll end up with `:Ack! '\bonkers` and find nothing.
" It took me a good long time to notice this one.  Computers are total fucking
" garbage.
nnoremap <bs> viw:<C-U>call <SID>AckMotion(visualmode())<CR>

function! s:CopyMotionForType(type)
    if a:type ==# 'v'
        silent execute "normal! `<" . a:type . "`>y"
    elseif a:type ==# 'char'
        silent execute "normal! `[v`]y"
    endif
endfunction

function! s:AckMotion(type) abort
    let reg_save = @@

    call s:CopyMotionForType(a:type)

    execute "normal! :Ack! --literal " . shellescape(@@) . "\<cr>"

    let @@ = reg_save
endfunction

" }}}
" Pulse Line {{{

function! s:Pulse() " {{{
    redir => old_hi
        silent execute 'hi CursorLine'
    redir END
    let old_hi = split(old_hi, '\n')[0]
    let old_hi = substitute(old_hi, 'xxx', '', '')

    let steps = 8
    let width = 1
    let start = width
    let end = steps * width
    let color = 233

    for i in range(start, end, width)
        execute "hi CursorLine ctermbg=" . (color + i)
        redraw
        sleep 6m
    endfor
    for i in range(end, start, -1 * width)
        execute "hi CursorLine ctermbg=" . (color + i)
        redraw
        sleep 6m
    endfor

    execute 'hi ' . old_hi
endfunction " }}}

command! -nargs=0 Pulse call s:Pulse()

" }}}
" Highlight Word {{{
"
" This mini-plugin provides a few mappings for highlighting words temporarily.
"
" Sometimes you're looking at a hairy piece of code and would like a certain
" word or two to stand out temporarily.  You can search for it, but that only
" gives you one color of highlighting.  Now you can use <leader>N where N is
" a number from 1-6 to highlight the current word in a specific color.

function! HiInterestingWord(n) " {{{
    " Save our location.
    normal! mz

    " Yank the current word into the z register.
    normal! "zyiw

    " Calculate an arbitrary match ID.  Hopefully nothing else is using it.
    let mid = 86750 + a:n

    " Clear existing matches, but don't worry if they don't exist.
    silent! call matchdelete(mid)

    " Construct a literal pattern that has to match at boundaries.
    let pat = '\V\<' . escape(@z, '\') . '\>'

    " Actually match the words.
    call matchadd("InterestingWord" . a:n, pat, 1, mid)

    " Move back to our original location.
    normal! `z
endfunction " }}}

" Mappings {{{

nnoremap <silent> <leader>1 :call HiInterestingWord(1)<cr>
nnoremap <silent> <leader>2 :call HiInterestingWord(2)<cr>
nnoremap <silent> <leader>3 :call HiInterestingWord(3)<cr>
nnoremap <silent> <leader>4 :call HiInterestingWord(4)<cr>
nnoremap <silent> <leader>5 :call HiInterestingWord(5)<cr>
nnoremap <silent> <leader>6 :call HiInterestingWord(6)<cr>

" }}}
" Default Highlights {{{

hi def InterestingWord1 guifg=#000000 ctermfg=16 guibg=#ffa724 ctermbg=214
hi def InterestingWord2 guifg=#000000 ctermfg=16 guibg=#aeee00 ctermbg=154
hi def InterestingWord3 guifg=#000000 ctermfg=16 guibg=#8cffba ctermbg=121
hi def InterestingWord4 guifg=#000000 ctermfg=16 guibg=#b88853 ctermbg=137
hi def InterestingWord5 guifg=#000000 ctermfg=16 guibg=#ff9eb8 ctermbg=211
hi def InterestingWord6 guifg=#000000 ctermfg=16 guibg=#ff2c4b ctermbg=195

" }}}

" }}}
" MS to UTC {{{

function! MS2UTC(ms)
    let seconds = strpart(a:ms, 0, strlen(a:ms) - 3)
    return substitute(system("date -ur " . seconds), "\n\n*", "", "")
endfunction

function! MS2UTCWord()
    return MS2UTC(expand("<cword>"))
endfunction

function! ReplaceMS2UTCWord()
    let res = MS2UTC(expand("<cword>"))
    execute 'normal! ciw"' . res . '"'
endfunction

" nnoremap <leader>U :echo MS2UTCWord()<cr>
nnoremap <leader>U :call ReplaceMS2UTCWord()<cr>

" }}}

" }}}
" Environments (GUI/Console) ---------------------------------------------- {{{

if has('gui_running')
    " GUI Vim
else
    " Mouse support
    set mouse=a
endif

" }}}
" Neovim ------------------------------------------------------------------ {{{

if has('nvim')
    tnoremap <Esc> <C-\><C-n>
    tnoremap <leader><esc> <esc>
    " nnoremap <bs> <c-w>h
    let g:terminal_scrollback_buffer_size = 10000
    let $NVIM_TUI_ENABLE_CURSOR_SHAPE=1
    set inccommand=nosplit

    let g:terminal_color_0 = '#070807'
    let g:terminal_color_1 = '#e93f40'
    let g:terminal_color_2 = '#88dc02'
    let g:terminal_color_3 = '#fb7d01'
    let g:terminal_color_4 = '#0abcfe'
    let g:terminal_color_5 = '#fe5691'
    let g:terminal_color_6 = '#76dff3'
    let g:terminal_color_7 = '#f4f4f4'
    let g:terminal_color_8 = '#5d5d5d'
    let g:terminal_color_9 = '#e93f40'
    let g:terminal_color_10 = '#9df903'
    let g:terminal_color_11 = '#fadf31'
    let g:terminal_color_12 = '#40cdfe'
    let g:terminal_color_13 = '#fe2b74'
    let g:terminal_color_14 = '#09cef2'
    let g:terminal_color_15 = '#fefffe'
else
    set encoding=utf-8
endif

source ~/.vimrc_local

" }}}