" Fold Settings {{{
" vim:foldmarker={{{,}}}:foldmethod=marker
" }}}
" vim-plug Config {{{

packadd! matchit

call plug#begin($HOME . '/.vim/plugged')

" Basic config
Plug 'vim-scripts/L9'            " utilities for other plugins
Plug 'scrooloose/nerdcommenter'
Plug 'tpope/vim-surround'        " surround text with s S like this to 'this'
Plug 'tpope/vim-repeat'          " use the . command with more than vim builtins
Plug 'tpope/vim-unimpaired'      " vim options toggleing and other cool stuff
Plug 'tpope/vim-eunuch'          " issue common unix commands from vim
Plug 'tpope/vim-obsession'       " session management
Plug 'Lokaltog/vim-easymotion'   " quick way to navigate around buffers
Plug 'junegunn/vim-easy-align'   " quick text alignment commands
Plug 'Raimondi/delimitMate'      " auto close delimiters
Plug 'wellle/targets.vim'        " more text objects
Plug 'kana/vim-textobj-user'
Plug 'Julian/vim-textobj-variable-segment'
Plug 'whatyouhide/vim-textobj-xmlattr'
Plug 'michaeljsmith/vim-indent-object'
Plug 'itchyny/lightline.vim'     " customize your status line
Plug 'maximbaz/lightline-ale'
Plug 'DataWraith/auto_mkdir'     " make directories that don't exist in file path
Plug 'ConradIrwin/vim-bracketed-paste'

" color schemes
Plug 'acepukas/Zenburn'
Plug 'morhetz/gruvbox'
Plug 'altercation/vim-colors-solarized'
Plug 'chriskempson/base16-vim'
Plug 'whatyouhide/vim-gotham'

" TMUX
Plug 'edkolev/tmuxline.vim'           " generate a status line theme for tmux
Plug 'benmills/vimux'                 " issue commands to tmux pane from vim
Plug 'christoomey/vim-tmux-navigator' " easily navigate tmux panes and vim

" Major feature plugins
Plug 'romainl/vim-qf'                 " commands for quickfix windows
Plug 'ervandew/supertab'
Plug 'junegunn/fzf', { 'dir': $HOME . '/.fzf', 'do': './install --all' }
Plug 'junegunn/fzf.vim'
Plug 'tpope/vim-fugitive'
Plug 'tommcdo/vim-fubitive'
Plug 'airblade/vim-gitgutter'
Plug 'scrooloose/nerdtree', { 'on': 'NERDTreeToggle' }
Plug 'Valloric/YouCompleteMe', { 'do': './install.py --clang-completer --tern-completer' }
Plug 'SirVer/ultisnips'
Plug 'honza/vim-snippets'
Plug 'sjl/gundo.vim/'

" C++ development plugins
"
" Plug 'acepukas/vim-cpp'
Plug 'majutsushi/tagbar'
Plug 'vim-scripts/TagHighlight'
Plug 'rdnetto/YCM-Generator', { 'branch': 'stable' }
" Plug 'xolox/vim-easytags'
Plug 'xolox/vim-misc'
Plug 'vhdirk/vim-cmake'

" Go plugins
Plug 'fatih/vim-go'

" web dev plugins
"
Plug 'w0rp/ale'
Plug 'pangloss/vim-javascript'
Plug 'shawncplus/phpcomplete.vim'
Plug 'StanAngeloff/php.vim'
Plug 'captbaritone/better-indent-support-for-php-with-html'
Plug 'alvan/vim-php-manual'
Plug 'heavenshell/vim-jsdoc'
Plug 'digitaltoad/vim-pug'
Plug 'wavded/vim-stylus'
Plug 'flowtype/vim-flow'
Plug 'gregsexton/MatchTag'
Plug 'rstacruz/sparkup', { 'rtp': 'vim' }
Plug 'othree/html5-syntax.vim'
Plug 'hail2u/vim-css3-syntax'
Plug 'ap/vim-css-color'
Plug 'posva/vim-vue'
" Plug 'groenewege/vim-less'
" Plug 'nono/vim-handlebars'
" Plug 'acepukas/vim-handlebars-conf'

Plug 'freitass/todo.txt-vim'

Plug 'ryanoasis/vim-devicons'

call plug#end()
" }}}
" Terminal {{{

if !(has('win32') || has('win64') || has('gui_running'))

  if has('termguicolors')
    set t_8f=[38;2;%lu;%lu;%lum
    set t_8b=[48;2;%lu;%lu;%lum
    set termguicolors
  endif

  if &term =~ "xterm"
      set t_Co=256
      if has("terminfo")
          let &t_Sf=nr2char(27).'[3%p1%dm'
          let &t_Sb=nr2char(27).'[4%p1%dm'
      else
          let &t_Sf=nr2char(27).'[3%dm'
          let &t_Sb=nr2char(27).'[4%dm'
      endif
  endif

  if &term =~ '256color'
    " Disable Background Color Erase (BCE) so that color schemes work
    " properly when Vim is used inside tmux and GNU screen.
    " See also http://snk.tuxfamily.org/log/vim-256color-bce.html
    set t_ut=
  endif

  if &term =~ '^screen'
      " Page up/down keys
      " http://sourceforge.net/p/tmux/tmux-code/ci/master/tree/FAQ
      execute "set t_kP=\e[5;*~"
      execute "set t_kN=\e[6;*~"

      " Home/end keys
      map <Esc>OH <Home>
      map! <Esc>OH <Home>
      map <Esc>OF <End>
      map! <Esc>OF <End>

      " Arrow keys
      execute "set <xUp>=\e[1;*A"
      execute "set <xDown>=\e[1;*B"
      execute "set <xRight>=\e[1;*C"
      execute "set <xLeft>=\e[1;*D"
  endif

endif
" }}}
" Character Encoding {{{
if has("multi_byte")
    if &termencoding == ""
        let &termencoding = &encoding
    endif
    set encoding=utf-8
    setglobal fileencoding=utf-8 bomb
    set fileencodings=ucs-bom,utf-8,latin1
endif
" }}}
" Initial Commands for setting up vim {{{

" allow per directory .vimrc files
set exrc

" secure prevents certain functions from being used within per dir .vimrc files
set secure

" setting gui opts here before enabling syntax highlighting
if has('gui_running')
  " gvim specific stuff
  set guioptions=acM
endif

if !exists("g:syntax_on")
  syntax enable
endif

set synmaxcol=512

" prevents cursor from jumping to start of line on buffer switch for example
set nostartofline

" default is 4000 which is too slow
set updatetime=250

" allow for fast return to NORMAL mode via ESC
set timeoutlen=250
set ttimeoutlen=0

" save 1000 lines of history
set history=1000

" persistent undo
set undofile
set undodir=$HOME/.vimundo

set undolevels=1000
set undoreload=10000

set title
set belloff=all

" read file when changed externally
set autoread

" allows for more commands by using <leader> in custom mappings
let g:mapleader=" "
let mapleader=g:mapleader

let g:maplocalleader="-"
let maplocalleader=g:maplocalleader

" setting environment paths
set path=.,./**,,

set tags=tags;/

" Delete comment character when joining commented lines
if v:version > 703 || v:version == 703 && has("patch541")
  set formatoptions+=j
endif

" Use only 1 space after "." when joining lines instead of 2
set nojoinspaces

" Split windows below and right instead of above and left
set splitbelow splitright

" }}}
" UI Setup {{{

set mouse=a

" line context
set scrolloff=7

" Text formatting
set expandtab
set softtabstop=2
set shiftwidth=2
set shiftround
set copyindent
set textwidth=0
set tabstop=2
set showmatch
set fileformats=unix,dos,mac

" Searching (REGEX)
set incsearch
set hlsearch " highlighting

" backspace behaves
set backspace=indent,eol,start

" always show invisible chars
set list

" use the same symbols as TextMate for tabstops and EOLs
set listchars+=tab:▸\  " tabs
set listchars+=trail:.
set listchars+=eol:¬
set listchars+=extends:»
set listchars+=precedes:«
set listchars+=nbsp:⣿
set showbreak=↪\  " for wrapped lines

" display line number column
set number

" use relative line numbers
set relativenumber

" allow for wild menu feature
set wildmenu

" Disable output and VCS files
set wildignore+=*.o,*.out,*.obj,.git,*.rbc,*.rbo,*.class,.svn,*.gem

" Disable archive files
set wildignore+=*.zip,*.tar.gz,*.tar.bz2,*.rar,*.tar.xz

" Ignore bundler and sass cache
set wildignore+=*/vendor/gems/*,*/vendor/cache/*,*/.bundle/*,*/.sass-cache/*

" Ignore rails temporary asset caches
set wildignore+=*/tmp/cache/assets/*/sprockets/*,*/tmp/cache/assets/*/sass/*

" Ignore build dir
set wildignore+=build/*,media/*

" Ignore node modules
set wildignore+=node_modules/*,bower_components/*

" Disable temp and backup files
set wildignore+=*.swp,*~,._*

set wildignore+=types_*taghl,tags

" zenburn colorscheme {{{
" colorscheme configuration
" let g:zenburn_enable_TagHighlight=1
" let g:zenburn_disable_Label_underline=1
" let g:zenburn_alternate_Error=1
" colorscheme zenburn
" }}}

" gruvbox colorscheme {{{
function! GruvboxCustom() abort

  " Better highlighting for ale errors
  highlight! link ALEErrorSign GruvboxRedSign
  highlight! link ALEWarningSign GruvboxYellowSign

  " custom highlighting for javascript
  " overrides settings from pangloss/vim-javascript
  highlight! link jsObjectKey          GruvboxBlue
  highlight! link jsStorageClass       GruvboxRed
  highlight! link jsGlobalNodeObjects  GruvboxAqua
  highlight! link jsGlobalObjects      GruvboxYellow
  highlight! link jsFunction           GruvboxAqua
  highlight! link jsFuncArgs           GruvboxYellow
  highlight! link jsDestructuringBlock GruvboxYellow
  highlight! link jsArrowFunction      GruvboxRed
  highlight! link jsObjectBraces       GruvboxFg3
  highlight! link jsTemplateBraces     GruvboxAqua
  highlight! link jsBrackets           GruvboxGreen
  highlight! link jsUndefined          GruvboxPurple
  highlight! link jsNull               GruvboxPurple
  highlight! link jsSuper              GruvboxOrange
  highlight! link jsClassMethodType    GruvboxOrange

  " custom go highlighting based off of go-vim syntax highlighting
  highlight! link goReceiverType    GruvboxAqua
  highlight! link goTypeName        GruvboxAqua
  highlight! link goTypeConstructor GruvboxAqua
  highlight! link goField           GruvboxFg3

endfunction

augroup gruvbox_custom
  autocmd!
  autocmd ColorScheme gruvbox call GruvboxCustom()
augroup END

let g:gruvbox_underline = 0
let g:gruvbox_invert_selection = 0
let g:gruvbox_italicize_comments = 0
let g:gruvbox_contrast_dark = 'medium'
" let g:gruvbox_number_column = 'bg1'
" let g:gruvbox_sign_column = 'bg0'
set background=dark
colorscheme gruvbox

" }}}

" solarized colorscheme {{{
" set background=dark
" colorscheme solarized
" }}}

" base16-ocean colorscheme {{{
" set background=dark
" colorscheme base16-ocean
" }}}

" gotham colorscheme {{{

" function! GothamCustom() abort
"   highlight! link javascriptFuncName SpellLocal
"   highlight! link javascriptAsyncFuncKeyword PreProc
" endfunction
"
" augroup gotham_custom
"   autocmd!
"   autocmd ColorScheme gotham call GothamCustom()
" augroup END
"
" colorscheme gotham

" }}}

" highlight off in insert mode
augroup search_highlight
  autocmd!
  autocmd InsertEnter * :setlocal nohlsearch
  autocmd InsertLeave * :setlocal hlsearch
augroup END

" do not display mode in output statusline
set nosmd

if has('gui_running')
  if has("gui_win32") " NT Windows
    augroup win_gui
      autocmd!
      autocmd GUIEnter * :simalt ~x
    augroup END
    set guifont=DejaVu\ Sans\ Mono\ for\ Powerline:h14
  elseif has("mac")
    set guifont=DejaVu\ Sans\ Mono\ for\ Powerline:h16
  else
    set guifont=DejaVu\ Sans\ Mono\ for\ Powerline\ 20
  endif
endif

" color column for 80 character mark
set cc=80

" clipboard
if has("clipboard")
  if has("mac")
    set clipboard=unnamed
  elseif has("unix")
    set clipboard^=unnamedplus
  endif
endif

" }}}
" Back Up Config {{{
set noswapfile
" }}}
" Session Management {{{
"session management as projects
set sessionoptions=buffers,folds,options,tabpages,winsize
" }}}
" Custom Commands "{{{

" I don't want help right now!
vnoremap <F1> <Esc>
inoremap <F1> <Esc>

" kill the arrow keys
nnoremap <Left>  :nohlsearch<CR>
nnoremap <Right> :nohlsearch<CR>
nnoremap <Up>    :nohlsearch<CR>
nnoremap <Down>  :nohlsearch<CR>

" fast saving
nnoremap <leader>w :w!<cr>

" fast editing of vimrc file
nnoremap <leader>e :vsplit $MYVIMRC<cr>
nnoremap <leader>v :so $MYVIMRC<cr>

" fast editing of todo.txt file
nnoremap <leader>t :e ~/Dropbox/todo/todo.txt<cr>

" no highlight search
" update diff windows
" start syntax highlighting from beginning
" redraw
nnoremap <silent> <backspace> :nohlsearch<cr>:diffupdate<cr>:syntax sync fromstart<cr>:redraw!<cr>

" prevent leaving visual mode when shifting left or right
xnoremap > >gv
xnoremap < <gv

" normal mode command will reselect most recently pasted text
nnoremap gV `[v`]

" change to directory of current file for buffer only, not entire vim instance.
nnoremap <leader>cd :cd %:p:h<cr> :echo expand("%:p:h")<cr>

iabbrev xdate <c-r>=strftime("%Y-%m-%d")<cr>

" piece-wise copy items from line above
inoremap <C-L> @@@<ESC>hhkywjl?@@@<CR>P/@@@<CR>3s

" EscapeVimRegex will escape strings that are to be searched
" against within a regex, preventing characters with special
" meaning from interfering with the search

function! EscapeVimRegex(str) abort
  let l:str = a:str
  let l:subs = [
    \{'char' : '\\',  'rep' : '\\\\'},
    \{'char' : '\^',  'rep' : '\\^'},
    \{'char' : '\$',  'rep' : '\\$'},
    \{'char' : '\.',  'rep' : '\\.'},
    \{'char' : '\*',  'rep' : '\\*'},
    \{'char' : '\~',  'rep' : '\\~'},
    \{'char' : '\[',  'rep' : '\\['},
    \{'char' : '\\n', 'rep' : '\\\\n'},
    \{'char' : '\:',  'rep' : '\\:'}
  \]
  for sub in l:subs
    let l:str = substitute(l:str, sub['char'], sub['rep'], 'g')
  endfor
  return l:str
endfunction

" string substitution for currently visually selected text
xnoremap <leader>r "sy:%s:<C-R>=EscapeVimRegex(@s)<CR>::g<Left><Left>

" count occurrences of visually selected text
xnoremap <leader>c "sy:%s:<C-R>=EscapeVimRegex(@s)<CR>::n<CR>

function! ClearWhiteSpace() abort
  :%s/	/  /ge
  :%s/
//ge
  :%s/\s\+$//
endfunction

command! ClearWhiteSpace :call ClearWhiteSpace()

" do not enter visual mode
nnoremap Q <Nop>

" do not look shit up! ANNOYING!
" nnoremap K <Nop>
vnoremap K <Nop>

" make n search forward always and N search backward always no matter what
" direction searching takes place in. zz forces centering on each search term.
nnoremap <expr> n  'Nn'[v:searchforward] . 'zz'
nnoremap <expr> N  'nN'[v:searchforward] . 'zz'

" navigate wrapped text more easily
nnoremap k gk
nnoremap j gj

" C-n and C-p now complete commands in command mode like up and down arrow
cnoremap <c-n>  <down>
cnoremap <c-p>  <up>

" recall last buffer
nnoremap <leader>l <C-^>

" Toggle semicolon, comma or neither at
" end of line without moving cursor
nnoremap <leader>; :call ToggleSemiColonComma()<cr>

function! ToggleSemiColonComma() abort
    let l:last = getline(line("."))[-1:]
    if l:last =~ ","
        execute "normal! mz$x`z"
    elseif l:last =~ ";"
        execute "normal! mz$r,`z"
    elseif l:last !~ "(,|;)"
        execute "normal! mzA;`z"
    endif
endfunction

" Calculate desired em value based on px font and parent el px font. So first
" argument to PxToEm would be the desired font size in pixels (px). Second
" argument is the size in pixels of the parent HTML element. The output is the
" font-size in EMs based on calculation plus a comment indicating the inputs
" for calculation. Font size in px of parent element must be known for this to
" work. Only really useful for css/less/scss.

" Example:
" :PxToEm 18 16<enter>

" expected output would be something like:
"   font-size: 1.125em; /* == (18px / 16px) */

function! PxToEm(sz,psz) abort
python << EOF
import vim

try:
  # get args
  sz = float(vim.eval("a:sz"))
  psz = float(vim.eval("a:psz"))

  res = sz / psz
  out = "font-size: "
  out += "%.3f" % round(res,3)
  out += "em; /* == ("
  out += "%d" % sz
  out += "px / "
  out += "%d" % psz
  out += "px) */"
  cmd = "normal a" + out

  vim.command(cmd)

except Exception, e:
  print e

EOF
endfunction

command! -nargs=+ PxToEm :call PxToEm(<f-args>)
nnoremap <leader>f :PxToEm 

" quick short cut for deleting all lines with selected text
xnoremap <leader>d "zy:g/"/d

" delete/close buffer
nnoremap <F12> :bd<CR>

function! Preserve(command) abort
  " Preparation: save last search, and cursor position.
  let _s=@/
  let l = line(".")
  let c = col(".")
  " Do the business:
  execute a:command
  " Clean up: restore previous search history, and cursor position
  let @/=_s
  call cursor(l, c)
endfunction

" display syntax information about element under cursor
map <F10> :echo "hi<" . synIDattr(synID(line("."),col("."),1),"name") . '> trans<'
\ . synIDattr(synID(line("."),col("."),0),"name") . "> lo<"
\ . synIDattr(synIDtrans(synID(line("."),col("."),1)),"name") . ">"<CR>

" }}}
" BOM Management {{{
" making sure that no bom is prepended to files when written
augroup bomb
  autocmd!
  autocmd BufWrite * :set nobomb
  " autocmd BufWrite * :set fileformat=unix
augroup END
" }}}
" File Type Settings {{{

if exists("+omnifunc")

  augroup omnifunc
    autocmd!

    autocmd FileType python set omnifunc=pythoncomplete#Complete
    " autocmd FileType javascript set omnifunc=javascriptcomplete#CompleteJS
    autocmd FileType html set omnifunc=htmlcomplete#CompleteTags
    autocmd FileType handlebars set omnifunc=htmlcomplete#CompleteTags
    autocmd FileType xhtml set omnifunc=htmlcomplete#CompleteTags
    autocmd FileType css set omnifunc=csscomplete#CompleteCSS
    autocmd FileType xml set omnifunc=xmlcomplete#CompleteTags
    autocmd FileType php set omnifunc=phpcomplete#CompletePHP
    autocmd FileType c set omnifunc=ccomplete#Complete


    autocmd Filetype *
      \ if &omnifunc == "" |
      \ setlocal omnifunc=syntaxcomplete#Complete |
      \ endif

  augroup END

endif

augroup filetypes
  autocmd!

  " support for cmake files
  autocmd BufNewFile,BufRead CMakeLists.txt set filetype=cmake

  " support for json syntax highlighting
  autocmd BufRead,BufNewFile *.json set filetype=json

  " support for stylus syntax highlighting
  autocmd BufRead,BufNewFile *.styl set filetype=stylus

  " support for markdown syntax highlighting
  autocmd BufRead,BufNewFile *.md set filetype=markdown

  " vim-vue workaround for randomly stopping syntax highlighting
  autocmd FileType vue syntax sync fromstart

augroup END
" }}}