" ====================================== deni.vim settings ======================================
if &compatible
 set nocompatible
endif

" install dir 
let s:dein_dir = expand('~/.cache/dein') 
let s:dein_repo_dir = s:dein_dir . '/repos/github.com/Shougo/dein.vim'
 
" dein installation check
if &runtimepath !~# '/dein.vim'
 if !isdirectory(s:dein_repo_dir)
 execute '!git clone https://github.com/Shougo/dein.vim' s:dein_repo_dir
 endif
 execute 'set runtimepath^=' . fnamemodify(s:dein_repo_dir, ':p')
endif
 
" begin settings
if dein#load_state(s:dein_dir)
 call dein#begin(s:dein_dir)
 
 " .toml file
 let g:rc_dir = expand('~/.vim')
 let s:toml = g:rc_dir . '/dein.toml'
 let s:lazy_toml = g:rc_dir . '/dein_lazy.toml'
 
 " read toml and cache
 call dein#load_toml(s:toml, {'lazy': 0})
 call dein#load_toml(s:lazy_toml, {'lazy': 1})

 " end settings
 call dein#end()
 call dein#save_state()
endif
 
" plugin installation check
if dein#check_install()
 call dein#install()
endif

" ====================================== general settings ======================================
" https://vim-jp.org/vimdoc-ja/map.html#mapleader
" Leaderキーをスペースに設定
let mapleader = "\<Space>"

" シンタックスを有効にする
syntax on

" https://vim-jp.org/vimdoc-ja/filetype.html#:filetype-plugin-on
" https://vim-jp.org/vimdoc-ja/filetype.html#:filetype-indent-on
" ファイル形式別プラグインとインデントを有効にする
" これがないとvim-goなどが動作しない
filetype plugin indent on

" https://github.com/posva/vim-vue#my-syntax-highlighting-stops-working-randomly
" vueファイルのシンタックスが効かなくなる問題対応
au FileType vue syntax sync fromstart

" バックスペースとCtrl+hで削除を有効にする
set backspace=2

" 改行時自動インデント
set smartindent

" 行番号を表示
set number

" カーソルから相対的な行数を表示する
set relativenumber

" https://vim-jp.org/vimdoc-ja/options.html#'tabstop'
" タブでも常に空白を挿入
set tabstop=4
set shiftwidth=4
set expandtab

" インクリメントサーチを有効にする
set incsearch

" https://vim-jp.org/vimdoc-ja/options.html#'ignorecase'
" 検索時大文字小文字を区別しない
set ignorecase

" https://vim-jp.org/vimdoc-ja/options.html#'smartcase'
" 検索時に大文字を入力した場合ignorecaseが無効になる
set smartcase

" ハイライトサーチを有効にする
set hlsearch

" undoできる最大数
set undolevels=1000

" mac os のクリップボードを共有
set clipboard+=unnamed

" カーソルが常に中央に来るようにする
set scrolloff=100

" スワップファイルに書き込まれる時間(ミリ秒単位)
set updatetime=450

set lazyredraw
set ttyfast

" 一行が長いファイルをsyntaxを制御することで軽くする
set synmaxcol=256

" カーソルラインを表示する
set cursorline

" https://vim-jp.org/vimdoc-ja/pi_netrw.html#g:netrw_liststyle
" netrwツリー表示を有効にする
let g:netrw_liststyle = 3

" 拡張子ごとのインデントを指定する
augroup fileTypeIndent
    autocmd!
    autocmd BufNewFile,BufRead *.html setlocal tabstop=4 softtabstop=4 shiftwidth=4
    autocmd BufNewFile,BufRead *.js setlocal tabstop=2 softtabstop=2 shiftwidth=2
    autocmd BufNewFile,BufRead *.vue setlocal tabstop=2 softtabstop=2 shiftwidth=2
augroup END

" https://vim-jp.org/vimdoc-ja/options.html#'wildmode'
" wildmenuを有効にする
set wildmenu
set wildmode=full

" grepした結果をquickfixに表示する
au QuickFixCmdPost *grep* cwindow

" ====================================== key mappings ======================================
" ファイル保存と終了
nmap <Leader>w :w<CR>
nmap <Leader>q :q!<CR>

" 検索
nmap <C-G><C-G> :Ggrep <C-R><C-W><CR><CR>

" 置換
nmap <Leader>re :%s;<C-R><C-W>;g<Left><Left>;

" visualで選択したテキストを置換する
vnoremap <Leader>re y:%s/<C-r>=substitute(@", "<C-v><NL>", "\\\\n", "g")<CR>//g<Left><Left>

" ハイライトを削除する
nmap <Esc><Esc> :nohlsearch<CR>

" 画面移動
nmap <C-H> <C-W>h
nmap <C-J> <C-W>j
nmap <C-K> <C-W>k
nmap <C-L> <C-W>l

" vimrcを開く
nmap <Leader>. :e ~/.vimrc<CR>

" Ctrl+cでnormalモード
nmap <C-c> <Esc>

" text object key mapping
" cut
nmap c8 ci(
nmap c2 ci"
nmap c7 ci'
nmap c@ ci`
nmap c[ ci[
nmap c{ ci{

nmap ca8 ca(
nmap ca2 ca"
nmap ca7 ca'
nmap ca@ ca`
nmap ca[ ca[
nmap ca{ ca{

" delete
nmap d8 di(
nmap d2 di"
nmap d7 di'
nmap d@ di`
nmap d[ di[
nmap d{ di{

nmap da8 da(
nmap da2 da"
nmap da7 da'
nmap da@ da`
nmap da[ da[
nmap da{ da{

" yank
nmap y8 yi(
nmap y2 yi"
nmap y7 yi'
nmap y@ yi`
nmap y[ yi[
nmap y{ yi{

nmap ya8 ya(
nmap ya2 ya"
nmap ya7 ya'
nmap ya@ ya`
nmap ya[ ya[
nmap ya{ ya{

" visual
nmap v8 vi(
nmap v2 vi"
nmap v7 vi'
nmap v@ vi`
nmap v[ vi[
nmap v{ vi{

nmap va8 va(
nmap va2 va"
nmap va7 va'
nmap va@ va`
nmap va[ va[
nmap va{ va{

" カーソルラインの位置を保存する
if has("autocmd")
    autocmd BufReadPost *
    \ if line("'\"") > 0 && line ("'\"") <= line("$") |
    \   exe "normal! g'\"" |
    \ endif
endif

" undoの保存先
if has('persistent_undo')
  set undodir=~/.vim/undo
  set undofile
endif

" numberとrelativenumberの切り替え
function! ToggleRelativenumber() abort
  if &relativenumber == 1
     setlocal norelativenumber
  else
     setlocal relativenumber
  endif
endfunction
nnoremap <silent> <Leader>n :call ToggleRelativenumber()<CR>

" 自作アプリケーションランチャー
nnoremap <silent> <Leader>l :belowright term ++close gol -f<CR>

" visual paste
vnoremap <silent> <C-p> "0p<CR>

" ターミナルを下部で開く
nnoremap <silent> <Leader>te :belowright term<cr>

" ====================================== vim-go settings ======================================
" ファイル保存時go importを実行する
let g:go_fmt_command = "goimports"

" ファイル保存時、linterを実行する
let g:go_metalinter_autosave = 1

" linter実行時、go vetのみを実行する
let g:go_metalinter_autosave_enabled = ['vet']

" vim-lspをしようするので、vim-goの`Ctrl+]`を無効にする
let g:go_def_mapping_enabled = 0

" GoRunやGoTest時の画面分割方法変更
let g:go_term_mode = 'split'

" key mapping
au FileType go nmap <silent> <Leader>c <Plug>(go-coverage)
au FileType go nmap <silent> <Leader>r <Plug>(go-run)
au FileType go nmap <silent> <Leader>t <Plug>(go-test)
au FileType go nmap <silent> <Leader>c <Plug>(go-coverage)
au FileType go nmap <silent> <Leader>at :GoAddTags<CR>
au FileType go nmap <silent> <Leader>rt :GoRemoveTags<CR>
au FileType go nmap <silent> <Leader>fs :GoFillStruct<CR>
au FileType go nmap <silent> <Leader>ki :GoKeyify<CR>
au FileType go nmap <silent> <Leader>dd :GoDeclsDir<CR>
au FileType go nmap <silent> <Leader>dl :GoDecls<CR>
au FileType go nmap <silent> <Leader>ip :GoImpl<CR>
au FileType go nmap <silent> <Leader>rn :GoRename<CR>
au FileType go nmap <silent> <F12> :GoDebugStart<CR>
au FileType go nmap <silent> <F12><F12> :GoDebugStop<CR>

" ====================================== fzf settings ======================================
nmap <C-P> :GFiles<CR>

" ====================================== lsp settings ======================================
nmap <silent> <C-]> :LspDefinition<CR>
nmap <silent> <Leader>rf :LspReferences<CR>
nmap <silent> <Leader>im :LspImplementation<CR>

" 非同期補完を有効にする
let g:lsp_async_completion = 1

" ====================================== lsp golang settings ======================================
" https://github.com/saibing/bingo/wiki/Install
if executable('bingo')
    au User lsp_setup call lsp#register_server({
        \ 'name': 'bingo',
        \ 'cmd': {server_info->['bingo', '-mode', 'stdio', '-logfile', '/Users/skanehira/bingo.log']},
        \ 'whitelist': ['go'],
        \ })
endif

let g:lsp_log_verbose = 1
let g:lsp_log_file = expand('~/vim-lsp.log')

" ====================================== lsp php settings ======================================
au User lsp_setup call lsp#register_server({
            \ 'name': 'php-language-server',
            \ 'cmd': {server_info->['php', expand('~/.cache/dein/repos/github.com/felixfbecker/php-language-server/bin/php-language-server.php')]},
            \ 'whitelist': ['php'],
            \ })

" ====================================== lsp js settings ======================================
if executable('flow-language-server')
    au User lsp_setup call lsp#register_server({
        \ 'name': 'flow-language-server',
        \ 'cmd': {server_info->[&shell, &shellcmdflag, 'flow-language-server --stdio']},
        \ 'root_uri':{server_info->lsp#utils#path_to_uri(lsp#utils#find_nearest_parent_file_directory(lsp#utils#get_buffer_path(), '.flowconfig'))},
        \ 'whitelist': ['javascript', 'javascript.jsx'],
        \ })
endif

" ====================================== lsp docker settings ======================================
if executable('docker-langserver')
    au User lsp_setup call lsp#register_server({
        \ 'name': 'docker-langserver',
        \ 'cmd': {server_info->[&shell, &shellcmdflag, 'docker-langserver --stdio']},
        \ 'whitelist': ['dockerfile'],
        \ })
endif

" ====================================== lsp css settings ======================================
if executable('css-languageserver')
    au User lsp_setup call lsp#register_server({
        \ 'name': 'css-languageserver',
        \ 'cmd': {server_info->[&shell, &shellcmdflag, 'css-languageserver --stdio']},
        \ 'whitelist': ['css', 'less', 'sass'],
        \ })
endif

" ====================================== asyncomplete settings ======================================
inoremap <expr> <C-j> pumvisible() ? "\<C-n>" : "\<Tab>"
inoremap <expr> <C-k> pumvisible() ? "\<C-p>" : "\<S-Tab>"
inoremap <expr> <cr> pumvisible() ? "\<C-y>" : "\<cr>"

" ====================================== vim-markdown settings ======================================
" mdを開くときの折りたたみを無効にする
let g:vim_markdown_folding_disabled = 1

" ====================================== vim-surround settings ======================================
nmap <Leader>7 ysiw'
nmap <Leader>2 ysiw"
nmap <Leader>` ysiw`
nmap <Leader>8 ysiw)
nmap <Leader>[ ysiw]
nmap <Leader>{ ysiw}

" ====================================== ultisnips settings ======================================
let g:UltiSnipsExpandTrigger="<tab>"
let g:UltiSnipsJumpForwardTrigger="<tab>"
let g:UltiSnipsJumpBackwardTrigger="<s-tab>"

" ultisnipes自動補完
if has('python3')
    call asyncomplete#register_source(asyncomplete#sources#ultisnips#get_source_options({
        \ 'name': 'ultisnips',
        \ 'whitelist': ['*'],
        \ 'completor': function('asyncomplete#sources#ultisnips#completor'),
        \ }))
endif

" ====================================== profiling ======================================
" vim +'call ProfileCursorMove()' <カーソルを動かすのが重いファイル>
function! ProfileCursorMove() abort
  let profile_file = expand('./vim-profile.log')
  if filereadable(profile_file)
    call delete(profile_file)
  endif

  normal! gg
  normal! zR

  execute 'profile start ' . profile_file
  profile func *
  profile file *

  augroup ProfileCursorMove
    autocmd!
    autocmd CursorHold <buffer> profile pause | q
  augroup END

  for i in range(1000)
    call feedkeys('j')
  endfor
endfunction

" ====================================== emment ======================================
let g:user_emmet_install_global = 0
let g:user_emmet_settings = {
\ 'variables': {
\   'lang' : 'ja'
\ }
\}
au FileType html,css,vue EmmetInstall
au FileType html,css,vue imap <C-f> <C-y>,

" ====================================== vim-keymaps ======================================
imap <c-g> <Plug>KeyMapRotate
let g:keymaps =  [
      \  {
      \    'name': 'normal',
      \  },
      \  {
      \    'name': 'coding',
      \    'keymap': {
      \      'inoremap': {
      \        '1': '!',
      \        '!': '1',
      \        '2': '"',
      \        '"': '2',
      \        '3': '#',
      \        '#': '3',
      \        '4': '$',
      \        '$': '4',
      \        '5': '%',
      \        '%': '5',
      \        '6': '&',
      \        '&': '6',
      \        '7': "'",
      \        "'": '7',
      \        '8': '(',
      \        '(': '8',
      \        '9': ')',
      \        ')': '9',
      \        '@': '`',
      \        '`': '@',
      \        '-': '=',
      \        '=': '-',
      \      },
      \    },
      \  },
      \]


" ====================================== lightline ======================================
set laststatus=2
if !has('gui_running')
  set t_Co=256
endif

" ====================================== ale ======================================
let g:ale_sign_error = 'xx'
let g:ale_sign_warning = '!!'
let g:ale_echo_msg_error_str = 'E'
let g:ale_echo_msg_warning_str = 'W'
let g:ale_echo_msg_format = '[%linter%] %s [%severity%]'
let g:ale_set_highlights = 0