"""""""""""""""""""""""""""""""""""""""""""""""""""""""
" vimrc
"""""""""""""""""""""""""""""""""""""""""""""""""""""""

" Initializing {{{1

" Skip initialization if '+eval' feature is disabled {{{
" Note: (see: :help no-eval-feature)
"   In '-eval' environment, the argument of 'if' (including '| endif')
"   is ignored. So all lines after 'if' are ignored too. But
"   backslashes of line-continuation are still recognized and
"   cause errors when 'compatible' option is set. So
"   setting 'cpoptions' to enable line-continuation before
"   'if' statement makes sure all lines get ignored without error.
" }}}
set cpoptions-=C | if 0 | endif

" Default properties
let g:is_windows = has('win32') || has('win64')
let g:is_mac     = has('mac')   || has('macunix') || has('gui_macvim')
let g:is_gui     = has('gui_running')
let $MYVIMDIR    = expand( g:is_windows ? '~/vimfiles' : '~/.vim' )
let $VIMLOCAL    = expand($MYVIMDIR . '/local')

" Reset all autocmd defined in vimrc.
" TODO: create ex command to define vimrc autocmd.
augroup vimrc
  autocmd!
augroup END

if has('vim_starting')
  autocmd vimrc VimEnter * call <SID>display_startup_time()

  let s:startuptime = reltime()
  function! s:display_startup_time()
    echomsg 'Startup time:' reltimestr( reltime(s:startuptime) )
    unlet s:startuptime
  endfunction
endif



" Colorscheme {{{1

augroup vimrc
  autocmd ColorScheme hybrid highlight LineNr ctermfg=14 guifg=#676b41
  autocmd ColorScheme hybrid highlight Comment ctermfg=11 guifg=#707880 gui=none,italic
augroup END

if has('vim_starting')
  set t_Co =256
  if &t_Co < 256
    colorscheme desert
  else
    colorscheme smyck256
  endif
endif



" Commands and functions {{{1

" SID {{{2

function! s:SID()
  return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze_SID$')
endfunction


" Reload and Edit .vimrc {{{2

command! Rv  source $MYVIMRC | if g:is_gui | source $MYGVIMRC | endif
command! Ev  edit   $MYVIMRC
if g:is_gui
 command! Evg edit $MYGVIMRC
endif


" Set indent easily {{{2

command! -nargs=* IndentBy call <SID>set_indent(<f-args>)
command! ShortIndent  IndentBy 2 1
command! MediumIndent IndentBy 4 1

function! s:set_indent(n_space, expand_tab)
  let &l:shiftwidth  = a:n_space
  let &l:tabstop     = a:n_space
  let &l:softtabstop = a:n_space
  let &l:expandtab   = a:expand_tab
endfunction


" QuickfixDo {{{2

command! -nargs=+ QfDo call <SID>quickfix_do(<q-args>)

" Execute the specified command for each buffer in the quickfix list.
" From: http://stackoverflow.com/questions/4792561/how-to-do-search-replace-with-ack-in-vim/4793316#4793316
function! s:quickfix_do(command)
    let buffer_numbers = {}
    for fixlist_entry in getqflist()
      let buffer_numbers[ fixlist_entry['bufnr'] ] = 1
    endfor
    let buffer_number_list = keys(buffer_numbers)

    let current_bufnr = bufnr('%')
    for bufnr in buffer_number_list
      if bufexists( str2nr(bufnr) )
        execute 'keepalt buffer' bufnr
        execute a:command
      endif
    endfor
    execute 'keepalt buffer' current_bufnr
endfunction


" Restore last cursor position {{{2

command! RestoreCursorPosition call <SID>restore_cursor_position()

function! s:restore_cursor_position()
  if line("'\"") > 1 && line("'\"") <= line("$")
    execute 'normal! g`"'
  endif
endfunction


" Capture command outputs {{{2

command! -nargs=+ -complete=command
  \ Capture call <SID>capture_output_of(<q-args>)
cnoreabbrev cap Capture

" Capture command outputs.
" If any errors occurred, capture nothing.
function! s:capture_output_of(commands)
  redir => output
  try
    silent execute a:commands
  catch
    echoerr v:exception | return
  finally
    redir END
  endtry

  new
  file `=printf('Output of: [ %s ]', a:commands)`
  setlocal buftype   =nofile
  setlocal bufhidden =delete
  call setline(1, split(output, '\n'))
endfunction


" Grep by external programs {{{2

" Helper functions {{{3

function! s:make_grepprg_obj(program, command, grepprg)
  return {
    \ 'program' : a:program,
    \ 'command' : a:command,
    \ 'grepprg' : a:grepprg,
    \ 'executable' : a:program !=# 'vim' ? executable(a:program) : 1
    \ }
endfunction

function! s:select_executable_programs()
  return filter(copy(s:grepprgs.order), "s:grepprgs.prgs[v:val].executable")
endfunction

function! s:select_first_executable_grepprg()
  let executables = s:select_executable_programs()
  return s:grepprgs.prgs[ executables[0] ]
endfunction

function! s:display_available_greps()
  let greps = s:select_executable_programs()
  let current = s:grepprgs.current.program
  return join( map(greps, "v:val ==# current ? '['.v:val.']' : v:val "), ' ' )
endfunction

" Run grep by the specified program.
function! s:grep_by(is_append_mode, bang, program, args)
  let save_grepprg = &grepprg

  let config = s:grepprgs.prgs[a:program]
  let &grepprg = config.grepprg

  let grep = 'grep' . (a:is_append_mode ? 'add' : '') . a:bang
  silent execute grep a:args '| cwindow | redraw!'
  echo len(getqflist()) "matches."
  let &grepprg = save_grepprg
endfunction

" Change the current grep program.
function! s:change_grep_program(program) abort
  if ! has_key(s:grepprgs.prgs, a:program)
    echoerr a:program 'is unknown as a grep command.'
    return
  endif

  let config = s:grepprgs.prgs[a:program]
  if ! config.executable
    echoerr a:program 'can not be executed.'
    return
  endif

  let s:grepprgs.current = config
  echo 'Grep is set to:' a:program
endfunction

" Various grep commands {{{3

" The dictionary which stores some information about grep commands.
let s:grepprgs = {
  \ 'order' : ['ag', 'pt', 'vim'],
  \ 'prgs' : {
  \   'ag'  : s:make_grepprg_obj('ag', 'AgGrep',  'ag --nocolor --nogroup'),
  \   'pt'  : s:make_grepprg_obj('pt', 'PtGrep',  'pt --nocolor --nogroup'),
  \   'vim' : s:make_grepprg_obj('vim', 'VimGrep',  'internal')
  \  }
  \ }
" Set the first executable command to the current grep program.
let s:grepprgs.current = s:select_first_executable_grepprg()

" Define the custom grep commands.
for [s:program, s:config] in items(s:grepprgs.prgs)
  " Grep command
  execute printf(
    \ "command! -bang -nargs=+ -complete=file %s call <SID>grep_by(0, '<bang>', '%s', <q-args>)",
    \ s:config.command, s:program)

  " GrepAdd command
  execute printf(
    \ "command! -bang -nargs=+ -complete=file %sAdd call <SID>grep_by(1, '<bang>' '%s', <q-args>)",
    \ s:config.command, s:program)
endfor
unlet s:program s:config

command! -nargs=1 ChangeGrep call <SID>change_grep_program(<q-args>)
command! ShowGreps echo 'Available greps: ' <SID>display_available_greps()


" Load rc-bundles {{{2

" 'rc-bundle' meeans the bundles that used mainly in .vimrc itself.
" All rc-bundles must be in '$MYVIMDIR/rcbundle/'.
command! -nargs=1 RcBundle
  \ if has('vim_starting') |
  \   call <SID>load_rc_bundle(<f-args>) |
  \ endif

function! s:load_rc_bundle(bundle_name)
  let bundle_rtp = expand('$MYVIMDIR/rcbundle/' . a:bundle_name)
  execute 'set runtimepath+=' . bundle_rtp
  execute 'runtime plugin/' . a:bundle_name
  execute 'helptags' bundle_rtp . '/doc'
  if isdirectory(bundle_rtp . '/after')
    execute 'set runtimepath+=' . bundle_rtp . '/after'
  endif
endfunction


" Take diff of windows {{{2

" Take diff of opened windows or close diff mode if it opened.
command! Windiff call <SID>toggle_win_diff(&diff)

function! s:toggle_win_diff(is_opened)
  if a:is_opened
    diffoff!
  else
    windo diffthis
  endif
endfunction


" Others {{{2

" Print each path of &runtimepath.
command! Rtp echo substitute(&runtimepath, ',', '\n', 'g')

" Remove trailing whitespaces without cursor moving.
command! Rtw :%s/\v\s+$// | let v:hlsearch = 0 | normal! ``

" Print syntax names at the current cursor position.
command! SyntaxNames :echo map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")')


" Basic options {{{1

language C
set helplang =en,ja

set encoding      =utf-8
set fileencoding  =utf-8
set fileencodings =utf-8,cp932

if exists('&ambiwidth')
  set ambiwidth =double
endif

filetype plugin indent on
syntax on

" Default tab/space settings.
set tabstop     =4
set shiftwidth  =4
set softtabstop =4
set expandtab
set autoindent
set smartindent

" Search settings.
set hlsearch
set incsearch
set ignorecase
set smartcase

" Avoid highlighting the last search pattern at reloading vimrc.
nohlsearch

" Disable file backups.
set nobackup
set nowritebackup
set noswapfile

if has('persistent_undo')
  if ! isdirectory($VIMLOCAL . '/undo')
    call mkdir($VIMLOCAL . '/undo')
  endif
  set undofile
  set undodir =$VIMLOCAL/undo
endif

" Briefly jump to the matching bracket.
set showmatch
set matchtime =2
set matchpairs& matchpairs+=<:>

" Folds settings.
set foldmethod =marker
set foldcolumn =3

set cursorline
set number
set relativenumber
set hidden
set ruler
set showcmd
set showmode
set autoread
set nostartofline
set title
set wildmenu
set list
set listchars   =tab:>\ "
set backspace   =indent,eol,start
set linespace   =1
set mouse       =a
set clipboard   =unnamed
set keywordprg  =:help
set scrolloff   =3
set textwidth   =0
set history     =50
set laststatus  =2
set cmdheight   =2
set completeopt =longest,menuone
set whichwrap   =b,s,<,>,[,]
set statusline  =%f%m%r%h%w\ -\ [%{(&fenc!=''?&fenc:&enc)}\ %{&ff}\ %Y]\ [%Llines\]\ (%04l,%04v)
set formatoptions =croql
set fileignorecase
set timeoutlen  =1200
set ttimeoutlen =10 " To eliminate delays on <Esc> in terminal.
set gdefault

" Indent counts of leading backslash for line continuations in vim script.
let g:vim_indent_cont = 2



" Default events {{{1

augroup vimrc
  autocmd WinEnter * checktime
  autocmd BufReadPost * RestoreCursorPosition
augroup END



" Filetype settings {{{1

" Options for each file type {{{2

" Helper function {{{

function! s:delegate_filetypes(filetypes)
  for [name_pattern, type] in items(a:filetypes)
    execute 'autocmd BufNewFile,BufRead' name_pattern
      \ 'setlocal filetype='.type
  endfor
endfunction

" }}}

augroup vimrc
  " Groovy local settings
  autocmd FileType groovy setlocal cindent cinoptions& cinoptions+=j1

  " Show relative line numbers in help files.
  autocmd FileType help setlocal relativenumber

  " Configure filetypes which have to be assigned manually.
  call s:delegate_filetypes({
    \ '*.gradle'     : 'groovy',
    \ '*.es6'        : 'javascript',
    \ '.babelrc'     : 'json',
    \ '.pryrc'       : 'ruby',
    \ 'Guardfile'    : 'ruby',
    \ 'Vagrantfile'  : 'ruby',
    \ 'Dockerfile.*' : 'Dockerfile'
    \ })
augroup END


" Indent settings {{{2

augroup vimrc
  autocmd FileType javascript ShortIndent
  autocmd FileType coffee     ShortIndent
  autocmd FileType css        ShortIndent
  autocmd FileType scss       ShortIndent
  autocmd FileType sass       ShortIndent
  autocmd FileType haml       ShortIndent
  autocmd FileType yaml       ShortIndent
  autocmd FileType ruby       ShortIndent
  autocmd FileType vim        ShortIndent
  autocmd FileType vimspec    ShortIndent
  autocmd FileType scala      ShortIndent
  autocmd FileType sql        ShortIndent
  autocmd FileType json       ShortIndent
  autocmd FileType html       ShortIndent
  autocmd FileType xhtml      ShortIndent
  autocmd FileType eruby      ShortIndent
  autocmd FileType jsp        ShortIndent
  autocmd FileType vue        ShortIndent
  autocmd FileType c          MediumIndent
  autocmd FileType cs         MediumIndent
  autocmd FileType vb         MediumIndent
  autocmd FileType java       MediumIndent
  autocmd FileType groovy     MediumIndent
  autocmd FileType xml        MediumIndent
  autocmd FileType sh         MediumIndent
  autocmd FileType markdown   MediumIndent
  autocmd FileType text       IndentBy 4 0
  autocmd FileType help       IndentBy 8 0
augroup END


" Apply file type settings {{{2
if ! has('vim_starting')
  " Apply file type settings to the current buffer when vimrc is reloaded.
  doautocmd vimrc FileType
endif



" Key mappings {{{1

" Set up {{{2

" Use custom mapping commands.
RcBundle mapping.vim
call mapping#set_sid(s:SID())
let g:mapping_named_key_format = '\[%s]'

" Change the mapping of text object {rhs} to {lhs}.
function! s:map_text_object(lhs, rhs)
  execute 'Map ox' 'i' . a:lhs  'i' . a:rhs
  execute 'Map ox' 'a' . a:lhs  'a' . a:rhs
endfunction

" Define 'mapleader' before all mappings usiing <Leader>.
let mapleader = "-"
Map nv - <Nop>

" Disable these keys to use as the main leader keys.
Map n m       <Nop>
Map n q       <Nop>
Map n <Space> <Nop>


" Numbers {{{2

" Invert numbers by <Space> (to type 6 - 9 by left hand).
for s:n in range(1, 9)
  execute 'Map nvo <Space>' . s:n . ' ' . (10 - s:n)
endfor
unlet s:n


" Insert mode {{{2

Map i <C-j> <Down>
Map i <C-k> <Up>
Map i <C-h> <Left>
Map i <C-l> <Right>
Map i <C-a> <Esc><S-i>
Map i <C-e> <End>
Remap i <C-CR> <End><CR>
Remap i <S-CR> <C-o>O
Remap i <S-Tab> <Tab><Tab>

" Break undo sequence after these deletions in Insert mode.
Map i <C-w> <C-g>u<C-w>
Map i <C-u> <C-g>u<C-u>

" Break a line without inserting the comment leader.
Map i <C-]> <C-o>:set formatoptions-=ro<CR><CR><C-o>:set formatoptions+=ro<CR>


" Visual mode {{{2

" Reselect visual block after indent.
Map v < <gv
Map v > >gv


" Command-line mode {{{2

" Like emacs.
Map c <C-a> <Home>
Map c <C-b> <Left>
Map c <C-e> <End>
Map c <C-f> <Right>
Map c <C-n> <Down>
Map c <C-p> <Up>

" Paste current path by '%%'.
Map c (expr) %% getcmdtype() == ':' ? expand('%:h') : '%%'


" Basic operation in normal mode {{{2

Map n mm m
Map n _  `
Map n <C-h>     :us:vert help
Map n <Leader>h :us:help
Map n <Space>w  ::update
Map n <Space>W  ::update!
Map n <Space>q  ::quit
Map n <Space>Q  ::quit!
Map n <C-j> <C-e>gj
Map n <C-k> <C-y>gk
Map n Y y$
Map n Q q
Map n <Leader>d ::pwd
Map n zp zMzv

" Break lines and Insert spaces in normal mode.
Map n <C-CR>          o<Esc>
Map n <S-CR>          O<Esc>
Map n <S-Space>       i<Space><Esc>
Map n <Leader><Space> a<Space><Esc>

" Remove trailing whitespaces.
Map n (silent) <Leader>c ::Rtw

" In US keyboard, typing ':' is so hard..
Map nv ; :
Map nv : ;


" Fix the direction of the ';', ',', 'n', 'N' {{{2

" Make the ';' key always move to the right.
" Make the ',' key always move to the left.
Map nvo (expr) f <SID>map_repeat_keys_and_move_to_occurrence(1, 'f')
Map nvo (expr) F <SID>map_repeat_keys_and_move_to_occurrence(0, 'F')
Map nvo (expr) t <SID>map_repeat_keys_and_move_to_occurrence(1, 't')
Map nvo (expr) T <SID>map_repeat_keys_and_move_to_occurrence(0, 'T')

" Make the 'n' key always move forward.
" Make the 'N' key always move backward.
Map nvo (expr) n <SID>search_pattern_to_fixed_direction('n', 'N')
Map nvo (expr) N <SID>search_pattern_to_fixed_direction('N', 'n')

function! s:map_repeat_keys_and_move_to_occurrence(direct_to_right, command)
  if a:direct_to_right
    Map nvo : ;
    Map nvo , ,
  else
    Map nvo : ,
    Map nvo , ;
  endif
  return a:command
endfunction

function! s:search_pattern_to_fixed_direction(normal_key, reverse_key)
  return v:searchforward ? a:normal_key : a:reverse_key
endfunction


" Text objects {{{2

call s:map_text_object('d', '"')
call s:map_text_object('s', "'")
call s:map_text_object('m', ')')
call s:map_text_object('n', '}')
call s:map_text_object('y', '>')


" Toggle options {{{2

MapNamedKey co toggle

" Toggle search highlight.
Map n (silent) \[toggle]h ::let v:hlsearch = ! v:hlsearch

" Toggle scrollbinds of each window.
Map n \[toggle]S ::windo setlocal scrollbind! scrollbind?

" Toggle indent width.
Map n \[toggle]i :f:<SID>toggle_indent_width()

function! s:toggle_indent_width()
  if &tabstop <= 2
    call s:set_indent(4, &expandtab)
    echo 'Medium indent (4)'
  else
    call s:set_indent(2, &expandtab)
    echo 'Short indent (2)'
  endif
endfunction

" Toggle colorschemes.
Map n \[toggle]c :f:<SID>toggle_colorschemes()

let s:togglable_colors = ['smyck256', 'hybrid']
function! s:toggle_colorschemes()
  let current = index(s:togglable_colors, g:colors_name)
  let next = (current + 1) % len(s:togglable_colors)
  execute 'colorscheme' s:togglable_colors[next]
endfunction

" Toggle comment continuation at line breaking.
Map n \[toggle]* :f:<SID>toggle_comment_continuation()

function! s:toggle_comment_continuation()
  let will_continue = ( match(&formatoptions, '\v[ro]') != -1 )
  if will_continue
    set formatoptions -=ro
    echo 'Do not continue comment lines'
  else
    set formatoptions +=ro
    echo 'Continue comment lines'
  endif
endfunction


" Disallow some delete operations to change clipboard {{{2

" The 'd' and 'c' keys can change clipboard.
for s:lkey in ['s', 'x']
  let s:ukey = toupper(s:lkey)
  execute 'Map nv' s:lkey '"_' . s:lkey
  execute 'Map nv' s:ukey '"_' . s:ukey
endfor

" Leave the default operation
" ('ms' is used by 'easymotion').
Map nv mx x
Map nv mX X

" The 'md' and 'mc' commands delete texts without copy.
Map nv md "_d
Map nv mD "_D
Map nv mc "_c
Map nv mC "_C


" Paste texts smartly {{{2

Map i (silent) <C-v> <C-o>:set paste<CR><C-r>*<C-o>:set nopaste<CR>
Map c <C-v> <C-r>*


" Grep by external programs {{{2

" Toggle the current grep program.
let s:grep_mappings = {
  \ 'a' : 'ag',
  \ 'p' : 'pt',
  \ 'v' : 'vim'
  \ }
for [s:key, s:program] in items(s:grep_mappings)
  execute printf("Map n \\[grep]%s ::ChangeGrep %s", s:key, s:program)
endfor
unlet s:grep_mappings s:key s:program

" Start grep using the current program.
function! s:grep_by_current_program(is_append_mode)
  let command = s:grepprgs.current.command
  return ':' . command . (a:is_append_mode ? 'Add' : '') . '! '
endfunction

MapNamedKey <Space>s grep
Map n (expr) \[grep]s <SID>grep_by_current_program(0)
Map n (expr) \[grep]+ <SID>grep_by_current_program(1)
Map n \[grep]l ::ShowGreps


" Quickfix {{{2

Map n qo  ::cwindow
Map n qc  ::cclose
Map n qj  ::cnext
Map n qk  ::cprevious
Map n ql  ::cnfile
Map n qh  ::cpfile
Map n qgg ::cfirst
Map n qG  ::clast
Map n qn  ::cnewer
Map n qp  ::colder


" Buffers {{{2

MapNamedKey <Space>b buffer
Map n \[buffer]a ::buffer #
Map n \[buffer]d ::bdelete
Map n \[buffer]l ::ls
Map n \[buffer]s :us:ls<CR>:buffer
Map n \[buffer]j ::execute 'buffer' v:count1


" Tabs {{{2

" Use 't' as the prefix of tab motions.
MapNamedKey t tab
Map n \[tab]n ::tabnew
Map n \[tab]h gT
Map n \[tab]l gt
" TODO: mappings for tab motions



" Plugins {{{1

call w#neobundle#wrap()

" Declare bundles {{{2

function! s:declare_bundles()
  " Extension {{{3

  NeoBundlew 'Shougo/vimproc.vim', {
    \ 'disabled': g:is_windows,
    \ 'build': {
    \   'mac'   : 'make -f make_mac.mak',
    \   'linux' : 'make',
    \   'unix'  : 'gmake'
    \   }
    \ }

  NeoBundlew 'Shougo/unite.vim'

  NeoBundlew 'Shougo/neomru.vim', {
    \ 'depends': ['unite']
    \ }

  NeoBundlew 'haya14busa/unite-ghq', {
    \ 'depends': ['unite']
    \ }

  NeoBundlew 'Shougo/vimfiler.vim', {
    \ 'depends': ['unite']
    \ }

  NeoBundlewLazy 'Shougo/vimshell.vim', {
    \ 'depends': ['vimproc']
    \ }

  NeoBundlew 'Shougo/neocomplete.vim'

  NeoBundlew 'Shougo/tabpagebuffer.vim'

  NeoBundlew 'kana/vim-tabpagecd'

  NeoBundlew 'kana/vim-submode'

  NeoBundlew 'tpope/vim-repeat'

  NeoBundlew 'osyo-manga/vim-over'


  " Basic Editing {{{3

  NeoBundlew 'junegunn/vim-easy-align'

  NeoBundlew 'tpope/vim-commentary'

  NeoBundlew 'tpope/vim-surround'

  NeoBundlew 'cohama/lexima.vim'

  NeoBundlew 'LeafCage/yankround.vim'

  NeoBundlew 'ryym/vim-unimpaired', {
    \ 'rev': 'ryym'
    \ }


  " Text object {{{3

  NeoBundlew 'kana/vim-textobj-user'

  NeoBundlew 'kana/vim-textobj-entire'

  NeoBundlew 'kana/vim-textobj-line'

  NeoBundlew 'kana/vim-textobj-indent'

  NeoBundleLazy 'rhysd/vim-textobj-ruby', {
    \ 'filetypes': ['ruby']
    \ }


  " Operator {{{3

  NeoBundlew 'kana/vim-operator-user'

  NeoBundlew 'kana/vim-operator-replace'


  " Motion {{{3

  NeoBundlewLazy 'easymotion/vim-easymotion', {
    \ 'mappings': '<Plug>'
    \ }

  NeoBundlew 'nelstrom/vim-visual-star-search'

  NeoBundlew 'haya14busa/incsearch.vim'


  " Utility {{{3

  NeoBundlew 'rbgrouleff/bclose.vim'

  NeoBundlew 'thinca/vim-localrc'

  NeoBundlewLazy 'thinca/vim-quickrun', {
    \ 'commands': ['QuickRun']
    \ }

  NeoBundlewLazy 'kannokanno/previm', {
    \ 'depends': ['open-browser'],
    \ 'filetypes': ['markdown']
    \ }

  NeoBundlewLazy 'tyru/restart.vim', {
    \ 'gui': 1,
    \ 'commands': ['Restart']
    \ }

  NeoBundlewLazy 'tyru/open-browser.vim', {
    \ 'mappings': '<Plug>(openbrowser-'
    \ }

  NeoBundlew 'thinca/vim-prettyprint'

  NeoBundlewLazy 'ryym/macspeech.vim', {
    \ 'disabled': !g:is_mac,
    \ 'commands': ['MacSpeech', 'MacSpeechSelected']
    \ }

  NeoBundlew 'lambdalisue/vim-unified-diff'


  " VCS {{{3

  NeoBundlewLazy 'tpope/vim-fugitive', {
    \ 'commands': ['Gstatus', 'Git', 'Gdiff', 'Gblame']
    \ }

  NeoBundlewLazy 'cohama/agit.vim', {
    \ 'commands': ['Agit']
    \ }


  " Filetype {{{3

  NeoBundlewLazy 'mattn/emmet-vim', {
    \ 'filetypes': ['html', 'xml', 'eruby', 'jsp', 'javascript']
    \ }
  NeoBundlewLazy 'PProvost/vim-ps1', {
    \ 'filetypes': ['ps1']
    \ }

  NeoBundlewLazy 'kchmck/vim-coffee-script', {
    \ 'filetypes': ['coffee']
    \ }

  NeoBundlewLazy 'bruno-/vim-man', {
    \ 'disabled': g:is_windows,
    \ 'mappings': ['<Plug>(Man)', '<Plug>(Sman)', '<Plug>(Vman)'],
    \ 'commands': ['Man', 'Sman', 'Vman']
    \ }

  NeoBundleLazy 'derekwyatt/vim-scala', {
    \ 'filetypes': ['scala']
    \ }

  NeoBundlew 'hail2u/vim-css3-syntax'

  NeoBundlew 'othree/html5.vim'

  NeoBundlew 'pangloss/vim-javascript'

  NeoBundlew 'mxw/vim-jsx'

  NeoBundlew 'ryym/vim-riot'

  NeoBundlew 'elixir-lang/vim-elixir'

  NeoBundlewLazy 'digitaltoad/vim-pug', {
    \ 'filetypes': ['pug'],
    \ }

  NeoBundlewLazy 'slim-template/vim-slim', {
    \ 'filetypes': ['slim']
    \ }

  NeoBundlewLazy 'posva/vim-vue', {
    \ 'filetypes': ['vue']
    \ }

  NeoBundlew 'tpope/vim-rails'

  NeoBundlewLazy 'leafgarland/typescript-vim', {
    \ 'filetypes': ['typescript']
    \ }


  " UI {{{3

  NeoBundlew 'itchyny/lightline.vim'

  NeoBundlew 'nathanaelkane/vim-indent-guides'

  NeoBundlew 'w0ng/vim-hybrid'

  NeoBundlew 'LeafCage/foldCC.vim'


  " Others {{{3

  NeoBundlewLazy 'thinca/vim-themis', {
    \ 'filetypes': ['vimspec']
    \ }

  NeoBundlew 'kana/vim-vspec'

  NeoBundlew 'vim-jp/vimdoc-ja'


  "}}}
endfunction


" Configure bundles {{{2

function! s:configure_bundles(neobundle_wrapper)
  let nbw = a:neobundle_wrapper
  " unite and extentions {{{3
  if nbw.tap('unite')
    MapNamedKey <Space>u unite
    MapNamedKey <Space>U uniteNq

    function! s:map_unite_commands(key, command, end_key)
      execute 'Map n' '\[unite]'   . a:key ':u:' . a:command . a:end_key
      execute 'Map n' '\[uniteNq]' . a:key ':u:' . a:command '-no-quit -winheight=15' . a:end_key
    endfunction

    " unite {{{4
    let s:mappings = [
      \   ['u', 'Unite'                    , '<Space>'],
      \   ['b', 'Unite buffer_tab'         , '<CR>'],
      \   ['f', 'Unite file'               , '<CR>'],
      \   ['r', 'Unite file_rec/async'     , '<CR>'],
      \   ['o', 'Unite'                    , ' output:'],
      \   ['c', 'UniteWithCurrentDir file' , '<CR>'],
      \   ['C', 'UniteWithCurrentDir'      , '<Space>'],
      \   ['d', 'UniteWithBufferDir file'  , '<CR>'],
      \   ['D', 'UniteWithBufferDir'       , '<Space>'],
      \   ['k', 'UniteWithCursorWord line' , '<CR>'],
      \   ['K', 'UniteWithCursorWord'      , '<Space>']
      \ ]
    for [s:key, s:command, s:end_key] in s:mappings
      call s:map_unite_commands(s:key, s:command, s:end_key)
    endfor
    unlet s:mappings s:key s:command s:end_key

    function! nbw.hooks.on_source(_)
      " Show dotfiles at :Unite file
      call unite#custom#source('file', 'matchers', 'matcher_default')

      " Don't list up unneccesary files.
      call unite#custom#source('file_rec,file_rec/async',
        \ 'ignore_pattern',
        \ 'node_modules/.*\|bower_components/.*\|*.png\|*.jpg\|*.jpeg\|*.gif')

      call unite#custom#profile('default', 'context', {
        \ 'start_insert': 1
        \ })

      call unite#custom#default_action('directory', 'lcd')

      let g:unite_source_alias_aliases = {
        \ 'f'  : 'file',
        \ 'fr' : 'file_rec',
        \ 'b'  : 'buffer',
        \ 'bt' : 'buffer_tab',
        \ 'g'  : 'grep',
        \ 'l'  : 'line',
        \ 'nb' : 'neobundle'
        \ }

      if executable('ag')
        let g:unite_source_rec_async_command = ['ag', '--follow', '--nocolor',
          \ '--nogroup', '--hidden', '-g', '']
        let g:unite_source_grep_comand = 'ag'
      endif

      " Key mappings in unite buffers
      autocmd vimrc FileType unite call <SID>map_keys_on_unite()
      function! s:map_keys_on_unite()
        Map n (buffer expr) s unite#smart_map('s', unite#do_action('split'))
        Map n (buffer expr) v unite#smart_map('v', unite#do_action('vsplit'))
        Map n (buffer expr) f unite#smart_map('f', unite#do_action('vimfiler'))

        " For 'buffer' or 'buffer_tab'
        Map n (buffer expr) d unite#smart_map('d', unite#do_action('delete'))
        Map n (buffer expr) w unite#smart_map('w', unite#do_action('wipeout'))
      endfunction
    endfunction

    " unite-mru {{{4
    if nbw.tap('neomru')
      call s:map_unite_commands('m', 'Unite file_mru', '<CR>')
      function! nbw.hooks.on_source(_)
        let g:unite_source_alias_aliases['fm'] = 'file_mru'
      endfunction
    endif

    " unite-ghq {{{4
    if nbw.tap('unite-ghq')
      call s:map_unite_commands('g', 'Unite ghq', '<CR>')
    endif


    " }}}

    delfunction s:map_unite_commands
  endif


  " vimfiler {{{3
  if nbw.tap('vimfiler')
    MapNamedKey <Space>f vimfiler
    Map n \[vimfiler]f :us:VimFiler
    Map n \[vimfiler]s :us:VimFiler -split -winwidth=60
    Map n \[vimfiler]c ::VimFilerCurrentDir
    Map n \[vimfiler]d ::VimFilerBufferDir
    Map n \[vimfiler]e ::VimFilerBufferDir -split -simple -winwidth=35 -no-quit
    Map n \[vimfiler]E :us:VimFiler        -split -simple -winwidth=35 -no-quit

    function! nbw.hooks.on_source(_)
      let g:vimfiler_as_default_explorer  = 1
      let g:vimfiler_safe_mode_by_default = 0

      " Key mappings in vimfiler buffers
      autocmd vimrc FileType vimfiler call <SID>map_keys_on_vimfiler()
      function! s:map_keys_on_vimfiler()
        " TODO: This conflicts with the default mapping '<Space>'(mark file).
        Remap n (buffer) <Space>q <Plug>(vimfiler_exit)

        Remap n (silent buffer expr) Ar vimfiler#do_action('rec')
      endfunction

    endfunction
  endif


  " vimshell {{{3
  if nbw.tap('vimshell')
    MapNamedKey <Space>t vimshell
    Map n \[vimshell]t :us:VimShell
    Map n \[vimshell]c ::VimShellCurrentDir
    Map n \[vimshell]d ::VimShellBufferDir
  endif


  " neocomplete {{{3
  if nbw.tap('neocomplete')
    Map i (expr) <Tab> pumvisible() ? "\<C-n>" : "\<Tab>"
    Map n \[toggle]o ::NeoCompleteToggle
  endif


  " submode {{{3
  if nbw.tap('submode')
    function! nbw.hooks.on_source(_)
      let g:submode_keep_leaving_key = 1
      let g:submode_timeout          = 0
      let g:submode_timeoutlen       = 3000
    endfunction

    function! nbw.hooks.on_post_source(_)
      call w#submode#wrap()

      " Submode scroll {{{4
      SbmDefine scroll
      SbmScrollEnter n <Leader>s
      SbmScroll n <r> u <C-u>
      SbmScroll n <r> d <C-d>
      SbmScroll n <r> f <C-f>
      SbmScroll n <r> b <C-b>
      SbmScroll n j     2<C-e>j
      SbmScroll n k     2<C-y>k
      SbmScroll n J     4<C-e>j
      SbmScroll n K     4<C-y>k
      SbmScroll n <C-j> 6<C-e>j
      SbmScroll n <C-k> 6<C-y>k

      " Submode window-resize {{{4
      SbmDefine winRes
      SbmWinResEnter n <C-w>m
      SbmWinResEnter n <C-w><C-m>

      " 'L'ower, 'H'eighten, 'S'horten, 'W'iden
      for [s:k, s:command] in items({
        \ 'l': '<C-w>-',
        \ 'h': '<C-w>+',
        \ 's': '<C-w><',
        \ 'w': '<C-w>>'
        \ })
        execute 'SbmWinRes n' s:k               1 . s:command
        execute 'SbmWinRes n' toupper(s:k)      3 . s:command
        execute 'SbmWinRes n' '<C-' . s:k . '>' 5 . s:command
      endfor
      unlet s:k s:command

      " Submode tab-motion {{{4
      SbmDefine tab
      SbmTabEnter n tt
      SbmTab n l gt
      SbmTab n h gT

      " }}}
    endfunction
  endif


  " easy-align {{{3
  if nbw.tap('easy-align')
    Remap nv ga <Plug>(EasyAlign)
  endif


  " vim-over {{{3
  if nbw.tap('over')
    Remap n <Space>o ::OverCommandLine
  endif


  " yankround {{{3
  if nbw.tap('yankround')
    Remap nx p     <Plug>(yankround-p)
    Remap n  P     <Plug>(yankround-P)
    Remap nx gp    <Plug>(yankround-gp)
    Remap n  gP    <Plug>(yankround-gP)
    Remap n <C-p> <Plug>(yankround-prev)
    Remap n <C-n> <Plug>(yankround-next)
  endif


  " lexima {{{3
  if nbw.tap('lexima')
    function! nbw.hooks.on_post_source(_)
      " For vspec {{{4
      call lexima#add_rule({
        \ 'char'        : '<CR>',
        \ 'input_after' : '<CR>end',
        \ 'at'          : '^\s*\%(describe\|it\|context\)\s\+.\+\%#',
        \ 'filetype'    : 'vim'
        \ })
      call lexima#add_rule({
        \ 'char'        : '<CR>',
        \ 'input_after' : '<CR>end',
        \ 'at'          : '^\s*\%(before\|after\)\s*\%#',
        \ 'filetype'    : 'vim'
        \ })

      " Supress auto-closing for folds in vim. {{{4
      call lexima#add_rule({
        \ 'char'     : '{',
        \ 'input'    : '{',
        \ 'at'       : '{{\%#',
        \ 'delete'   : 2,
        \ 'filetype' : 'vim'
        \ })
      call lexima#add_rule({
        \ 'char'     : '<CR>',
        \ 'input'    : '<CR>',
        \ 'at'       : '{\{3\}\%#',
        \ 'filetype' : 'vim'
        \ })

      " }}}
    endfunction
  endif


  " unimpaired {{{3
  if nbw.tap('unimpaired')
    let g:unimpaired_mapping = {
      \ 'encodings' : 0,
      \ 'excludes'  : {
      \     'nextprevs' : ['n'],
      \     'toggles'   : ['c', 'h', 'i', 's']
      \   }
      \ }
    function! nbw.hooks.on_post_source(_)
      Remap no [d <Plug>unimpairedContextPrevious
      Remap no ]d <Plug>unimpairedContextNext

      call g:Unimpaired_toggle_option_by('t', 'expandtab')
      call g:Unimpaired_toggle_option_by('s', 'scrollbind')
      call g:Unimpaired_toggle_option_by('p', 'spell')
    endfunction
  endif


  " operator-replace {{{3
  if nbw.tap('operator-replace')
    Remap nvo mr <Plug>(operator-replace)
  endif


  " EasyMotion {{{3
  if nbw.tap('easymotion')
    Remap nvo ms <Plug>(easymotion-s2)
    Remap nvo mf <Plug>(easymotion-fl2)
    Remap nvo mF <Plug>(easymotion-Fl2)
    Remap nvo mt <Plug>(easymotion-tl2)
    Remap nvo mT <Plug>(easymotion-Tl2)
    Remap nvo m/ <Plug>(easymotion-fn)
    Remap nvo m? <Plug>(easymotion-Fn)
    Remap nvo m: <Plug>(easymotion-next)
    Remap nvo m, <Plug>(easymotion-prev)

    function! nbw.hooks.on_source(_)
      " Disable default mappings.
      let g:EasyMotion_do_mapping = 0

      let g:EasyMotion_space_jump_first = 1
      let g:EasyMotion_smartcase        = 1
      let g:EasyMotion_use_upper        = 1
      let g:EasyMotion_keys = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

      highlight link EasyMotionIncSearch    Search
      highlight link EasyMotionTarget       ErrorMsg
      highlight link EasyMotionShade        Comment
      highlight link EasyMotionTarget2First Todo
    endfunction
  endif


  " incsearch {{{3
  if nbw.tap('incsearch')
    Remap nvo /  <Plug>(incsearch-forward)
    Remap nvo ?  <Plug>(incsearch-backward)
    Remap nvo g/ <Plug>(incsearch-stay)
    Remap nvo n  <Plug>(incsearch-nohl-n)
    Remap nvo N  <Plug>(incsearch-nohl-N)
    Remap nvo *  <Plug>(incsearch-nohl-*)
    Remap nvo #  <Plug>(incsearch-nohl-#)
    Remap nvo g* <Plug>(incsearch-nohl-g*)
    Remap nvo g# <Plug>(incsearch-nohl-g#)

    " Allow to use default search function by prefixing <Leader> key
    " mainly to search Japanese on MacVim
    " (https://github.com/haya14busa/incsearch.vim/issues/52).
    Map nvo <Leader>/ /

    function! nbw.hooks.on_source(_)
      let g:incsearch#auto_nohlsearch = 1
      let g:incsearch#consistent_n_direction = 1
      let g:incsearch#magic = '\v'
    endfunction
  endif


  " bclose {{{3
  if nbw.tap('bclose')
    Map n \[buffer]d ::Bclose
    Map n \[buffer]D ::Bclose!
  endif


  " quick-run {{{3
  if nbw.tap('quickrun')
    Map nv <Leader>r :r:QuickRun
  endif


  " open-browser {{{3
  if nbw.tap('open-browser')
    Remap nv <Leader>wo <Plug>(openbrowser-open)
    Remap nv <Leader>ws <Plug>(openbrowser-search)
  endif


  " restart {{{3
    if nbw.try_tap('restart')
      " This doesn't work under the terminal.
      Map n <Leader><Leader>r ::Restart
      Map n <Leader><Leader>R ::Restart!
    endif


  " macspeech {{{3
  if nbw.try_tap('macspeech')
    Map v  <Leader><Leader>q :r:MacSpeechSelected
    Map nv <Leader><Leader>Q ::MacSpeechStop

    function! nbw.hooks.on_source(bundle)
      let g:macspeech_voice = 'Ava'
    endfunction
  endif


  " unified-diff {{{3
  if nbw.tap('unified-diff')
    function! nbw.hooks.on_source(bundle)
      set diffexpr=unified_diff#diffexpr()

      let unified_diff#executable = 'git'
      let unified_diff#iwhite_arguments = [
        \   '--ignore--all-space',
        \ ]
    endfunction
  endif


  " fugitive {{{3
  if nbw.tap('fugitive')
    MapNamedKey <Space>g git
    Map nv \[git]g :s:Git
    Map nv \[git]s ::Gstatus
    Map nv \[git]d ::Gdiff
    Map nv \[git]b ::Gblame -w

    function! nbw.hooks.on_post_source(bundle)
      " Detect current opened file to enable fugitive.
      call fugitive#detect(expand('#:p'))
    endfunction
  endif


  " vim-jsx {{{3
  if nbw.tap('jsx')
    " Apply syntax highlighting to '*.js' files.
    let g:jsx_ext_required = 0
  endif


  " man (man page) {{{3
  if nbw.try_tap('man')
    MapNamedKey ma man
    Map n \[man]m :s:Vman
    Remap n \[man]w <Plug>(Vman)
  endif


  " indent-guides {{{3
  if nbw.tap('indent-guides')
    Remap n \[toggle]g <Plug>IndentGuidesToggle

    function! nbw.hooks.on_source(_)
      let g:indent_guides_start_level = 2
      let g:indent_guides_guide_size  = 1
      let g:indent_guides_exclude_filetypes = ['help', 'man']
      if g:is_gui
        autocmd vimrc VimEnter * IndentGuidesEnable
      endif
    endfunction
  endif


  " lightline {{{3
  if nbw.tap('lightline')
    if ! has('vim_starting')
      " Override default statusline when vimrc is reloaded.
      call lightline#update()
    endif
  endif


  " foldCC {{{3
  if nbw.tap('foldCC')
    let g:foldCCtext_head = "printf('%s %d: ', repeat(v:folddashes, v:foldlevel), v:foldlevel)"
    let g:foldCCtext_tail = "printf('%d lines ', v:foldend - v:foldstart + 1)"
    set foldtext =FoldCCtext()
  endif


  " }}}
endfunction


" Load bundles by NeoBundle {{{2

call w#neobundle#execute({
  \   'vimrc'             : $MYVIMRC,
  \   'bundle_dir'        : $MYVIMDIR  . '/bundle',
  \   'declare_bundles'   : function('s:declare_bundles'),
  \   'configure_bundles' : function('s:configure_bundles')
  \ })
delfunction s:declare_bundles
delfunction s:configure_bundles


" Another plugins {{{2

runtime macros/matchit.vim



" Local settings {{{1

if filereadable($VIMLOCAL . '/vimrc')
  source $VIMLOCAL/vimrc
  command! Evl edit $VIMLOCAL/vimrc
endif

" }}}

" vim: expandtab softtabstop=2 shiftwidth=2 foldmethod=marker