set nocompatible " turn off vi compatible, should be first let mapleader = "\" let maplocalleader = "," " =========== " : Plugins : " =========== let s:load_dynamic_plugins=$VIM_LOAD_DYNAMIC_PLUGINS != "false" function! Develop(bundle) let bundle_directory = $DEVELOPMENT . '/' . a:bundle if isdirectory(bundle_directory) let &runtimepath .= ',' . bundle_directory else execute "Plug 'Julian/" . a:bundle . "'" endif endfunction command! -nargs=1 Develop call Develop('') if has('vim_starting') source ~/.vim/bundle/vim-plug/plug.vim endif call plug#begin(expand('~/.vim/bundle/')) " --- Themes --- Plug 'morhetz/gruvbox' " --- Additional Filetype Support --- Plug 'sheerun/vim-polyglot' Plug 'guns/vim-clojure-highlight', {'for': 'clojure'} Plug 'guns/vim-sexp', {'for': 'clojure'} Plug 'tpope/vim-fireplace', {'for': 'clojure'} Plug 'tpope/vim-leiningen', {'for': 'clojure'} Plug 'tpope/vim-sexp-mappings-for-regular-people', {'for': 'clojure'} " --- Plugins --- Plug 'ajh17/VimCompletesMe' " Plug 'alfredodeza/coveragepy.vim', {'for': 'python'} Plug 'AndrewRadev/linediff.vim', {'on': ['Linediff', 'LinediffReset']} Plug 'AndrewRadev/splitjoin.vim' Plug 'AndrewRadev/switch.vim' Plug 'b4winckler/vim-angry' Plug 'bfredl/nvim-miniyank' Plug 'bling/vim-airline' Plug 'bruno-/vim-man' Plug 'bruno-/vim-vertical-move' Plug 'dahu/vim-fanfingtastic' Plug 'godlygeek/tabular', {'on': 'Tabularize'} Plug 'kana/vim-vspec' Plug 'kana/vim-submode' Plug 'kien/rainbow_parentheses.vim' Plug 'kshenoy/vim-signature' Plug 'jaxbot/github-issues.vim', {'on': 'Gissues', 'for': 'gitcommit'} Plug 'jmcantrell/vim-diffchanges', {'on': 'DiffChangesDiffToggle'} Plug 'majutsushi/tagbar' Plug 'mhinz/vim-signify' Plug 'mbbill/undotree' Plug 'nathanaelkane/vim-indent-guides', {'on': 'IndentGuidesToggle'} Plug 't9md/vim-quickhl' Plug 'tommcdo/vim-exchange' Plug 'tomtom/tcomment_vim' Plug 'tpope/vim-abolish' Plug 'tpope/vim-dispatch' Plug 'tpope/vim-endwise' Plug 'tpope/vim-fugitive' Plug 'tpope/vim-obsession', {'on': 'Obsession'} Plug 'tpope/vim-repeat' Plug 'tpope/vim-rhubarb' Plug 'tpope/vim-surround' Plug 'Valloric/MatchTagAlways', {'for': ['html', 'xhtml', 'xml', 'jinja']} Plug 'Valodim/vim-zsh-completion' Plug 'w0rp/ale' Plug 'kana/vim-textobj-indent' Plug 'Julian/vim-textobj-python', {'for': 'python'} Plug 'kana/vim-textobj-syntax' Plug 'kana/vim-textobj-user' Plug 'Shougo/neomru.vim' Plug 'Shougo/denite.nvim' Develop vim-runt Develop vim-textobj-assignment Develop vim-textobj-brace Develop vim-textobj-variable-segment if executable("tmux") Plug 'tpope/vim-tbone' Plug 'wellle/tmux-complete.vim' let g:tmuxcomplete#trigger = '' endif if s:load_dynamic_plugins Plug 'davidhalter/jedi-vim' endif call plug#end() " ========= " : Basic : " ========= if has('autocmd') filetype plugin indent on endif if has('syntax') && !exists('g:syntax_on') syntax enable endif if has('vim_starting') set encoding=utf8 endif set autoread " automatically reload unmodified bufs set gdefault set hidden set lazyredraw " no redraw during macros (much faster) set linebreak set report=0 " :cmd always shows changed line count set textwidth=79 set nowrap let &showbreak='↪ ' set fillchars=diff:· set pastetoggle= " use f2 to toggle paste mode set isfname-== " remove =, which probably is an assign set tags=.tags,tags,.git/tags;$HOME " look up until $HOME for tags " ============ " : Bindings : " ============ if has("user_commands") " quick fingers command! -bang -complete=file -nargs=? E e command! -bang -complete=file -nargs=? Sp sp command! -bang -complete=file -nargs=? Vsp vsp command! -bang -complete=file -nargs=? W w command! -bang -complete=file -nargs=? WQ wq command! -bang -complete=file -nargs=? Wq wq command! -bang Q q command! -bang Qa qa command! -bang QA qa command! -bang Wa wa command! -bang WA wa endif " this one is reserved unfortunately, but for encryption just use vim -xn cnoreabbrev X x " testing mappings nnoremap ":w:Dispatch " . (empty(get(t:, 'runt_last_command', '')) ? runt#file(expand("%")) : t:runt_last_command) . "" nnoremap d ":SplitSensibly " . runt#find_test_file_for(expand("%")) . "" nnoremap dc ":w:Dispatch " . (empty(get(t:, 'runt_last_command', '')) ? runt#class(expand("%"), getpos(".")) : t:runt_last_command) . "" nnoremap dm ":w:Dispatch " . (empty(get(t:, 'runt_last_command', '')) ? runt#method(expand("%"), getpos(".")) : t:runt_last_command) . "" nnoremap dx :w:Dispatch tox nnoremap dK :call runt#follow() nnoremap dS ":w:Dispatch " . (empty(get(t:, 'runt_last_command', '')) ? runt#suite(expand("%")) : t:runt_last_command) . "" map p (miniyank-autoput) map P (miniyank-autoPut) map (miniyank-cycle) map (miniyank-tochar) map (miniyank-toline) map (miniyank-toblock) " Put exchange and splitjoin on s, use cl if you want that, but I rarely do. map s (Exchange) nnoremap s :SplitjoinSplit nnoremap ss :SplitjoinJoin " don't use Ex mode, use Q for formatting nmap Q gqap vmap Q gq " change Y to act like C, D map Y y$ nnoremap : ; nnoremap ; : nnoremap q; q: vnoremap : ; vnoremap ; : " swap ' and ` noremap ' ` noremap ` ' noremap g' g` noremap g` g' noremap ]' ]` noremap ]` ]' " sunmap ' sunmap ` sunmap g' sunmap g` " Preserve flags for &, and add it in visual mode. nnoremap & :&& xnoremap & :&& nnoremap :nohlsearch:diffupdate:syntax sync fromstart:XchangeClear:LinediffReset " make undo less drastic + prevent accidental irreversible undo " not sure why cr one is not working " inoremap u " inoremap u " inoremap u " inoremap u " inoremap u " delete a surrounding function call (which surround doesn't support OOTB) nmap dsc :call search('\<', 'bc')dt(ds) " quote a word nmap yq 'ysiw' . (get(b:, 'use_single_quotes', 0) ? "'" : '"') " '' is set to help " '' is set to pastetoggle let s:all_modes_mappings = { \ '' : ':make', \ \ '' : ':diffget[c', \ '' : ':diffget]c', \ '' : ':diffget', \ '' : ':diffput' \ \} for [key, value] in items(s:all_modes_mappings) let value = empty(value) ? '' : value . '' execute 'nnoremap ' . key . ' ' . value execute 'inoremap ' . key . ' ' . value execute 'vnoremap ' . key . ' ' . value endfor " Leader mappings " --------------- " " Here are explanations for non-self-explanatory ones: " " b : paste last deletion on its own line despite it being charwise " n : search forward, but not anything currently displayed " u : undo/redo toggle " B : paste system clipboard on its own line despite it not having a newline " N : search backward, but not anything currently displayed " S : remove trailing whitespace " 0 : minimize a window nnoremap :Denite buffer file file_mru tag nnoremap b o" nnoremap d :Denite -buffer-name=files file_rec nnoremap e :SplitSensibly:Denite file_rec: nnoremap f :Denite -buffer-name=buffers buffer_tab nnoremap h :Denite -buffer-name=tags tag nnoremap j :Denite -buffer-name=test_tags -input=test tag nnoremap k :Denite -buffer-name=tests -input=test/test_ file_rec nnoremap l :Denite -buffer-name=lines line nmap m (quickhl-manual-this) nnoremap n n nnoremap o EditFileWORD() nnoremap p "*p nnoremap r :Denite -buffer-name=mru file_mru nnoremap s :Switch nnoremap ta :TagbarToggle nnoremap tc :DiffChangesDiffToggle nnoremap td :DiffThese nnoremap te :call ToggleExpando() nnoremap ti :IndentGuidesToggle nnoremap tl :set list! nnoremap tp :set formatoptions-=c:set spell nnoremap tq :call ToggleQuickfix() nnoremap ts :set spell! nnoremap tu :UndotreeToggle nnoremap tw :set wrap! nnoremap u :set cpoptions+=uu:w:set cpoptions-=u nnoremap v :SplitSensibly $MYVIMRC nnoremap y "*y nnoremap gb :Gblame nnoremap gc :Gcommit nnoremap gd :Gdiff nnoremap ge :Gedit nnoremap gr :Gread nnoremap gs :Gstatus nnoremap gw :Gwrite nnoremap B o* nnoremap C ":SplitSensibly:Denite -buffer-name=config -input=. file:$HOME file_rec:" . $XDG_CONFIG_HOME . "" nmap M (quickhl-manual-reset) nnoremap N N nnoremap P "*P nnoremap S :%s/\s\+$//:let @/='' nnoremap U :PlugUpdate nnoremap Z :SplitSensibly $ZDOTDIR/.zshrc nnoremap DD :profile start profile.log:profile func *:profile file * nnoremap DQ :profile pause:noautocmd quitall! nnoremap VF ":SplitSensibly " . split(&runtimepath, ",")[0] . "/ftplugin/" . &filetype . ".vim" nnoremap VZ :SplitSensibly $ZDOTDIR/.zshrc.local nnoremap 0 :wincmd _ nnoremap ` :call DoCommentTagFormat() nnoremap . :setlocal autochdir nnoremap ; :lprevious nnoremap ' :lnext nnoremap [ :cprevious nnoremap ] :cnext nnoremap { :cpfile nnoremap } :cnfile nnoremap - :previous nnoremap = :next nnoremap :earlier 1f nnoremap \ :later 1f nnoremap / :Denite -buffer-name=grep grep:. nnoremap vnoremap d :Linediff vmap m (quickhl-manual-this) vnoremap p "*p vnoremap y "*y " ============== " : Completion : " ============== " insert mode completion set completeopt=menuone,longest,preview " follow type in autocomplete set pumheight=6 " Keep a small completion window set showcmd " display incomplete commands set suffixes+=.backup,.hbm,.ini " lower priority when completing set wildmenu " file completion helper window set wildmode=longest:full,full if exists('&wildignorecase') " TODO: Really I want wildsmartcase (which doesn't exist), but I " don't want to hit longest: if my match was because of case " insensitivity. set wildignorecase " ignore case in completions endif set wildignore+=*.db,*.o,*.obj set wildignore+=*.swp,*.bak,*.lock set wildignore+=*.git,*.hg,*.svn set wildignore+=MANIFEST,*.pyc,**/_trial_temp*/**,*.egg-info/**,*.egg/**,**/build/**,**/htmlcov/**,**/dist/**,**/_build/**,**/.tox/**,**/.testrepository/** set wildignore+=**/.vim-flavor/** set wildignore+=*DS_Store* set wildignore+=version.txt set wildignore+=**/tmp/** set wildignore+=*.png,*.jpg,*.gif set wildignore+=*.app,*.dmg,*.pdf,*.so set wildignore+=**/.gems/**,**/.chef/checksums/** set complete-=i " this is slow apparently. if filereadable("/usr/share/dict/words") set dictionary+=/usr/share/dict/words endif " =========== " : Folding : " =========== set foldmethod=indent set foldlevel=99 " ========== " : Guides : " ========== set cursorline " hilight current line set showmatch " show matching brackets for a moment set matchpairs+=<:> set matchtime=5 " show for how long (*tenths* of second) " show a line at column 79 if exists("&colorcolumn") highlight ColorColumn guibg=#2d2d2d set colorcolumn=+1 endif " =========== " : History : " =========== set directory=$XDG_CACHE_HOME/vim/swap//,~/tmp/vim//,~/tmp//,/var/tmp//,/tmp// " swap files set history=10000 " command line history if has('nvim') set shada='50,s100,n$XDG_CACHE_HOME/nvim/shada " 50 marks, unhuge register else set viminfo='50,s100,n$XDG_CACHE_HOME/vim/info " 50 marks, unhuge register endif set backup set backupdir=$XDG_CACHE_HOME/vim/backups,~/tmp,/tmp if exists("&undofile") set undofile set undodir=$XDG_CACHE_HOME/vim/undo,$HOME/tmp,/tmp endif set undolevels=500 " more undo " ============= " : Interface : " ============= set background=dark " make sure this is before colorschemes let g:preferred_colorscheme = 'gruvbox' if has('gui_running') || &t_Co > 8 execute 'silent colorscheme ' . g:preferred_colorscheme else colorscheme desert endif set laststatus=2 " always show status line if &statusline!~?'airline\|powerline' && (!exists("g:powerline_loaded") || !g:powerline_loaded) set statusline=[%l,%v\ %P%M]\ %f\ %r%h%w\ (%{&ff}) if exists("g:loaded_fugitive") set statusline+=\ %{fugitive#statusline()} endif endif set confirm " show confirm dialog instead of warn set display+=lastline " show as much of lastline possible set shortmess+=atI " show shorter messages set title " change window title to filename set equalalways " hopefully fix how often :sp's mess up set splitbelow " new :sp go on bottom set splitright " new :vsp go on right set winminheight=0 " allow totally minimizing a window set timeoutlen=500 " shorten the amount of time to wait " no bells or blinking set noerrorbells set novisualbell set vb t_vb= " Change the cursor to an underline in insert mode if &term =~ 'xterm\|screen' set t_SI=[4\ q set t_EI=[2\ q endif if has('multi_byte') || has('gui_running') set listchars=tab:▸\ ,eol:¬,trail:·,extends:→,precedes:← else set listchars=tab:>-,eol:$,trail:.,extends:>,precedes:< endif if has('mouse') set mouse=v " ugh no mouse while typing, just visual set mousemodel=popup endif " ============ " : Movement : " ============ set backspace=indent,eol,start " backspacing over everything in insert set nostartofline " never jump back to start of line set ruler " show the cursor position all the time set scrolloff=2 " keep lines above and below cursor set sidescrolloff=2 " same for horizontal set virtualedit=block " ========== " : Search : " ========== set ignorecase set smartcase " case-sensitive if upper in search term set incsearch " do incremental searching set hlsearch " hilight searches if exists('+inccommand') set inccommand=nosplit endif if executable("rg") " RIP set grepprg=rg\ --vimgrep\ --no-heading\ --smart-case\ $* set grepformat=%f:%l:%c:%m,%f:%l:%m elseif executable("ag") " if the silver searcher's around... set grepprg=ag\ --vimgrep\ $* set grepformat=%f:%l:%c:%m elseif filereadable("/usr/local/bin/grep") " or if there's a newer grep... set grepprg=/usr/local/bin/grep endif " ============== " : Formatting : " ============== if executable("par") set formatprg=par endif " ============ " : Spelling : " ============ set spellfile=~/.vim/spellfile.add " ============== " : Whitespace : " ============== set autoindent set expandtab " insert space instead of tab set shiftround " rounds indent to a multiple of shiftwidth set shiftwidth=4 " makes # of spaces = 4 for new tab set softtabstop=4 " makes the spaces feel like tab set tabstop=8 " makes # of spaces = 8 for preexisitng tab " =================== " : Plugin Settings : " =================== if has('nvim') function! s:SetHostProg(setting, job_id, data, event) let {a:setting} = a:data[0] endfunction call jobstart( \ ["findenv", "name", "neovim", "python"], \ {"on_stdout": function("s:SetHostProg", ["g:python_host_prog"])}, \ ) call jobstart( \ ["findenv", "name", "neovim3", "python"], \ {"on_stdout": function("s:SetHostProg", ["g:python3_host_prog"])}, \ ) endif let g:is_posix = 1 let g:tex_flavor='latex' let g:exchange_no_mappings = '1' if filereadable('/usr/local/bin/ctags') let g:tagbar_ctags_bin = '/usr/local/bin/ctags' else let g:tagbar_ctags_bin = '/usr/bin/ctags' endif " signature let g:SignatureMap = { \ 'Leader' : "M", \ 'PlaceNextMark' : "M,", \ 'PurgeMarks' : "M", \ 'PurgeMarkers' : "M", \ 'GotoNextLineAlpha' : "", \ 'GotoPrevLineAlpha' : "", \ 'GotoNextSpotAlpha' : "", \ 'GotoPrevSpotAlpha' : "", \ 'GotoNextLineByPos' : "", \ 'GotoPrevLineByPos' : "", \ 'GotoNextSpotByPos' : "", \ 'GotoPrevSpotByPos' : "", \ 'GotoNextMarker' : "]-", \ 'GotoPrevMarker' : "[-", \ 'GotoNextMarkerAny' : "]=", \ 'GotoPrevMarkerAny' : "[=", \ } let g:tcommentTextObjectInlineComment = 'ix' let g:tcommentMapLeader1 = '' let g:tcommentMapLeader2 = '' let g:undotree_TreeNodeShape = '✷' " more stupid things with default mappings let g:signify_mapping_next_hunk = '' let g:signify_mapping_prev_hunk = '' let g:signify_mapping_toggle_highlight = '' let g:signify_mapping_toggle = '' let g:signify_update_on_bufenter = 0 let g:signify_vcs_list = ['git', 'hg'] " ============ " : Autocmds : " ============ if has("eval") " diffthis with some sugar function! s:DiffTheseCommand() if &diff diffoff! else diffthis let window_count = tabpagewinnr(tabpagenr(), '$') if window_count == 2 wincmd w diffthis wincmd w endif endif endfunction command! DiffThese call DiffTheseCommand() " Split a window vertically if it would have at least 79 chars plus a bit " of padding, otherwise split it horizontally function! s:SplitSensiblyCommand(qargs) let padding = 5 " columns for window_number in range(1, winnr('$')) let buffer_number = winbufnr(window_number) let has_no_name = bufname(buffer_number) == '' if has_no_name && getbufline(buffer_number, 1, '$') == [''] if a:qargs != '' execute window_number . 'wincmd w' execute 'edit ' . a:qargs endif return endif endfor if winwidth(0) >= (79 + padding) * 2 execute 'vsplit ' . a:qargs wincmd L else execute 'split ' . a:qargs endif endfunction function! SplitSensibly(path) call SplitSensiblyCommand(a:path) endfunction command! -nargs=* -complete=file SplitSensibly call SplitSensiblyCommand('') command! -nargs=* -complete=file Ss call SplitSensiblyCommand('') command! -nargs=* -complete=file SS call SplitSensiblyCommand('') " If we're in a wide window, enable line numbers. function! WindowWidth() if winwidth(0) > 90 if exists("&relativenumber") setlocal number setlocal relativenumber elseif exists("&number") setlocal number endif else if exists("&relativenumber") setlocal nonumber setlocal norelativenumber elseif exists("&number") setlocal nonumber endif endif endfunction " Toggle the quick fix window function! ToggleQuickfix() " This is broken if someone decides to do copen or cclose without using " the mapping, but just look at the ugliness required to do it properly " http://vim.wikia.com/wiki/Toggle_to_open_or_close_the_quickfix_window if !exists("s:quickfix_open") let s:quickfix_open = 0 return ToggleQuickfix() else if s:quickfix_open :cclose let s:quickfix_open = 0 else :copen let s:quickfix_open = 1 endif endif endfunction " Expand the active window function! ToggleExpando() if !exists("s:expando_enabled") let s:expando_enabled = 0 return ToggleExpando() else augroup expando autocmd! if !s:expando_enabled autocmd WinEnter * :45wincmd > let s:expando_enabled = 1 30wincmd > else let s:expando_enabled = 0 wincmd = endif augroup END endif endfunction " Format tagged comment blocks based on the post-tag indentation let b:comment_tags = ['TODO', 'XXX', 'FIXME'] function! CommentTagFormat() let line_number = v:lnum let first_line = getline(line_number) let comment_leader = split(&commentstring, '%s')[0] let comment = '^\s*' . comment_leader . '\s*' for pattern in map(copy(b:comment_tags), 'comment . v:val . ":\\?\\s*"') if first_line =~ pattern let indent = len(matchstr(first_line, pattern)) - len(comment_leader) let second_line = getline(line_number + 1) call setline(line_number + 1, substitute(second_line, comment, comment_leader . repeat(' ', indent), '')) break endif endfor return 1 endfunction function! DoCommentTagFormat() setlocal formatoptions+=2 setlocal formatexpr=CommentTagFormat() endfunction " Edit file under cursor (not matching :help 'isfname) (:help gf) " Deliberately left off terminating if filename can't be found " to allow user to modify before execution. (:help cWORD) function! EditFileWORD() let file = expand('') if findfile(file, &path) != '' let file .= "\" endif return ":SplitSensibly " . file endfunction function! GdiffAll(...) if a:0 > 0 let branch = a:1 else let branch = 'develop' endif execute 'Git! diff --name-only ' . l:branch global/./execute 'tabedit ' . getline('.') . '| Gdiff ' l:branch . ' | tabprevious' close endfunction if has("autocmd") augroup misc autocmd! " Keep splits equal on resize autocmd VimResized * :wincmd = " Automagic line numbers autocmd BufEnter * :call WindowWidth() " Always do a full syntax refresh autocmd BufEnter * syntax sync fromstart " For help files, make behave like (jump to tag) autocmd FileType help nmap " Jump to the last known cursor position if it's valid (from the docs) autocmd BufReadPost * \ if line("'\"") > 0 && line("'\"") <= line("$") | \ execute "normal! g`\"" | \ endif augroup END " ===================== " : FileType Specific : " ===================== augroup filetypes autocmd! autocmd BufNewFile,BufRead Gemfile setlocal filetype=ruby autocmd BufNewFile,BufRead *.jinja2,*.j2 setlocal filetype=jinja autocmd BufNewFile,BufRead *.mako,*.mak setlocal filetype=html autocmd BufNewFile,BufRead *.tac setlocal filetype=python autocmd BufReadCmd *.egg call zip#Browse(expand("")) autocmd BufWritePost $MYVIMRC source $MYVIMRC " Auto-close fugitive buffers autocmd BufReadPost fugitive://* set bufhidden=delete augroup END augroup formatstupidity " ftplugins are stupid and try to mess with formatoptions autocmd! autocmd BufNewFile,BufRead * setlocal formatoptions-=ro autocmd BufNewFile,BufRead * silent! setlocal formatoptions+=jln augroup END endif endif " ============================ " : Local / Project Specific : " ============================ set secure set exrc