" vim:fdm=marker

let s:darwin = has('mac')

set nocompatible
" otherwise NERDTree shows strange character instead of arrows
set encoding=utf-8

" Plugin: vim-plug {{{
"https://github.com/junegunn/vim-plug/wiki/faq#automatic-installation
if empty(glob('~/.vim/autoload/plug.vim'))
  silent !curl -fLo ~/.vim/autoload/plug.vim --create-dirs
    \ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
  autocmd VimEnter * PlugInstall
endif

" vim-plug, install under ~/.vim/plugged
call plug#begin('~/.vim/plugged')
" Plugins {{{
" General {{{
Plug 'AndrewRadev/splitjoin.vim'
Plug 'ConradIrwin/vim-bracketed-paste'
Plug 'Lokaltog/vim-easymotion'
Plug 'Raimondi/delimitMate'
Plug 'Valloric/MatchTagAlways'
Plug 'Valloric/YouCompleteMe', { 'do': './install.py --clang-completer --tern-completer' }
Plug 'Yggdroot/indentLine'
Plug 'airblade/vim-gitgutter'
Plug 'airblade/vim-rooter'
Plug 'bling/vim-airline'
Plug 'editorconfig/editorconfig-vim'
Plug 'haya14busa/incsearch.vim'
Plug 'haya14busa/vim-asterisk'
Plug 'honza/dockerfile.vim'
Plug 'janko-m/vim-test'
Plug 'jpalardy/vim-slime'
Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': 'yes \| ./install' }
Plug 'junegunn/fzf.vim'
Plug 'junegunn/vim-peekaboo'
Plug 'junegunn/vim-easy-align', { 'on': ['<Plug>(EasyAlign)', 'EasyAlign'] }
Plug 'junegunn/vim-emoji'
Plug 'kannokanno/previm'
Plug 'keith/investigate.vim'
Plug 'kien/rainbow_parentheses.vim'
Plug 'kshenoy/vim-signature'
Plug 'majutsushi/tagbar'
Plug 'mhinz/vim-grepper'
Plug 'scrooloose/nerdtree', { 'on': 'NERDTreeToggle' }
Plug 'scrooloose/syntastic'
Plug 'sjl/gundo.vim'
Plug 'szw/vim-g'
Plug 'terryma/vim-expand-region'
Plug 'terryma/vim-multiple-cursors'
Plug 'tommcdo/vim-exchange'
Plug 'tomtom/tcomment_vim'
Plug 'tpope/vim-abolish'
Plug 'tpope/vim-characterize'
Plug 'tpope/vim-dispatch'
Plug 'tpope/vim-obsession'
Plug 'tpope/vim-projectionist'
Plug 'tpope/vim-repeat'
Plug 'tpope/vim-rsi'
Plug 'tpope/vim-sensible'
Plug 'tpope/vim-surround'
Plug 'tpope/vim-unimpaired'
Plug 'tyru/open-browser.vim'
Plug 'unblevable/quick-scope'
" }}}
" colorscheme {{{
Plug 'NLKNguyen/papercolor-theme'
Plug 'altercation/vim-colors-solarized'
Plug 'chriskempson/tomorrow-theme', { 'rtp': 'vim' }
Plug 'gilgigilgil/anderson.vim'
Plug 'godlygeek/csapprox'
Plug 'google/vim-colorscheme-primary'
Plug 'itchyny/landscape.vim'
Plug 'jnurmine/Zenburn'
Plug 'jonathanfilip/vim-lucius'
Plug 'jpo/vim-railscasts-theme'
Plug 'jscappini/material.vim'
Plug 'junegunn/seoul256.vim'
Plug 'morhetz/gruvbox'
Plug 'nanotech/jellybeans.vim'
Plug 'romainl/Apprentice'
Plug 'tomasr/molokai'
Plug 'w0ng/vim-hybrid'
Plug 'zenorocha/dracula-theme', { 'rtp': 'vim' }
" }}}
" Git {{{
Plug 'low-ghost/nerdtree-fugitive'
Plug 'tpope/vim-fugitive'
Plug 'tpope/vim-git'
Plug 'Xuyuanp/nerdtree-git-plugin'
" }}}
" Front-End {{{
Plug 'ap/vim-css-color', { 'for': ['css', 'scss'] }
Plug 'cakebaker/scss-syntax.vim'
Plug 'digitaltoad/vim-pug', { 'for': 'pug' }
Plug 'hail2u/vim-css3-syntax'
Plug 'heavenshell/vim-jsdoc', { 'for': 'javascript' }
Plug 'kewah/vim-stylefmt', { 'for': ['css', 'scss'] }
Plug 'pangloss/vim-javascript', { 'for': 'javascript' }
Plug 'mxw/vim-jsx', { 'for': 'javascript' }
Plug 'kchmck/vim-coffee-script', { 'for': 'coffee' }
Plug 'maksimr/vim-jsbeautify', { 'for': ['html', 'json'] }
Plug 'marijnh/tern_for_vim', { 'do': 'npm i' }
Plug 'mattn/emmet-vim'
Plug 'millermedeiros/vim-esformatter', { 'for': 'javascript' }
Plug 'mvolkmann/vim-js-arrow-function', { 'for': 'javascript' }
Plug 'moll/vim-node'
Plug 'mtscout6/syntastic-local-eslint.vim', { 'for': 'javascript' }
Plug 'othree/html5.vim'
" }}}
" snippets {{{
Plug 'SirVer/ultisnips'
Plug 'honza/vim-snippets'
" }}}
" tmux {{{
Plug 'christoomey/vim-tmux-navigator'
Plug 'edkolev/tmuxline.vim'
Plug 'wellle/tmux-complete.vim'
" }}}
" clojure & clojurescript {{{
Plug 'guns/vim-sexp', { 'for': 'clojure' }
Plug 'tpope/vim-fireplace', { 'for': 'clojure' }
Plug 'tpope/vim-sexp-mappings-for-regular-people', { 'for': 'clojure' }
Plug 'venantius/vim-cljfmt', { 'for': 'clojure' }
" }}}
" Elixir {{{
Plug 'elixir-lang/vim-elixir', { 'for': ['elixir', 'eelixir'] }
" }}}
" Elm {{{
Plug 'ElmCast/elm-vim', { 'for': ['elm'] }
" }}}
" }}}
call plug#end()
" }}}

" Allow hidden buffers, don't limit to 1 file per window/split
set hidden

" enable hybrid line number mode
set relativenumber
set number

" more intuitive split
set splitbelow
set splitright

" turn off backup for now
set nobackup
set noswapfile

" change the terminal's title
set title

" highlight current line
set cursorline

if (exists('+colorcolumn'))
  set colorcolumn=80
endif

" enable mouse in all modes
if has('mouse')
  set mouse=a
endif

" flashing instead of beeping
set visualbell

" toggle paste mode
set pastetoggle=<F2>

let mapleader = "\<Space>"

" Indentation {{{
" use soft tab
set expandtab
" number of visual spaces per TAB
set tabstop=2
" number of space to use for autoindenting
set shiftwidth=2
" }}}
" Mappings {{{
cmap w!! w !sudo tee > /dev/null %

" Move visual block
vnoremap J :m '>+1<CR>gv=gv
vnoremap K :m '<-2<CR>gv=gv

" jk is escape
inoremap jk <Esc>

" move vertically by visual line
nnoremap j gj
nnoremap k gk

" swap the jump keys
nnoremap ' `
nnoremap ` '

" Part of the Right Hand system, http://reefpoints.dockyard.com/2013/09/11/vim-staying-on-home-row-via-map.html
" in INSERT mode, save & back to INSERT mode
inoremap ;j <C-O>:update<CR>
" in NORMAL mode, save & back to NORMAL mode
nnoremap ;j :update<CR>

" Quickly edit/reload the vimrc file
nnoremap <leader>ev :e $MYVIMRC<CR>
nnoremap <leader>sv :so $MYVIMRC<CR>

nnoremap <leader>ft :set ft=

nnoremap <leader>w :w<cr>

" Resize window
noremap <up>    <C-W>+
noremap <down>  <C-W>-
noremap <left>  3<C-W><
noremap <right> 3<C-W>>

" http://vim-jp.org/blog/2015/06/30/visual-ctrl-a-ctrl-x.html
" not work on Neovim yet
vnoremap <c-a> <c-a>gv
vnoremap <c-x> <c-x>gv

vnoremap Y "*y
" Yank from the cursor to the end of the line, to be consistent with C and D.
nnoremap Y "*y$

" Visual shifting (does not exit Visual mode)
vnoremap > >gv
vnoremap < <gv

" Map tab to indent in visual mode
vmap <Tab> >gv
vmap <S-Tab> <gv

" Learn the following 2 from Damian Conway
" 1) exchange 'S' for:
nmap  S  :%s//g<LEFT><LEFT>
" 2) exchange 'M' for:
nmap <expr>  M  ':%s/' . @/ . '//g<LEFT><LEFT>'

if s:darwin
  " try to open the current file in default application
  nnoremap <leader>o :silent !open '%'<cr>
endif
" }}}
" Search {{{
set hlsearch
set ignorecase
set smartcase
" Plugin: incsearch {{{2
map /  <Plug>(incsearch-forward)
map ?  <Plug>(incsearch-backward)
map g/ <Plug>(incsearch-stay)
" turns 'hlsearch' off automatically after searching-related motions
let g:incsearch#auto_nohlsearch = 1
map n  <Plug>(incsearch-nohl-n)
map N  <Plug>(incsearch-nohl-N)
map *  <Plug>(incsearch-nohl-*)
map #  <Plug>(incsearch-nohl-#)
map g* <Plug>(incsearch-nohl-g*)
map g# <Plug>(incsearch-nohl-g#)
" }}}2
" Plugin: vim-asterisk {{{2
map *   <Plug>(asterisk-*)
map #   <Plug>(asterisk-#)
map g*  <Plug>(asterisk-g*)
map g#  <Plug>(asterisk-g#)
map z*  <Plug>(asterisk-z*)
map gz* <Plug>(asterisk-gz*)
map z#  <Plug>(asterisk-z#)
map gz# <Plug>(asterisk-gz#)
" }}}2
" }}}
" Plugin: EasyMotion {{{
" Bi-directional 2-character search
" `s{char}{char}{label}`
nmap s <Plug>(easymotion-s2)
" Turn on case sensitive feature
let g:EasyMotion_smartcase = 1
" JK motions: Line motions
map <leader>j <Plug>(easymotion-j)
map <leader>k <Plug>(easymotion-k)
" }}}
" Plugin: editorconfig {{{
let g:EditorConfig_exclude_patterns = ['fugitive://.*', 'scp://.*']
" }}}
" Plugin: fzf {{{
nnoremap <silent> <C-p> :FZF --cycle<CR>
" }}}
" Plugin: fzf.vim {{{
nnoremap <leader>b :Buffers<CR>
nnoremap <leader>C :Colors<CR>
nnoremap <leader>f :Files<CR>
" }}}
" Plugin: gundo.vim {{{
nnoremap <F5> :GundoToggle<CR>
" }}}
" Plugin: indentLine {{{
let g:indentLine_conceallevel=0
" }}}
" Plugin: investigate.vim {{{
if s:darwin
  let g:investigate_use_dash=1
endif
" }}}
" Plugin: nerdtree {{{
augroup nerdtree
  autocmd!
  let g:NERDTreeHijackNetrw = 0
  map <silent> <leader>n :NERDTreeToggle<CR> :NERDTreeMirror<CR>
  " open a NERDTree automatically when vim starts up if no files were specified
  "autocmd StdinReadPre * let s:std_in=1
  "autocmd VimEnter * if argc() == 0 && !exists("s:std_in") | NERDTree | endif

  " close vim if the only window left open is a NERDTree
  autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTreeType") && b:NERDTreeType == "primary") | q | endif
augroup END
" }}}
" Plugin: open-browser.vim {{{
let g:netrw_nogx = 1 " disable netrw's gx mapping.
nmap gx <Plug>(openbrowser-smart-search)
vmap gx <Plug>(openbrowser-smart-search)
" }}}
" Plugin: previm {{{
nnoremap <silent> <leader>pv :PrevimOpen<CR>
" }}}
" Plugin: quick-scope {{{
let g:qs_highlight_on_keys = ['f', 'F', 't', 'T']
" }}}
" Plugin: rainbow_parentheses.vim {{{
augroup rainbow_parentheses.vim
  autocmd!
  autocmd VimEnter * RainbowParenthesesActivate
  autocmd BufEnter * RainbowParenthesesLoadRound
  autocmd BufEnter * RainbowParenthesesLoadSquare
  autocmd BufEnter * RainbowParenthesesLoadBraces
augroup END
" }}}
" Plugin: scss-syntax.vim {{{
augroup scss-syntax.vim
  autocmd!
  autocmd FileType scss setlocal iskeyword+=-
augroup END
" }}}
" Plugin: syntastic {{{
set statusline+=%#warningmsg#
set statusline+=%{SyntasticStatuslineFlag()}
set statusline+=%*

let g:syntastic_always_populate_loc_list = 1
let g:syntastic_auto_loc_list = 0

" :h syntastic-fish
let g:syntastic_shell = '/bin/zsh'
let g:syntastic_aggregate_errors = 0
let g:syntastic_javascript_checkers = ['eslint']

nnoremap <silent> <leader>sc :SyntasticCheck<CR>
" }}}
" Plugin: tagbar {{{
nmap <F8> :TagbarToggle<CR>
let g:tagbar_type_coffee = {
    \ 'ctagstype' : 'coffee',
    \ 'kinds'     : [
        \ 'c:classes',
        \ 'm:methods',
        \ 'f:functions',
        \ 'v:variables',
        \ 'f:fields',
    \ ]
\ }
let g:tagbar_type_markdown = {
    \ 'ctagstype' : 'markdown',
    \ 'kinds' : [
        \ 'h:Heading_L1',
        \ 'i:Heading_L2',
        \ 'k:Heading_L3'
    \ ]
\ }
" }}}
" Plugin: tern_for_vim {{{
let maplocalleader=","
let g:tern_map_keys=1
let g:tern_show_argument_hints='on_hold'
" }}}
" Plugin: tmuxline.vim {{{
let g:tmuxline_theme = 'airline'
let g:tmuxline_powerline_separators = 0
" }}}
" Plugin: UltiSnips {{{
" to avoid conflict with YouCompleteMe
set rtp+=~/dotfiles/vim/
let g:UltiSnipsEditSplit="vertical"
let g:UltiSnipsExpandTrigger="<c-j>"
let g:UltiSnipsSnippetsDir="~/dotfiles/vim/snips/"
let g:UltiSnipsSnippetDirectories=["UltiSnips", "snips"]
" }}}
" Plugin: vim-airline {{{
" make symbols look okay
let g:airline_powerline_fonts = 1
" }}}
" Plugin: vim-coffee-script {{{
augroup vim-coffeescript-script
  autocmd!
  autocmd FileType coffee setl foldmethod=indent nofoldenable
  let coffee_compile_vert = 1
  let coffee_watch_vert   = 1
  autocmd FileType coffee noremap <buffer> <C-c>c :CoffeeCompile<cr>
  autocmd FileType coffee noremap <buffer> <C-c>r :CoffeeRun<cr>
  autocmd FileType coffee noremap <buffer> <C-c>w :CoffeeWatch<cr>
augroup END
" }}}
" Plugin: vim-css3-syntax {{{
augroup vim-css3-syntax
  autocmd!
  " Plugin: vim-css3-syntax
  autocmd FileType css setlocal iskeyword+=-
augroup END
" }}}
" Plugin: vim-stylefmt {{{
" require `npm i -g stylefmt`
nnoremap <silent> <leader>cs :Stylefmt<CR>
vnoremap <silent> <leader>cs :StylefmtVisual<CR>
" }}}
" Plugin: vim-dispatch {{{
autocmd FileType html let b:dispatch = '!open %:p'
nnoremap <F9> :Dispatch<CR>
" }}}
" Plugin: vim-easy-align {{{
" Start interactive EasyAlign in visual mode (e.g. vipga)
xmap ge <Plug>(EasyAlign)
" Start interactive EasyAlign for a motion/text object (e.g. gaip)
nmap ge <Plug>(EasyAlign)
" }}}
" Plugin: vim-emoji {{{
" trigger by CTRL-X CTRL-U in INSERT mode with terminal vim
" Using Emojis as Git Gutter symbols, work only with terminal vim(?)
silent! if emoji#available()
  let g:gitgutter_sign_added = emoji#for('small_blue_diamond')
  let g:gitgutter_sign_modified = emoji#for('small_orange_diamond')
  let g:gitgutter_sign_removed = emoji#for('small_red_triangle')
  let g:gitgutter_sign_modified_removed = emoji#for('collision')
endif
" Plugin: vim-esformatter {{{
nnoremap <silent> <leader>es :Esformatter<CR>
vnoremap <silent> <leader>es :EsformatterVisual<CR>
" }}}
" Plugin: vim-expand-region {{{
vmap v <Plug>(expand_region_expand)
vmap <C-v> <Plug>(expand_region_shrink)
" }}}
" Plugin: vim-fugitive {{{
nmap <leader>gb :Gblame<cr>
nmap <leader>gs :Gstatus<cr>
" }}}
" Plugin: vim-g {{{
let g:vim_g_command = "Go"
let g:vim_g_f_command = "Gf"
" }}}
" Plugin: vim-grepper {{{
nnoremap <leader>ag :Grepper -tool ag -highlight<cr>
nnoremap <leader>* :Grepper -tool ag -cword -noprompt<cr>
nmap gs <plug>(GrepperOperator)
xmap gs <plug>(GrepperOperator)
" }}}
" Plugin: vim-javascript {{{
let g:javascript_conceal_function   = "ƒ"
let g:javascript_conceal_null       = "ø"
let g:javascript_conceal_this       = "@"
let g:javascript_conceal_return     = "⇚"
let g:javascript_conceal_undefined  = "¿"
let g:javascript_conceal_NaN        = "ℕ"
let g:javascript_conceal_prototype  = "¶"
let g:javascript_conceal_static     = "•"
let g:javascript_conceal_super      = "Ω"
" }}}
" Plugin: vim-jsbeautify {{{
augroup vim-jsbeautify
  autocmd!
  autocmd FileType html noremap <buffer> <c-f> :call HtmlBeautify()<CR>
  autocmd FileType html vnoremap <buffer> <c-f> :call RangeHtmlBeautify()<CR>
  autocmd FileType json noremap <buffer> <c-f> :call JsonBeautify()<cr>
  autocmd FileType json vnoremap <buffer> <c-f> :call RangeJsonBeautify()<cr>
augroup END
" }}}
" Plugin: vim-jsdoc {{{
let g:jsdoc_allow_input_prompt = 1
" reserve <C-l> for the mapping used by 'vim-tmux-navigator'
let g:jsdoc_default_mapping    = 0
" }}}
" Plugin: vim-jsx {{{
let g:jsx_ext_required = 0
" }}}
" Plugin: vim-signature {{{
nnoremap ]" :<C-U>call signature#mark#Goto("next", "spot", "global")<CR>
nnoremap [" :<C-U>call signature#mark#Goto("prev", "spot", "global")<CR>
" }}}
" Plugin: vim-slime {{{
let g:slime_target = "tmux"
" }}}
" Plugin: vim-test {{{
let test#strategy = "dispatch"
nmap <silent> <leader>t :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>
" }}}
" Autocommands {{{1
augroup docker " {{{2
  " reference: https://github.com/docker/docker/blob/master/contrib/syntax/vim/ftdetect/dockerfile.vim
  autocmd BufNewFile,BufRead [Dd]ockerfile,Dockerfile.* set filetype=dockerfile
augroup END " }}}2
augroup git " {{{2
  autocmd!
  " commit message
  autocmd FileType gitcommit setlocal spell textwidth=72
augroup END " }}}2
augroup markdown " {{{2
  autocmd!
  " force *.md as MarkDown, https://github.com/tpope/vim-markdown
  autocmd BufNewFile,BufReadPost *.md set filetype=markdown
  
  " highlight markdown fenced code syntax 
  let g:markdown_fenced_languages = ['html', 'json', 'python', 'scss', 'sh', 'sql', 'yaml']
augroup END " }}}2
" }}}1

" Auto-save a file when you leave insert mode
autocmd InsertLeave,TextChanged * if expand('%') != '' | update | endif

" Temporarily disabled {{{
" cut down key stroke for normal mode
" but lose the capability for repeating the linewise character search
"nnoremap ; :

" bind K to grep word under cursor
"nnoremap K :grep! "\b<C-R><C-W>\b"<CR>:cw<CR>
" }}}

" Local config
if filereadable($HOME . "/.vimrc.local")
  source ~/.vimrc.local
endif

if has('nvim')
  " let $NVIM_TUI_ENABLE_TRUE_COLOR=1
  let $NVIM_TUI_ENABLE_CURSOR_SHAPE=1

  " save screen estate
  let $FZF_DEFAULT_OPTS = $FZF_DEFAULT_OPTS.' --inline-info'
endif