Skip to content

Instantly share code, notes, and snippets.

@robvolk
Created December 16, 2017 20:55
Show Gist options
  • Save robvolk/64c0b1adaaf00aa7576d40d887c5d379 to your computer and use it in GitHub Desktop.
Save robvolk/64c0b1adaaf00aa7576d40d887c5d379 to your computer and use it in GitHub Desktop.
" Rob Volk's .vimrc, completely based off of " This is Rob Volk's .vimrc, completely based off of Gary Bernhardt's .vimrc file
" vim:set ts=2 sts=2 sw=2 expandtab:
autocmd!
call pathogen#infect('bundle/{}')
call plug#begin('~/.vim/plugged')
Plug 'prettier/vim-prettier', {
\ 'do': 'yarn install',
\ 'for': ['javascript', 'typescript', 'css', 'less', 'scss', 'json', 'graphql'] }
Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --all' }
call plug#end()
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" BASIC EDITING CONFIGURATION
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
set nocompatible
" allow unsaved background buffers and remember marks/undo for them
set hidden
" remember more commands and search history
set history=10000
set expandtab
set tabstop=4
set shiftwidth=4
set softtabstop=4
set autoindent
set laststatus=2
set showmatch
set incsearch
set hlsearch
" make searches case-sensitive only if they contain upper-case characters
set ignorecase smartcase
" highlight current line
set cmdheight=1
set switchbuf=useopen
set showtabline=2
set winwidth=79
" This makes RVM work inside Vim. I have no idea why.
set shell=bash
" Prevent Vim from clobbering the scrollback buffer. See
" http://www.shallowsky.com/linux/noaltscreen.html
set t_ti= t_te=
" keep more context when scrolling off the end of a buffer
set scrolloff=3
" Don't make backups at all
set nobackup
set nowritebackup
set backupdir=~/.vim-tmp,~/.tmp,~/tmp,/var/tmp,/tmp
set directory=~/.vim-tmp,~/.tmp,~/tmp,/var/tmp,/tmp
" allow backspacing over everything in insert mode
set backspace=indent,eol,start
" display incomplete commands
set showcmd
" Enable highlighting for syntax
syntax on
" Enable file type detection.
" Use the default filetype settings, so that mail gets 'tw' set to 72,
" 'cindent' is on in C files, etc.
" Also load indent files, to automatically do language-dependent indenting.
filetype plugin indent on
" use emacs-style tab completion when selecting files, etc
set wildmode=longest,list
" make tab completion for files/buffers act like bash
set wildmenu
let mapleader=","
" Fix slow O inserts
:set timeout timeoutlen=1000 ttimeoutlen=100
" Normally, Vim messes with iskeyword when you open a shell file. This can
" leak out, polluting other file types even after a 'set ft=' change. This
" variable prevents the iskeyword change so it can't hurt anyone.
let g:sh_noisk=1
" Modelines (comments that set vim options on a per-file basis)
set modeline
set modelines=3
" Turn folding off for real, hopefully
set foldmethod=manual
set nofoldenable
" Insert only one space when joining lines that contain sentence-terminating
" punctuation like `.`.
set nojoinspaces
" If a file is changed outside of vim, automatically reload it without asking
set autoread
" Function to trim trailing whitespaces
" fun! <SID>StripTrailingWhitespaces()
"     let l = line(".")
"     let c = col(".")
"     %s/\s\+$//e
"     call cursor(l, c)
" endfun
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" CUSTOM AUTOCMDS
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
augroup vimrcEx
" Clear all autocmds in the group
autocmd!
autocmd FileType text setlocal textwidth=78
" Jump to last cursor position unless it's invalid or in an event handler
autocmd BufReadPost *
\ if line("'\"") > 0 && line("'\"") <= line("$") |
\ exe "normal g`\"" |
\ endif
"for ruby, autoindent with two spaces, always expand tabs
autocmd FileType ruby,haml,eruby,yaml,html,javascript,sass,cucumber,markdown,liquid,typescript set ai sw=2 sts=2 et
autocmd FileType python set sw=4 sts=4 et
autocmd! BufRead,BufNewFile *.sass setfiletype sass
autocmd BufRead *.mkd set ai formatoptions=tcroqn2 comments=n:&gt;
autocmd BufRead *.markdown set ai formatoptions=tcroqn2 comments=n:&gt;
" Indent p tags
" autocmd FileType html,eruby if g:html_indent_tags !~ '\\|p\>' | let g:html_indent_tags .= '\|p\|li\|dt\|dd' | endif
" Don't syntax highlight markdown because it's often wrong
autocmd! FileType mkd setlocal syn=off
" Leave the return key alone when in command line windows, since it's used
" to run commands there.
autocmd! CmdwinEnter * :unmap <cr>
autocmd! CmdwinLeave * :call MapCR()
" *.md is markdown
autocmd! BufNewFile,BufRead *.md setlocal ft=
" indent slim two spaces, not four
autocmd! FileType *.slim set sw=2 sts=2 et
" auto trim whitespaces on save
" autocmd FileType c,cpp,java,php,ruby,python,javascript,haml,yaml,html,sass,cucumber,slim autocmd BufWritePre <buffer> :call <SID>StripTrailingWhitespaces()
augroup END
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" COLOR
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
:set t_Co=256 " 256 colors
:set background=dark
:color grb256
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" STATUS LINE
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
:set statusline=%<%f\ (%{&ft})\ %-4(%m%)%=%-19(%3l,%02c%03V%)
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" MISC KEY MAPS
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
map <leader>y "*y
" Move around splits with <c-hjkl>
nnoremap <c-j> <c-w>j
nnoremap <c-k> <c-w>k
nnoremap <c-h> <c-w>h
nnoremap <c-l> <c-w>l
" Insert a hash rocket with <c-l>
imap <c-l> <space>=><space>
" Can't be bothered to understand ESC vs <c-c> in insert mode
imap <c-c> <esc>
nnoremap <leader><leader> <c-^>
" Close all other windows, open a vertical split, and open this file's test
" alternate in it.
nnoremap <leader>s :call FocusOnFile()<cr>
function! FocusOnFile()
tabnew %
normal! v
normal! l
call OpenTestAlternate()
normal! h
endfunction
" Reload in chrome
map <leader>l :w\|:silent !reload-chrome<cr>
" Align selected lines
vnoremap <leader>ib :!align<cr>
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" MULTIPURPOSE TAB KEY
" Indent if we're at the beginning of a line. Else, do completion.
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
function! InsertTabWrapper()
let col = col('.') - 1
if !col || getline('.')[col - 1] !~ '\k'
return "\<tab>"
else
return "\<c-p>"
endif
endfunction
inoremap <expr> <tab> InsertTabWrapper()
inoremap <s-tab> <c-n>
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" OPEN FILES IN DIRECTORY OF CURRENT FILE
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
cnoremap <expr> %% expand('%:h').'/'
map <leader>e :edit %%
map <leader>v :view %%
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" RENAME CURRENT FILE
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
function! RenameFile()
let old_name = expand('%')
let new_name = input('New file name: ', expand('%'), 'file')
if new_name != '' && new_name != old_name
exec ':saveas ' . new_name
exec ':silent !rm ' . old_name
redraw!
endif
endfunction
map <leader>n :call RenameFile()<cr>
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" PROMOTE VARIABLE TO RSPEC LET
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
function! PromoteToLet()
:normal! dd
" :exec '?^\s*it\>'
:normal! P
:.s/\(\w\+\) = \(.*\)$/let(:\1) { \2 }/
:normal ==
endfunction
:command! PromoteToLet :call PromoteToLet()
:map <leader>p :PromoteToLet<cr>
" """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" " EXTRACT VARIABLE (SKETCHY)
" """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" function! ExtractVariable()
" let name = input("Variable name: ")
" if name == ''
" return
" endif
" " Enter visual mode (not sure why this is needed since we're already in
" " visual mode anyway)
" normal! gv
" " Replace selected text with the variable name
" exec "normal c" . name
" " Define the variable on the line above
" exec "normal! O" . name . " = "
" " Paste the original selected text to be the variable value
" normal! $p
" endfunction
" vnoremap <leader>rv :call ExtractVariable()<cr>
" """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" " INLINE VARIABLE (SKETCHY)
" """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" function! InlineVariable()
" " Copy the variable under the cursor into the 'a' register
" :let l:tmp_a = @a
" :normal "ayiw
" " Delete variable and equals sign
" :normal 2daW
" " Delete the expression into the 'b' register
" :let l:tmp_b = @b
" :normal "bd$
" " Delete the remnants of the line
" :normal dd
" " Go to the end of the previous line so we can start our search for the
" " usage of the variable to replace. Doing '0' instead of 'k$' doesn't
" " work; I'm not sure why.
" normal k$
" " Find the next occurence of the variable
" exec '/\<' . @a . '\>'
" " Replace that occurence with the text we yanked
" exec ':.s/\<' . @a . '\>/' . escape(@b, "/")
" :let @a = l:tmp_a
" :let @b = l:tmp_b
" endfunction
" nnoremap <leader>ri :call InlineVariable()<cr>
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Md5 COMMAND
" Show the MD5 of the current buffer
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
command! -range Md5 :echo system('echo '.shellescape(join(getline(<line1>, <line2>), '\n')) . '| md5')
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" OpenChangedFiles COMMAND
" Open a split for each dirty file in git
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
function! OpenChangedFiles()
only " Close all windows, unless they're modified
let status = system('git status -s | grep "^ \?\(M\|A\|UU\)" | sed "s/^.\{3\}//"')
let filenames = split(status, "\n")
exec "edit " . filenames[0]
for filename in filenames[1:]
exec "sp " . filename
endfor
endfunction
command! OpenChangedFiles :call OpenChangedFiles()
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" InsertTime COMMAND
" Insert the current time
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
command! InsertTime :normal a<c-r>=strftime('%F %H:%M:%S.0 %z')<cr>
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" FindConditionals COMMAND
" Start a search for conditional branches, both implicit and explicit
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
command! FindConditionals :normal /\<if\>\|\<unless\>\|\<and\>\|\<or\>\|||\|&&<cr>
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Diff tab management: open the current git diff in a tab
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
command! GdiffInTab tabedit %|vsplit|Gdiff
nnoremap <leader>d :GdiffInTab<cr>
nnoremap <leader>D :tabclose<cr>
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Test quickfix list management
"
" If the tests write a tmp/quickfix file, these mappings will navigate through
" it
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
function! GetBufferList()
redir =>buflist
silent! ls
redir END
return buflist
endfunction
function! BufferIsOpen(bufname)
let buflist = GetBufferList()
for bufnum in map(filter(split(buflist, '\n'), 'v:val =~ "'.a:bufname.'"'), 'str2nr(matchstr(v:val, "\\d\\+"))')
if bufwinnr(bufnum) != -1
return 1
endif
endfor
return 0
endfunction
function! ToggleQuickfix()
if BufferIsOpen("Quickfix List")
cclose
else
call OpenQuickfix()
endif
endfunction
function! OpenQuickfix()
cgetfile tmp/quickfix
topleft cwindow
if &ft == "qf"
cc
endif
endfunction
nnoremap <leader>q :call ToggleQuickfix()<cr>
nnoremap <leader>Q :cc<cr>
nnoremap <leader>j :cnext<cr>
nnoremap <leader>k :cprev<cr>
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" RemoveFancyCharacters COMMAND
" Remove smart quotes, etc.
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
function! RemoveFancyCharacters()
let typo = {}
let typo["“"] = '"'
let typo["”"] = '"'
let typo["‘"] = "'"
let typo["’"] = "'"
let typo["–"] = '--'
let typo["—"] = '---'
let typo["…"] = '...'
:exe ":%s/".join(keys(typo), '\|').'/\=typo[submatch(0)]/ge'
endfunction
command! RemoveFancyCharacters :call RemoveFancyCharacters()
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Selecta Mappings
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Run a given vim command on the results of fuzzy selecting from a given shell
" command. See usage below.
function! SelectaCommand(choice_command, selecta_args, vim_command)
try
let selection = system(a:choice_command . " | selecta " . a:selecta_args)
catch /Vim:Interrupt/
" Swallow the ^C so that the redraw below happens; otherwise there will be
" leftovers from selecta on the screen
redraw!
return
endtry
redraw!
exec a:vim_command . " " . selection
endfunction
function! SelectaFile(path)
call SelectaCommand("find " . a:path . "/* -type f", "", ":e")
endfunction
nnoremap <leader>f :call SelectaFile(".")<cr>
nnoremap <leader>gv :call SelectaFile("app/views")<cr>
nnoremap <leader>gc :call SelectaFile("app/controllers")<cr>
nnoremap <leader>gm :call SelectaFile("app/models")<cr>
nnoremap <leader>gh :call SelectaFile("app/helpers")<cr>
nnoremap <leader>gl :call SelectaFile("lib")<cr>
nnoremap <leader>gp :call SelectaFile("public")<cr>
nnoremap <leader>gs :call SelectaFile("public/stylesheets")<cr>
nnoremap <leader>gf :call SelectaFile("features")<cr>
"Fuzzy select
function! SelectaIdentifier()
" Yank the word under the cursor into the z register
normal "zyiw
" Fuzzy match files in the current directory, starting with the word under
" the cursor
call SelectaCommand("find * -type f", "-s " . @z, ":e")
endfunction
nnoremap <c-g> :call SelectaIdentifier()<cr>
""""""""""""""""""""""
" Rob's stuff
""""""""""""""""""""""
:set autoread
nmap <silent> <leader>t :FZF<CR>
let g:ackprg = 'ag --nogroup --nocolor --column'
" navigate between buffers
nmap <tab> :bnext<cr>
" vim-test
nmap <silent> <leader>r :TestNearest<CR>
nmap <silent> <leader>T :TestFile<CR>
nmap <silent> <leader>a :TestSuite<CR>
nmap <silent> <leader>l :TestLast<CR>
nmap <silent> <leader>g :TestVisit<CR>
function! RunTestFile()
:wa
:TestLast
endfunction
function! MapCR()
nnoremap <cr> :call RunTestFile() <cr>
endfunction
call MapCR()
let g:easytags_cmd = '/usr/local/bin/ctags'
let g:easytags_async=1
let g:easytags_on_cursorhold=0
let g:easytags_by_filetype='~/.vim/tags'
let g:easytags_syntax_keyword = 'always'
let g:easytags_auto_highlight = 0
" Quickly edit/reload the vimrc file
nmap <silent> <leader>ev :e $MYVIMRC<CR>
nmap <silent> <leader>sv :so $MYVIMRC<CR>
map <C-n> :NERDTreeToggle<CR>
" Trim trailing whitespace on save
autocmd BufWritePre * :%s/\s\+$//e
" run docker tests
function! RunDockerTests()
:wa
:! docker-compose run test
endfunction
nmap <silent> <leader>tt :call RunDockerTests() <cr>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment