" Tom Ryder (tejr)’s Literate Vimrc
" =================================
"
" Last updated: Thu, 27 Jun 2019 00:23:17 +0000
"
" │ And I was lifted up in heart, and thought
" │ Of all my late-shown prowess in the lists,
" │ How my strong lance had beaten down the knights,
" │ So many and famous names; and never yet
" │ Had heaven appeared so blue, nor earth so green,
" │ For all my blood danced in me, and I knew
" │ That I should light upon the Holy Grail.
" │
" │ —Tennyson
"
" This is an attempt at something like a “literate vimrc”, in the tradition of
" Donald Knuth’s “literate programming”: <http://www.literateprogramming.com/>
"
" The dotfiles project containing this file is maintained here:
" <https://sanctum.geek.nz/cgit/dotfiles.git>
"
" This is a long file, and comments abound within. Should this be bothersome,
" one could execute this command in Vim itself to strip out all lines either
" blank or comprising solely comments:
"
" :g/\m^$\|^\s*"/d
"
" This file should be saved as ‘vimrc’—no leading period—in the user runtime
" directory. On Unix-like operating systems, hereinafter referred to as
" “*nix”, that directory is ‘~/.vim’; on Windows, it’s ‘~/vimfiles’.
" Fortunately, those are the only two kinds of operating systems that exist,
" anywhere in the world.
"
" It requires Vim 7.0 or newer, with the +eval feature, and the 'compatible'
" option turned off, chiefly to allow line continuations. The vimrc stub at
" ~/.vimrc (Unix) or ~/_vimrc (Windows) should check that these conditions are
" met before loading this file with ‘:runtime vimrc’.
"
" All of this should survive a pass of the Vim script linter Vint with no
" errors, warnings, or style problems: <https://github.com/Kuniwak/vint>
"
" We’ll begin by making sure we’re all speaking the same language. Since it’s
" been the future for a few years now, this file has characters outside the
" ASCII character set, which prompts Vint to suggest declaring the file
" encoding with a :scriptencoding command. The :help for that command
" specifies that this should be done after 'encoding' is set, so we’ll do that
" here, too.
"
" On *nix, I keep the primary locale environment variable $LANG defined, and
" it almost always specifies a multibyte locale. This informs Vim’s choice of
" internal character encoding, but the default for the 'encoding' option in
" the absence of a valid $LANG is ‘latin1’. Since this is almost never what
" I want, we’ll manually choose the UTF-8 encoding for Unicode in the absence
" of any other explicit specification.
"
if &encoding ==# 'latin1' && !exists('$LANG')
set encoding=utf-8
endif
scriptencoding utf-8
" With encoding handled, we’ll turn our attention to the value of the
" 'runtimepath' option, since any scripts loaded from the paths specified
" therein control so much of the behaviour of Vim.
"
" Working with 'runtimepath' and other options set with comma-separated
" strings is error-prone, whether the strings are paths or not. In
" particular, splitting the list is surprisingly complicated, as revealed by
" the tokenizer function copy_option_part in src/misc2.c in Vim’s source code.
" This awkwardness is largely because commas within each list item need to be
" escaped with backslashes, but backslashes themselves are not. To make it
" even more complicated, each separating comma may be followed by any number
" of spaces, or more commas, that will be ignored. This means that you can
" have a path starting with spaces or commas as the first value in the list,
" but not any of the following values. Worse, there’s no way to escape
" leading whitespace characters to prevent them being skipped; backslashes
" don’t work, because they only escape commas in this context. Read the
" source code if you don’t believe me. Vim, I love you, but you are really
" weird.
"
" In an effort to abstract this away a bit, we’ll define a script-local
" function that can split such values into their constituent parts. The
" pattern required for the split() breaks down like this:
"
" \\ ← Literal backslash
" \@<! ← Negative lookbehind assertion; means that whatever occurred
" before this pattern—in this case, a backslash—cannot precede what
" follows, but anything that does precede it is not removed from
" the data as part of the split delimiter
" , ← Literal comma
" [, ]* ← Any number of commas and spaces
"
" Once we have the individual elements, we have to remove the escaping for
" periods, specifically remove up to one backslash before all periods. We do
" that with a map() over substitute(), string-eval style, to accommodate older
" Vim before Funcref variables were added. As explained above, we don’t need
" to unescape backslashes themselves, as one might expect.
"
function! s:OptionSplit(expr, ...) abort
if a:0 > 1
echoerr 'Too many arguments'
endif
let [expr, keepempty] = [a:expr, a:0 ? a:1 : 0]
return map(
\ split(expr, '\\\@<!,[, ]*', keepempty),
\ 'substitute(v:val, ''\\,'', '','', ''g'')',
\)
endfunction
" The next problem will be how we add values to the list correctly and safely.
" We create a second script-local function that does the two rounds of
" escaping necessary for a string that can be used in an :execute wrapper over
" a :set command string.
function! s:EscItemExec(item) abort
let [item] = [a:item]
return escape(escape(item, ','), '\ %#|"')
endfunction
if exists('$MYVIM')
execute 'set runtimepath^='.s:EscItemExec($MYVIM)
elseif strlen(&runtimepath) > 0
let s:runtimepath = s:OptionSplit(&runtimepath)
let $MYVIM = s:runtimepath[0]
endif
function! s:Mkpath(path) abort
let [path] = [a:path]
return isdirectory(path)
\ || exists('*mkdir') && mkdir(path)
endfunction
let s:cache = $MYVIM.'/cache'
call s:Mkpath(s:cache)
let &viminfo .= ',n'.s:cache.'/viminfo'
set backup
let s:backupdir = s:cache.'/backup'
call s:Mkpath(s:backupdir)
execute 'set backupdir^='.s:EscItemExec(
\ s:backupdir.(has('patch-8.1.251') ? '//' : ''),
\)
if has('unix')
if !has('patch-8.1.1519')
set backupskip&
endif
set backupskip^=/dev/shm/*,/usr/tmp/*,/var/tmp/*
endif
let s:directory = s:cache.'/swap'
call s:Mkpath(s:directory)
execute 'set directory^='.s:EscItemExec(s:directory).'//'
if has('persistent_undo')
set undofile
let s:undodir = s:cache.'/undo'
call s:Mkpath(s:undodir)
execute 'set undodir^='.s:EscItemExec(s:undodir).'//'
endif
filetype plugin indent on
function! s:ReloadFileType() abort
if exists('g:did_load_filetypes')
doautocmd filetypedetect BufRead
endif
endfunction
command! -bar ReloadFileType
\ call s:ReloadFileType()
function! s:ReloadVimrc() abort
ReloadFileType
redraw
echomsg fnamemodify($MYVIMRC, ':p:~').' reloaded'
endfunction
command! -bar ReloadVimrc
\ noautocmd source $MYVIMRC | call s:ReloadVimrc()
augroup vimrc
autocmd!
augroup END
autocmd vimrc BufWritePost $MYVIMRC,$MYVIM/vimrc
\ ReloadVimrc
if exists('##SourceCmd')
autocmd vimrc SourceCmd $MYVIMRC,$MYVIM/vimrc
\ ReloadVimrc
endif
set history=10000
set spelllang=en_nz
let s:spellfile = s:cache.'/spell/'.join([
\ split(&spelllang, '_')[0],
\ &encoding,
\ 'add',
\], '.')
execute 'set spellfile='.s:EscItemExec(s:spellfile)
let &spellcapcheck = '[.?!]\%( \|[\n\r\t]\)'
set dictionary^=/usr/share/dict/words
let s:ref = $MYVIM.'/ref'
let s:dictionary = s:ref.'/dictionary.txt'
execute 'set dictionary^='.s:EscItemExec(s:dictionary)
let s:thesaurus = s:ref.'/thesaurus.txt'
execute 'set thesaurus^='.s:EscItemExec(s:thesaurus)
set comments= commentstring= define= include=
set path-=/usr/include
set autoindent
set expandtab
set shiftwidth=4
set smarttab
if v:version > 703 || v:version == 703 && has('patch693')
set softtabstop=-1
else
let &softtabstop = &shiftwidth
endif
set backspace+=eol
set backspace+=indent
set backspace+=start
set linebreak
if has('multi_byte_encoding')
set showbreak=…
else
set showbreak=...
endif
if exists('+breakindent')
set breakindent
endif
set confirm
set noesckeys
set formatoptions+=l
set formatoptions+=1
if v:version > 703 || v:version == 703 && has('patch541')
set formatoptions+=j
endif
set cpoptions+=J
if has('patch-8.1.728')
set formatoptions+=p
endif
if has('gui_running')
set guioptions+=M
endif
set hidden
set hlsearch
nohlsearch
set incsearch
set lazyredraw
set listchars+=tab:>-
set listchars+=trail:-
set listchars+=nbsp:+
if has('multi_byte_encoding')
set listchars+=extends:»,precedes:«
else
set listchars+=extends:>,precedes:<
endif
set nomodeline
set nrformats-=octal
set noruler
set sessionoptions-=localoptions
set sessionoptions-=options
set noshowcmd
set shortmess+=I
if !&loadplugins || globpath(&runtimepath, 'plugin/matchparen.vim') ==# ''
set showmatch matchtime=3
endif
set splitbelow splitright
set synmaxcol=500
if &term =~# '^putty\|^tmux'
set ttyfast
endif
set ttymouse=
set virtualedit+=block
set visualbell t_vb=
set wildmenu
set wildmode=list:longest,full
set wildignore=*~,#*#
\,*.7z
\,.DS_Store
\,.git
\,.hg
\,.svn
\,*.a
\,*.adf
\,*.asc
\,*.au
\,*.aup
\,*.avi
\,*.bin
\,*.bmp
\,*.bz2
\,*.class
\,*.db
\,*.dbm
\,*.djvu
\,*.docx
\,*.exe
\,*.filepart
\,*.flac
\,*.gd2
\,*.gif
\,*.gifv
\,*.gmo
\,*.gpg
\,*.gz
\,*.hdf
\,*.ico
\,*.iso
\,*.jar
\,*.jpeg
\,*.jpg
\,*.m4a
\,*.mid
\,*.mp3
\,*.mp4
\,*.o
\,*.odp
\,*.ods
\,*.odt
\,*.ogg
\,*.ogv
\,*.opus
\,*.pbm
\,*.pdf
\,*.png
\,*.ppt
\,*.psd
\,*.pyc
\,*.rar
\,*.rm
\,*.s3m
\,*.sdbm
\,*.sqlite
\,*.swf
\,*.swp
\,*.tar
\,*.tga
\,*.ttf
\,*.wav
\,*.webm
\,*.xbm
\,*.xcf
\,*.xls
\,*.xlsx
\,*.xpm
\,*.xz
\,*.zip
if exists('+wildignorecase')
set wildignorecase
endif
if !exists('syntax_on')
syntax enable
endif
autocmd vimrc ColorScheme *
\ let &cursorline = g:colors_name ==# 'sahara'
if !exists('$COLORFGBG') && get(v:, 'termrbgresp', '') ==# ''
set background=dark
endif
if &background ==# 'dark'
\ && (has('gui_running') || &t_Co >= 256)
\ && globpath(&runtimepath, 'colors/sahara.vim') !=# ''
colorscheme sahara
endif
nnoremap <Backspace> <C-^>
nnoremap <expr> <Space>
\ line('w$') < line('$')
\ ? "\<PageDown>"
\ : ":\<C-U>next\<CR>"
if &loadplugins && globpath(&runtimepath, 'plugin/insert_cancel.vim') !=# ''
imap <C-C> <Plug>(InsertCancel)
endif
imap <C-K><C-K> <Plug>(DigraphSearch)
nnoremap <C-L>
\ :<C-U>nohlsearch<CR><C-L>
inoremap <C-L> <C-O>:execute "normal \<C-L>"<CR>
vmap <C-L> <Esc><C-L>gv
noremap &
\ :&&<CR>
ounmap &
sunmap &
nmap g: <Plug>(ColonOperator)
nnoremap [a
\ :previous<CR>
nnoremap ]a
\ :next<CR>
nnoremap [b
\ :bprevious<CR>
nnoremap ]b
\ :bnext<CR>
nnoremap [c
\ :cprevious<CR>
nnoremap ]c
\ :cnext<CR>
nnoremap [l
\ :lprevious<CR>
nnoremap ]l
\ :lnext<CR>
nmap [<Space> <Plug>(PutBlankLinesAbove)
nmap ]<Space> <Plug>(PutBlankLinesBelow)
let mapleader = '\'
let maplocalleader = ','
if maplocalleader ==# ','
noremap ,, ,
sunmap ,,
endif
nnoremap <Leader><Tab>
\ :<C-U>set autoindent! autoindent?<CR>
nnoremap <Leader>c
\ :<C-U>set cursorline! cursorline?<CR>
nnoremap <Leader>h
\ :<C-U>set hlsearch! hlsearch?<CR>
nnoremap <Leader>i
\ :<C-U>set incsearch! incsearch?<CR>
nnoremap <Leader>s
\ :<C-U>set spell! spell?<CR>
noremap <Leader>C
\ :<C-U>set cursorcolumn! cursorcolumn?<CR>
ounmap <Leader>C
sunmap <Leader>C
noremap <Leader>l
\ :<C-U>set list! list?<CR>
ounmap <Leader>l
sunmap <Leader>l
noremap <Leader>n
\ :<C-U>set number! number?<CR>
ounmap <Leader>n
sunmap <Leader>n
noremap <Leader>N
\ :<C-U>set ruler! ruler?<CR>
ounmap <Leader>N
sunmap <Leader>N
noremap <Leader>w
\ :<C-U>set wrap! wrap?<CR>
ounmap <Leader>w
sunmap <Leader>w
nnoremap <Leader>f
\ :<C-U>set formatoptions?<CR>
nnoremap <Leader>u
\ :<C-U>set spelllang=en_us<CR>
nnoremap <Leader>z
\ :<C-U>set spelllang=en_nz<CR>
nmap <Leader>b <Plug>(CopyLinebreakToggle)
nnoremap <Leader>a
\ :<C-U>ToggleFlagLocal formatoptions a<CR>
noremap <Leader>L
\ :<C-U>ToggleFlagLocal colorcolumn +1<CR>
ounmap <Leader>L
sunmap <Leader>L
nmap <Leader>p <Plug>PasteInsert
nnoremap <Leader>F
\ :<C-U>ReloadFileType<CR>
nnoremap <Leader>t
\ :<C-U>set filetype?<CR>
nnoremap <Leader>T
\ :<C-U>set filetype=<CR>
nnoremap <Leader>d
\ :PutDate<CR>
nnoremap <Leader>D
\ :PutDate!<CR>
nnoremap <Leader>g
\ :<C-U>echo expand('%:p')<CR>
nnoremap <Leader>G
\ :<C-U>cd %:h<Bar>pwd<CR>
nnoremap <Leader>P
\ :<C-U>Establish %:h<CR>
nnoremap <Leader>H
\ :<C-U>history :<CR>
nnoremap <Leader>k
\ :<C-U>marks<CR>
nnoremap <Leader>K
\ :<C-U>function<CR>
nnoremap <Leader>m
\ :<C-U>nmap<CR>
nnoremap <Leader>M
\ :<C-U>nmap <buffer><CR>
nnoremap <Leader>S
\ :<C-U>scriptnames<CR>
nnoremap <Leader>U
\ :<C-U>command<CR>
nnoremap <Leader>v
\ :<C-U>let g: v:<CR>
nnoremap <Leader>V
\ :<C-U>let b: t: w:<CR>
nnoremap <Leader>y
\ :<C-U>registers<CR>
nnoremap <Leader><Delete>
\ :bdelete<CR>
nnoremap <Leader><Insert>
\ :<C-U>enew<CR>
nnoremap <Leader>e
\ :<C-U>set modifiable noreadonly<CR>
nnoremap <Leader>E
\ :<C-U>set nomodifiable readonly<CR>
nnoremap <Leader>j
\ :<C-U>buffers<CR>:buffer<Space>
nmap <Leader>o <Plug>(SelectOldFiles)
noremap <Leader>x
\ :StripTrailingWhitespace<CR>
ounmap <Leader>x
sunmap <Leader>x
noremap <Leader>X
\ :SqueezeRepeatBlanks<CR>
ounmap <Leader>X
sunmap <Leader>X
nnoremap <Leader>=
\ :<C-U>KeepPosition execute 'normal! 1G=G'<CR>
nnoremap <Leader>+
\ :<C-U>KeepPosition execute 'normal! 1GgqG'<CR>
onoremap <Leader>_
\ :<C-U>execute 'normal! `[v`]'<CR>
onoremap <Leader>%
\ :<C-U>execute 'normal! 1GVG'<CR>
omap <Leader>5 <Leader>%
map <Leader>{ <Plug>(VerticalRegionUp)
sunmap <Leader>{
map <Leader>} <Plug>(VerticalRegionDown)
sunmap <Leader>}
noremap <Leader>\ `"
sunmap <Leader>\
nnoremap <Leader><lt>
\ :<C-U>'[,']<lt><CR>
nnoremap <Leader>>
\ :<C-U>'[,']><CR>
nnoremap <Leader>/
\ :<C-U>vimgrep /\c/j **<S-Left><S-Left><Right>
nnoremap <Leader>?
\ :<C-U>lhelpgrep \c<S-Left>
nnoremap <Leader>.
\ :<C-U>lmake!<CR>
nnoremap <Leader>q gqap
map <Leader>r <Plug>(ReplaceOperator)
sunmap <Leader>r
ounmap <Leader>r
nnoremap <Leader>!
\ :<Up><Home><S-Right>!<CR>
nmap <Leader>1 <Leader>!
nmap <Leader># <Plug>(AlternateFileType)
nmap <Leader>3 <Leader>#
nmap <Leader>$ <Plug>(Fortune)
nmap <Leader>4 <Leader>$
nmap <Leader>& <Plug>(RegexEscape)
nmap <Leader>7 <Leader>&
xmap <Leader>& <Plug>(RegexEscape)
xmap <Leader>7 <Leader>&
nnoremap <silent> <Leader>* *N
nmap <Leader>8 <Leader>*
nnoremap <silent> <Leader>`
\ :<C-U>ScratchBuffer<CR>
nnoremap <silent> <Leader>~
\ :<C-U>vertical ScratchBuffer<CR>
nnoremap <Leader>R
\ :<C-U>ReloadVimrc<CR>
inoreabbrev tr@ tom@sanctum.geek.nz
inoreabbrev tr/ <https://sanctum.geek.nz/>
inoreabbrev almsot almost
inoreabbrev wrnog wrong
inoreabbrev Fielding Feilding
inoreabbrev THe The
inoreabbrev THere There
" Here endeth the literate vimrc. Let us praise God.
"
" │ Consequently, it is soon recognized that they write for the sake of
" │ filling up the paper, and this is the case sometimes with the best
" │ authors…as soon as this is perceived the book should be thrown away,
" │ for time is precious.
" │
" │ —Schopenhauer
"