Literate ~/.vimrc ¶ This blog post is my ~/.vimrc now. Hold on, let me explain.

Why would anyone do a thing like this? ¶ I have tons of comments in my ~/.vimrc file. I try to leave a lot of comments because everything in my Vim configuration is hard-won knowledge. My ~/.vimrc is accumulated knowledge from the day I first opened the editor and couldn’t figure out how to leave until now, many years later, when I open my editor and don’t have any reason to leave. I have tweaked, cajoled, and tamed this beast called Vim. I think a lot of folks have configuration kind of like that – it’s knowledge that is locked-away, not privately or purposefully, just badly-documented and ubiquitous. This is a problem. So I made a thing. This is an experiment that seeks to answer: can my ~/.vimrc be a page on my website?

Literate programming ¶ Literate programming is the idea that your code should work as a narrative as well as a functional piece of software. This is a practice that was popularized by Donald Knuth and was utilized in writing the source code for TeX. The are times when literate programming may not be appropriate; however, in this instance – the case of a .vimrc – I feel like literate programming will be helpful to remind me what a setting is and why I applied it. This also may mean that my accumulated Vim knowledge (however limited it may be) is more generally accessible than if it were just a plaintext documents sitting in my dotfiles.

Literate Vimscript ¶ My resolve to make a literate ~/.vimrc led to some searching on DuckDuckGo and a slow, settling realization that I was going to have to write the plugin that does this. Keeping your Emacs configuration as a literate document written in org-mode is pretty common practice at this point, so I made the faulty assumption that a Vim configuration written in Markdown would be a common aspiration as well. I was wrong and thus was the genesis of LiterateVimrc. “Literate” Vimrc is more than a bit of a misnomer. It, unlike Donald Knuth’s vision of Literate Programming, does not support a loosely coupled web of macros – instead it just lets you write a file in Markdown that has codeblocks (as defined by v0.27 of the CommonMark spec) containing Vimscript as your ~/.vimrc file.

Install ¶ To install LiterateVimsrc copy the autoload/literavevimrc.vim file into your ~/.vim/autoload directory, move your current ~/.vimrc to ~/.vimrc.md and add ~~~ to to first and last lines of that file (to create fenced codeblock). Inside your (now empty) ~/.vimrc add the line execute literatevim#load("~/.vimrc.md") and everything should remain the same. Now you are free to add text explaining your configuration and divide your configuration into blocks. This blog post is currently acting as my ~/.vimrc file, as of this writing. This may be a bad idea. I do expect to update it somewhat regularly, but his frontmatter should remain the same.

My ~/.vimrc ¶ This begins the content of my ~/.vimrc file. It includes various explanations and links that may only make sense to me. Here be dragons. You have been warned. The first lines that should be in every ~/.vimrc – disabling arrow keys – because it’s not enough to use vim, you’ve got to live it. noremap <up> <nop> inoremap <up> <nop> noremap <down> <nop> inoremap <down> <nop> noremap <left> <nop> noremap <right> <nop> inoremap <left> <nop> inoremap <right> <nop> " B A start

What is this ‘Vee-Eye’ of which you speak? ¶ Vim’s compatible mode means lots of plugins won’t work. It evidently means that you can’t use \ in vim scripts to break a command across a few lines. nocompatible is also necessary for Vundle which is my vim packagemanager of choice. set nocompatible

Plugins ¶ All of my plugins. To install all of my plugins on a brand new machine I can run vim +PluginInstall +qall , which is pretty neat. filetype off " required set rtp+=~/.vim/bundle/Vundle.vim call vundle#begin() " let Vundle manage Vundle, required Plugin 'gmarik/Vundle.vim' " Other plugins Plugin 'vim-pandoc/vim-pandoc-syntax' Plugin 'tpope/vim-surround' Plugin 'groenewege/vim-less' Plugin 'kien/ctrlp.vim' Plugin 'Lokaltog/vim-easymotion' Plugin 'jistr/vim-nerdtree-tabs' Plugin 'scrooloose/syntastic' Plugin 'godlygeek/tabular' Plugin 'majutsushi/tagbar' Plugin 'goldfeld/vim-seek' Plugin 'altercation/vim-colors-solarized' Plugin 'ajgrf/parchment' Plugin 'chriskempson/base16-vim' Plugin 'joonty/vdebug' Plugin 'vim-airline/vim-airline' " BOOO! Plugin 'vim-airline/vim-airline-themes' Plugin 'scrooloose/nerdtree' Plugin 'sheerun/vim-polyglot' Plugin 'Shougo/neocomplete' Plugin 'Shougo/neosnippet' Plugin 'juvenn/mustache' Plugin 'nathanaelkane/vim-indent-guides' Plugin 'tpope/vim-fugitive' Plugin 'tpope/vim-rsi' Plugin 'airblade/vim-gitgutter' call vundle#end() " required filetype plugin indent on " required

A Random solution to a random problem ¶ This disables Background Color Erase (BCE) when the $TERM env var contains the text 256color . The problem I was seeing is summarized on Suraj N. Kurapati’s blog post. This may, in fact, not be necessary. At least according to reddit if &term =~ '256color' set t_ut= endif

Basic options ¶ let mapleader=',' set t_Co=256 " My terminal's got all those colors, yo set title " Change the terminal title set encoding=utf-8 " Show utf-8 chars set showcmd " count highlighted set ruler " Show where I am in the command area set showmode " -- INSERT (appreciation)-- :) set laststatus=2 " always show the status line " ↪ (0 = never, 1 = default [multi-window only]) set mouse= " Use the mouse set modelines=0 " Don't read first/last lines of file for settings set hidden " Stash unwritten files in buffer set vb " Don't beep at me set cursorline " Highlight current line set scrolloff=3 " Start scrolling when I'm 3 lines from top/bottom set history=1000 " Remember commands and search history set backspace=2 " Backspace over indent, eol, and insert set mousehide " Hide the mouse pointer while typing set number " Show linenumbers set nowrap " Turn off linewrap set list " Show invisible chars set tabstop=4 " 4 spaces set shiftwidth=4 " 4 spaces set softtabstop=4 " 4 spaces set expandtab " Expand tabs to spaces set hlsearch " highlight my search set incsearch " incremental search set wrapscan " Set the search scan to wrap around the file set ignorecase " when searching set smartcase " …unless I use an uppercase character

Syntax ¶ I have actually been considering what it would be like to work without syntax highlighting. I may be too far gone to start trying, but it’d certainly make me more attune to various code problems rather than code colors. In any event, with some of the huge files I view the syntax sync minline option and the synmaxcol=2048 are lifesavers. syntax on " Syntax highlighting syntax sync minlines=256 " Makes big files slow set synmaxcol=2048 " Also long lines are slow set autoindent " try your darndest to keep my indentation set smartindent " Be smarter about indenting dummy

Format options ¶ c - Auto-wrap comments using textwidth, inserting the current comment leader automatically. o - Automatically insert the current comment leader after hitting ‘o’ or ‘O’ in Normal mode. t - Auto-wrap text using textwidth q - Allow formatting of comments with “gq”. r - Automatically insert the current comment leader after hitting in Insert mode. I have a different setting for format options when emailing in mutt. There I use set formatoptions=aw which works for format-flowed emails. set formatoptions=cotqr " I like smart comments

Folding ¶ At some point in the past I used to use the marker for folding (which was opened with {{{ and closed by }}} ) I found this a nice way to divide up things like my ~/.vimrc for instance; however, what’s even nicer is folding on indent. It makes reading yaml files super easy. I read lots of very (VERY) large yaml files. I suppose I could do this with an autocmd , but I set it globally instead ¯\_(ツ)_/¯ . " set foldmethod=marker " Fold on 3x{ set foldmethod=indent set nofoldenable " But turn it off initially

Fishshell ¶ I needed this for running some commands in Vim inside fishshell which I used for a time and then abandoned. I think that fishshell is really great (and it’s an actual programming language), the problem with it is two-fold: Nobody wants to push fishshell on a server – which I understand Using it requires a million little hacks like the one below This is the flip side of fixing all the dumb decisions of the bourne shell – everyone else has already worked around them (obligatory xkcd). " set shell=/bin/bash\ --login " set shell=bash " Needed if using fishshell

Backup and Swap files ¶ I hate all the little backup and swap files all over the place. There has been 1 time when these would have come in handy in the past decade as far as I can remember. set nobackup set nowritebackup set noswapfile

Colorschemes ¶ " Colorscheme if filereadable(expand("~/.vimrc_background")) let base16colorspace=256 source ~/.vimrc_background else colorscheme Tomorrow-Night endif " GUI Font (same as my gnome-terminal font) " https://github.com/adobe/source-code-pro set guifont=Source\ Code\ Pro\ 14 " Use the same symbols as TextMate for tabstops and EOLs set listchars=tab:▸\ ,eol:¬\,trail:·

Vim 7.0.3 new features ¶ Maybe I should update the stuff that hedges on a machine not having Vim 7.0.3 since version 8 is out now. This is a project for later. if v:version >= 703 set colorcolumn=75 set undodir=~/.vim-undo set undofile set undolevels=1000 "max number of changes that can be undone set undoreload=10000 "max number lines to save for undo on buffer reload " Toggle line numbers in normal mode, set by default set number relativenumber function! NumberToggle() if(&relativenumber == 1) set number norelativenumber else set number relativenumber endif endfunc nnoremap <leader>n :call NumberToggle()<cr> endif

OSX ¶ I don’t really know why I still have OSX hacks in all my dotfiles. Maybe someday I’ll be forced to jump off the Linux ship. I assume I’ll be jumping to a BSD or something at that point though. if has("unix") let s:uname = system("uname") if s:uname == "Darwin

" set clipboard=unnamed endif endif

Very Magic ¶ I’m not sure if I should turn this off. Half the time I think it’s great, the other half it’s a pain. I guess leaving it on for now seems fine. nnoremap / /\v

Mappings ¶ " Vimrc editing nnoremap <silent><leader>ev :vsplit $MYVIMRC<cr> nnoremap <silent><leader>sv :source $MYVIMRC<cr> " un-highlight search results nnoremap <silent><leader><space> :noh<cr> " Toggle auto-indent before clipboard paste set pastetoggle=<leader>p " Shortcut to rapidly toggle `set list` nnoremap <silent><leader>l :set list!<cr> " Normal/Visual tab for bracket pairs nnoremap <tab> % vnoremap <tab> % "Opens a vertical split and switches over (,v) nnoremap <leader>v <C-w>v<C-w>l "Moves around split windows nnoremap <leader>w <C-w><C-w> "Close a window nnoremap <silent><leader>q :q<cr> " Close buffer noremap <silent><leader>d :bd<cr> " Buffer previous noremap <silent><leader>z :bp<CR> " Buffer next noremap <silent><leader>x :bn<CR> nnoremap <S-Tab> gT nnoremap <silent> <S-t> :tabnew %<CR> " Set working directory nnoremap <leader>. :lcd %:p:h<CR> " Vmap for maintain Visual Mode after shifting > and <, prevents the use of " '.' to repeat " vmap < <gv " vmap > >gv " Better use of folding " nnoremap <leader>z za

Status Line ¶ I leave this status line here more as a reference than anything. Currently (as can be seen in the Plugins section) I’m using vim-airline for my statusbar. augroup ft_statuslinecolor au! au InsertEnter * hi StatusLine ctermfg=196 guifg=#FF3145 au InsertLeave * hi StatusLine ctermfg=130 guifg=#CD5907 augroup END set statusline=%f " Path. set statusline+=%m " Modified flag. set statusline+=%r " Readonly flag. set statusline+=%w " Preview window flag. set statusline+=\ " Space. set statusline+=%= " Right align. " Line and column position and counts. set statusline+=\ %l\/%L\ \/\/\ %03c)

Autocmds ¶ Don’t expand tabs in Makefile s or php files autocmd FileType make setlocal noexpandtab autocmd Filetype php setlocal noexpandtab autocmd Filetype go setlocal noexpandtab Highlight any trailing whitespace in red highlight ExtraWhitespace ctermbg=red guibg=red match ExtraWhitespace /\s\+$/ autocmd BufWinEnter * match ExtraWhitespace /\s\+$/ autocmd InsertEnter * match ExtraWhitespace /\s\+\%#\@<!$/ autocmd InsertLeave * match ExtraWhitespace /\s\+$/ autocmd BufWinLeave * call clearmatches() Ensure that puppet files are handled properly in Vim. IIRC I pulled this line from the office wiki somewhere… " detect puppet filetype autocmd BufRead,BufNewFile *.pp set filetype=puppet autocmd BufRead,BufNewFile *.pp setlocal tabstop=4 shiftwidth=4 softtabstop=4 expandtab textwidth=80 smarttab These are the settings I use for my email. I try to send format=flowed emails that sill look good in terminal readers like Mutt. augroup mail_filetype autocmd! autocmd VimEnter /tmp/mutt* set formatoptions=aw tw=72 augroup END

Plugin settings ¶ " Tagbar (requires Exuberant ctags 5.5+) nnoremap <silent><leader>c :TagbarToggle<cr> It’s kind of insane that you can use Vim to drive a debugger like XDebug. As evidenced by the path maps here, I haven’t used this in a while and it was a pain to setup when I did. Kept here as a reminder that Vim is amazing. " Xdebug local debugger let g:vdebug_options = { \ 'server': '33.33.33.1', \ 'port': '9000', \ 'path_maps' : { \ '/srv/www/local.people.dev': '/Users/tyler/Development/upsync-vagrant/shared/people' \ } \} let g:syntastic_javascript_jshint_conf="$HOME/.jshintrc" let g:syntastic_error_symbol = '✘' let g:syntastic_warning_symbol = "▲" " let g:syntastic_python_python_exec = '/usr/bin/python3' let g:jedi#force_py_version=2 NERDTree was the first plugin I ever installed. " NERDTree Settings---------------------------------------------------- {{{ "map <leader>t :NERDTreeToggle<cr> nnoremap <leader>t :NERDTreeTabsToggle<cr> " Close vim if NERDTree is the last thing standing autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTreeType") && b:NERDTreeType == "primary") | q | endif " }}} " Included for Airline ------------------------------------------------ {{{ let g:airline_theme = 'tomorrow' let g:airline_powerline_fonts = 1 " let g:airline#extensions#tabline#enabled = 1 " }}} " CtrlP --------------------------------------------------------------- {{{ let g:ctrlp_max_files = 0 " Set no max file limit let g:ctrlp_working_path_mode = 0 " Search current directory not project root if executable("ag") set grepprg=ag\ --nogroup\ --nocolor " let g:ctrlp_user_command = 'ag %s -l --nocolor -g ""' let g:ctrlp_user_command = { \ 'types': { \ 1: ['.git', 'git --git-dir=%s/.git ls-files -oc --exclude-standard'], \ 2: ['.hg', 'hg --cwd %s locate -I .'], \ }, \ 'fallback': 'ag %s -l --nocolor -g ""' \ } endif let g:ctrlp_show_hidden = 1 "}}} These are all settings for neocomplete and neosnippet which requires Vim 7.0.4 or higher and +lua when you do vim --version . if v:version >= 704 && has("lua") " Neocomplete.vim --------------------------------------------------- {{{ " Disable AutoComplPop. let g:acp_enableAtStartup = 0 " Use neocomplete. let g:neocomplete#enable_at_startup = 1 " Use smartcase. let g:neocomplete#enable_smart_case = 1 " Set minimum syntax keyword length. let g:neocomplete#sources#syntax#min_keyword_length = 3 let g:neocomplete#lock_buffer_name_pattern = '\*ku\*' " I will probably never hit <TAB> 10 times let g:neocomplete#max_list = 10 " Automatically open and close the popup menu / preview window " https://github.com/JessicaKMcIntosh/TagmaBufMgr/issues/8 au CursorMovedI,InsertLeave * if pumvisible() == 0|silent! pclose|endif set completeopt=menuone,menu,longest " Define dictionary. let g:neocomplete#sources#dictionary#dictionaries = { \ 'default' : '', \ 'vimshell' : $HOME.'/.vimshell_hist', \ 'scheme' : $HOME.'/.gosh_completions' \ } " Define keyword. if !exists('g:neocomplete#keyword_patterns') let g:neocomplete#keyword_patterns = {} endif let g:neocomplete#keyword_patterns['default'] = '\h\w*' " Plugin key-mappings. inoremap <expr><C-g> neocomplete#undo_completion() inoremap <expr><C-l> neocomplete#complete_common_string() " Recommended key-mappings. " <CR>: close popup and save indent. inoremap <silent> <CR> <C-r>=<SID>my_cr_function()<CR> function! s:my_cr_function() return neocomplete#smart_close_popup() . "\<CR>" " For no inserting <CR> key. "return pumvisible() ? neocomplete#close_popup() : "\<CR>" endfunction " <TAB>: completion. inoremap <expr><TAB> pumvisible() ? "\<C-n>" : "\<TAB>" " <C-h>, <BS>: close popup and delete backword char. inoremap <expr><C-h> neocomplete#smart_close_popup()."\<C-h>" inoremap <expr><BS> neocomplete#smart_close_popup()."\<C-h>" inoremap <expr><C-y> neocomplete#close_popup() inoremap <expr><C-e> neocomplete#cancel_popup() " Close popup by <Space>. " inoremap <expr><Space> pumvisible() ? neocomplete#close_popup() : "\<Space>" " Enable omni completion. autocmd FileType css setlocal omnifunc=csscomplete#CompleteCSS autocmd FileType html,markdown setlocal omnifunc=htmlcomplete#CompleteTags autocmd FileType javascript setlocal omnifunc=javascriptcomplete#CompleteJS autocmd FileType python setlocal omnifunc=pythoncomplete#Complete autocmd FileType xml setlocal omnifunc=xmlcomplete#CompleteTags autocmd FileType php set omnifunc=phpcomplete#CompletePHP " Enable heavy omni completion. if !exists('g:neocomplete#sources#omni#input_patterns') let g:neocomplete#sources#omni#input_patterns = {} endif let g:neocomplete#sources#omni#input_patterns.php = '[^. \t]->\h\w*\|\h\w*::' let g:neocomplete#sources#omni#input_patterns.c = '[^.[:digit:] *\t]\%(\.\|->\)' let g:neocomplete#sources#omni#input_patterns.cpp = '[^.[:digit:] *\t]\%(\.\|->\)\|\h\w*::' " For perlomni.vim setting. " https://github.com/c9s/perlomni.vim let g:neocomplete#sources#omni#input_patterns.perl = '\h\w*->\h\w*\|\h\w*::' " }}} " Neosnippet.vim ------------------------------------------------------ {{{ " Plugin key-mappings. imap <C-k> <Plug>(neosnippet_expand_or_jump) smap <C-k> <Plug>(neosnippet_expand_or_jump) xmap <C-k> <Plug>(neosnippet_expand_target) " SuperTab like snippets behavior. imap <expr><TAB> neosnippet#expandable_or_jumpable() ? \ "\<Plug>(neosnippet_expand_or_jump)" \: pumvisible() ? "\<C-n>" : "\<TAB>" smap <expr><TAB> neosnippet#expandable_or_jumpable() ? \ "\<Plug>(neosnippet_expand_or_jump)" \: "\<TAB>" " For snippet_complete marker. if has('conceal') set conceallevel=2 concealcursor=i endif " Enable snipMate compatibility feature. let g:neosnippet#enable_snipmate_compatibility = 1 " Tell Neosnippet about the other snippets let g:neosnippet#snippets_directory='~/.vim/bundle/vim-snippets/snippets' " }}} endif " }}} Indent guides are neat. I need to figure out a way to have the ctermbg vary with colorscheme though :

" Indent Guides ------------------------------------------------------- {{{ let g:indent_guides_enable_on_vim_startup = 1 " }}}