set guioptions=M

let g:is_windows = has('win32')

if exists("+undofile")
    if isdirectory($HOME . '/.vim/_undo') == 0 && !g:is_windows
        :silent !mkdir -p ~/.vim/_undo > /dev/null 2>&1
    endif
    set undodir=./.vim-undo//,~/.vim/_undo//
    set undofile
endif

" Plug
call plug#begin('~/.vim/plugged')

" file management
Plug 'ctrlpvim/ctrlp.vim'
Plug 'FelikZ/ctrlp-py-matcher'
Plug 'justinmk/vim-dirvish'

Plug 'bronson/vim-trailing-whitespace'
Plug 'junegunn/vim-easy-align', { 'on': ['<Plug>(EasyAlign)'] }
Plug 'tpope/vim-commentary'
Plug 'coderifous/textobj-word-column.vim'
Plug 'tpope/vim-repeat'
Plug 'tpope/vim-surround'
if !g:is_windows
    Plug 'christoomey/vim-tmux-navigator'
    Plug 'jgdavey/tslime.vim'
endif
Plug 'joereynolds/vim-minisnip'
Plug 'ajh17/VimCompletesMe'

Plug 'xuanduc987/matchit.zip'

" colorscheme
Plug 'xuanduc987/badwolf'
Plug 'albertorestifo/github.vim'

if filereadable(expand("~/.vimplug.local"))
    source ~/.vimplug.local
endif

call plug#end()

" set
set autoindent
set backspace=indent,eol,start
set nrformats-=octal
set incsearch
set laststatus=2
set wildmenu
set scrolloff=1 sidescrolloff=5
set display+=lastline
set formatoptions+=j " Delete comment character when joining commented lines
setglobal tags-=./tags tags-=./tags; tags^=./tags;
set autoread
set history=1000
if !empty(&viminfo)
    set viminfo^=!
endif

if has('gui_running')
    set encoding=utf-8
endif

set textwidth=80
set nowrap
set colorcolumn=+1 " Color column textwidth + 1

set shiftwidth=4
set expandtab
set smarttab

set hlsearch
set ignorecase " searches are case insensitive...
set smartcase " ... unless they contain at least one capital letter
set gdefault " use global flag by default

set belloff=all " no bell

set ambiwidth=double
set number
set mouse=n " Enable mouse support normal mode only

set ttyfast
set lazyredraw
set ttimeout timeout timeoutlen=800 ttimeoutlen=50
set synmaxcol=200

set nobackup noswapfile

" Natural split
set splitbelow
set splitright

set list " Show special characters for inivisible chars
if (&termencoding ==# 'utf-8' || &encoding ==# 'utf-8') && version >= 700
    let &listchars = "tab:»-,trail:⋅,extends:»,precedes:«"
else
    set listchars=tab:>\ ,trail:-,extends:>,precedes:<
endif

set wildignore+=*.o,*.out,*.obj,.git,*.rbc,*.rbo,*.class,.svn,*.gem,*.swp,*~,._*

" mapping
let mapleader = " "

nnoremap <leader>q :q<cr>

" easy move between windows
nnore <silent> <C-K> :wincmd k<CR>
nnore <silent> <C-J> :wincmd j<CR>
nnore <silent> <C-H> :wincmd h<CR>
nnore <silent> <C-L> :wincmd l<CR>

" Adjust viewports to the same size
nore <Leader>= <C-w>=

" Toggle paste mode
nmap <leader>4 <F4>
nnore <silent> <F4> :set invpaste<CR>:set paste?<CR>
inore <silent> <F4> <ESC>:set invpaste<CR>:set paste?<CR>
set pastetoggle=<F4>

" expand current directory
cnoremap %% <C-R>=fnameescape(expand('%:h')).'/'<cr>
" expand home directory
cnoremap $$ <C-R>=fnameescape(expand('~')).'/'<cr>

" clear highlight
nnore <leader><CR> :noh<CR>

" In command-line mode, C-p use history to complete
cnoremap <C-P> <Up>

" replace last search
nnore s :%s//
xnore s :s//

" easy upper case
inoremap <c-u> <esc>gUiwea

" Easy copy-paste
xnoremap <leader>y "+y
nnoremap <leader>y "+y
xnoremap <leader>p "+p
nnoremap <leader>p "+p

" Ctrl+Space to omni complete
inoremap <c-space> <C-X><C-O>

" Magic search
nnoremap /  /\v
nnoremap ?  ?\v

" copy from unimpaired
function! s:MapNextFamily(map,cmd)
  let map = '<Plug>unimpaired'.toupper(a:map)
  let cmd = '".(v:count ? v:count : "")."'.a:cmd
  let end = '"<CR>'.(a:cmd == 'l' || a:cmd == 'c' ? 'zv' : '')
  execute 'nnoremap <silent> '.map.'Previous :<C-U>exe "'.cmd.'previous'.end
  execute 'nnoremap <silent> '.map.'Next     :<C-U>exe "'.cmd.'next'.end
  execute 'nnoremap <silent> '.map.'First    :<C-U>exe "'.cmd.'first'.end
  execute 'nnoremap <silent> '.map.'Last     :<C-U>exe "'.cmd.'last'.end
  execute 'nmap <silent> ['.        a:map .' '.map.'Previous'
  execute 'nmap <silent> ]'.        a:map .' '.map.'Next'
  execute 'nmap <silent> ['.toupper(a:map).' '.map.'First'
  execute 'nmap <silent> ]'.toupper(a:map).' '.map.'Last'
  if exists(':'.a:cmd.'nfile')
    execute 'nnoremap <silent> '.map.'PFile :<C-U>exe "'.cmd.'pfile'.end
    execute 'nnoremap <silent> '.map.'NFile :<C-U>exe "'.cmd.'nfile'.end
    execute 'nmap <silent> [<C-'.a:map.'> '.map.'PFile'
    execute 'nmap <silent> ]<C-'.a:map.'> '.map.'NFile'
  endif
endfunction

call s:MapNextFamily('a','')
call s:MapNextFamily('b','b')
call s:MapNextFamily('l','l')
call s:MapNextFamily('q','c')
call s:MapNextFamily('t','t')

" insert blank line
nnoremap [<space>     :<c-u>put! =repeat(nr2char(10), v:count1)<cr>'[
nnoremap ]<space>     :<c-u>put =repeat(nr2char(10), v:count1)<cr>

" toogle quickfix/location list
function! GetBufferList()
  redir =>buflist
  silent! ls!
  redir END
  return buflist
endfunction

function! ToggleList(bufname, pfx)
  let buflist = GetBufferList()
  for bufnum in map(filter(split(buflist, '\n'), 'v:val =~ "'.a:bufname.'"'), 'str2nr(matchstr(v:val, "\\d\\+"))')
    if bufwinnr(bufnum) != -1
      exec(a:pfx.'close')
      return
    endif
  endfor
  if a:pfx == 'l' && len(getloclist(0)) == 0
      echohl ErrorMsg
      echo "Location List is Empty."
      return
  endif
  let winnr = winnr()
  exec(a:pfx.'open')
  if winnr() != winnr
    wincmd p
  endif
endfunction

nmap <silent> <leader>c :call ToggleList("Quickfix List", 'c')<CR>
nmap <silent> <leader>l :call ToggleList("Location List", 'l')<CR>

" change cursor shape for urxvt, xterm,...
if exists('$TMUX')
    let &t_SI = "\<Esc>Ptmux;\<Esc>\<Esc>[6 q\<Esc>\\"
    let &t_SR = "\<Esc>Ptmux;\<Esc>\<Esc>[4 q\<Esc>\\"
    let &t_EI = "\<Esc>Ptmux;\<Esc>\<Esc>[2 q\<Esc>\\"
elseif !g:is_windows
    let &t_SI = "\<Esc>[6 q"
    let &t_SR = "\<Esc>[4 q"
    let &t_EI = "\<Esc>[2 q"
endif

" autocmd
augroup vimrc
    autocmd!

    " Remember last location in file, but not for commit messages.
    " see :help last-position-jump
    au BufReadPost * if &filetype !~ '^git\c' && line("'\"") > 0 && line("'\"") <= line("$")
                \| exe "normal! g`\"" | endif

    au FileType qf call AdjustWindowHeight(3, 15)
    " Auto adjust quickfix window
    function! AdjustWindowHeight(minheight, maxheight)
      exe max([min([line("$"), a:maxheight]), a:minheight]) . "wincmd _"
    endfunction
augroup END

" statusline
set statusline=%m                      " modified flag
set statusline+=\ \                    " separator
set statusline+=%f                     " Relative path to file
set statusline+=\ \                    " separator
set statusline+=%h                     " [help]
set statusline+=%r                     " read only flag
set statusline+=%w                     " preview window flag
set statusline+=%y                     " filetype
set statusline+=%=
set statusline+=[%{&fileencoding}]\ \  " file encoding
set statusline+=%-8(%l,%c%V%)          " Line, column-virtual column
set statusline+=\ %6P

if !g:is_windows
    function! SudoWrite()
        write !sudo tee %
        edit!
    endfun

    command! SudoWrite call SudoWrite()
endif

" plugin settings
" disable built-ins
let g:loaded_logipat       = 1
let g:loaded_tarPlugin     = 1
let g:loaded_tar           = 1
let loaded_gzip            = 1
let g:loaded_zipPlugin     = 1
let g:loaded_zip           = 1
let g:loaded_vimballPlugin = 1
let g:loaded_vimball       = 1
let g:loaded_netrw         = 1
let g:loaded_netrwPlugin   = 1

" snippet
let g:minisnip_trigger = '<C-j>'

" Tslime
if !g:is_windows
    let g:tslime_always_current_session = 1
    let g:tslime_always_current_window = 1
    vmap <C-c><C-c> <Plug>SendSelectionToTmux
    nmap <C-c><C-c> <Plug>NormalModeSendToTmux
    nmap <C-c>r <Plug>SetTmuxVars
endif

" ctrlp
nore <Leader>b :CtrlPBuffer<CR>
nore <Leader>; :CtrlPTag<CR>
nore <Leader>, :CtrlPBufTag<CR>
let g:ctrlp_clear_cache_on_exit = 0
if has('python')
    let g:ctrlp_match_func = { 'match': 'pymatcher#PyMatch' }
endif
let g:ctrlp_custom_ignore = {
            \ 'dir': '\v[\/]\.(git|hg|svn)$',
            \ 'file': '\.pyc$\|\.pyo$\|\.rbc$|\.rbo$\|\.class$\|\.o$\|\~$\',
            \ }

" If ag is available use it as filename list generator instead of 'find'
if executable("ag")
    set grepprg=ag\ --nogroup\ --nocolor
    let g:ctrlp_user_command = 'ag -i --nocolor --nogroup
                \ --ignore ".git" --ignore ".svn"
                \ --ignore ".DS_Store" --ignore "node_modules"
                \ --hidden -g "" %s'
endif

" EasyAlign
xmap <CR> <Plug>(EasyAlign)

" VimCompletesMe
let g:vcm_direction = 'p'

" read .vimrc.local
if filereadable(expand("~/.vimrc.local"))
    source ~/.vimrc.local
endif