vim2 advent calendar 2019 15日目です。
導入
vimと一口に言ってもその設定項目は多岐に渡ります。さらにプラグインも入れればプラグインそのものと設定を含めて、百人いれば百通りのvim環境が出来上がるでしょう。
なんだかんだでvimを使い続けて5年ほどになりますが、今まで煮詰めてきた自分のvim環境を百通りのうちの一つとして紹介するのがこの記事の趣旨です。
neovim
vimと言ってもいくつか種類がありますが、自分が使用しているのはneovimです。
非同期がサポートされたあたりで乗り換えています。現在はvimでも非同期をサポートしており、neovimでしか動かなかったようなプラグインもvimで動くようになっているようです。今回のアドベントカレンダーに合わせて、neovim専用になっていた設定ファイルをvimでも使えるようにしたかったのですが、手元で試してみた限りうまくいかなかったのでいくつかの部分がneovimでしか動かなくなっています。ご了承ください。一応本来の想定は記述しておきます。
フォルダ構成
dotfiles
vim含め、様々な設定ファイルをdotfilesで管理しています。
dotfilesのルートは以下の構成になっています。
% tree -a -L 1
.
├── .config
├── .ctags
├── .git
├── .gitignore
├── .tmux
├── .vimrc
├── .zplugrc
├── .zsh
├── .zshrc
├── bin
├── etc
├── nvim -> /Users/takumikawase/dotfiles/.config/nvim
└── tags
更に.configの中身は以下のようになっています。
% tree -a -L 1
.
├── anyenv
├── coc
├── efm-langserver
├── nvim
└── xbuild
いくつかのファイルは省略しています。
vimの設定ファイルはデフォルトでは.vimrcですが、neovimの設定ファイルはデフォルトでは.config/nvim下にあるinit.vimとなっています。
vimとneovimで同じ設定ファイルを使い回すために.vimrcの中身は以下の二行のみです。
set runtimepath+=$XDG_CONFIG_HOME/nvim
source $XDG_CONFIG_HOME/nvim/init.vim
これでvimを起動すると同時にneovimの設定ファイルをそのまま読み込んでくれます。あとはneovimの設定ファイルでvimかneovimかによって処理を分岐させることでvim, neovim量対応の設定が可能です。
自分のdotfilesについては「CUI環境とdotfilesを紹介する」を参照してください。
nvim
nvimのフォルダ構成になります。
% tree -a -L 1
.
├── autocmds.vim
├── autoload
├── coc-settings.json
├── coc.toml
├── color.vim
├── colors
├── commands.vim
├── dein.toml
├── dein.vim
├── dein_lang.toml
├── dein_lazy.toml
├── dein_lsp.toml
├── dein_plugin.toml
├── dein_vim.toml
├── func.vim
├── init.vim
├── keymappings.vim
├── linux.vim
├── mac.vim
├── tags
└── types.vim
元々は一つの.vimrcを使用していましたが、neovimへの移行に伴い段階的に機能ごとにファイル分けを行いました。
それぞれのファイルの役割は以下の通りです。
init.vim
起動時に最初に読み込まれるファイルです。このファイルを起点に他のファイルを読み込んでいきます。
更に、setコマンドで各種設定を行なっています。
init.vim
" settings for mac and unix
if has('mac')
" settings for mac
source $HOME/.config/nvim/mac.vim
" settings for linux
else
source $HOME/.config/nvim/linux.vim
endif
" load dein.vim
source $XDG_CONFIG_HOME/nvim/dein.vim
" color scheme
source $XDG_CONFIG_HOME/nvim/color.vim
" load other setting files
" key mappings
source $HOME/.config/nvim/keymappings.vim
" settings for each filetypes
source $HOME/.config/nvim/types.vim
" launch commands
" source $HOME/.config/nvim/commands.vim
" autocommands
source $HOME/.config/nvim/autocmds.vim
" functions
" source $HOME/.config/nvim/func.vim
set number
set title
set ambiwidth=double
set tabstop=4
set expandtab
set shiftwidth=4
set smartindent
set list
set listchars=tab:»-,trail:-,extends:»,precedes:«,nbsp:%
set nrformats-=octal
set hidden
set history=200
set virtualedit=block
set whichwrap=b,s,h,l,[,],<,>
set backspace=indent,eol,start
set wildmenu
set fenc=utf-8
set nobackup
set noswapfile
set autoread
set showcmd
set cursorline
set visualbell
set laststatus=2
set wrapscan
set modeline
set autowrite
set display=lastline
set matchpairs& matchpairs+=<:>
set matchtime=1
set showtabline=2
set wildmenu
set wildignore=*.o,*.obj,*.pyc,*.so,*.dll
set mouse=a
set updatetime=100
" search system
set showmatch
set smartcase
set ignorecase
set infercase
set hlsearch
set incsearch
" foldmethod
set foldmethod=marker
set foldlevel=0
set foldcolumn=1
" disable the preview window
set completeopt-=preview
if has('nvim')
set pumblend=5
endif
最後のset pumblendはneovimのfloating windowを使うためのオプションです。
dein.vim
後述するvimのプラグインマネージャーであるdeinで、各種プラグインを読み込むためのファイルです。
ちなみにインストールするプラグインはtomlファイルで管理していますが、tomlファイルも用途ごとにファイルを分けています。
dein.vim
" dein Scripts-----------------------------
if &compatible
set nocompatible " Be iMproved
endif
" set cache and config dirs
let s:dein_cache_dir = $XDG_CACHE_HOME . '/dein'
let s:dein_config_dir = $XDG_CONFIG_HOME . '/nvim'
" Required:
set runtimepath+=$XDG_CACHE_HOME/dein/repos/github.com/Shougo/dein.vim
let s:dein_dir = s:dein_cache_dir . '/repos/github.com/Shougo/dein.vim'
if !isdirectory(s:dein_dir)
call system('git clone https://github.com/Shougo/dein.vim ' . shellescape(s:dein_dir))
endif
" Required:
if dein#load_state(s:dein_cache_dir)
call dein#begin(s:dein_cache_dir)
let s:toml = s:dein_config_dir . '/dein.toml'
let s:toml_lazy = s:dein_config_dir . '/dein_lazy.toml'
let s:toml_coc = s:dein_config_dir . '/coc.toml'
let s:toml_lang = s:dein_config_dir . '/dein_lang.toml'
let s:toml_plugin = s:dein_config_dir . '/dein_plugin.toml'
let s:toml_vim = s:dein_config_dir . '/dein_vim.toml'
call dein#load_toml(s:toml, {'lazy': 0})
call dein#load_toml(s:toml_lazy, {'lazy': 1})
call dein#load_toml(s:toml_coc, {'lazy': 1})
call dein#load_toml(s:toml_lang, {'lazy': 1})
call dein#load_toml(s:toml_plugin, {'lazy': 0})
if !has('nvim')
call dein#load_toml(s:toml_vim, {'lazy': 0})
endif
call dein#end()
call dein#save_state()
" Let dein manage dein
" Required:
" call dein#add('/Users/kawasetakumi/.cache/dein/repos/github.com/Shougo/dein.vim')
" Add or remove your plugins here:
" call dein#add('Shougo/neosnippet.vim')
" call dein#add('Shougo/neosnippet-snippets')
" You can specify revision/branch/tag.
" call dein#add('Shougo/vimshell', { 'rev': '3787e5' })
" Required:
" call dein#end()
" call dein#save_state()
endif
" Required:
filetype plugin indent on
" if dein#check_install(['vimproc'])
" call dein#install(['vimproc'])
" endif
" If you want to install not installed plugins on startup.
if dein#check_install()
call dein#install()
endif
" End dein Scripts-------------------------
autocmds.vim
autocmd類をこちらに定義しています。現在は各種Filetypeをトリガーに動くautocmdが全てを占めています。
autocmds.vim
"" push quickfix window always to the bottom
autocmd FileType qf wincmd J
" for go lang
augroup go
autocmd!
autocmd FileType go :highlight goErr cterm=bold ctermfg=214
autocmd FileType go :match goErr /\<err\>/
augroup END
" for python
augroup python
autocmd!
autocmd FileType python :syn match pythonOperator "\(+\|=\|-\|\^\|\*\)"
autocmd FileType python :syn match pythonDelimiter "\(,\|\.\|:\)"
autocmd FileType python :syn keyword self self
autocmd FileType python :hi link pythonOperator Statement
autocmd FileType python :hi link pythonDelimiter Special
autocmd FileType python :hi link self Type
" autocmd FileType python :highlight self cterm=bold ctermfg=214
" autocmd FileType python :match self /self/
" autocmd FileType python :highlight colon cterm=bold ctermfg=214
" autocmd FileType python :match colon /:/
augroup END
" for c++
augroup cpp
autocmd!
autocmd FileType cpp :highlight cppcoloncolon cterm=bold ctermfg=214
autocmd FileType cpp :match cppcoloncolon /\:\:/
augroup END
augroup typescript
autocmd!
autocmd FileType typescript :syn match Operator "\(|\|+\|=\|-\|\^\|\*\)"
autocmd FileType typescript :syn match Delimiter "\(\.\|:\)"
autocmd FileType typescript :hi link Operator Statement
autocmd FileType typescript :hi link Delimiter Special
augroup END
augroup typescriptreact
autocmd!
autocmd BufNewFile,BufRead *.tsx set filetype=typescript.tsx
autocmd FileType typescript.tsx :syn match Operator "\(|\|+\|=\|-\|\^\|\*\)"
autocmd FileType typescript.tsx :syn match Delimiter "\(\.\|:\)"
autocmd FileType typescript.tsx :hi link Operator Statement
autocmd FileType typescript.tsx :hi link Delimiter Special
augroup END
augroup denite-windows
autocmd!
autocmd FileType denite set winblend=5
autocmd FileType denite-filter set winblend=5
augroup END
" Define mappings
autocmd FileType denite call s:denite_my_settings()
function! s:denite_my_settings() abort
nnoremap <silent><buffer><expr> <CR>
\ denite#do_map('do_action')
nnoremap <silent><buffer><expr> d
\ denite#do_map('do_action', 'delete')
nnoremap <silent><buffer><expr> p
\ denite#do_map('do_action', 'preview')
nnoremap <silent><buffer><expr> q
\ denite#do_map('quit')
nnoremap <silent><buffer><expr> i
\ denite#do_map('open_filter_buffer')
nnoremap <silent><buffer><expr> <Space>
\ denite#do_map('toggle_select').'j'
endfunction
autocmd FileType denite-filter call s:denite_filter_my_settings()
function! s:denite_filter_my_settings() abort
imap <silent><buffer> <C-o> <Plug>(denite_filter_quit)
endfunction
autocmd FileType defx call s:defx_my_settings()
function! s:defx_my_settings() abort
" Define mappings
nnoremap <silent><buffer><expr> <CR>
\ defx#do_action('drop')
nnoremap <silent><buffer><expr> c
\ defx#do_action('copy')
nnoremap <silent><buffer><expr> m
\ defx#do_action('move')
nnoremap <silent><buffer><expr> p
\ defx#do_action('paste')
nnoremap <silent><buffer><expr> l
\ defx#do_action('open')
nnoremap <silent><buffer><expr> E
\ defx#do_action('open', 'vsplit')
nnoremap <silent><buffer><expr> P
\ defx#do_action('open', 'pedit')
nnoremap <silent><buffer><expr> o
\ defx#do_action('open_or_close_tree')
nnoremap <silent><buffer><expr> K
\ defx#do_action('new_directory')
nnoremap <silent><buffer><expr> N
\ defx#do_action('new_file')
nnoremap <silent><buffer><expr> M
\ defx#do_action('new_multiple_files')
nnoremap <silent><buffer><expr> C
\ defx#do_action('toggle_columns',
\ 'mark:indent:icon:filename:type:size:time')
nnoremap <silent><buffer><expr> S
\ defx#do_action('toggle_sort', 'time')
nnoremap <silent><buffer><expr> d
\ defx#do_action('remove')
nnoremap <silent><buffer><expr> r
\ defx#do_action('rename')
nnoremap <silent><buffer><expr> !
\ defx#do_action('execute_command')
nnoremap <silent><buffer><expr> x
\ defx#do_action('execute_system')
nnoremap <silent><buffer><expr> yy
\ defx#do_action('yank_path')
nnoremap <silent><buffer><expr> .
\ defx#do_action('toggle_ignored_files')
nnoremap <silent><buffer><expr> ;
\ defx#do_action('repeat')
nnoremap <silent><buffer><expr> h
\ defx#do_action('cd', ['..'])
nnoremap <silent><buffer><expr> ~
\ defx#do_action('cd')
nnoremap <silent><buffer><expr> q
\ defx#do_action('quit')
nnoremap <silent><buffer><expr> <Space>
\ defx#do_action('toggle_select') . 'j'
nnoremap <silent><buffer><expr> *
\ defx#do_action('toggle_select_all')
nnoremap <silent><buffer><expr> j
\ line('.') == line('$') ? 'gg' : 'j'
nnoremap <silent><buffer><expr> k
\ line('.') == 1 ? 'G' : 'k'
nnoremap <silent><buffer><expr> <C-l>
\ defx#do_action('redraw')
nnoremap <silent><buffer><expr> <C-g>
\ defx#do_action('print')
nnoremap <silent><buffer><expr> cd
\ defx#do_action('change_vim_cwd')
endfunction
color.vim
カラースキームやハイライトの設定をここでまとめて行っています。
color.vim
set t_8f=^[[38;2;%lu;%lu;%lum
set t_8b=^[[48;2;%lu;%lu;%lum
colorscheme default
set bg=light
" syntax highlight
if has('syntax')
syntax enable
endif
" hi fold'
hi Folded ctermbg=0 ctermfg=2
hi FoldColumn ctermbg=8 ctermfg=2
" hi popup
hi Pmenu ctermfg=15 ctermbg=0
hi PmenuSel ctermfg=0 ctermbg=15
hi PMenuSbar ctermfg=15 ctermbg=0
" hilight color
hi Search ctermbg=lightyellow
hi Search ctermfg=black
hi CursorColumn ctermbg=lightyellow
hi CursorColumn ctermfg=black
hi SpellBad ctermfg=black
hi SpellRare ctermfg=black
keymappings.vim
ファイル名通りキーマッピングをここでまとめて定義しています。キーマッピングはプラグインで設定されるものが衝突しやすいので:nnoremapなどを使って確認しながら設定することをおすすめします。
keymappings.vim
" set <Leader> to <Space>
let mapleader = "\<Space>"
" mappings for plugins
nmap [denite] <Nop>
map <Space>u [denite]
" mappings for the quickfix window
nnoremap <Space>n :cn<CR>
nnoremap <Space>p :cp<CR>
nnoremap <Space>q :ccl<CR>
nnoremap <Space>w :botright cwindow<CR>
nnoremap <Space><Space> i<Space><Esc>
" mapping for ctags
nnoremap <C-]> g<C-]>
nnoremap j gj
nnoremap k gk
nnoremap <Down> gj
nnoremap <Up> gk
nnoremap gj j
nnoremap gk k
nnoremap <C-6> :b #
" change the terminal mode to the normal mode.
tnoremap <silent> <ESC> <C-\><C-n>
autocmd FileType go nmap [vim-go] <Nop>
autocmd FileType go nmap <leader>g [vim-go]
autocmd FileType go nmap [vim-go]t <Plug>(go-test)
function! s:build_go_files()
let l:file = expand('%')
if l:file =~# '^\f\+_test\.go$'
call go#test#Test(0, 1)
elseif l:file =~# '^\f\+\.go$'
call go#cmd#Build(0)
endif
endfunction
autocmd FileType go nmap [vim-go]b :<C-u>call <SID>build_go_files()<CR>
autocmd FileType go nmap [vim-go]c <Plug>(go-coverage-toggle)
autoload
プラグインの設定は、関数としてautoload以下にまとめて置いておき、プラグインの読み込みの際にdeinの機能で関数を呼び出しています。
プラグイン
実際に使用しているプラグインについて紹介していきます。
先程から名前が出ている通りプラグインマネージにはdeinを使用しています。最初期はvim-plugを使用していましたが、deinが流行ってくるのにあわせて移行しました。
正直これについてはvim-plugでもdeinでもどちらでも良い気がします。
tomlファイル
使用したいプラグインと設定をtomlファイルに書き込みdeinでロードすることでプラグインが使用可能になります。
deinの関数で一つずつプラグインを追加することも可能なようですが、deinを使う場合はtomlファイルによるプラグインの管理をおすすめします。
更にtomlファイルを読み込む際、lazyオプションを追加することで遅延ロードが可能になります。vim起動時にたくさんのプラグインを読み込むのは起動が遅くなるので、起動時に必要かに応じてlazyオプションを付与するのが良いと思います。
現在使用しているtomlファイルは以下のとおりです。
% ls -1 | grep toml [~/.config/nvim]
dein_plugin.toml
dein.toml
coc.toml # lazy
dein_lang.toml # lazy
dein_vim.toml
dein_lazy.toml # lazy
# lazyと横に書いているものは遅延ロードされるtomlファイルです。遅延ロードを行う際は、tomlファイル内のプラグイン一つ一つに対して読み込む条件を設定します。
dein.toml
vimを起動する際に必ず実行するプラグイン群です。
[[plugins]]
repo = 'Shougo/dein.vim'
[[plugins]]
repo = 'itchyny/lightline.vim'
depends = 'gina.vim'
hook_add = 'call config#init#lightline#hook_add()'
[[plugins]]
repo = 'soramugi/auto-ctags.vim'
hook_add = '''
let g:auto_ctags = 1
'''
[[plugins]]
repo = 'tpope/vim-surround'
[[plugins]]
repo = 't9md/vim-quickhl'
hook_add = 'call config#init#vim_quickhl#hook_add()'
[[plugins]]
repo = 'w0rp/ale'
hook_add = 'call config#init#ale#hook_add()'
[[plugins]]
repo = 'maximbaz/lightline-ale'
[[plugins]]
repo = 'junegunn/fzf'
build = './install --all'
[[plugins]]
repo = 'junegunn/fzf.vim'
[[plugins]]
repo = 'airblade/vim-gitgutter'
[[plugins]]
repo = 'lambdalisue/gina.vim'
[[plugins]]
repo = 'ryanoasis/vim-devicons'
[[plugins]]
repo = 'luochen1990/rainbow'
hook_add = '''
let g:rainbow_active = 1
'''
余談ですが、deinではhook_add, hook_sourceなどのフックを使用してプラグインを読むこむ際のどこかのタイミングに処理を挟むことができます。
基本的にはhook_addでプラグインの使用に必要な設定を行っていますが、設定が長い場合は関数として切り出してファイルをautoload/config/initフォルダ以下に置き、その関数をコールするようにしています。
また、場合によっては他のフックを使いますが、そちらも同じようなルールで運用しています。
itchyny/lightline.vim
vimの下部にステータスラインを追加するプラグインです。他のプラグインと連携して表示する情報を増やすことができます。
gina.vimを使用したブランチの表示、cocを使用した関す情報の表示を行っています。
lightline.vim
function! config#init#lightline#hook_add() abort
let g:lightline = {
\ 'colorscheme': 'wombat',
\ 'active': {
\ 'left': [['mode', 'paste'],
\ ['gitbranch', 'readonly', 'filename', 'modified']],
\ 'right': [['lineinfo'], ['percent'], ['fileformat', 'fileencoding', 'filetype'],
\ ['cocstatus', 'currentfunction']]
\ },
\ 'component_function': {
\ 'gitbranch': 'gina#component#repo#branch',
\ 'mode': 'LightlineMode',
\ 'cocstatus': 'coc#status',
\ 'currentfunction': 'CocCurrentFunction'
\ }
\ }
endfunction
function! LightlineMode()
return &ft == 'denite' ? 'Denite' :
\ &ft == 'vimfiler' ? 'VimFiler' :
\ winwidth(0) > 60 ? lightline#mode() : ''
endfunction
function! CocCurrentFunction()
return get(b:, 'coc_current_function', '')
endfunction
lightlineの設定例です。このように設定が複数行に渡る場合は関数に切り出してファイルとしてautoload/config/init以下に置いておき、hookからコールするようにしています。
soramugi/auto-ctags.vim
vimにはctagsと連携して関数定義に移動する機能が備わっています。実はその機能はLSPを導入することでより便利に行うことが可能なのですが、後述のtagbarというプラグインのためにctagsを生成するようにしています。ただ、デフォルトではctagsは手動で実行する必要があるのでそれを自動化するプラグインです。g:auto_ctagsオプションをオンにすることで保存時に自動で生成してくれます。
tpope/vim-surround
ある文字列を囲んでいるHTMLタグやクォートなどを消したり変更したり追加するコマンドを追加するプラグインです。コマンドが覚えにくいのでなれないうちは都度調べる必要があるのが面倒ですが、ちょくちょく機能が欲しくなるプラグインです。
t9md/vim-quickhl
単語のハイライトを自動で行ったり、特定の文字列をハイライトできるプラグインです。いくらでもハイライトがつけられるのでコードリーディングの際などに便利です。
w0rp/ale
言語のlinterを使ってコードをチェックしてくれるプラグインです。デフォルトでも多くのlinterやその他ツールに対応しているので、とりあえずlinter等をインストールすればすぐ使えるのが強みです。最近はLSP機能も入ったようですが、自分は使用していません。
ale.vim
function! config#init#ale#hook_add() abort
highlight clear ALEError
highlight clear ALEWarning
let g:ale_lint_on_enter = 0
let g:ale_sign_column_always = 1
let g:ale_set_loclist = 0
let g:ale_set_quickfix = 1
if has('mac')
let s:header_path = '-I/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/include'
let g:ale_cpp_clang_options = '-std=c++14 -Wall ' . s:header_path
let g:ale_cpp_gcc_options = '-std=c++14 -Wall ' . s:header_path
endif
let g:ale_linters = {
\ 'c': ['clangd'],
\ 'cpp' : ['clangd']
\ }
endfunction
設定例です。c, cppのlinterについてはclangdを使用するように明示しています。
airblade/vim-gitgutter
gitの差分が発生した場合に、どこにどのような差分が発生しているかを行頭に表示してくれます。
lambdalisue/gina.vim
vim中でgitを扱うためにプラグインですが、自分は基本的にtmuxで開いている別ペインでgitを使用しています。
なのでlightlineでブランチを表示するためにプラグインになりかけてます...
luochen1990/rainbow
vimでも括弧の色分けができるようになります。素のvimでも対応する括弧にハイライトをつけたり、%コマンドで対応する括弧に移動ができますが、色による視認性の方が高いです。
dein_vim.toml
neovimではなくvimでneovim用に作られたプラグインを動かすための前提プラグイン用です。
dein.vimの方で、使用しているクライアントがnvimでない(=vim)のときに読み込みます。
[[plugins]]
repo = 'roxma/vim-hug-neovim-rpc'
[[plugins]]
repo = 'roxma/nvim-yarp'
ただ、これで動くと思っていたのですが、どうもpythonがうまく呼べてないようで、エラーが出てうまくいっていません。(情報欲しいです!)
dein_lazy.toml
名前の通り遅延ロードしているプラグインです。比較的重そうなプラグインや、特定の状況下で動く必ずしも起動時に必要ではないプラグインは出来るだけ遅延ロードさせるようにしています。
[[plugins]]
repo = 'Shougo/denite.nvim'
on_cmd = ['Denite']
depends = ['vim-devicons']
hook_add = 'call config#init#denite#hook_add()'
hook_post_source = 'call config#init#denite#hook_post_source()'
[[plugins]]
repo = 'Shougo/neomru.vim'
on_cmd = ['Denite']
on_source = ['denite.nvim']
[[plugins]]
repo = 'Shougo/neoyank.vim'
on_cmd = ['Denite']
on_source = ['denite.nvim']
[[plugins]]
repo = 'cespare/vim-toml'
on_ft = 'toml'
[[plugins]]
repo = 'majutsushi/tagbar'
on_cmd = ['TagbarToggle']
hook_add = 'call config#init#tagbar#hook_add()'
hook_source = 'call config#init#tagbar#hook_source()'
[[plugins]]
repo = 'cohama/lexima.vim'
on_event = 'InsertEnter'
[[plugins]]
repo = 'scrooloose/nerdtree'
on_cmd = ['NERDTreeToggle']
depends = ['vim-devicons', 'vim-nerdtree-syntax-highlight', 'nerdtree-git-plugin']
hook_add = 'call config#init#nerdtree#hook_add()'
hook_source = 'call config#init#nerdtree#hook_source()'
[[plugins]]
repo = 'Xuyuanp/nerdtree-git-plugin'
[[plugins]]
repo = 'tiagofumo/vim-nerdtree-syntax-highlight'
[[plugins]]
repo = 'ryanoasis/vim-devicons'
Shougo/denite.nvim
開いているバッファーやカレントディレクトリ以下のファイル、最近開いたファイルなどに素早くアクセスするためのインターフェースを提供するプラグインです。
ファイラーのように一覧表示されているのも便利ですが、名前のわかっているファイルへの移動についてはこちらのほうが高速です。こちらを導入する際にはripgrepなどの導入も合わせて行うと効果的です。遅延ロードの条件はdenite実行時にしています。
denite.vim
function! config#init#denite#hook_add() abort
" defined in keymappings.vim
" Prefix for denite
" nmap [denite] <Nop>
" map <Space>u [denite]
" key mappings for Denite and sources
nnoremap <silent> [denite]y :<C-u>Denite neoyank -split=floating<CR>
nnoremap <silent> [denite]u :<C-u>Denite buffer file/rec -split=floating<CR>
nnoremap <silent> [denite]f :<C-u>Denite file/rec -split=floating<CR>
nnoremap <silent> [denite]b :<C-u>Denite buffer -split=floating<CR>
nnoremap <silent> [denite]m :<C-u>Denite file_mru -split=floating<CR>
nnoremap <silent> [denite]a :<C-u>Denite -resume -split=floating<CR>
" settings for grep
nnoremap <silent> [denite]g :<C-u>Denite grep -buffer-name=search-buffer-denite -split=floating<CR>
nnoremap <silent> [denite]w :<C-u>DeniteCursorWord grep -buffer-name=search-buffer-denite -split=floating<CR>
nnoremap <silent> [denite]r :<C-u>Denite -resume -buffer-name=search-buffer-denite -split=floating<CR>
nnoremap <silent> [denite]n :<C-u>Denite -resume -buffer-name=search-buffer-denite -cursor-pos=+1 -immediately -split=floating<CR>
nnoremap <silent> [denite]p :<C-u>Denite -resume -buffer-name=search-buffer-denite -cursor-pos=-1 -immediately -split=floating<CR>
endfunction
function! config#init#denite#hook_post_source() abort
" Change the prompt
call denite#custom#option('default', 'prompt', '>')
" Add action keybinds
call denite#custom#map('insert', '<C-v>', '<denite:do_action:vsplit>')
call denite#custom#map('insert', '<C-s>', '<denite:do_action:split>')
call denite#custom#map('normal', '<C-v>', '<denite:do_action:vsplit>')
call denite#custom#map('normal', '<C-s>', '<denite:do_action:split>')
call denite#custom#map('insert', '<C-n>', '<denite:move_to_next_line>')
call denite#custom#map('insert', '<C-p>', '<denite:move_to_previous_line>')
call denite#custom#map('normal', '<C-n>', '<denite:move_to_next_line>')
call denite#custom#map('normal', '<C-p>', '<denite:move_to_previous_line>')
" Variables
"grepでagを使用するように設定
call denite#custom#var('grep', 'command', ['rg'])
"カレントディレクトリ内の検索もagを使用する
call denite#custom#var('file/rec', 'command', ['rg', '--files', '--glob', '!.git'])
" call denite#custom#var('file/rec', 'command', ['ag', '--follow', '--nocolor', '--nogroup', '-g', ''])
"その他のgrepの設定
call denite#custom#var('grep', 'default_opts',['-i', '--vimgrep', '--no-heading'])
call denite#custom#var('grep', 'recursive_opts', [])
call denite#custom#var('grep', 'pattern_opt', ['--regexp'])
call denite#custom#var('grep', 'separator', ['--'])
call denite#custom#var('grep', 'final_opts', [])
endfunction
Shougo/neomru.vim
deniteのソースに"最近開いたバッファ"を追加します。deniteのインターフェースで検索を行う際に最近開いたバッファも検索対象として結果に出てくるようになります。
Shougo/neoyank.vim
上記同様に、yankしたものについてもdeniteのソースに追加できます。
cespare/vim-toml
vimでtomlファイルを編集する際に、シンタックスを追加してくれるプラグインです。deinなどでtomlファイルを編集する場合は入れておくと便利かもしれません。
majutsushi/tagbar
前述したctagsの中身を画面に表示するプラグインです。ctagsによる生成がうまく行っていれば、ファイル内の変数やクラス、関数などの一覧が表示されます。
tagbar.vim
function! config#init#tagbar#hook_add() abort
let g:tagbar_width=40
nmap <Space>z :TagbarToggle<CR>
endfunction
function! config#init#tagbar#hook_source() abort
let g:tagbar_type_go = {
\ 'ctagstype' : 'go',
\ 'kinds' : [
\ 'p:package',
\ 'i:imports:1',
\ 'c:constants',
\ 'v:variables',
\ 't:types',
\ 'n:interfaces',
\ 'w:fields',
\ 'e:embedded',
\ 'm:methods',
\ 'r:constructor',
\ 'f:functions'
\ ],
\ 'sro' : '.',
\ 'kind2scope' : {
\ 't' : 'ctype',
\ 'n' : 'ntype'
\ },
\ 'scope2kind' : {
\ 'ctype' : 't',
\ 'ntype' : 'n'
\ },
\ 'ctagsbin' : 'gotags',
\ 'ctagsargs' : '-sort -silent'
\ }
let g:tagbar_type_typescript = {
\ 'ctagsbin' : 'ctags',
\ 'kinds': [
\ 'e:enums:0:1',
\ 'f:function:0:1',
\ 't:typealias:0:1',
\ 'M:Module:0:1',
\ 'I:import:0:1',
\ 'i:interface:0:1',
\ 'C:class:0:1',
\ 'm:method:0:1',
\ 'p:property:0:1',
\ 'v:variable:0:1',
\ 'c:const:0:1',
\ ],
\ 'sort' : 0
\ }
endfunction
goとtypescriptについてはデフォルトでは物足りないので設定を追加しています。
cohama/lexima.vim
括弧やクォートを入力した際に対応する閉じ括弧を自動で付け足してくれるプラグインです。基本的には便利ですが、括弧を消したときや閉じ括弧を入力したときにうまく括弧の数が揃わない場合があるので注意が必要です。また、pythonの複数行コメントを入力したい場合など、クォートの数がイレギュラーな場合はうまく補完ができません。
scrooloose/nerdtree
vimのファイラーです。少し前までdefxを使用していましたが、ファイルのアイコンを表示した際にファイル名の表記が崩れるのでこちらに移行しました。
こちらでもファイル名の表記は多少崩れますが、defxに比べれば少ないので許容範囲内としています。vimにも実はファイラーは付属していますが、defxやnerdtreeのほうが操作が直感的でわかりやすいです。
nerdtree.vim
function! config#init#nerdtree#hook_add() abort
nnoremap <silent> <Space>v :<C-u>NERDTreeToggle<CR>
endfunction
function! config#init#nerdtree#hook_source() abort
let g:NERDTreeWinSize = 40
let g:WebDevIconsUnicodeGlyphDoubleWidth = 0
let g:WebDevIconsNerdTreeBeforeGlyphPadding = ''
let g:WebDevIconsNerdTreeAfterGlyphPadding = ' '
let g:WebDevIconsUnicodeDecorateFolderNodes = 0
endfunction
Xuyuanp/nerdtree-git-plugin
nerdtree上で、gitのステータスを表示してくれるプラグインです。
tiagofumo/vim-nerdtree-syntax-highlight
nerdtree上で、シンタックスハイライトを追加してくれるプラグインです。純粋に視認性が上がるのでおすすめです。
ryanoasis/vim-devicons
vim内でdeviconを表示するためのプラグインです。deniteやnerdtreeでファイル名の頭にアイコンがつくようになってsyntax-highlightと同じく視認性が上がります。
dein_lang.toml
言語依存のプラグインをon_ftを使用して特定のファイルタイプのときに実行するようにしています。vimのデフォルトだと言語のサポート(syntax highlight)が不十分な場合に補ったり特定の言語のサポートツールをvimで使えるようにします。
[[plugins]]
repo = 'rust-lang/rust.vim'
on_ft = 'rust'
hook_source = 'call config#init#rust#hook_source()'
[[plugins]]
repo = 'octol/vim-cpp-enhanced-highlight'
on_ft = ['c', 'cpp']
[[plugins]]
repo = 'fatih/vim-go'
on_ft = 'go'
hook_source = 'call config#init#vim_go#hook_source()'
[[plugins]]
repo = 'neovimhaskell/haskell-vim'
on_ft = 'haskell'
rust-lang/rust.vim
vimでrustを書く際に、シンタックスハイライトを効かせたり、その他フォーマッターなどのサポートが導入できます。
octol/vim-cpp-enhanced-hightlight
より新しいバージョンのc, c++についてもシンタックスハイライトが効くようになるプラグインです。
fatih/vim-go
vimでgoを書くならば必須のプラグイン。goは周辺のツールが充実しており、それらをvimでうまく使えるようにしてくれます。
vim_go.vim
function! config#init#vim_go#hook_source() abort
let g:go_highlight_array_whitespace_error = 1
let g:go_highlight_chan_whitespace_error = 1
let g:go_highlight_extra_types = 1
let g:go_highlight_space_tab_error = 1
let g:go_highlight_trailing_whitespace_error = 1
let g:go_highlight_operators = 1
let g:go_highlight_functions = 1
let g:go_highlight_function_parameters = 1
let g:go_highlight_function_calls = 1
let g:go_highlight_types = 1
let g:go_highlight_fields = 1
let g:go_highlight_build_constraints = 1
let g:go_highlight_generate_tags = 1
let g:go_highlight_variable_declarations = 1
let g:go_highlight_variable_assignments = 1
let g:go_fmt_command = "goimports"
let g:go_auto_type_info = 1
let g:go_auto_sameids = 1
let g:go_list_type = "quickfix"
endfunction
neovimhaskell/haskell-vim
同じくvimでhaskellを書きやすいようにシンタックスハイライトやインデントのルールなどを追加してくれるプラグインです。
coc.toml
lspクライアントであるcoc.nvimのためのtomlファイルです。もともとlsp関連プラグイン用のファイルとしてdein_lspがありましたが、coc.nvimを導入したことでlsp関連は全て間に合うのでこのようなファイル名になりました。
[[plugins]]
repo = 'neoclide/coc.nvim'
rev = 'release'
on_i = 1
merged = '0'
hook_source = 'call config#init#coc#hook_source()'
coc.vim
function! config#init#coc#hook_source() abort
" if hidden is not set, TextEdit might fail.
set hidden
" Some servers have issues with backup files, see #649
set nobackup
set nowritebackup
" Better display for messages
" set cmdheight=2
" You will have bad experience for diagnostic messages when it's default 4000.
set updatetime=300
" don't give |ins-completion-menu| messages.
set shortmess+=c
" always show signcolumns
set signcolumn=yes
" Use tab for trigger completion with characters ahead and navigate.
" Use command ':verbose imap <tab>' to make sure tab is not mapped by other plugin.
inoremap <silent><expr> <TAB>
\ pumvisible() ? "\<C-n>" :
\ <SID>check_back_space() ? "\<TAB>" :
\ coc#refresh()
inoremap <expr><S-TAB> pumvisible() ? "\<C-p>" : "\<C-h>"
function! s:check_back_space() abort
let col = col('.') - 1
return !col || getline('.')[col - 1] =~# '\s'
endfunction
" Use <c-space> to trigger completion.
inoremap <silent><expr> <c-space> coc#refresh()
" Use <cr> to confirm completion, `<C-g>u` means break undo chain at current position.
" Coc only does snippet and additional edit on confirm.
inoremap <expr> <cr> pumvisible() ? "\<C-y>" : "\<C-g>u\<CR>"
" Or use `complete_info` if your vim support it, like:
" inoremap <expr> <cr> complete_info()["selected"] != "-1" ? "\<C-y>" : "\<C-g>u\<CR>"
" Use `[g` and `]g` to navigate diagnostics
nmap <silent> [g <Plug>(coc-diagnostic-prev)
nmap <silent> ]g <Plug>(coc-diagnostic-next)
" Remap keys for gotos
nmap <silent> gd <Plug>(coc-definition)
nmap <silent> gy <Plug>(coc-type-definition)
nmap <silent> gi <Plug>(coc-implementation)
nmap <silent> gr <Plug>(coc-references)
" Use K to show documentation in preview window
nnoremap <silent> K :call <SID>show_documentation()<CR>
function! s:show_documentation()
if (index(['vim','help'], &filetype) >= 0)
execute 'h '.expand('<cword>')
else
call CocAction('doHover')
endif
endfunction
" Highlight symbol under cursor on CursorHold
" autocmd CursorHold * silent call CocActionAsync('highlight')
" Remap for rename current word
nmap <leader>rn <Plug>(coc-rename)
" Remap for format selected region
xmap <leader>f <Plug>(coc-format-selected)
nmap <leader>f <Plug>(coc-format-selected)
augroup mygroup
autocmd!
" Setup formatexpr specified filetype(s).
autocmd FileType typescript,json setl formatexpr=CocAction('formatSelected')
" Update signature help on jump placeholder
autocmd User CocJumpPlaceholder call CocActionAsync('showSignatureHelp')
augroup end
" Remap for do codeAction of selected region, ex: `<leader>aap` for current paragraph
xmap <leader>a <Plug>(coc-codeaction-selected)
nmap <leader>a <Plug>(coc-codeaction-selected)
" Remap for do codeAction of current line
nmap <leader>ac <Plug>(coc-codeaction)
" Fix autofix problem of current line
nmap <leader>qf <Plug>(coc-fix-current)
" Create mappings for function text object, requires document symbols feature of languageserver.
xmap if <Plug>(coc-funcobj-i)
xmap af <Plug>(coc-funcobj-a)
omap if <Plug>(coc-funcobj-i)
omap af <Plug>(coc-funcobj-a)
" Use <tab> for select selections ranges, needs server support, like: coc-tsserver, coc-python
nmap <silent> <TAB> <Plug>(coc-range-select)
xmap <silent> <TAB> <Plug>(coc-range-select)
xmap <silent> <S-TAB> <Plug>(coc-range-select-backword)
" Use `:Format` to format current buffer
command! -nargs=0 Format :call CocAction('format')
" Use `:Fold` to fold current buffer
command! -nargs=? Fold :call CocAction('fold', <f-args>)
" use `:OR` for organize import of current buffer
command! -nargs=0 OR :call CocAction('runCommand', 'editor.action.organizeImport')
" Add status line support, for integration with other plugin, checkout `:h coc-status`
" set statusline^=%{coc#status()}%{get(b:,'coc_current_function','')}
" Using CocList
" Show all diagnostics
nnoremap <silent> <space>a :<C-u>CocList diagnostics<cr>
" Manage extensions
nnoremap <silent> <space>e :<C-u>CocList extensions<cr>
" Show commands
nnoremap <silent> <space>c :<C-u>CocList commands<cr>
" Find symbol of current document
nnoremap <silent> <space>o :<C-u>CocList outline<cr>
" Search workspace symbols
nnoremap <silent> <space>s :<C-u>CocList -I symbols<cr>
" Do default action for next item.
nnoremap <silent> <space>j :<C-u>CocNext<CR>
" Do default action for previous item.
nnoremap <silent> <space>k :<C-u>CocPrev<CR>
" Resume latest coc list
nnoremap <silent> <space>r :<C-u>CocListResume<CR>
endfunction
ほとんど公式からもってきたものそのままになっています。
終わり
以上が自分のvimの設定になっています。今まで多種多様な設定及びプラグインを導入しては削除を繰り返してきましたが、最近は以上のような構成で落ち着いています。
vimプラグインは開発が活発で様々なプラグインが存在しますが、プラグインの導入はだんだんとコストがかかるようになります。
vimの起動時間、キーマッピングの衝突、機能の使い方を覚えるetc...
たまにはインストールしているプラグインの一覧を見て、あまり使っていないようであれば消してしまってもいいと思います。また必要になったらインストールすればいいだけですし
それを繰り返していくことでだんだんと自分の理想の環境ができてくると思います。