自分のinit.vimを解説してみる(Windows対応とかカラースキームの自動ダウンロードとかプラグインマネージャの自動インストールとか)
自分のinit.vimを解説してみました。
(途中で.vimrcの内容も解説しています。)
最近Vim始めたけどどういう設定したらいいのかわからないという人や、最近プラグインをインストールしてみて快適になったけど代わりに初期セットアップが少しめんどうになったから自動化したいと考えてる人、MacでもWindowsでも設定ファイル使いまわせるようにしたい人、などなどの参考になったらいいなぁと思ってます。(あと未来の自分がなんでこんなコードになってるのかわからなくなったとき用に...)
説明とかいいからコード読みたいって人へ
設定ファイルそのまま置いておきます。
init.vim
" vimの設定を読み込む
if has('win64')
source ~\_vimrc
else
source ~/.vimrc
endif
" XDG Base Directory Specification
let s:config_home = has('win64') ? $LOCALAPPDATA : empty($XDG_CONFIG_HOME) ? $HOME . '/.config' : $XDG_CONFIG_HOME
" vim-plugがインストールされていなかったらインストールする
let s:plug_path = has('win64') ? $LOCALAPPDATA . '\nvim-data\site\autoload\plug.vim' : $HOME . '/.local/share/nvim/site/autoload/plug.vim'
if !filereadable(s:plug_path)
call g:DownloadIfNotFileReadable(s:plug_path, 'https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim')
" ついでにプラグインもインストールする
if has('win64')
" Windowsの場合
source ~/AppData/Local/nvim/plugin_settings/vim-plug_setting.vim
else
" Windows以外の場合
if empty($XDG_CONFIG_HOME)
source ~/.config/nvim/plugin_settings/vim-plug_setting.vim
else
source $XDG_CONFIG_HOME/nvim/plugin_settings/vim-plug_setting.vim
endif
endif
PlugInstall
endif
" ここからneovim向けの設定
" カラースキームの設定
" gruvboxがローカルに無かったらダウンロードする
call g:DownloadIfNotFileReadable(has('win64') ? s:config_home . '\nvim\colors\gruvbox.vim' : s:config_home . '/nvim/colors/gruvbox.vim', 'https://raw.githubusercontent.com/morhetz/gruvbox/master/colors/gruvbox.vim')
" カラースキームをgruvboxに指定する
colorscheme gruvbox
" コマンドラインを2行にする
set cmdheight=2
" 開いたファイルがあるディレクトリに自動でcdする
set autochdir
" undo履歴を保持し続ける
if has('persistent_undo')
set undodir=~/.vimundo
set undofile
endif
" python3のパスを指定
if has('win64')
if !empty(system('where /Q python && echo has'))
let g:python3_host_prog = s:config_home . '\Programs\Python\Python37-32\python.exe'
endif
else
let g:python3_host_prog = system("bash -c 'echo -n $(which python3)'")
endif
" filetypeの追加
autocmd BufNewFile,BufRead *.fish setfiletype fish
autocmd BufNewFile,BufRead *.vim setfiletype vim
autocmd BufNewFile,BufRead *.swift setfiletype swift
autocmd BufNewFile,BufRead *.kt setfiletype kotlin
" プラグインの設定
" vim-plugの設定を読み込む
if has('win64')
source ~/AppData/Local/nvim/plugin_settings/vim-plug_setting.vim
elseif !empty($XDG_CONFIG_HOME)
source $XDG_CONFIG_HOME/nvim/plugin_settings/vim-plug_setting.vim
else
source ~/.config/nvim/plugin_settings/vim-plug_setting.vim
endif
" vim-indent-guidesの設定を読み込む
if has('win64')
source ~/AppData/Local/nvim/plugin_settings/vim-indent-guides_setting.vim
elseif !empty($XDG_CONFIG_HOME)
source $XDG_CONFIG_HOME/nvim/plugin_settings/vim-indent-guides_setting.vim
else
source ~/.config/nvim/plugin_settings/vim-indent-guides_setting.vim
endif
" asyncompleteの設定を読み込む
if has('win64')
source ~/AppData/Local/nvim/plugin_settings/asyncomplete_setting.vim
elseif !empty($XDG_CONFIG_HOME)
source $XDG_CONFIG_HOME/nvim/plugin_settings/asyncomplete_setting.vim
else
source ~/.config/nvim/plugin_settings/asyncomplete_setting.vim
endif
" aleの設定を読み込む
if has('win64')
source ~/AppData/Local/nvim/plugin_settings/ale_setting.vim
elseif !empty($XDG_CONFIG_HOME)
source $XDG_CONFIG_HOME/nvim/plugin_settings/ale_setting.vim
else
source ~/.config/nvim/plugin_settings/ale_setting.vim
endif
" vim-lspの設定を読み込む
if has('win64')
source ~/AppData/Local/nvim/plugin_settings/vim-lsp_setting.vim
elseif !empty($XDG_CONFIG_HOME)
source $XDG_CONFIG_HOME/nvim/plugin_settings/vim-lsp_setting.vim
else
source ~/.config/nvim/plugin_settings/vim-lsp_setting.vim
endif
" vim-closetagの設定を読み込む
if has('win64')
source ~/AppData/Local/nvim/plugin_settings/vim-closetag_setting.vim
elseif !empty($XDG_CONFIG_HOME)
source $XDG_CONFIG_HOME/nvim/plugin_settings/vim-closetag_setting.vim
else
source ~/.config/nvim/plugin_settings/vim-closetag_setting.vim
endif
" Neosnippetの設定を読み込む
if has('win64')
source ~/AppData/Local/nvim/plugin_settings/neosnippet_setting.vim
elseif !empty($XDG_CONFIG_HOME)
source $XDG_CONFIG_HOME/nvim/plugin_settings/neosnippet_setting.vim
else
source ~/.config/nvim/plugin_settings/neosnippet_setting.vim
endif
" myDE向けの設定を読み込む
if !empty($container_name)
if !empty($XDG_CONFIG_HOME)
source $SDG_CONFIG_HOME/nvim/plugin_settings/settings_for_myde.vim
else
source ~/.config/nvim/plugin_settings/settings_for_myde.vim
endif
endif
" キーバインド
tnoremap <silent> <ESC> <C-\><C-n>
nnoremap <silent> <C-t><C-m> :split<CR> <C-w>j :terminal<CR> :resize 6<CR> i
.vimrc
" 文字コードの設定
" バッファ内での文字コードの指定
set encoding=utf-8
" fileencodingの設定を適用できないとき用の対策
set modifiable
" 書き込むときのデフォルトの文字コードの指定
set fileencoding=utf-8
" 読み込むときの文字コードの指定(左の方が優先度が高い)
set fileencodings=utf-8,cp932,sjis,euc-jp
" 改行コードの設定
" 左の方が優先度が高い
if has('win64')
" Windowsのときは<CR+LF>を最優先する
set fileformats=dos,unix,mac
else
" それ以外のときは<CR>を最優先する
set fileformats=unix,dos,mac
endif
" 行番号を表示する
set number
" シンタックスハイライトをオンにする
syntax enable
" カラースキームの設定
" ファイルが無かったらダウンロードする関数
function! g:DownloadIfNotFileReadable(file_path, remote_url) abort
if filereadable(a:file_path)
" ファイルがローカルに存在していたら何もしない
return
endif
" OS別のcurlコマンド
let l:curl_command = has('win64') ? 'curl.exe' : 'curl'
" ファイルをダウンロードする
let l:message = system(l:curl_command . ' -Lo ' . a:file_path . ' --create-dirs ' . a:remote_url)
if l:message !~# '.*% Total.*% Received.*% Xferd.*'
" ダウンロードに失敗したらエラーメッセージを表示する
echo 'error: ' . l:message
endif
endfunction
" neovimから読み込まれていたときは処理しない
if !has('nvim')
" gruvboxがなかったらダウンロードする
call g:DownloadIfNotFileReadable(has('win64') ? $HOME . '\vimfiles\colors\gruvbox.vim' : $HOME . '/.vim/colors/gruvbox.vim', 'https://raw.githubusercontent.com/morhetz/gruvbox/master/colors/gruvbox.vim')
" カラースキームをgruvboxに指定する
colorscheme gruvbox
endif
" ライトテーマを使う
set background=light
"インデントの設定
" インデントにスペースを使う
set expandtab
" Tab文字の長さの設定
set tabstop=4
" 一つのインデントのスペースの数
set shiftwidth=4
" よくわからないけどとりあえず書いておく。
" backspaceしたときに一度に消されるスペースの数らしい
set softtabstop=4
" 改行したときにインデントしてくれる
set autoindent
" インデントがスマートになる(らしい)
set smartindent
" 全角文字をちゃんと表示する
set ambiwidth=double
" 折り返したときの設定
" 折り返したときにインデントする
set breakindent
" 折り返したときの追加のインデントの深さを指定する
set breakindentopt=shift:0
" 行末にセミコロンを挿入する
function! InsertEndSemicolon() abort
" カーソルの現在位置を取得する
let s:currentPosition = getpos('.')
" 行末にセミコロンがなかったら挿入する
if !(getline('.') =~ ';$')
execute ':normal A;'
endif
" カーソル位置を戻す
call setpos('.', s:currentPosition)
endfunction
" ノーマルモードでセミコロンを押すとInsertEndSemicolon()が呼ばれるようにする
nnoremap <silent> ; :call InsertEndSemicolon()<CR>
" インサートモードでセミコロン2度押しでその場にセミコロンを入力できるようにする
inoremap <silent> ;; ;
" インサートモードでセミコロン押してからエスケープキーを押すと行末にセミコロンを挿入してからノーマルモードに戻る
inoremap <silent> ;<ESC> <ESC>:call InsertEndSemicolon()<CR>
" 言語ごとのインデントの設定
filetype indent on
autocmd FileType java setlocal shiftwidth=2 softtabstop=2
autocmd FileType typescriptreact setlocal shiftwidth=2 softtabstop=2
" ローカルのvimの設定を読み込む(set columnsの上書きとかをする)
" ファイルがあるときだけ読み込む
if filereadable($HOME . '/.vimrc_local')
source ~/.vimrc_local
endif
vim-plug_setting.vim
" vim-plugの設定
call plug#begin(stdpath('data') . '/plugged')
" <C--><C-->でコメントインアウトを切替できるようにするプラグイン
Plug 'tomtom/tcomment_vim'
" ノーマルモードで cs"' ってやったら"を'に置換してくれる
Plug 'tpope/vim-surround'
" インデントを可視化してくれるやつ
Plug 'nathanaelkane/vim-indent-guides'
" 自動で閉じ括弧とか入力してくれるやつ
Plug 'cohama/lexima.vim'
" 自動でHTMLの閉じタグを入力してくれるプラグイン
Plug 'alvan/vim-closetag'
" lintしてくれるやつ
Plug 'w0rp/ale'
" 補完に使うプラグインたち
Plug 'prabirshrestha/async.vim'
Plug 'prabirshrestha/vim-lsp'
Plug 'mattn/vim-lsp-settings'
Plug 'prabirshrestha/asyncomplete.vim'
Plug 'prabirshrestha/asyncomplete-lsp.vim'
Plug 'Shougo/neosnippet.vim'
Plug 'Shougo/neosnippet-snippets'
Plug 'prabirshrestha/asyncomplete-neosnippet.vim'
call plug#end()
vim-indent-guides_setting.vim
let g:indent_guides_enable_on_vim_startup = 1
let g:indent_guides_start_level= 1
let g:indent_guides_guide_size = 0
autocmd VimEnter,Colorscheme * :hi IndentGuidesOdd ctermbg=220
autocmd VimEnter,Colorscheme * :hi IndentGuidesEven ctermbg=214
asyncomplete_setting.vim
set completeopt+=preview
autocmd! CompleteDone * if pumvisible() == 0 | pclose | endif
ale_setting.vim
" let g:ale_sign_column_always = 1
set signcolumn=yes
highlight SignColumn ctermbg=15
highlight SignColumn ctermfg=15
highlight SignColumn guisp=15
highlight SignColumn guifg=15
highlight SignColumn guibg=15
let g:ale_sign_error = '☠️'
let g:ale_sign_warning = '⚠️'
vim-lsp_setting.vim
" ノーマルモードで"def"と入力したら変数や関数の定義元にジャンプするようにする
nnoremap <silent> def :LspDefinition<CR>
" "neosnippet"からの補完情報を取得するようにする
call asyncomplete#register_source(asyncomplete#sources#neosnippet#get_source_options({
\ 'name': 'neosnippet',
\ 'whitelist': ['*'],
\ 'completor': function('asyncomplete#sources#neosnippet#completor'),
\ }))
vim-closetag_setting.vim
" filenames like *.xml, *.html, *.xhtml, ...
" These are the file extensions where this plugin is enabled.
"
let g:closetag_filenames = '*.html,*.xhtml,*.phtml'
" filenames like *.xml, *.xhtml, ...
" This will make the list of non-closing tags self-closing in the specified files.
"
let g:closetag_xhtml_filenames = '*.xhtml,*.jsx'
" filetypes like xml, html, xhtml, ...
" These are the file types where this plugin is enabled.
"
let g:closetag_filetypes = 'html,xhtml,phtml,typescriptreact'
" filetypes like xml, xhtml, ...
" This will make the list of non-closing tags self-closing in the specified files.
"
let g:closetag_xhtml_filetypes = 'xhtml,jsx'
" integer value [0|1]
" This will make the list of non-closing tags case-sensitive (e.g. `<Link>` will be closed while `<link>` won't.)
"
let g:closetag_emptyTags_caseSensitive = 1
" dict
" Disables auto-close if not in a "valid" region (based on filetype)
"
let g:closetag_regions = {
\ 'typescript.tsx': 'jsxRegion,tsxRegion',
\ 'javascript.jsx': 'jsxRegion',
\ 'typescriptreact': 'jsxRegion,tsxRegion',
\ 'javascriptreact': 'jsxRegion',
\ }
" Shortcut for closing tags, default is '>'
"
let g:closetag_shortcut = '>'
" Add > at current position without closing the current tag, default is ''
"
let g:closetag_close_shortcut = '<leader>>'
neosnippet_setting.vim
" Ctrl + kで補完候補のコードを展開したりできるようにする
imap <C-k> <Plug>(neosnippet_expand_or_jump)
smap <C-k> <Plug>(neosnippet_expand_or_jump)
xmap <C-k> <Plug>(neosnippet_expand_target)
if has('conceal')
set conceallevel=0 concealcursor=niv
endif
settings_for_myde.vim
" dockerコンテナ内向けの設定
" うまくいかなかったときの保険として、'name'の直の最初に'myde-'をつける
" この3つ以外は、パスが通ってるとこにコマンド配置しておけば勝手にいいかんじにしてくれる(vim-lsp-settingが)
if executable('/home/myde/omnisharp-lsp/run')
au User lsp_setup call lsp#register_server({
\ 'name': 'myde-omnisharp-lsp',
\ 'cmd': {server_info->['/home/myde/omnisharp-lsp/run', '-lsp']},
\ 'whitelist': ['cs']
\ })
endif
if executable('/home/myde/eclipse-jdt-ls/eclipse-jdt-ls')
au User lsp_setup call lsp#register_server({
\ 'name': 'myde-eclipse-jdt-ls',
\ 'cmd': {server_info->['/home/myde/eclipse-jdt-ls/eclipse-jdt-ls']},
\ 'whitelist': ['java']
\ })
endif
if executable('/home/myde/myCommands/kotlin-language-server')
au User lsp_setup call lsp#register_server({
\ 'name': 'myde-kotlin-language-server',
\ 'cmd': {server_info->['/home/myde/myCommands/kotlin-language-server']},
\ 'whitelist': ['kotlin']
\ })
endif
Vimの設定を読み込む
VimとNeovimの両方に適用したい設定は.vimrcに書くようにしているので読み込みます。
if has('win64')
source ~\_vimrc
else
source ~/.vimrc
endif
Windowsとそれ以外とでファイル名が異なるのでif文で分岐しています。
(フォルダの区切りはWindowsでもそれ以外でも"/"で大丈夫だったような気がしますが一応分けてます。)
いきなりではありますが、ここからしばらくは.vimrcに記述している内容になります。
文字コードの設定
set encoding=utf-8
バッファ内での文字コードの設定だそうです。過去のぼくがそうコメントでそう言ってました。
ちなみにぼくはまだVimのバッファについてよくわかってないです(´・ω・`)
fileencodingの設定を適用できないとき用の対策
set modifiable
次で出てくるfileencodingというやつの設定を適用できないとき用の対策だそうです。過去のぼくがコメントで(ry
先にfileencodingのことを書いたほうがわかりやすいような気がしますがぼくの.vimrcにはこの順番で書いてあるので、なにか理由が有るのか無いのかわかりませんがこの順番で書いています。
書き込むときのデフォルトの文字コードの指定
set fileencoding=utf-8
ファイルに書き込むときの文字コードをUTF-8に指定しています。
調べ直してみたら開いたファイルの文字コードがなんであれUTF-8で保存されるようになるっぽいので設定しないほうがいいのかも?
でも現状困ってないからよし(よくない)
※不都合に出会ったらこの記事共々修正します。
読み込むときの文字コードの指定
set fileencodings=utf-8,cp932,sjis,euc-jp
ファイルを開くときにどの文字コードとして読み込むかを指定しています。
左のものから順に試してみて、問題なく開けたらその文字コードで開かれます。
指定してある文字コードのどれにもマッチしなかった場合は"encoding"に指定してある文字コードで読み込まれるそうです。[1]
改行コードの設定
if has('win64')
" Windowsのときは<CR+LF>を最優先する
set fileformats=dos,unix,mac
else
" それ以外のときは<CR>を最優先する
set fileformats=unix,dos,mac
endif
ファイルを開くときに、どの改行コードで開くかを指定しています。
Windowsの場合とそれ以外とで優先順位を変えています。
"fileencodings"と同じく、左にあるものから順に照らし合わせ、問題がなかったものが使われます。
新規ファイルの場合は一番左のものが使われます。
行番号を表示する
set number
画面左端に行番号を表示するようにします。
シンタックスハイライトをオンにする
syntax enable
文字が色分けされて表示されるようになります。(なぜかここだけZennのシンタックスハイライトが効いていませんが、コメント行や、if・elseなどの色が変わってたりするやつがそれです。)
ファイルが無かったらダウンロードする関数を定義
function! g:DownloadIfNotFileReadable(file_path, remote_url) abort
if filereadable(a:file_path)
" ファイルがローカルに存在していたら何もしない
return
endif
" OS別のcurlコマンド
let l:curl_command = has('win64') ? 'curl.exe' : 'curl'
" ファイルをダウンロードする
let l:message = system(l:curl_command . ' -Lo ' . a:file_path . ' --create-dirs ' . a:remote_url)
if l:message !~# '.*% Total.*% Received.*% Xferd.*'
" ダウンロードに失敗したらエラーメッセージを表示する
echo 'error: ' . l:message
endif
endfunction
長いので分割します
function! g:DownloadIfNotFileReadable(file_path, remote_url) abort
"DownloadIfNotFileReadable"という名前で関数を定義しています。
"g:"というのはスコープを指定するもので、今回の場合はこのファイルの中でも外でも読み込まれてさえいればどこからでも呼び出せる、というスコープになります。
(init.vimからも使いたいのでこのスコープにしています。)
引数にはダウンロード先のパス、ダウンロードしたいファイルのURLを受け取るようにしています。
末尾に付いてる"abort"というのは、この関数内で何かエラーが発生したらその場で関数を抜けるようにする、というものです。
(ただし、このあと使うシェルコマンドの実行のときはそのまま継続されます。あくまでvimscriptの処理が失敗した場合、のようです。)
if filereadable(a:file_path)
" ファイルがローカルに存在していたら何もしない
return
endif
引数で渡されたパスにファイルが存在するか確認して、もしファイルがもう既に存在したら何もせずに関数を終了します。
" OS別のcurlコマンド
let l:curl_command = has('win64') ? 'curl.exe' : 'curl'
Windowsの場合、"curl"という文字列はcurlではない別のプログラムのエイリアスになっていることがあって、"curl.exe"まで打たないとちゃんとcurlを実行してくれないのでそのための対策です。[2]
let l:message = system(l:curl_command . ' -Lo ' . a:file_path . ' --create-dirs ' . a:remote_url)
curlコマンドを実行します。
エラーメッセージの出力に使いたいので、実行結果の出力を変数に保管しておきます。
if l:message !~# '.*% Total.*% Received.*% Xferd.*'
" ダウンロードに失敗したらエラーメッセージを表示する
echo 'error: ' . l:message
endif
curlコマンドがもしエラーを吐いていたらエラーメッセージとして出力します。
条件分岐は正規表現を使って無理やり実現しています(´・ω・`)
カラースキームの設定(Vim版)
" neovimから読み込まれていたときは処理しない
if !has('nvim')
" gruvboxがなかったらダウンロードする
call g:DownloadIfNotFileReadable(has('win64') ? $HOME . '\vimfiles\colors\gruvbox.vim' : $HOME . '/.vim/colors/gruvbox.vim', 'https://raw.githubusercontent.com/morhetz/gruvbox/master/colors/gruvbox.vim')
" カラースキームをgruvboxに指定する
colorscheme gruvbox
endif
" ライトテーマを使う
set background=light
長いので分割
if !has('nvim')
VimとNeovimではカラースキームの保存先が異なるので、Vimのときだけ実行するようにしています。
call g:DownloadIfNotFileReadable(has('win64') ? $HOME . '\vimfiles\colors\gruvbox.vim' : $HOME . '/.vim/colors/gruvbox.vim', 'https://raw.githubusercontent.com/morhetz/gruvbox/master/colors/gruvbox.vim')
先ほど定義した関数を使って、gruvboxがなかった場合はダウンロードして取ってくるようにしています。
colorscheme gruvbox
カラースキームにgruvboxを指定しています。
Neovimの場合はダウンロード先が違い、この時点ではファイルが用意できていないので"if has('nvim')"のスコープ内にしています。
set background=light
ダークテーマかライトテーマかを選べます。ここではライトテーマにするよう指定しています。
インデントにスペースを使う
set expandtab
インデントするときに半角スペースを使うように指定しています。
Tab文字の長さの設定
set tabstop=4
Tab文字1つの長さを指定しています。
この場合は半角スペース4つ分になります。
インデント1つあたりのスペースの数
set shiftwidth=4
"set expandtab"してある状態でTabキーを押したときに入力される半角スペースの数です。
1度にまとめて削除されるスペースの数
set softtabstop=4
BACKSPACEキーを1回押すたびにまとめて削除される半角スペースの数を指定しています。
改行したときに自動でインデントしてくれるようにする
set autoindent
これを書いておくと改行したときに自動でインデントされるようになります。
オートインデントをスマートにする
set smartindent
"{"や"}"によってインデントの深さを変えてくれたりするようになります。
全角文字をちゃんと表示する
set ambiwidth=double
これを設定しないと絵文字がちゃんと表示されなかったりします。
折り返したときにインデントする
set breakindent
1行が長くて画面に収まりきらないときに折り返して表示してくれるようになります。
折り返したときの追加のインデントの深さを指定する
set breakindentopt=shift:0
1行が長すぎて折り返し表示したときに行の先頭をどこに合わせるかを設定しています。
この場合は元の行の先頭に合わせてくれるようになります。
行末にセミコロンを挿入する関数を定義
function! InsertEndSemicolon() abort
" カーソルの現在位置を取得する
let s:currentPosition = getpos('.')
" 行末にセミコロンがなかったら挿入する
if !(getline('.') =~ ';$')
execute ':normal A;'
endif
" カーソル位置を戻す
call setpos('.', s:currentPosition)
endfunction
コメント行に書いてある通りです。
(というかvim scriptでこんなちゃんとした処理書くことをあんまりしていないのでコメントに書いてある以上のことは今のぼくにはわからないです。。。)
定義した関数をキーショートカットで呼び出せるようにする
" ノーマルモードでセミコロンを押すとInsertEndSemicolon()が呼ばれるようにする
nnoremap <silent> ; :call InsertEndSemicolon()<CR>
" インサートモードでセミコロン2度押しでその場にセミコロンを入力できるようにする
inoremap <silent> ;; ;
" インサートモードでセミコロン押してからエスケープキーを押すと行末にセミコロンを挿入してからノーマルモードに戻る
inoremap <silent> ;<ESC> <ESC>:call InsertEndSemicolon()<CR>
やりたいこととしてはコメント行に書いてある通りです。
"nnoremap"から始まる行はノーマルモードのときに有効なキーショートカット、"inoremap"から始まる行はインサートモードのときに有効なキーショートカットを定義しています。
"<silent>"と書いておくと、キーショートカットを押したときにもなにも表示しないで関数を呼び出してくれます。
"<silent>"の後ろの";"や";;"、";<ESC>"が登録したいキーショートカットです。ここに書いた順番でキーを押すとキーショートカットが実行されます。
("<ESC>"というのはescキーのことです、ノーマルモードに戻るときに連打するやつです。)
";"や";;"、";<ESC>"の後ろに書いてあるのが、実際に実行したい内容です。キーショートカットを実行すると、ここに書いてあることがそっくりそのまま実際に入力されます。
("<CR>"というのはEnterキーを押す、という意味です。)
例えば
nnoremap <silent> ; :call InsertEndSemicolon()<CR>
の場合、ノーマルモードで";"と入力すると、":call InsertEndSemicolon()"と入力してからEnterキーを押す、というところまでやってくれます。
言語ごとのインデントの設定
filetype indent on
開いたファイルの拡張子によってインデントの設定を変える、という機能を有効化しています。
autocmd FileType java setlocal shiftwidth=2 softtabstop=2
autocmd FileType typescriptreact setlocal shiftwidth=2 softtabstop=2
JavaもしくはReactフレームワークを使っているときのTypeScriptファイルを開いた場合はshiftwidth、softtabstopの値をそれぞれ2で上書きするようにしています。
端末固有の設定を読み込む
if filereadable($HOME . '/.vimrc_local')
source ~/.vimrc_local
endif
環境によって値を変えたい、というような設定項目があった場合にホームディレクトリにある".vimrc_local"というファイル内に記述すれば自動で読み込んで設定を上書きしてくれるようにするための記述です。
例えばPCの画面サイズによって値を変えたい、みたいな設定があったら".vimrc_local"に記述するようにしています。
(たしか画面端の余白の大きさを設定するのに使っていたような気がします。現在は使っていないのであんまり覚えてないです。。。)
.vimrcに記述している内容はここまでになります。ここからは再びinit.vimに記述している内容に戻ります。
XDG Base Directory Specification
Windowsの場合と$XDG_CONFIG_HOMEという環境変数が設定されている場合と、それ以外の場合でカラースキームのダウンロード先などが異なるのであらかじめパスを取得しておきます。
let s:config_home = has('win64') ? $LOCALAPPDATA : empty($XDG_CONFIG_HOME) ? $HOME . '/.config' : $XDG_CONFIG_HOME
三項演算子を2重で使ってそれぞれの場合に対応しています。
vim-plugがインストールされていなかったらインストールする
vim-plug本体と使いたいプラグインをインストールします。
let s:plug_path = has('win64') ? $LOCALAPPDATA . '\nvim-data\site\autoload\plug.vim' : $HOME . '/.local/share/nvim/site/autoload/plug.vim'
if !filereadable(s:plug_path)
call g:DownloadIfNotFileReadable(s:plug_path, 'https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim')
" ついでにプラグインもインストールする
if has('win64')
" Windowsの場合
source ~/AppData/Local/nvim/plugin_settings/vim-plug_setting.vim
else
" Windows以外の場合
if empty($XDG_CONFIG_HOME)
source ~/.config/nvim/plugin_settings/vim-plug_setting.vim
else
source $XDG_CONFIG_HOME/nvim/plugin_settings/vim-plug_setting.vim
endif
endif
PlugInstall
endif
これも長いので分割します
let s:plug_path = has('win64') ? $LOCALAPPDATA . '\nvim-data\site\autoload\plug.vim' : $HOME . '/.local/share/nvim/site/autoload/plug.vim'
Windowsの場合とそれ以外とでvim-plugのインストール先が異なるので、実行している環境に合わせたパスをあらかじめ変数に入れています。
if !filereadable(s:plug_path)
インストールされていないときだけ実行すればいいので、vim-plugがインストールされているかどうかで分岐しています。
call g:DownloadIfNotFileReadable(s:plug_path, 'https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim')
.vimrcで定義した関数を使ってvim-plugをダウンロードしています。
" ついでにプラグインもインストールする
if has('win64')
" Windowsの場合
source ~/AppData/Local/nvim/plugin_settings/vim-plug_setting.vim
else
" Windows以外の場合
if empty($XDG_CONFIG_HOME)
source ~/.config/nvim/plugin_settings/vim-plug_setting.vim
else
source $XDG_CONFIG_HOME/nvim/plugin_settings/vim-plug_setting.vim
endif
endif
プラグインをインストールするための前準備として、インストールしたいプラグインの情報をまとめて記述しておいたファイルを読み込んでいます。
vim-plug_setting.vimの内容については後ほど紹介します。
PlugInstall
プラグインをインストールします。
カラースキームの設定(Neovim版)
call g:DownloadIfNotFileReadable(has('win64') ? s:config_home . '\nvim\colors\gruvbox.vim' : s:config_home . '/nvim/colors/gruvbox.vim', 'https://raw.githubusercontent.com/morhetz/gruvbox/master/colors/gruvbox.vim')
.vimrcで定義した関数を使って、ファイルがなかった場合はダウンロードするようにしています。
colorscheme gruvbox
カラースキームに"gruvbox"を指定します。
コマンドラインを2行にする
set cmdheight=2
echoコマンドを使ったときに結果が出力されたりする場所の行数を2行にしています。
ファイルを開いたときに、自動でそのファイル置かれているフォルダに移動する
set autochdir
これを設定しておくと、ファイルを開いたときに自動でそのファイルが置かれているフォルダに移動してくれるようになります。
例えば、"nvim hoge/fuga.py"のようにしてファイルを開いていたとしても":!python3 fuga.py"で実行できます。
※補足:Vim・NeovimのExモードでは、"!"から始めることでシェルコマンドが実行できます。print文を使って変数の中身を確認したい、というような場合などにとても重宝します。
(細かい話をすると、Vim内でのカレントディレクトリが開いたファイルを置いているディレクトリに設定されます。そのため、Vimを閉じたらいつの間にかディレクトリが変わっていた、というようなことは起こらないです。)
undo履歴を保持し続けるようにする
if has('persistent_undo')
set undodir=~/.vimundo
set undofile
endif
Vimを閉じてもundoの履歴を保持し続けるようにしています。
python3のパスを指定
if has('win64')
if !empty(system('where /Q python && echo has'))
let g:python3_host_prog = s:config_home . '\Programs\Python\Python37-32\python.exe'
endif
else
let g:python3_host_prog = system("bash -c 'echo -n $(which python3)'")
endif
Neovimのプラグインの中にはPythonを使うものもあるので、Pythonがインストールされているパスを教えています。
Windowsの場合は、Pythonがインストールされていたら決め打ちでパスを指定しています。
かなりの力技な気がするのでもっとスマートなやりかたをご存知でしたら教えてくださると嬉しいですm(_ _)m
Windows以外の場合、純粋に
echo -n $(which python3)
としてしまうと、使っているシェルによっては動かなかったりするので明示的にbashで実行するようにしています。
また
which python3
だけにすると改行が含まれてしまい、Neovimがうまくパスを認識できないためechoコマンドを使って改行なしで出力するようにしています。
(これを書いていて気づいたのですが、最近のMacに標準でインストールされているbashは最新ではなくなったみたいなので、zshがインストールされていたらそっちを優先して使う、などのようにしておいたほうがいいかもしれないですね。。。)
拡張子ごとにfiletypeを指定する
autocmd BufNewFile,BufRead *.fish setfiletype fish
autocmd BufNewFile,BufRead *.vim setfiletype vim
autocmd BufNewFile,BufRead *.swift setfiletype swift
autocmd BufNewFile,BufRead *.kt setfiletype kotlin
拡張子を見てファイルタイプをセットするようにしています。
ほとんどの場合Vimが勝手に認識してくれるのですが、たまにうまくファイルタイプを認識できていない拡張子に遭遇するので、そういった場合はこのようにして追加でファイルタイプを指定します。
("filetype"が設定されていないとコード補完系のプラグインが動かなかったりするのでちゃんと指定するようにしています。)
プラグインごとの追加の設定を読み込む
" vim-plugの設定を読み込む
if has('win64')
source ~/AppData/Local/nvim/plugin_settings/vim-plug_setting.vim
elseif !empty($XDG_CONFIG_HOME)
source $XDG_CONFIG_HOME/nvim/plugin_settings/vim-plug_setting.vim
else
source ~/.config/nvim/plugin_settings/vim-plug_setting.vim
endif
" vim-indent-guidesの設定を読み込む
if has('win64')
source ~/AppData/Local/nvim/plugin_settings/vim-indent-guides_setting.vim
elseif !empty($XDG_CONFIG_HOME)
source $XDG_CONFIG_HOME/nvim/plugin_settings/vim-indent-guides_setting.vim
else
source ~/.config/nvim/plugin_settings/vim-indent-guides_setting.vim
endif
" asyncompleteの設定を読み込む
if has('win64')
source ~/AppData/Local/nvim/plugin_settings/asyncomplete_setting.vim
elseif !empty($XDG_CONFIG_HOME)
source $XDG_CONFIG_HOME/nvim/plugin_settings/asyncomplete_setting.vim
else
source ~/.config/nvim/plugin_settings/asyncomplete_setting.vim
endif
" aleの設定を読み込む
if has('win64')
source ~/AppData/Local/nvim/plugin_settings/ale_setting.vim
elseif !empty($XDG_CONFIG_HOME)
source $XDG_CONFIG_HOME/nvim/plugin_settings/ale_setting.vim
else
source ~/.config/nvim/plugin_settings/ale_setting.vim
endif
" vim-lspの設定を読み込む
if has('win64')
source ~/AppData/Local/nvim/plugin_settings/vim-lsp_setting.vim
elseif !empty($XDG_CONFIG_HOME)
source $XDG_CONFIG_HOME/nvim/plugin_settings/vim-lsp_setting.vim
else
source ~/.config/nvim/plugin_settings/vim-lsp_setting.vim
endif
" vim-closetagの設定を読み込む
if has('win64')
source ~/AppData/Local/nvim/plugin_settings/vim-closetag_setting.vim
elseif !empty($XDG_CONFIG_HOME)
source $XDG_CONFIG_HOME/nvim/plugin_settings/vim-closetag_setting.vim
else
source ~/.config/nvim/plugin_settings/vim-closetag_setting.vim
endif
" Neosnippetの設定を読み込む
if has('win64')
source ~/AppData/Local/nvim/plugin_settings/neosnippet_setting.vim
elseif !empty($XDG_CONFIG_HOME)
source $XDG_CONFIG_HOME/nvim/plugin_settings/neosnippet_setting.vim
else
source ~/.config/nvim/plugin_settings/neosnippet_setting.vim
endif
プラグイン固有の設定は別ファイルに分けて書くようにしているので、それらのファイルを読み込むようにしています。
それぞれのファイルの中身は以下の通りです
vim-plug固有の設定
call plug#begin(stdpath('data') . '/plugged')
" <C--><C-->でコメントインアウトを切替できるようにするプラグイン
Plug 'tomtom/tcomment_vim'
" ノーマルモードで cs"' ってやったら"を'に置換してくれる
Plug 'tpope/vim-surround'
" インデントを可視化してくれるやつ
Plug 'nathanaelkane/vim-indent-guides'
" 自動で閉じ括弧とか入力してくれるやつ
Plug 'cohama/lexima.vim'
" 自動でHTMLの閉じタグを入力してくれるプラグイン
Plug 'alvan/vim-closetag'
" lintしてくれるやつ
Plug 'w0rp/ale'
" 補完に使うプラグインたち
Plug 'prabirshrestha/async.vim'
Plug 'prabirshrestha/vim-lsp'
Plug 'mattn/vim-lsp-settings'
Plug 'prabirshrestha/asyncomplete.vim'
Plug 'prabirshrestha/asyncomplete-lsp.vim'
Plug 'Shougo/neosnippet.vim'
Plug 'Shougo/neosnippet-snippets'
Plug 'prabirshrestha/asyncomplete-neosnippet.vim'
call plug#end()
vim-plugでは
call plug#begin(stdpath('data') . '/plugged')
から
call plug#end()
の間に使いたいプラグインの情報を書いておくと、自動でプラグインを有効化してくれます。
また、Exモードで
:PlugInstall
と実行すると、プラグインのインストールも行ってくれます。
"Plug"のあとの文字列は、Githubの'ユーザー名/リポジトリ名'になっています。
例えば"hoge"という方が"fuga"という名前のリポジトリで公開してくださっているプラグインを使いたい場合は、
Plug 'hoge/fuga'
のように記述します。
Indent Guides固有の設定
" Indent Guidesを有効化する
let g:indent_guides_enable_on_vim_startup = 1
" いくつめのインデントから色をつけるかの指定
let g:indent_guides_start_level= 1
" インデント1つあたりの、色をつけるスペースの数
let g:indent_guides_guide_size = 0
" インデントにつける色の設定
autocmd VimEnter,Colorscheme * :hi IndentGuidesOdd ctermbg=220
autocmd VimEnter,Colorscheme * :hi IndentGuidesEven ctermbg=214
Indent Guidesはインデントを可視化してくれるプラグインです。
設定している内容に関してはコメント行に書いてある通りです。
(現在Indent Guidesはメンテナンスが終了しているようです。移行先探さないと・・・。)
asyncomplete.vim固有の設定
set completeopt+=preview
autocmd! CompleteDone * if pumvisible() == 0 | pclose | endif
asyncomplete.vimはコード補完をしてくれるプラグインです。
たしか補完候補をプレビューウィンドウで表示するためにこの設定を書いた、というかどこからかコピペしてきたような気がしますがコメントも残っていないので真相は不明です・・・。
ALE (Asynchronous Lint Engine)固有の設定
" let g:ale_sign_column_always = 1
set signcolumn=yes
highlight SignColumn ctermbg=15
highlight SignColumn ctermfg=15
highlight SignColumn guisp=15
highlight SignColumn guifg=15
highlight SignColumn guibg=15
let g:ale_sign_error = '☠️'
let g:ale_sign_warning = '⚠️'
ALEは、ソースコードを読んでエラーや警告があった場合には表示してくれるプラグインです。
警告やエラーがある行に表示する絵文字を設定しています。
また、恐らく多分きっとエラーや警告の絵文字を表示する列の背景色とかも指定しています。(コメントが残っていないのではっきりとはわからないです。コメントはちゃんと残しましょう。)
vim-lsp固有の設定
" ノーマルモードで"def"と入力したら変数や関数の定義元にジャンプするようにする
nnoremap <silent> def :LspDefinition<CR>
" "neosnippet"からの補完情報を取得するようにする
call asyncomplete#register_source(asyncomplete#sources#neosnippet#get_source_options({
\ 'name': 'neosnippet',
\ 'whitelist': ['*'],
\ 'completor': function('asyncomplete#sources#neosnippet#completor'),
\ }))
vim-lspは、VimでLanguage Server Protocolを扱えるようにするためのプラグインです。
asyncomplete.vimなどのコード補完プラグインと組み合わせて使います。
設定内容に関してはコメント行に書いてある通りです。
closetag.vim固有の設定
" filenames like *.xml, *.html, *.xhtml, ...
" These are the file extensions where this plugin is enabled.
"
let g:closetag_filenames = '*.html,*.xhtml,*.phtml'
" filenames like *.xml, *.xhtml, ...
" This will make the list of non-closing tags self-closing in the specified files.
"
let g:closetag_xhtml_filenames = '*.xhtml,*.jsx'
" filetypes like xml, html, xhtml, ...
" These are the file types where this plugin is enabled.
"
let g:closetag_filetypes = 'html,xhtml,phtml,typescriptreact'
" filetypes like xml, xhtml, ...
" This will make the list of non-closing tags self-closing in the specified files.
"
let g:closetag_xhtml_filetypes = 'xhtml,jsx'
" integer value [0|1]
" This will make the list of non-closing tags case-sensitive (e.g. `<Link>` will be closed while `<link>` won't.)
"
let g:closetag_emptyTags_caseSensitive = 1
" dict
" Disables auto-close if not in a "valid" region (based on filetype)
"
let g:closetag_regions = {
\ 'typescript.tsx': 'jsxRegion,tsxRegion',
\ 'javascript.jsx': 'jsxRegion',
\ 'typescriptreact': 'jsxRegion,tsxRegion',
\ 'javascriptreact': 'jsxRegion',
\ }
" Shortcut for closing tags, default is '>'
"
let g:closetag_shortcut = '>'
" Add > at current position without closing the current tag, default is ''
"
let g:closetag_close_shortcut = '<leader>>'
closetag.vimは、HTML形式のタグを自動で閉じてくれるプラグインです。
公式のREADMEに書いてあった内容にプラスして、ファイルタイプが"typescriptreact"だった場合にも有効化されるようにしています。
Neosnippet固有の設定
imap <C-k> <Plug>(neosnippet_expand_or_jump)
smap <C-k> <Plug>(neosnippet_expand_or_jump)
xmap <C-k> <Plug>(neosnippet_expand_target)
if has('conceal')
set conceallevel=0 concealcursor=niv
endif
Neosnippetは簡単なコード補完を行ってくれるプラグインです。
このように設定しておくと、選択した補完候補をCtrl + kで展開してくれたりするようにしています。
(公式のREADMEに書いてある内容のコピペです。)
個別の設定はしていないけど使っているプラグインたちの紹介
tcomment
Ctrlキーを押しながら"-"2度押しでカーソルがある行をコメントアウト・コメントインしてくれます。
surround.vim
カーソルがある行内での置換を楽にしてくれるプラグイン。
ノーマルモードで例えば"csab"と入力すると、カーソル行内の"a"を"b"に置換してくれます。
ダブルクオートをシングルクオートに置換したい、という場合などに重宝します。
lexima.vim
括弧やクオートを自動で閉じてくれるプラグインです。
もはや居てくれないと困る存在です。
async.vim
asyncomplete.vimの動作に必要なプラグインです。
vim-lsp-settings
vim-lspの設定をコマンド1つでやってくれるようになるプラグインです。
(これが無かったらvim-lsp扱えていませんでした。。。)
asyncomplete-lsp.vim
asyncomplete.vimとvim-lspの仲介をしてくれるプラグインです。
Neosnippet-snippets
Neosnippetにスニペットの情報を提供するプラグインです。
asyncomplete-neosnippet.vim
asyncomplete.vimとNeosnippetの仲介をしてくれるプラグインです。
自作Dockerコンテナ用の設定を読み込む
プラグインがインストールされた状態のNeovimをDockerコンテナとして用意することで初期セットアップの手間を省こうとしていた頃の名残です。
現在は使っていないのですが、もしかしたら将来dockerfileを書くときに役立つかもしれない・・・と思ったので残してあります。
(せっかくGit管理しているので普通だったら消したほうがいいとは思うのですがそうすると、過去のコミットにこの情報が載っている、ということ自体を忘れそうなので消さずに残しています・・・。)
if !empty($container_name)
if !empty($XDG_CONFIG_HOME)
source $SDG_CONFIG_HOME/nvim/plugin_settings/settings_for_myde.vim
else
source ~/.config/nvim/plugin_settings/settings_for_myde.vim
endif
endif
"settings_for_myde.vim"の中身はこんな感じです。
" dockerコンテナ内向けの設定
" うまくいかなかったときの保険として、'name'の直の最初に'myde-'をつける
" この3つ以外は、パスが通ってるとこにコマンド配置しておけば勝手にいいかんじにしてくれる(vim-lsp-settingが)
if executable('/home/myde/omnisharp-lsp/run')
au User lsp_setup call lsp#register_server({
\ 'name': 'myde-omnisharp-lsp',
\ 'cmd': {server_info->['/home/myde/omnisharp-lsp/run', '-lsp']},
\ 'whitelist': ['cs']
\ })
endif
if executable('/home/myde/eclipse-jdt-ls/eclipse-jdt-ls')
au User lsp_setup call lsp#register_server({
\ 'name': 'myde-eclipse-jdt-ls',
\ 'cmd': {server_info->['/home/myde/eclipse-jdt-ls/eclipse-jdt-ls']},
\ 'whitelist': ['java']
\ })
endif
if executable('/home/myde/myCommands/kotlin-language-server')
au User lsp_setup call lsp#register_server({
\ 'name': 'myde-kotlin-language-server',
\ 'cmd': {server_info->['/home/myde/myCommands/kotlin-language-server']},
\ 'whitelist': ['kotlin']
\ })
endif
キーショートカットの追加(Neovim版)
tnoremap <silent> <ESC> <C-\><C-n>
Neovimでターミナルを開いているときにもescキーでインサートモードからノーマルモードに移るようにしています。
nnoremap <silent> <C-t><C-m> :split<CR> <C-w>j :terminal<CR> :resize 6<CR> i
ノーマルモードのときに、Ctrlキーを押しながら"tm"と入力することで画面を水平分割してからターミナルを起動するようにしています。
あとがき
自分が使っているinit.vimをWindows対応にしたので、いい機会だと思ってこの記事を書き始めました。
が、思っていたよりもかなりボリューミーになって驚いています。いつの間にか結構な量を設定してたんですね。。。
記事の内容に関しては、なるべく正確な情報になるよう改めて調べ直しながら書いてはいますが、誤りなどがありましたらコメントで教えてくださるとうれしいです。
Discussion