" === Startup ===
" https://gist.github.com/1518874
if has('vim_starting') && has('reltime')
  let g:startuptime = reltime()
  augroup vimrc-startuptime
    autocmd! VimEnter * let g:startuptime = reltime(g:startuptime) | redraw
    \ | echomsg 'startuptime: ' . reltimestr(g:startuptime)
  augroup END
endif


if has('vim_starting')
  set runtimepath& runtimepath+=$HOME/.vim
endif

let s:is_win = has('win32') || has('win64')
if s:is_win
  language messages en
endif


" === My functions ===
function! s:source_if(file)
  let realpath = expand(a:file)

  if filereadable(realpath)
    source `=realpath`
  endif
endfunction

function! MyStatusLine()
  let line  = ''

  let line .= '%<' " Truncate point
  let line .= '%f' " Filename
  let line .= '%m' " Modified flag
  let line .= ' %{cfi#format("<%s()>", "")}' " current-func-info.vim
  let line .= '%=' " Separation point
  let line .= '%y' " Filetype
  let line .= '%r' " Readonly flag
  let line .= '[%{&l:fenc}:%{&ff}]' " File encoding and format
  let line .= '  %-10.(%l,%c%V%)' " Current line status
  let line .= '%P' " Percentage through file of displayed window

  return line
endfunction

" === Load plugins ===
call s:source_if('~/.vim/neobundle.vimrc')

syntax enable
colorscheme jellybeans


" === Settings ===

" ===== Encoding =====
set encoding=utf-8
set fileencoding=utf-8
set fileencodings=ucs-bom,utf-8,iso-2022-jp,euc-jp,cp932
set fileformat=unix
set fileformats=unix,dos,mac

" ===== Backup =====
set backup backupcopy=yes backupdir=~/.vimbackup
set swapfile directory=~/.vimbackup
if !isdirectory(&backupdir)
  call mkdir(&backupdir, "p")
endif
if has('persistent_undo')
  set undodir=~/.vimbackup
  set undofile
endif


" Vim 以外の所でファイルが変更された場合自動で読み込む
set autoread
set ambiwidth=double
set backspace=indent,eol,start
set clipboard=unnamed
set formatoptions& formatoptions-=ro formatoptions+=mM
set helplang=ja,en
set keywordprg=:help
set laststatus=2 statusline=%!MyStatusLine()
set showtabline=2
set ignorecase smartcase incsearch hlsearch
set imdisable
" <C-a> / <C-b> で10進数のみ対応させる
set nrformats="hex"
set list listchars=tab:»-,trail:-,eol:↲,extends:»,precedes:«,nbsp:%
"set pastetoggle=<C-e>
set nomore
set showcmd showmode
set wildmenu wildmode=list:longest
set splitbelow splitright
set novisualbell t_vb=
set conceallevel=2 concealcursor=i
set title
set completeopt-=preview

" set autoindent
set expandtab
set tabstop=2
set softtabstop=2
set shiftwidth=2
set shiftround

let g:vim_indent_cont = 0
let mapleader = ","


" === autocmd ===
augroup vimrc
  autocmd!
augroup END

autocmd vimrc FileType git-diff,help,quickrun,quickfix,qf,ref,vcs-status nnoremap <buffer> q <C-w>c

" 保存時にディレクトリが存在しなければ自動で作成する
autocmd vimrc BufWritePre * call s:auto_mkdir(expand("<afile>:p:h"))
function! s:auto_mkdir(directory)
  if !isdirectory(a:directory)
    call mkdir(a:directory, "p")
  endif
endfunction


" === command ===
" 文字コードを変えて最読込
command! -nargs=? -bang -complete=file Utf8 edit<bang> ++enc=utf-8  <args>
command! -nargs=? -bang -complete=file Euc  edit<bang> ++enc=euc-jp <args>
command! -nargs=? -bang -complete=file Sjis edit<bang> ++enc=cp932  <args>

" 文字コードを変換
command! -nargs=0 ToUtf8    setlocal fileencoding=utf-8
command! -nargs=0 ToEuc     setlocal fileencoding=euc-jp
command! -nargs=0 ToSjis    setlocal fileencoding=cp932
command! -nargs=0 ToWindows setlocal fileencoding=cp932 fileformat=dos
command! -nargs=0 ToUnix    setlocal fileencoding=utf-8 fileformat=unix

command! -nargs=1 -bang -complete=file Rename saveas<bang> <args> | call delete(expand('#:p'))
command! RemoveTrailingSpaces %s/\s\+$// | nohlsearch
command! RemoveBlankLines :g /^$/d


" === Key mappings ===
nnoremap <Leader>ev :<C-u>tabedit $MYVIMRC<CR>
nnoremap <Leader>eg :<C-u>tabedit $MYGVIMRC<CR>

noremap ; :
noremap : ;

nnoremap j gj
nnoremap k gk

cnoremap <C-b> <Left>
cnoremap <C-f> <Right>

nnoremap q <Nop>
nnoremap Q q

nnoremap Y y$

" Very magic
nnoremap / /\v
nnoremap ? ?\v

" タブ
nnoremap <C-t> <Nop>
nnoremap <C-t>o :<C-u>tabonly<CR>
nnoremap <C-t>h <C-w>h
nnoremap <C-t>j <C-w>j
nnoremap <C-t>k <C-w>k
nnoremap <C-t>l <C-w>l
nnoremap <silent> <Left> :<C-u>execute 'tabmove' tabpagenr() - 2<CR>
nnoremap <silent> <Right> :<C-u>execute 'tabmove' tabpagenr()<CR>

nnoremap vv <C-v>
noremap! <C-BS> <C-w>

cnoremap <C-x> <C-r>=expand("%:p:h")<CR>/

cnoremap <expr> / getcmdtype() == '/' ? '\/' : '/'
cnoremap <expr> ? getcmdtype() == '?' ? '\?' : '?'

nnoremap <Leader>a ggVG

" 括弧までの選択を簡単にする
onoremap ) f)
onoremap ( t(
vnoremap ) f)
vnoremap ( t(


" === Plugin settings ===

" alignta.vim
vnoremap <Leader>a :Alignta<Space>


" altercmd.vim
call altercmd#load()
command! -bar -nargs=+ MapAlterCommand CAlterCommand <args> | AlterCommand <cmdwin> <args>

MapAlterCommand sl setl
MapAlterCommand sf setf

" autocdmodx.vim
let g:autochmodx_ignore_scriptish_file_patterns = [
\ '\c.*\.rb$',
\]


" capslock.vim
imap <C-a> <C-o><Plug>CapsLockToggle


" caw.vim
nmap gc <Plug>(caw:prefix)
vmap gc <Plug>(caw:prefix)


" eskk.vim

" なんかあんまり辞書登録ちゃんとされてる気がしないので毎回書き込んでみる
let g:eskk#dictinary_save_count = 1
let g:eskk#egg_like_newline = 1
let g:eskk#egg_like_newline_completion = 1

if has('vim_starting')
  let g:eskk#dictionary = '~/.skk-jisyo'

  if has('mac')
    let g:eskk#large_dictionary = expand('~/Library/Application\ Support/AquaSKK/SKK-JISYO.L')
  elseif has('unix')
    let g:eskk#large_dictionary = expand('/usr/share/skk/SKK-JISYO.L')
  elseif s:is_win
    let g:eskk#large_dictionary = expand('~/SKK-JISYO.L')
  endif
endif


" fugitive.vim
nnoremap <Leader>gd :<C-u>Gdiff<Enter>
nnoremap <Leader>gs :<C-u>Gstatus<Enter>
  nnoremap <Leader>gl :<C-u>Glog<Enter>
nnoremap <Leader>ga :<C-u>Gwrite<Enter>
nnoremap <Leader>gc :<C-u>Gcommit<Enter>
  nnoremap <Leader>gC :<C-u>Git commit --amend<Enter>
  nnoremap <Leader>gb :<C-u>Gblame<Enter>


" gist.vim
let g:gist_update_on_write = 2


" ===== gitv.vim =====
autocmd FileType git :setl foldlevel=99
autocmd FileType gitv call s:my_gitv_settings()
function! s:my_gitv_settings()
  setlocal iskeyword+=/,-,.
  nnoremap <silent><buffer> C :<C-u>Git checkout <C-r><C-w><CR>
endfunction


" neocomplcache.vim
let g:neocomplcache_enable_at_startup = 1
let g:neocomplcache_auto_completion_start_length = 2


" neosnippet.vim
let g:neosnippet#snippets_directory = "~/.vim/snippets"

imap <C-k> <Plug>(neosnippet_expand_or_jump)
smap <C-k> <Plug>(neosnippet_expand_or_jump)

imap <expr> <TAB> neosnippet#expandable() <Bar><Bar> neosnippet#jumpable() ?
\ "\<Plug>(neosnippet_expand_or_jump)" :
\ pumvisible() ? "\<C-n>" : "\<TAB>"


" octoeditor.vim
let g:octopress_path = '~/works/octopress-github'


" open-browser.vim
nmap gx <Plug>(openbrowser-smart-search)
vmap gx <Plug>(openbrowser-smart-search)


" operator-replace.vim
map R <Plug>(operator-replace)


" vim-precious
map <Leader>q <Plug>(precious-quickrun-op)
omap ic <Plug>(textobj-precious-i)
vmap ic <Plug>(textobj-precious-i)


" quickrun.vim
map <Leader>r <Plug>(quickrun)

let g:quickrun_config = {}
let g:quickrun_config['_'] = {
\   'runner': 'vimproc',
\   'runner/vimproc/updatetime': 100,
\   'outputter': 'multi:buffer:quickfix',
\   'outputter/buffer/split': ':botright 8sp',
\   'hook/close_buffer/enable_failure': 1,
\   'hook/close_quickfix/enable_exit': 1,
\   'hook/unite_quickfix/enable_failure': 1,
\   'hook/close_unite_quickfix/enable_hook_loaded': 1,
\   'hook/time/enable': 1,
\   'hook/u_nya_/enable': 1,
\   'hook/quickfix_replate_tempname_to_bufnr/enable_exit' : 1,
\   'hook/quickfix_replate_tempname_to_bufnr/priority_exit' : -10,
\ }

if has('mac')
  let g:quickrun_config['markdown'] = {
  \   'outputter': 'null',
  \   'command':   'open',
  \   'cmdopt':    '-a',
  \   'args':      'Marked',
  \   'exec':      '%c %o %a %s',
  \ }
else
  let g:quickrun_config['markdown'] = {
  \   'outputter': 'multi',
  \   'outputter/multi/targets': ['buffer', 'browser']
  \ }
endif

let g:quickrun_config['jsx'] = {
\   'command': 'jsx',
\   'exec': ['%c --run %s']
\ }

let g:quickrun_config['watchdogs_checker/_'] = {
\   'hook/unite_quickfix/enable_failure': 1,
\   'hook/u_nya_/enable': 0,
\ }

augroup QuickRunPHPUnit
  autocmd!
  autocmd BufWinEnter,BufNewFile *Test.php  set filetype=php.phpunit
  autocmd BufWinEnter,BufNewFile *_test.php set filetype=php.phpunit
augroup END
let g:quickrun_config['php.phpunit'] = {
\   'command': 'phpunit',
\   'outputter': 'phpunit',
\   'hook/close_buffer/enable_failure': 0,
\   'hook/close_quickfix/enable_exit': 0,
\   'hook/unite_quickfix/enable_failure': 0,
\ }


" ref.vim
let g:ref_use_vimproc = 1
let g:ref_phpmanual_path = $HOME . '/share/phpmanual'

let g:ref_source_webdict_sites = {
\   'default': 'alc',
\   'alc': {
\     'url': 'http://eow.alc.co.jp/search?q=%s',
\   },
\   'wikipedia:ja': 'http://ja.wikipedia.org/wiki/%s',
\ }
function! g:ref_source_webdict_sites.alc.filter(output)
  return join(split(a:output, "\n")[38 :], "\n")
endfunction

nmap <silent> K <Plug>(ref-keyword)
vmap <silent> K <Plug>(ref-keyword)
noremap <Space>ra :<C-u>Ref webdict alc<Space>
noremap <Space>rm :<C-u>Ref man<Space>


" ===== restart.vim =====
if has('gui_running')
  let bundle = neobundle#get('restart.vim')
  function! bundle.hooks.on_source(bundle)
    command!
    \   -bar
    \   RestartWithSession
    \   let g:restart_sessionoptions = 'blank,curdir,folds,help,localoptions,tabpages'
    \   | Restart
  endfunction

  MapAlterCommand res[tart] Restart
endif


" ===== shaberu.vim =====
if has('mac')
  NeoBundleSource shaberu.vim

  let g:shaberu_user_define_say_command = 'SayKana "%%TEXT%%"'

  augroup vimrc-shaberu-vim
    autocmd VimEnter * ShaberuSay 'おかえりなさいませ、ごしゅじんさま'
    autocmd VimLeave * ShaberuSay 'いってらっしゃいませ、ごしゅじんさま'
    autocmd BufWritePost .gvimrc nested source $MYGVIMRC | ShaberuSay 'ビムアールシーをよみこみました'
  augroup END
endif


" ===== smartinput.vim =====
call smartinput#map_to_trigger('i', '<Space>', '<Space>', '<Space>')
call smartinput#map_to_trigger('i', '<', '<', '<')
call smartinput#map_to_trigger('i', '>', '>', '>')
call smartinput#map_to_trigger('i', '%', '%', '%')
call smartinput#map_to_trigger('i', '?', '?', '?')

call smartinput#define_rule({'at': '\%#', 'char': '<', 'input': '<><Left>'})
call smartinput#define_rule({'at': '\%#\_s*>', 'char': '>', 'input': '<C-r>=smartinput#_leave_block(''>'')<Enter><Right>'})
call smartinput#define_rule({'at': '<\%#>', 'char': '<BS>', 'input': '<BS><Del>'})

call smartinput#define_rule({'at': '{\%#}', 'char': '<Space>', 'input': '<Space><Space><Left>'})
call smartinput#define_rule({'at': '{\%#}', 'char': '%', 'input': '%<Space><Space>%<Left><Left>'})
call smartinput#define_rule({'at': '{% \%# %}', 'char': '<BS>', 'input': '<BS><BS><Del><Del>'})
call smartinput#define_rule({'at': '{\%#}', 'char': '{', 'input': '{<Space><Space>}<Left><Left>'})
call smartinput#define_rule({'at': '{{ \%# }}', 'char': '<BS>', 'input': '<BS><BS><Del><Del>'})

call smartinput#define_rule({'at': '<\%#>', 'char': '?', 'input': '?<Space>?<Left><Left>'})
call smartinput#define_rule({'at': '<?\%# ?>', 'char': '<BS>', 'input': '<BS><Del><Del>'})

imap <C-j> <Plug>(eskk:toggle)
cmap <C-j> <Plug>(eskk:toggle)


" ===== smartword.vim =====
map w <Plug>(smartword-w)
map b <Plug>(smartword-b)
map e <Plug>(smartword-e)
map ge <Plug>(smartword-ge)
noremap W w
noremap B b
noremap E e
noremap gE ge


" ===== sonictemplate.vim =====
let g:sonictemplate_vim_template_dir = expand('~/.vim/templates/')


" ===== submode.vim =====
let g:submode_keep_leaving_key = 1

" タブの切り替え
call submode#enter_with('tabpage', 'n', '', 'gt', 'gt')
call submode#enter_with('tabpage', 'n', '', 'gT', 'gT')
call submode#map('tabpage', 'n', '', 't', 'gt')
call submode#map('tabpage', 'n', '', 'T', 'gT')

" ウィンドウのリサイズ
call submode#enter_with('winsize', 'n', '', '<C-w>>', '<C-w>>')
call submode#enter_with('winsize', 'n', '', '<C-w><', '<C-w><')
call submode#enter_with('winsize', 'n', '', '<C-w>+', '<C-w>+')
call submode#enter_with('winsize', 'n', '', '<C-w>-', '<C-w>-')
call submode#map('winsize', 'n', '', '>', '<C-w>>')
call submode#map('winsize', 'n', '', '<', '<C-w><')
call submode#map('winsize', 'n', '', '+', '<C-w>+')
call submode#map('winsize', 'n', '', '-', '<C-w>-')


" ===== tmpwin.vim =====
nnoremap <silent><Leader>tt :<C-u>call tmpwin#toggle(
\   {'open' : '15split', 'move_cursor': 1},
\   'TweetVimHomeTimeline')<CR>


" ===== unite.vim =====
let g:unite_source_history_yank_enable = 1

let g:unite_source_grep_command = 'ag'
let g:unite_source_grep_default_opts = '--nocolor --nogroup'
let g:unite_source_grep_recursive_opt = ''
let g:unite_source_grep_max_candidates = 200

call unite#custom#alias('file', 'tabopen', 'tabdrop')
call unite#custom#alias('directory', 'tabopen', 'tabvimfiler')

nnoremap [unite] <Nop>
nmap ,f [unite]

noremap <silent> [unite]b :<C-u>UniteWithBufferDir -buffer-name=files -start-insert file file/new<CR>
noremap <silent> [unite]c :<C-u>Unite -auto-preview colorscheme<CR>
noremap <silent> [unite]I :<C-u>Unite -auto-quit neobundle/update<CR>
noremap <silent> [unite]o :<C-u>Unite outline<CR>
noremap <silent> [unite]u :<C-u>Unite -buffer-name=files -start-insert buffer file_rec/async:! file file_mru<CR>

autocmd vimrc FileType unite call s:unite_my_settings()
function! s:unite_my_settings() "{{{
  nmap <buffer> <ESC> <Plug>(unite_exit)
  imap <buffer> jj <Plug>(unite_insert_leave)
  nmap <buffer> ' <Plug>(unite_quick_match_default_action)
  imap <buffer> ' <Plug>(unite_quick_match_default_action)
  nmap <buffer> x <Plug>(unite_toggle_mark_current_candidate)
  imap <buffer> <C-BS> <Plug>(unite_delete_backward_path)
endfunction "}}}


" ===== vimfiler.vim =====
let g:vimfiler_as_default_explorer = 1


" ===== vimshell.vim =====
let bundle = neobundle#get('vimshell')
function! bundle.hooks.on_source(bundle)
  let g:vimshell_user_prompt = 'getcwd()'
  let g:vimshell_prompt = "/ _ / X < "
endfunction

nmap <C-@> <Plug>(vimshell_switch)
nmap <C-Space> <Plug>(vimshell_switch)
nnoremap ! :VimShellExecute<Space>


" ===== watchdogs.vim =====
let g:watchdogs_check_BufWritePost_enable = 1
let g:watchdogs_check_CursorHold_enable = 0

let bundle = neobundle#get('vim-quickrun')
function! bundle.hooks.on_source(bundle)
  call watchdogs#setup(g:quickrun_config)
endfunction



" === Other === {{{1
" vim hacks #161
nnoremap <sid>(command-line-enter) q:
xnoremap <sid>(command-line-enter) q:
nnoremap <sid>(command-line-norange) q:<C-u>

nmap :  <sid>(command-line-enter)
xmap :  <sid>(command-line-enter)

autocmd vimrc CmdwinEnter * call s:init_cmdwin()
function! s:init_cmdwin()
  nnoremap <buffer> q :<C-u>quit<CR>
  nnoremap <buffer> <TAB> :<C-u>quit<CR>
  inoremap <buffer> <expr> <CR> pumvisible() ? "\<C-y>\<CR>" : "\<CR>"
  inoremap <buffer> <expr> <C-h> pumvisible() ? "\<C-y>\<C-h>" : "\<C-h>"
  inoremap <buffer> <expr> <BS> pumvisible() ? "\<C-y>\<C-h>" : "\<C-h>"

  startinsert!
endfunction

" kana's useful tab function {{{
function! s:move_window_into_tab_page(target_tabpagenr)
  " Move the current window into a:target_tabpagenr.
  " If a:target_tabpagenr is 0, move into new tab page.
  if a:target_tabpagenr < 0  " ignore invalid number.
    return
  endif
  let original_tabnr = tabpagenr()
  let target_bufnr = bufnr('')
  let window_view = winsaveview()

  if a:target_tabpagenr == 0
    tabnew
    tabmove  " Move new tabpage at the last.
    execute target_bufnr 'buffer'
    let target_tabpagenr = tabpagenr()
  else
    execute a:target_tabpagenr 'tabnext'
    let target_tabpagenr = a:target_tabpagenr
    topleft new  " FIXME: be customizable?
    execute target_bufnr 'buffer'
  endif
  call winrestview(window_view)

  execute original_tabnr 'tabnext'
  if 1 < winnr('$')
    close
  else
    enew
  endif

  execute target_tabpagenr 'tabnext'
endfunction " }}}
nnoremap <silent> <Space>ao :<C-u>call <SID>move_window_into_tab_page(0)<Cr>