1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WSL で Vimmer っぽい設定にしたい

Posted at

目次

はじめに

本記事は、Windows ユーザー向けに、WSL での Vim の設定を Vimmer っぽくする方法をまとめたものです。ちなみに Vimmer とは、キーボードだけで巧みに Vim を操る熟練ユーザーのことです。
筆者はちょっと Vimmer 気分を味わいたくて遊び感覚で始めただけです。でも気がつくと、思いのほか楽しくてすっかり夢中になっていました。
興味のある方は、筆者同様、気楽に試していただけたらと思います。

1. 準備

以下のテスト環境で、説明したいと思います。
Windows 11; Windows ターミナル; Ubuntu 24.04

vim --version でバージョン情報が表示されなければ、以下のコマンドで vim をインストールしてください。

WSL : Ubuntu / Debian系の場合
sudo apt update
sudo apt install vim

1-1. カーソルの形状の変更とその理由

vim の場合、カーソルの形が、バー(bar: 縦に細長いカーソル)だとカーソルの位置がわかりづらいです。カーソルの形は、ブロック状のものがおすすめです。Windows ターミナルの場合、「塗りつぶされたボックス」などにすると、ia コマンドの挿入位置を一目で把握できるし、ビジュアルモードでも選択範囲が明確で視認性が高くなるからです。

以下のように、カーソルの形がバーだと、viw 等で単語を選択しても、選択範囲が不完全に見えます。
p1.png

Windows ターミナルでカーソルの形状を変更する方法
設定の「プロファイル」から対象のシェルを選び、「外観」にある「カーソルの形」から変更可能です。

1-2. sudoedit コマンドを使おう

WSL(Ubuntu など)のデフォルトのエディタを nano から vim に変更すると、次のようなメリットがあります。
具体的なメリット

  • less コマンドとの連携が可能で、less コマンドで閲覧中のファイルを v キーひとつ打つだけで即座に vim で編集可能になる
  • sudoedit コマンドの利用が可能で、root 権限のファイルを、自分の設定やプラグインで安全に編集できる

特に 2 つ目の sudoeditsudo -e と同義)を活用する最大の利点は、自分専用の設定(.vimrc)やプラグインをそのまま使えることです。
通常、sudo vim で編集すると root ユーザーの設定が参照されるため、使い慣れたキーバインドや補完機能が効かず、root 側に設定ファイルをコピーする手間が生じます。しかし sudoedit を使えば、一般ユーザーの環境を維持したまま一時ファイルとして編集できるため、root 側を汚さず常にフルパワーの vim で作業が可能です。

WSL : 例、SSH クライアント設定ファイルを編集
sudoedit /etc/ssh/ssh_config

エイリアスを設定して短縮する方法
~/.bashrc にエイリアスを登録することで自分好みに短縮できます。

~/.bashrc : 例
alias se='sudoedit'
WSL のデフォルトのエディタを nano から vim に変更する方法はこちら

sudo update-alternatives --config editor とコマンドを実行すると、利用できるエディタの候補が表示されるので、vim の該当の選択肢番号を入力します。
下記の例では、3 と入力。

WSL
$ sudo update-alternatives --config editor
alternative editor (/usr/bin/editor を提供) には 4 個の選択肢があります。

  選択肢    パス                優先度   状態
------------------------------------------------------------
* 0        /bin/nano            40     自動モード
  1        /bin/ed             -100    手動モード
  2        /bin/nano            40     手動モード
  3        /usr/bin/vim.basic   30     手動モード
  4        /usr/bin/vim.tiny    15     手動モード

現在の選択 [*] を保持するには <Enter>、さもなければ選択肢の番号のキーを押してください: 3

確認方法
再び sudo update-alternatives --config editor とコマンドを実行して、3 の前に * があれば成功です。


2. Vim キーマッピングのカスタマイズ

Vim の設定は、~/.vimrc に記述します。
(.vimrc でのコメントアウトは「"」です)

~/.vimrc 設定ファイルの一例

~/.vimrc
" Leader キーをスペースに変更
let mapleader = ' '

" プラグイン
call plug#begin('~/.vim/plugged')
" 画面内の任意の場所にジャンプ
Plug 'easymotion/vim-easymotion'
" 囲み文字の操作
Plug 'tpope/vim-surround'
" マルチカーソルの操作
Plug 'mg979/vim-visual-multi'
call plug#end()

" 任意の 2 文字検索でジャンプ(easymotion)
map <Leader>f <Plug>(easymotion-s2)
" マルチカーソル
let g:VM_maps = {}
" 下方向にカーソル追加
let g:VM_maps["Add Cursor Down"] = '<Leader>d'
" 上方向にカーソル追加
let g:VM_maps["Add Cursor Up"]   = '<Leader>u'

" インサートモードでの Esc キーの代替
inoremap <silent> jj <Esc>

" 行頭・行末移動の変更
nnoremap H ^
nnoremap L $
xnoremap H ^
xnoremap L g_
onoremap H ^
onoremap L $

" ウィンドウの分割
" 水平方向の分割
nnoremap <Leader>s <C-w>s
" 垂直方向の分割
nnoremap <Leader>v <C-w>v
" 分割したウィンドウへのカーソル移動
" 左のウィンドウへ移動
nnoremap <Leader>h <C-w>h
" 下のウィンドウへ移動
nnoremap <Leader>j <C-w>j
" 上のウィンドウへ移動
nnoremap <Leader>k <C-w>k
" 右のウィンドウへ移動
nnoremap <Leader>l <C-w>l

" 画面内の最初の行に移動(Ctrl+k)
nnoremap <C-k> H
" 画面内の最後の行に移動(Ctrl+j)
nnoremap <C-j> L

" 10 行分下に移動(J) 
nnoremap J 10j
" 10 行分上に移動(K)
nnoremap K 10k

" インデント(ノーマルモードで 1 行、連打可能)
" >> を > に変更
nnoremap > >>
" << を < に変更
nnoremap < <<
" インデント保持(ビジュアルモードで 複数行、連打可能)
xnoremap > >gv
xnoremap < <gv

" 行移動(ノーマルモードで 1 行 Alt+j/k)
nnoremap <silent> <Esc>j :m .+1<CR>==
nnoremap <silent> <Esc>k :m .-2<CR>==
" 行移動(ビジュアルモードで複数行  Alt+j/k)
xnoremap <silent> <Esc>j :m '>+1<CR>gv=gv
xnoremap <silent> <Esc>k :m '<-2<CR>gv=gv

" 選択したテキストを * で前方検索
xnoremap * y/\V<C-R>=escape(@", '/\')<CR><CR>
" 選択したテキストを # で後方検索
xnoremap # y?\V<C-R>=escape(@", '?\')<CR><CR>

" 不要なレジスタ保存を防止
for key in ['x', 's', 'c', 'C', 'S']
  execute 'nnoremap ' . key . ' "_' . key
  execute 'xnoremap ' . key . ' "_' . key
endfor
onoremap c "_c

" 連続ペーストを可能に
xnoremap p "_dP

" 検索のハイライトの解除
nnoremap <Leader><CR> :nohl<CR>

" 保存してウィンドウを閉じる
nnoremap <Leader>q :wq<CR>
" 強制的にウィンドウを閉じる
nnoremap <Leader>x :q!<CR>

" システムクリップボードと連携
set clipboard=unnamedplus

" インデントをスペースで行う
" Tab キーでスペースを挿入する
set expandtab
" タブ文字の表示幅(通常は、shiftwidth と揃える)
set tabstop=2
" >> や自動インデントで使われる幅
set shiftwidth=2
" Tab キーや Backspac キーの操作感を調整
set softtabstop=2

" 不可視文字を表示
set list
" 表示させる文字を設定
set listchars=tab:->,eol:,space:" vim カラースキーム
colorscheme slate
" 強制的に不可視文字をコメントと同じ色
highlight! link SpecialKey Comment
highlight! link NonText Comment

" 改行コードを全形式(LF/CRLF/CR)で自動判別
set fileformats=unix,dos,mac
" ステータスラインを常に表示
set laststatus=2
" dos/unix/mac をステータスラインに表示
set statusline=%f\ [%{&ff}]

" 行番号
set number
" 検索のハイライト
set hlsearch
" 検索結果の総数と現在の位置を表示
set shortmess-=S
" 行頭と行末で左右の移動キーで行をまたぐ
set whichwrap=b,s,h,l,<,>,[,]

2-1. Leader キーの設定と Esc の代替

Leader キーを , カンマや Space キーなどに設定しておくと、既存の操作と衝突せずにキーマッピングの幅が広がるので便利です。

~/.vimrc
" Leader キーをスペースに変更
let mapleader = ' '

次に、インサートモードでの Esc キーの代替を定番の jj にします。

~/.vimrc
" インサートモードでの Esc キーの代替
inoremap <silent> jj <Esc>

2-2. ウィンドウの分割とカーソルの画面移動

以下のようにキーマップを割り当てます。

~/.vimrc
" ウィンドウの分割
" 水平方向の分割
nnoremap <Leader>s <C-w>s
" 垂直方向の分割
nnoremap <Leader>v <C-w>v
" 分割したウィンドウへのカーソル移動
" 左のウィンドウへ移動
nnoremap <Leader>h <C-w>h
" 下のウィンドウへ移動
nnoremap <Leader>j <C-w>j
" 上のウィンドウへ移動
nnoremap <Leader>k <C-w>k
" 右のウィンドウへ移動
nnoremap <Leader>l <C-w>l
  • ウィンドウの分割
    Ctrl-w s / vSpace s / v に割り当て
    s : 水平方向、v : 垂直方向、Space : Leader キー)
  • 分割したウィンドウへのカーソル移動
    Ctrl-w h / j / k / lSpace h / j / k / l に割り当て
    h / j / k / l : 左 / 下 / 上 / 右、Space : Leader キー)
(参考)Vim での複数ファイル・バッファについて

Vim での複数ファイルの開き方は以下のとおりです。

WSL : 例、Vim での複数ファイルの開き方
vim test1.txt test2.txt test3.txt

vim のあとに半角空白を入れて、ファイルを並べるだけなので簡単です。
次にバッファの切り替えについて記述します。ちなみに、Vim のバッファとは、テレビに例えるなら「放送中の番組」です。チャンネル(番号)を切り替えて、裏で開いた複数の画面を閲覧することをイメージするとわかりやすいと思います。
現在開いているバッファの一覧を表示する
Vim のコマンドモードで、ls と入力します。

Vim : コマンドモード
:ls
  1 %a   "test1.txt"1
  2      "test2.txt"0
  3      "test3.txt"0
続けるにはENTERを押すかコマンドを入力してください

先頭の数字がバッファ番号です。この番号でバッファの切り替えが可能です。%a の記号はバッファの状態を表します。
各記号の意味
% : 現在編集してカーソルがあるバッファ(カレントバッファ)
a : 画面上に表示されているバッファ
# : 直前に編集していたバッファ
+ : 未保存のバッファ

バッファを切り替える
現在カーソルがある画面をコマンドモードで、:b<番号> と入力すると、指定した番号のバッファに切り替わります。上記の例で、test2.txt に切り替えたい場合は、:b2 と入力します。

Vim : コマンドモード : test2.txt に切り替える
:b2

途中から新しいバッファを開いて編集する
コマンドモードで、edit コマンド(e と省略可)を利用します。:e ファイルパス で指定します。

Vim : コマンドモード : test4.txt を開く
:e ./test4.txt

以上の最低限の知識とウィンドウの分割、カーソルの画面移動のキーマップを組み合わせるだけで、とても気持ちよくスムーズに操作できるようになると思います。

2-3. 行頭・行末移動の変更

行頭・行末へカーソルを移動する基本的なキーは以下のとおりです。
0 : 空白を含む行の先頭に移動
^ : 空白を除く行の先頭に移動
$ : 空白を含む行の末尾に移動
g_ : 空白を除く行の末尾に移動

ネット上では、Vim の行頭・行末移動(0, ^, $, g_)を、ホームポジションに近い HL キーに割り当てて効率化する例をよく見かけます。

~/.vimrc : ノーマルモード
nnoremap H ^
nnoremap L $

noremap を使うと、ノーマル、ビジュアル(選択を含む)、オペレーション待機モードでまとめて有効にすることが可能です。

~/.vimrc : n, v, op モードで有効
noremap H ^
noremap L $

オペレーション待機モードとは、y(ヤンク)やd(削除)などを入力したとき、「どこまで?」と Vim が待機することです。上記の設定では、例えば、dL と入力すると、現在位置から行末までを一括削除します。(D と同じ挙動)

選択モードについて簡潔に知りたい方はこちら

選択モードは、Windows のテキストエディタような GUI っぽい選択をイメージすれば OK です。マウス選択やノーマルモードで gh と打つと切り替わります。選択中に文字を打つと 置換(挿入)されます。
確認方法

  1. Vim でファイルを開いて、viw などで単語選択
  2. Ctrl + g選択モードに切り替え
    (ステータスライン : ビジュアル → セレクト)
  3. 文字を打つと、選択中の単語が消えて、入力した文字が置換(挿入)

モードを明確にしてカスタマイズしたい場合は、以下の
3 点セットが安全で一般的とされているようです。
nnoremap : ノーマルモード
xnoremap : ビジュアルモード(選択モードを除く)
onoremap : オペレーション待機モード

~/.vimrc : モード別のカスタマイズの一例
nnoremap H ^
nnoremap L $
xnoremap H ^
xnoremap L g_
onoremap H ^
onoremap L $
vnoremap と xnoremap の違いについて

vnoremap
→ ビジュアルモード + 選択モード
xnoremap
→ ビジュアルモードのみ
※ ビジュアルモードは通常の文字・行・矩形選択

vnoremap で設定すると、プラグインや特定の設定で、選択モードを有効にした際、意図しない副作用や衝突が生じる場合があります。xnoremap で有効範囲を狭めておくと、そうしたトラブルを回避できます。


注意点
上記の設定で、デフォルトの HL の機能は上書きされます。
H : 画面内の最初の行へ移動(デフォルト)
L : 画面内の最後の行へ移動(デフォルト)
デフォルトの機能も残したい場合は、別のキーに退避させてください。

~/.vimrc : 退避の一例
" 画面内の最初の行に移動(Ctrl+k)
nnoremap <C-k> H
" 画面内の最後の行に移動(Ctrl+j)
nnoremap <C-j> L

2-4. インデントの保持

VSCode 風に連打でインデントをつける方法です。
1 行の場合は、ノーマルモードで、>< で連打します。

~/.vimrc
" インデント(ノーマルモードで 1 行、連打可能)
" >> を > に変更
nnoremap > >>
" << を < に変更
nnoremap < <<

複数行の場合は、ビジュアルモードで範囲選択をして、>< で連打します。

~/.vimrc
" インデント保持(ビジュアルモードで 複数行、連打可能)
xnoremap > >gv
xnoremap < <gv

※ 設定を変更せずに .u(undo)の組み合わせでも連打可能です。

2-5. 行移動のキーマップを割り当て

VSCode 風に行移動をする方法です。
VSCode の行移動はデフォルトで、Alt + ↓ / ↑ です。 Vim では、それを Alt + j / k にします。
1 行の場合は、ノーマルモードで Alt + j / k です。

~/.vimrc
" 行移動(ノーマルモードで 1 行)
nnoremap <silent> <A-j> :m .+1<CR>==
nnoremap <silent> <A-k> :m .-2<CR>==

複数行の場合は、ビジュアルモードで範囲選択をして Alt + j / k です。

~/.vimrc
" 行移動(ビジュアルモードで複数行)
xnoremap <silent> <A-j> :m '>+1<CR>gv=gv
xnoremap <silent> <A-k> :m '<-2<CR>gv=gv

注意
WSL では Alt キーが端末に奪われることがよくあるようです。Windows ターミナルの WSL の場合、Alt + j / k を押すと、<Esc> + j / k が Vim に届いているみたいです。まず上記の設定を試してみて、うまくいかない場合は、下記の設定にしてみてください。

Windows ターミナルの WSL 用
1 行の場合は、ノーマルモードで Alt + j / k です。

~/.vimrc
" 行移動(ノーマルモードで 1 行)
nnoremap <silent> <Esc>j :m .+1<CR>==
nnoremap <silent> <Esc>k :m .-2<CR>==

複数行の場合は、ビジュアルモードで範囲選択をして Alt + j / k です。

~/.vimrc
" 行移動(ビジュアルモードで複数行)
xnoremap <silent> <Esc>j :m '>+1<CR>gv=gv
xnoremap <silent> <Esc>k :m '<-2<CR>gv=gv

===gv は自動インデント調整(不要なら削除)

2-6. レジスタ関連の設定

システムクリップボードとの連携やレジスタを汚さない方法について記述します。

まず Windows 側のクリップボードと連携するには、クリップボード機能が有効になっているパッケージをインストールする必要があります。

インストール方法はこちら
WSL
sudo apt update
sudo apt install vim-gtk3

確認方法
Vim を再起動し、コマンドモードで以下を確認してください。

Vim : コマンドモード
:echo has('clipboard')

結果が 1 になれば成功です。


~/.vimrc
" システムクリップボードと連携
set clipboard=unnamedplus
" 不要なレジスタ保存を防止
noremap x "_x
noremap s "_s
noremap c "_c
noremap C "_C
noremap S "_S
" 連続ペーストを可能に
vnoremap p "_dP

Vim では、ヤンク(コピー)、削除した文字列は、Windows 側のクリップボードではなく、レジスタ(Vim 独自の保存領域)に保存されます。
set clipboard=unnamedplus で Vim 側と OS 側のクリップボードの連携が可能になります。"+y"+p の特別なコマンドを使わずにコピペができるようになるので便利です。

Vim では、xsc などで削除した文字列もレジスタに残ります。でも常時レジスタに入れたくないときもあるかと思います。例えば、x で削除した文字列をレジスタに入れたくない場合は、noremap x "_x と記述すると、レジスタに残らなくなります。(noremap はビジュアルモードも含むので、特定の文字列を選択範囲して、xs キーで削除した文字列もレジスタに残りません)

dd(ノーマルモードで一行削除)もレジスタに入れたくない場合は、これまでの設定と同様に nnoremap dd "_dd と記述します。しかし切り取り用として d 系を残しておくのも考え方の一つだと思います。個人の好みに合わせて設定してください。

連続ペーストを可能にする方法は、vnoremap p "_dP と記述します。Vim ではもはや定番の方法です。最初にヤンク(コピー)して、ビジュアルモードで範囲選択をして、p(ペースト)、また、ビジュアルモードで範囲選択をして、p(ペースト)、・・・ と同じ文字列の連続ペーストができるようになります。

注意
上記の設定(noremapvnoremap)では、選択モードへの影響を考慮に入れていません。その辺の分類や説明は、以下に記述してあるので、良かったら併せて参照してみてください。
関連事項 : 2-3. 行頭・行末移動の変更
2-3. 全般、特に以下参照
→ 選択モードについて簡潔に知りたい方はこちら
vnoremapxnoremap の違いについて

上記の設定では、選択モードで選択中の文字列に、pxs キーなどを打っても挿入(置換)されません。

選択モードを除くモード別の設定はこちら
~/.vimrc
" システムクリップボードと連携
set clipboard=unnamedplus
" 不要なレジスタ保存を防止
nnoremap x "_x
xnoremap x "_x
nnoremap s "_s
xnoremap s "_s
nnoremap c "_c
xnoremap c "_c
onoremap c "_c
nnoremap C "_C
xnoremap C "_C
nnoremap S "_S
xnoremap S "_S
" 連続ペーストを可能に
xnoremap p "_dP

ただ、選択モードを除くモード別の設定ではちょっと冗長な感じがします。下記のようにすると、スッキリとまとまります。

~/.vimrc
" システムクリップボードと連携
set clipboard=unnamedplus
" 不要なレジスタ保存を防止
for key in ['x', 's', 'c', 'C', 'S']
  execute 'nnoremap ' . key . ' "_' . key
  execute 'xnoremap ' . key . ' "_' . key
endfor
onoremap c "_c
" 連続ペーストを可能に
xnoremap p "_dP

これで選択モードで、pxs キーなどの挿入ができるようになります。良かったら試してみてください。

2-7. カーソル移動や画面スクロール、検索

「2-3. 行頭・行末移動の変更」で、H(画面内の最初の行に移動)と L(画面内の最後の行に移動)を変更した方は、必要なら別のキーを割り当ててください。

~/.vimrc : H, L の代替キーの例
" 画面内の最初の行に移動(Ctrl+k)
nnoremap <C-k> H
" 画面内の最後の行に移動(Ctrl+j)
nnoremap <C-j> L

カーソル移動は、j / kなどで、1 行ずつ、画面スクロールは、Ctrl + d / u で半画面分下 / 上にスクロールできますが、その間くらいに 10 行分ずつ上下にカーソル移動できると便利です。

~/.vimrc
" 10 行分下に移動(J)
nnoremap J 10j
" 10 行分上に移動(K)
nnoremap K 10k

注意
ノーマルモードで J キーを押すと、デフォルトの機能ではカーソル行と下の行を結合させます。上記の設定で、その機能が失われます。

ただし、行の結合は、ビジュアルモードやコマンドモードでも可能だし、Ctrl + j を押すつもりが間違って、Shift + j を押して、気づかぬうちにファイルが編集されていたといったミスを防ぐことにもなります。試してみて良かったら変更してください。

検索では、ノーマルモードで * を押すと、単語検索できますが、ビジュアルモードでも、以下の設定で、範囲選択したテキストを *# で検索できるようになります。(マッチした次のテキストへのジャンプは n / N です)

~/.vimrc
" 選択したテキストを * で前方検索
xnoremap * y/\V<C-R>=escape(@", '/\')<CR><CR>
" 選択したテキストを # で後方検索
xnoremap # y?\V<C-R>=escape(@", '?\')<CR><CR>

検索のハイライトを消すキーも割り当てておくと便利です。下記の例では、Leader(Space) + Enter を押すと、検索のハイライトが解除されます。キーはご自由に設定してください。

~/.vimrc
" 検索のハイライトの解除
nnoremap <Leader><CR> :nohl<CR>

関連事項 : 3-4. その他の set コマンド
→ 検索のハイライト

2-8. ウィンドウを閉じる設定

以下の設定でウィンドウを閉じるようにします。

~/.vimrc
" 保存してウィンドウを閉じる
nnoremap <Leader>q :wq<CR>
" 強制的にウィンドウを閉じる
nnoremap <Leader>x :q!<CR>

よく画面を分割して複数のウィンドウを開く場合は、:qa:wqa にキーを割り当ててもいいかもしれません。組み合わせもいろいろあると思うので、お好きなように設定してください。

ちなみに :q は、ファイルやバッファを閉じているわけではなく、現在のウィンドウを閉じています。複数のウィンドウを開いている場合、ウィンドウを閉じてもバッファは残っています。再びコマンドモードでそのバッファ番号を指定すれば、バッファをウィンドウに表示することができます。そのウィンドウが最後の 1 つなら Vim 自体が終了します。

関連事項 : 2-2. ウィンドウの分割とカーソルの画面移動
→ (参考)Vim での複数ファイル・バッファについて

3. set コマンドによるカスタマイズ

set コマンドで、Vim の見た目や動作を設定します。
Vim のレジスタとシステムクリップボードとの連携は下記で記述してあるので、良かったら参照してみてください。
関連事項 : 2-6. レジスタ関連の設定

~/.vimrc
" システムクリップボードと連携
set clipboard=unnamedplus

3-1. インデントの設定

Vim では、インデントを

  • タブ文字で行う
  • スペースで行う

という 2 つの考え方があります。
ここでは、それぞれの代表的な設定と動作を説明します。

~/.vimrc : インデントをタブ文字で行う
" Tab キーでタブ文字を挿入する
set noexpandtab
" タブ文字の表示幅
set tabstop=2
" >> や自動インデントで使われる幅
set shiftwidth=2

上記の設定で、インサートモードで Tab キーを押すと、1 文字のタブ文字が挿入されますが、表示上はスペース 2 つ分に見えます。(tabstop はファイルを書き換えるのではなく、あくまでもタブ文字の見た目の幅を決める設定です)
>><< コマンドを押した場合は、shiftwidth の値(ここでは 2)だけインデントされます。

~/.vimrc : インデントをスペースで行う
" Tab キーでスペースを挿入する
set expandtab
" タブ文字の表示幅(shiftwidth と同じ値にする)
set tabstop=2
" >> や自動インデントで使われる幅
set shiftwidth=2
" Tab キーや Backspac キーの操作感を調整
set softtabstop=2

インサートモードで Tab キーを押すと、スペースが 2 文字挿入されます。>><< コマンドを押すと、スペース 2 文字分インデントされます。(tabstopshiftwidth の値を揃えておくと、表示とインデント幅が一致してわかりやすくなります)
set softtabstop=2 の設定で、Backspace を押した場合は、インデント単位(2 文字)で削除されます。

3-2. 不可視文字の表示

Vim のコード内で、タブや空白、改行などの不可視文字を表示する方法について記述します。以下のように set listset listchars で設定します。

~/.vimrc : 空白や制御文字を表示
" 不可視文字を表示
set list
" 表示させる文字を設定
set listchars=tab:>-,trail:_,eol:

上記の例では、表示させる文字の種類は、

  • tab : タブ文字を >- のように表示
  • trail : 行末の空白文字を _ のように表示
  • eol : 行末(改行)を のように表示
    それ以外にも、spacenbsp などがあります。
  • space : 半角スペース
  • nbsp : ノーブレークスペース(自動的な改行を防ぐ特殊な空白)

ちなみに筆者は、表示させる文字を下記のように設定しています。
set listchars=tab:->,eol:↲,space:・
インデントをスペースで行う設定にしている方は、WSL に次のコマンドを実行するとタブ幅の表示を確認できます。\t はタブ文字(エスケープシーケンス)です。

WSL
printf '\t\t  test  \n' > test.txt
vim test.txt

筆者の場合はこんな感じです。
p2.png

ちょっと不可視文字の色がうるさい印象です。
そこで次に不可視文字の色をカスタマイズします。
色を引っ込めるためにコメントと同じ色にしたいと思います。

その前に Vim のカラースキームを設定しておきます。
というのも不可視文字の色変更は、ハイライト(highlight)の設定を調整することを意味します。多くのカラースキームはハイライトを再定義するため、ハイライト調整はカラースキームの後で設定する必要があります。

Vim カラースキームの確認と変更方法はこちら
  • 現在のカラースキームを確認する
    コマンドモードで :colorscheme と入力して Enter を押す
  • 一時的にカラースキームを変更する
  1. カラースキームの一覧を表示する
    コマンドモードで :colorscheme と入力し半角スペースを一つ入れてCtrl + d を押す
  2. 選択可能なカラースキームの一覧が表示されるので、候補の中から好きなものを入力して、Enter を押す
    または、Tab キーを押すと、次の候補が順々に表示されるので、好きなものを選択して、Enter を押す
  • 永続的にカラースキームを変更する
    ~/.vimrc 設定ファイルに「colorscheme スキーム名」を記述する
~/.vimrc : 例
colorscheme slate

~/.vimrc : 不可視文字の色変更
" Vim カラースキーム
colorscheme slate
" 不可視文字をコメントと同じ色
highlight link SpecialKey Comment
highlight link NonText Comment

不可視文字の色を手っ取り早くコメントと同じ色にするには、highlight link A B の設定で行います。A(対応するハイライトグループ名)を B(コメント)とリンクする、と記述します。タブや行末などの各文字は、特定のハイライトグループに属しています。例えば、NonText(行末の $ など)や SpecialKey(タブなど)。

注意
個人の環境やカラースキームの仕様によってはうまくいかないかもしれません。すでに
SpecialKey などに色がついているとみなされると、変更がブロックされてしまいます。highlight の後に ! をつけると、ユーザーの設定を最優先にして強制的にコメントと同じ色に変更することができます。

~/.vimrc : 強制的に不可視文字の色を変更
" Vim カラースキーム
colorscheme slate
" 強制的に不可視文字をコメントと同じ色
highlight! link SpecialKey Comment
highlight! link NonText Comment

例えば、こんな感じになります。
p3.png

ハイライトの調整は、直接色を指定することも可能なので、ご興味のある方は調べてみてください。

3-3. 改行コードを自動判別

:set list は不可視文字を可視化するオプションです。デフォルトの設定では、行末を表す記号として $ が表示されます。3-2. で前述したとおり :set listchars=eol:↲ とすると、$ の代わりに が表示されます。$ については以下の点に気をつける必要があります。

  • $ は改行記号そのものではない(行末を示す可視化記号)
  • 改行があるかどうかは $ のあるなしでは判断できない
  • $ では、改行コードの形式(LF / CRLF / CR)を判別できない

意図的にファイルを作成して確認してみます。

WSL
printf 'test' > test.txt

printf は末尾に改行をつけません。よってファイルの最終行には改行文字は存在しません。Vim で test.txt を開いて、:set list とすると、以下のように表示されます。

Vim
test$

$ が表示されるのは、改行記号ではなく、「ここが行末ですよ」という可視化記号だからです。

次に改行コードの種類が LF(\n) と CRLF(\r\n) CR(\r)の確認用ファイルを作成します。

WSL
# 改行コード LF
printf 'test\ntest\n' > unix.txt
# 改行コード CRLF
printf 'test\r\ntest\r\n' > dos.txt
# 改行コード CR
printf 'test\rtest\r' > mac.txt

Vim で開いて、:set list とすると、

Vim
" unix.txt と dos.txt の場合
test$
test$
" mac.txt の場合
test^Mtest^M$

unix.txt と dos.txt はどちらも行末は $ です。mac.txt の \r は改行と認識されず 1 行になっています。
以上の結果から、$ では、改行コードの形式(LF/CRLF/CR)を判別できないのがわかると思います。

Vim ではファイルを開くとき、どの改行コードの形式か自動で判別します。その確認と変更には、set ffs(fileformats)を使います。現在の改行コード形式の自動判別がどうなっているか確認したい場合は、:set ffs? とします。最近の多くの環境の Vim では、デフォルトで fileformats=unix,dos または、unix,dos,mac (unix → LF, dos → CRLF, mac → CR)が設定されているようです。頭に verbose をつけると、それがどこで設定されたかまで一緒に表示してくれます。(デバッグ用途で便利)

Vim : コマンドモード
:verbose set ffs?

筆者の環境では、デフォルトの設定は、fileformats=unix,dos でした。先の例で、Vim で mac.txt を開いたとき、\r が改行として認識されなかったのは、改行コードの自動判別で、mac が対象外だったからです。古い Mac 形式(CR) も含めて設定したい場合は、~/.vimrc に以下のように記述します。

~/.vimrc
" 改行コードを全形式(LF/CRLF/CR)で自動判別
set fileformats=unix,dos,mac

Vim では、このリストの順に(unix → dox →mac)にファイルの改行コードをチェックしていきます。これで CR 形式のファイルも自動判別されるようになります。

Vim で現在のファイルの改行コードを確認・変更したい場合は、set ff(fileformat)を使います。
改行コードの確認は、:set ff? です。
先の例のそれぞれのファイルで確認すると、

  • unix.txt → fileformat=unix
  • dos.txt → fileformat=dos
  • mac.txt → fileformat=mac
    (mac.txt は、まだ自動判別の対象外だったときは、unix
(参考)改行コードの変更方法はこちら

LF に変更

Vim : LF に変更
:set ff=unix
:w

CRLF に変更

Vim : CRLF に変更
:set ff=dos
:w

CR に変更

Vim : CR に変更
:set ff=mac
:w

でも現在のファイルの改行コードをコマンドモードでいちいち確認するのは面倒です。~/.vimrc に以下の設定で記述すると、ステータスラインに常時改行コードの形式を表示することが可能になります。

~/.vimrc
" ステータスラインを常に表示
set laststatus=2
" dos/unix/mac をステータスラインに表示
set statusline=%f\ [%{&ff}]

%f : 現在開いているファイル
%{&ff} : 改行コード

こんな感じになります。
p4.png

(参考)改行コード LF と CRLF の混在ファイルについて 意図的に LF と CRLF の混在ファイルを作成して、Vim での挙動を確認してみます。
WSL
printf 'test\ntest\r\ntest\n' > mixed.txt

Vim で mixed.txt を開きます。(不可視文字の表示はなし)

Vim
test
test^M
test

:set ff? で改行コードを確認すると、unix と判定されます。CRLF(\r\n) の \r はただの文字(^M)として表示されます。

どちらかに統一するのが一般的です。
LF(unix)で統一する場合

Vim : コマンドモード
" \r を削除
:%s/\r$//e
" 改行コードを LF にする
:set ff=unix
" ファイルを保存
:w

:%s/\r$//e の末尾のe は「マッチしなくてもエラーにしない」フラグです。「もし CR がなくても文句言うな」的な感じです。お作法としてつけておくことが多いようです。
g フラグ(1 行の中で マッチするすべてを置換)は不要です。\r$$ は「行末」で、行末は 1 行に 1 つしかないからです。

CRLF(dos)で統一する場合

Vim : コマンドモード
" 改行コードを強制的に CRLF に読み直す
:e ++ff=dos
" ファイルを保存
:w

:e ++ff=dos は CRLF(\r\n)を 1 つの改行として解釈します。LF(\n) も改行として扱うので、単独の \r が残りません。
:e ++ff=unix は LF(\n)を改行として解釈します。CRLF(\r\n)は \n を改行として、\r は行末のただの文字として残ります。LF 統一では「\r を消す」処理が別に必要となります。

3-4. その他の set コマンド

前述した以外にも設定しておくと便利な set コマンドは以下のとおりです。

~/.vimrc
" 行番号
set number
" 検索のハイライト
set hlsearch
" 検索結果の総数と現在の位置を表示
set shortmess-=S
" 行頭と行末で行をまたいだ左右移動
set whichwrap=b,s,h,l,<,>,[,]
  • 検索ハイライト
    set hlsearch
    関連事項 : 2-7. カーソル移動や画面スクロール、検索
    → 検索のハイライトの解除

  • 検索結果の総数と現在の位置を表示
    set shortmess-=S
    /* で検索した際、ステータスラインの右端に検索結果の総数と現在の位置が表示されます。
    p5.png

  • 行頭と行末で左右の移動キーで行をまたぐ
    set whichwrap=b,s,h,l,<,>,[,]
    例えば、行頭(ノーマルモード)で h キーを押すと、前の行末へ移動、行末で l キーを押すと、次の行頭へ移動できるようになります。

4. プラグインの設定

4-1. Vim プラグインのインストール

定番の vim-plug をインストールします。長いですが、以下のコマンドをターミナルで実行してください。

WSL
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
  https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim

~/.vimrc に以下の内容を記述します。

~/.vimrc
call plug#begin('~/.vim/plugged')

" ここにプラグインを追加

call plug#end()

これで準備 OK です。

4-2. 人気のプラグイン 3 選

人気のプラグインを 3 つ入れてみます。

  • vim-easymotion : 画面内の任意の場所にジャンプ
  • vim-surround : 囲み文字の操作
  • vim-visual-multi : マルチカーソルの操作

~/.vimrc に 3 つのプラグインを記述します。

~/.vimrc
" プラグイン
call plug#begin('~/.vim/plugged')
Plug 'easymotion/vim-easymotion'
Plug 'tpope/vim-surround'
Plug 'mg979/vim-visual-multi'
call plug#end()

Vim を起動して、コマンドモードで以下のコマンドを実行すると、プラグインが 3 つまとめてインストールされます。

Vim : コマンドモード
:PlugInstall

インストールが無事に成功すれば、これで 3 つのプラグインが使えるようになります。

(参考)プラグインの更新・削除
  • プラグインの更新
    Vim のコマンドモードで、以下を実行
Vim : コマンドモード
:PlugUpdate
  • プラグインの削除
    ~/.vimrc から不要なプラグインを削除して、Vim を起動してコマンドモードで以下を実行
Vim : コマンドモード
:PlugClean

4-3. プラグインの設定と簡単な使い方

インストールした 3 つのプラグインの設定と簡単な使い方について説明します。

  • vim-easymotion
    画面内でジャンプしたい単語の文字を入力すると、そこへジャンプします。「任意の 1 文字検索でジャンプ」はデフォルトで <Leader><Leader> s <1文字> が割り当てられています。それを使ってもよいのですが、筆者は、「任意の 2 文字検索でジャンプ」のみを使っています。2 文字検索にすると、マーカー表示される数がぐっと減ってわかりやすくなるからです。キーは<Leader>f <1文字><1文字> を割り当てています。初めて使ったときは感動したものです。ぜひお試しを。.vimrc には以下のように記述します。
~/.vimrc
" vim-easymotion
map <Leader>f <Plug>(easymotion-s2)
  • vim-surround
    "( などの囲み文字の操作が簡単になります。
    例、
    • cs"' → " から ' に変更
    • ds" → " を削除
    • ysiw( → 単語を () で囲む(単語の前後に空白あり)
    • ysiw) → 単語を () で囲む(単語の前後に空白なし)
    • ysiw<span> → 単語を HTML タグ <span> で囲む
  • vim-visual-multi
    VSCode 風のマルチカーソルの操作が可能になります。単語選択・カーソル追加は、Ctrl + n で、スキップは q です。垂直方向のカーソル追加は、Ctrl + 下矢印 または、
    Ctrl + 上矢印。別のキーを割り当てたい場合は、例えば、以下のようにします。(Leader d で下方向にカーソルを追加、Leader u で上方向にカーソルを追加)
~/.vimrc
" マルチカーソル
let g:VM_maps = {}
" 下方向にカーソル追加
let g:VM_maps["Add Cursor Down"] = '<Leader>d'
" 上方向にカーソル追加
let g:VM_maps["Add Cursor Up"]   = '<Leader>u'

5. おわりに

WSL で Vimmer っぽい設定にする方法を一通りまとめてみました。自分で設定する際、モヤモヤしたところも調べて記事にすることにしました。ある程度設定さえ済ましてしまえば、あとはひたすら慣れるだけです。興味を持たれた方はぜひ挑戦してみてください。本記事が少しでもお役に立てれば幸いです。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?