はじめに(2020/10/14追記)
この記事ではWindowsでのWSLを用いない環境構築をメインに扱っていますが、WSLを使う選択肢があるならそちらの方が便利な場合が多いので1度考えてみると良いかもしれません。
概要
近頃、多くの競技プログラマがVSCodeなどの万能エディタやIDEを使用しています。私はVimのキーバインドが好きでVSCodeやEclipseにも必ずVimプラグインを入れて使っているのですが、やはりどうしても本家のほうが使いやすいことを証明したいと思い、Vimに戻ってきました。とはいってもVimがIDEに追いつくためにはかなりの量のカスタマイズが必要です。そこで、ここでは競技プログラミングのような単純なコーディングに活用範囲を絞って、「Vimって使いやすい!」と思ってもらえるような設定をお伝えしたいと思っています。
第二の目的として、WindowsでのVimの環境構築の記事が足りてないということがあります。Linux等では初めからVimが使えたり、パッケージ管理ツールで簡単にインストールできたりします。それに対してWindowsは環境構築が大変なせいかVim使用者がかなり少ないように思えます。それでも私はVimを使ってほしいのでこの記事を書くことにしました。
Q.そうは言うもののこれって本家VimじゃなくてNeovimの記事だよね?
そこだけは勘弁してください。Neovimの世界には暗黒美夢王をはじめとする有能なプラグイン作成者がいて、どうしてもNeovimが上位互換になっちゃうんです。基本的にはVimなので私のこだわりは気にしないで行きましょう。
OS
- Windows10(64bit)
これ以外の物でも基本的には変わらないので他のOSでこの通りできない場合は適時自分で調べて補ってください。
前提知識
- Windows及びコマンドプロンプトの基本的な使い方
- Vimの基本的な操作
前提として導入するもの
- Neovim
- Python3
- dein.vim
Neovimの導入
インストール
基本的にはこちらのサイトに従います。
https://vim.blue/neovim-dein-windows-10-install-simple/
- Neovimの配布サイトにアクセスする
- 中央の青いボタン「Install Now」をクリック
- 「Install from download」にある「Latest stable release」をクリック
- 下のほうにスクロールして、64bit版Windowsなら「nvim-win64.zip」をダウンロード
- ダウンロードしたzipファイルの中にある「Neovim」フォルダを好きな場所にコピー(本記事では
C:\Program Files
の中にコピーしたものとします)
環境変数PATHの設定
Windowsでプログラミングをやっている人は「またあれか」と思うかもしれませんが一応やり方を書いておきます。
- WindowsキーとPauseキーを同時に押してタスクマネージャーのシステム設定を開く
Pauseキーがない?それなら以下の手順で開きましょう
- WindowsキーとRキーを同時押しして「ファイル名を指定して実行」を開く
control
とタイプしてEnter- 「システムとセキュリティ」をクリック
- 「システム」をクリック
- 「システムの詳細設定」をクリック
- 「環境変数」をクリック
- 「ユーザー環境変数」の「PATH」を選択して「編集」をクリック
- 「新規」をクリックして
{インストールしたフォルダのパス}\Neovim\bin
を追加
インストール成功の確認兼起動
- WindowsキーとRキーを同時押しして「ファイル名を指定して実行」を開く
-
cmd
とタイプしてCtrl+Shift+Enterで管理者権限で実行 -
nvim
とタイプしてEnterで実行
- 以下のようなものが出たら起動成功
-
:q
と入力してEnterを押せば終了
Python3のインストールとNeovimでの認識
すでにPython3 (Python2とは別物) が導入されている人は下の「Python3をNeovimに読み込ませる」から読んでください。
Python3のインストール
- Python3の配布サイトにアクセスする
- 「Latest Python 3 Release」をクリック
- 下のほうにある「Files」の中の「Windows x86-64 executable installer」をダウンロード
- ダウンロードしてきたインストーラーを実行
- 「Add Python 3.x to PATH」にチェックして「Install Now」をクリックしてインストール
Python3をNeovimに読み込ませる
- Neovimを起動 (管理者権限が必要です)
-
:e $MYVIMRC
でEnterして init.vim の編集に入る (init.vimはVim上でのみ$MYVIMRC
として使えますがWindowsのフォルダ構成ではC:\Users\{ユーザー名}\AppData\Local\nvim
にあります なければ作ってください) - init.vimに
let g:python3_host_prog={Python3のpython.exeのパス}
を追記(インストーラーの指示にそのまま従っていればC:\Users\{ユーザー名}\AppData\Local\Programs\Python\{Python3x}\python.exe
になります)
let g:python3_host_prog='C:\Users\{ユーザー名}\AppData\Local\Programs\Python\{Python3x}\python.exe'
追記出来たらNeovimをいったん終了してもう一度開き、:echo has('python3')
で1
が出れば成功です
Gitの導入
本記事で導入するVimプラグインはすべてGitHub上にあるので、「Git for Windows」をインストールしておきます
「GitHub for Windows」「GitHub Desktop」等でgit
コマンドが使える状況にすでになっている場合はこのステップは飛ばしてください
インストール方法は下の記事に準じます。
いまさらGit for Windowsのインストール、GitHubに接続してみた。
- Git for Windowsの配布サイトに行き、中央の「Download」をクリックしてインストーラーをダウンロード
- インストーラーを起動してインストール(細かく設定したい人はしてもいいが本記事ではそのままインストールしたものとする)
- 新たにコマンドプロンプトを開き、
git version
を実行して正しくバージョンが表示されれば成功
dein.vimの導入
Vimのプラグインを導入するのは少し手間ですが、暗黒美夢王Shougo氏によるdein.vimを使えば超簡単にプラグインを管理することができます。
dein.vimの導入自体は少し難しいです(私もいくつものサイトを見たうえでなかなか成功しなくて困っていました)が、またまた他の方の記事に頼って成功した例を書き留めておきます。
今回はおすすめプラグイン 〜 Vimはいいぞ!ゴリラと学ぶVim講座(7)に従ってすすめていきます。こちらで紹介している方法なら、以後tomlファイルに記述するだけで自動的にインストールされ、tomlファイルから削除すれば自動的にア人ストールされます 超優秀です。本記事では、上記記事で使われているinit.vim
の書き方を真似つつ、Windows向けにしたり遅延インストールに対応させたりしています。
init.vimに以下を追記します。
"deinの設定-----------------------
let s:dein_dir = 'C:/Users/{ユーザー名}/.cache/dein'
let s:dein_repo_dir = s:dein_dir . '/repos/github.com/Shougo/dein.vim'
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^=' . s:dein_repo_dir
endif
if dein#load_state(s:dein_dir)
call dein#begin(s:dein_dir)
let s:rc_dir = 'C:/Users/{ユーザー名}/.vim'
if !isdirectory(s:rc_dir)
call mkdir(s:rc_dir, 'p')
endif
let s:toml = s:rc_dir . '/dein.toml'
let s:lazy_toml = s:rc_dir . '/dein_lazy.toml'
call dein#load_toml(s:toml, {'lazy': 0})
call dein#load_toml(s:lazy_toml, {'lazy' : 1})
call dein#end()
call dein#save_state()
endif
if dein#check_install()
call dein#install()
endif
let s:removed_plugins = dein#check_clean()
if len(s:removed_plugins) > 0
call map(s:removed_plugins, "delete(v:val, 'rf')")
call dein#recache_runtimepath()
endif
filetype plugin indent on
syntax enable
- 追記出来たら一度Neovimを終了します(neovimで追記していた場合)
- 次に、
C:\Users\{ユーザー名}
の中に.vim
という名前のフォルダを作り、dein.toml
、dein_lazy.toml
の2つのファイルを作っておきます(とりあえず空でいいです) - 再びNeovimを起動すると自動的に
dein.vim
がC:/Users/{ユーザー名}/.cache/dein/repos/github.com/Shougo/dein.vim
にインストールされます - 成功すると画像のようなメッセージが画面下部に表示されます(ユーザー名はもちろんあなたのユーザー名になります)
init.vimに書いておくべきおすすめ設定
2020/10/14追記
↓より詳しい記事を書きました
Vim/Neovimの設定ファイル(.vimrc, init.vim)の書き方を0から一人前まで
長いインストール作業、お疲れ様でした。ここまでは必要なものを導入しただけなので、Vimは何も便利になっていません。まずはプラグインなしで、init.vim
に書くだけでまともなエディタに近づく設定をお伝えします。
以下に私の基本設定を記します。
よく、何も考えずにこの.vimrc
を写せ!みたいな記事を見かけますが、長すぎるvimrcの写経は環境によってエラーが起きたりすることも多く、また何ができるようになったのかわからなければ使いこなせません。本記事の設定はできる限り書かれた内容を理解して使うことをお勧めします。また、私の設定がすべてではないので、読者様の都合に合わせて改変してください。
以下、私のおすすめ設定
"行番号を表示
set number
"シンタックスハイライトをon
syntax on
"行末まで検索した後行頭に戻って検索
set wrapscan
"検索結果をハイライト表示(:nohで消す)
set showmatch
"tabの代わりにスペースを使用
set expandtab
"tabキーで挿入されるスペースの数
set shiftwidth=4
"中括弧を始めた後などの改行のあと自動的にインデントを入れる
set smartindent
"インデント周りの各種機能で操作されるスペースの数
set softtabstop=4
"VimではUTF-8で文字を表示する
set encoding=utf-8
"UTF-8でファイルを読み込み、ダメだったらShift_JISを試す
set fileencodings=utf-8,sjis
"UTF-8でファイルを書き込む
set fileencodings=utf-8
"クリップボードとVimの無名レジスタを結合する
set clipboard+=unnamed
"コマンドモードでtabを使ってファイル名を補完するときに、1回目は最大共通文字列、次からは順番にファイル名を完全補完する
set wildmode=longest,full
"Ctrl+J,Ctrl+Kでパラグラフ一つ分移動
nnoremap <C-j> }
nnoremap <C-k> {
"「s*」でカーソル下の単語からの置換を途中まで記述
nnoremap <expr> s* ':%s/\<' . expand('<cword>') . '\>/'
" Vim起動時に画面下側にターミナルを立ち上げ、いいぐらいの高さにしておく(resizeの値は適宜調整)
if has('vim_starting')
split
wincmd j
resize 15
terminal
wincmd k
endif
"エディタとターミナルの操作をCtrl+Tで切り替え
tnoremap <C-t> <C-\><C-n><C-w>k
nnoremap <C-t> <C-w>j i
"ターミナルモード中にEscでターミナルノーマルモードに移行
tnoremap <Esc> <C-\><C-n>
以上です
- インデントにタブとスペースのどちらを使ってるかとか文字コードは何を多用するかとかは使用者によるので都合の良いように変更して使ってください
-
s*
を割り当ててしまったことによって一文字消して挿入モードに入るs
が使いにくくなったのでそれを多用する場合は調整してください - Vimでのターミナルの仕様についてはこちらをご覧ください
#おすすめプラグイン
ここからはVimをより使いやすくするための素晴らしいプラグイン達を紹介します。Vimのプラグインは無限の可能性を秘めているので、欲しいプラグインはdein.vim
を活用してどんどん入れていくといいです。
本記事で紹介しているプラグインの多くは実はこちらで紹介されているものなので内容が結構被ってます(ていうか正直パクリみたいなところもあります)。私がVSCodeからNeovimに移行するきっかけとなった記事です。ここでお礼を申し上げます。
dein.vimの簡単な使い方
上で設定したinit.vim
によって、dein.toml
にプラグインの名前を書けば次回起動時に自動的にインストールされます。ここでの「プラグインの名前」とは、下の画像で赤枠で囲った場所のことです。
この場合、dein.toml
に
[[plugins]]
repo = 'pepo-le/win-ime-con.nvim'
と書きます。簡単ですね。
小物系の軽いプラグイン
リントやコードスニペット等の重いプラグインは人によっては合わない場合があるのでとりあえず後回しにして、「あったら地味に便利で手放せない」といった「小物系」プラグインを紹介していきます。
pepo-le/win.ime-con.nvim
Vimの欠点「日本語を扱いにくい」を補うプラグインです。具体的には
- インサートモードでIMEがONの状態でノーマルモードに入ったとき、そのままコマンドが叩けるように一時的にIMEをOFFにする
- 再びインサートモードに切り替えると、IMEがONの状態でそのまま日本語が記述できる
といった機能です。単純ですがとてもありがたいです。
markonm/traces.vim
Vimで置換をするときに置換後の結果がリアルタイムでプレビューされるプラグインです。
エスケープが必要な記号や正規表現を含んだ置換は正しいかわかりにくかったりするのでこれがあるだけで結構ありがたいです。
vim-airline/vim-airline
ステータスバーがカッコよくなるプラグインです。それだけかと思われるかもしれませんが結構重要なものだと思ってます。
赤枠で囲ったのがステータスバーです。このようにvim-airlineを使えば現在のモードや文字コードなど意外と役立つ情報が一目でわかるようになります。
tpope/vim-surround
割と有名どころのプラグインです。括弧や引用符などの囲いを追加したり削除したりするキーバインドを追加します。自分は後述するrhysd/vim-operator-surroundのほうがよく使うので正直こちらはあまり使わないです。
kana/vim-textobj-user、kana/vim-operator-userとその依存プラグイン達
これはかなり深いプラグインです。プラグインの説明をする前に、Vimにおける テキストオブジェクト と オペレーター について簡単に説明しておこうと思います。
Vimには「操作+対象」という組み合わせでできたコマンドがたくさんあります。例えばカーソルが入っている最も近い丸カッコの中身を削除するコマンドはdi(
ですが、ここで d
は「削除」、 i(
は「丸カッコの中」を表します。もっと細かくみると i
は「内部」、 (
は丸カッコを表します。ちなみに括弧ごと削除するときは da(
となります。
ここで、d
のような「操作」を オペレーター 、 iw
のような「対象」を テキストオブジェクト と呼びます。
vim-textobj-user、vim-operator-userはその名の通りユーザー定義のテキストオブジェクト、オペレーターを作ることができるプラグインです。ただしこの記事では作り方は説明せず、代わりにこれらを使って有用なテキストオブジェクトやオペレーターを追加するプラグインを紹介します。全部入れると数がかなり多くて記号が重複してしまう可能性があるのでこちらの記事から必要なものを選んで追加することをお勧めします。参考までに私の構成を晒しておきます。
[[plugins]]
repo = 'kana/vim-textobj-user'
[[plugins]]
repo = 'kana/vim-textobj-entire'
[[plugins]]
repo = 'kana/vim-textobj-line'
[[plugins]]
repo = 'kana/vim-textobj-function'
[[plugins]]
repo = 'kana/vim-textobj-jabraces'
[[plugins]]
repo = 'kana/vim-textobj-indent'
[[plugins]]
repo = 'mattn/vim-textobj-url'
[[plugins]]
repo = 'thinca/vim-textobj-between'
[[plugins]]
repo = 'thinca/vim-textobj-comment'
[[plugins]]
repo = 'anyakichi/vim-textobj-xbrackets'
[[plugins]]
repo = 'mattn/vim-textobj-cell'
[[plugins]]
repo = 'RyanMcG/vim-textobj-dash'
[[plugins]]
repo = 'kana/vim-operator-user'
[[plugins]]
repo = 'kana/vim-operator-replace'
[[plugins]]
repo = 'rhysd/vim-operator-surround'
"textobj-userの衝突回避---------------
omap iF <Plug>(textobj-function-i)
omap aF <Plug>(textobj-function-a)
vmap iF <Plug>(textobj-function-i)
vmap aF <Plug>(textobj-function-a)
"vim-operator-replaceの設定---------
nmap R <Plug>(operator-replace)
nmap R <Plug>(operator-replace)
"vim-operator-surroundの設定---------
nmap sa <Plug>(operator-surround-append)
nmap sd <Plug>(operator-surround-delete)
nmap sr <Plug>(operator-surround-replace)
vmap sa <Plug>(operator-surround-append)
vmap sd <Plug>(operator-surround-delete)
vmap sr <Plug>(operator-surround-replace)
simeji/winresizer
Vim内のウィンドウ分割を利用する場合は必ず入れておきたいプラグインです。例えば私はターミナルを下のほうに常駐させてるので大きさを変えたいときがたまにあります。Vimのデフォルトのキーバインドでウィンドウサイズを変えようとすると、Ctrl+W
+
で一行分だけ広がるといった具合で、超やりにくいです。このプラグインを使うと、Ctrl+E
でリサイズモードに入り、H
J
K
L
の連続押しでいいところまで一気に調整して Enter
で確定することができます。正直Vimにデフォルトで備わってないのがおかしく感じるほど当たり前に使うプラグインです。
重いプラグイン
いよいよ補完、エラーチェックといったIDEっぽいプラグインを詰めていきます。ここではC++を使うものとして説明しますが、環境や使用言語によってかなり違うので適したものを調べたほうがよい場合もあります。
Shougo/deoplete.nvim
Vimで入力補完を行うツールです。さすがに補完ツールといえばこれな気がします。これがないと始まらないです。例によって設定はこちらを参考にさせていただきました。
[[plugins]]
repo = 'Shougo/deoplete.nvim'
hook_source = '''
call deoplete#enable()
"Tab補完の設定
inoremap <silent><expr> <Tab>
\ pumvisible() ? "\<C-n>" :
\ <SID>check_back_space() ? "\<TAB>" :
\ deoplete#manual_complete()
function! s:check_back_space() abort
let col = col('.') - 1
return !col || getline('.')[col - 1] =~ '\s'
endfunction
"Shift+Tabで前の補完候補へ
inoremap <expr><S-TAB> pumvisible() ? "\<C-p>" : "\<C-h>"
'''
on_i = 1
C++の補完プラグイン、リンターを導入する前に、clangの導入
プラグインの場所に書くには結構重いんですが、C++の補完ライブラリを使うにはどうしてもclangは欠かせません。導入方法を詳しく書くか迷いましたが、こちらの記事に沿ってやるだけなので説明はカットします。これ以外の方法でも、 clang
コマンドがちゃんと使えればokです。
成功すれば以下のように clang -v
でバージョン情報が見れます。
zchee/deoplete-clang
clangを使ってその場で補完先を探してくれます。deopleteと連携できるので、deopleteの補完方法と同じように使うことができます。
[[plugins]]
repo = 'zchee/deoplete-clang'
hook_source='''
call deoplete#custom#var('clangx', 'default_cpp_options', '-std=gnu++17')
let g:deoplete#sources#clang#libclang_path = 'C:\msys64\mingw64\bin/libclang.dll'
let g:deoplete#sources#clang#clang_header = 'C:\msys64\mingw64\lib\clang'
'''
on_ft = ['c', 'cpp']
depends = ['deoplete.nvim']
補完機能の有無自体好みですが、画像のように補完先をきれいに列挙してくれます。
w0rp/ale
他言語対応の素晴らしいリンターです。少し重いですが、IDE並の仕事でおかしいところをチェックしてくれます。当然効率は上がります。
おまけ:競プロ並みの1ファイルコードをさっさと実行する
実は私はVimでも他のエディタ/IDEでもデバッガは使っていません。単純にプリントデバッグのほうが使いやすいと信じているからです。その代わりIDEのような1回のキーストロークでコンパイルするキーマップだけは実装しています。これは私と同じ、下側にターミナルを常に作っていて、C++を使っている人専用のキーマップだと思ってください。
nnoremap <expr> <F6> '<C-w>jig++ -std=gnu++17 -O2 -o a.out ' . expand("%:p") . '<CR>'
はい。これだけです。すごくシンプルでゴリ押し感満載のキーマップですが、コンパイルオプションを固定してすぐにコンパイルできるのはやはりありがたいです。
実は私はAtCoderの自動サンプルチェック&提出スクリプトを作っているのですが、今は人に見せれるようなものでないパクリ、曖昧変数名満載の汚いコードなので公開はやめておきます。また機会があれば記事にしようと思います。
最後に
ここまで読んでくださった方、本当にありがとうございました。お疲れ様でした!!!
これからもVimとともに快適な人生を送りましょう!