Vimのウインドウサイズを変更する(Ctrl-w と :resize)
上下に分割したウインドウが半々のままだと、メインで読みたいファイルの表示領域が足りません。キーボードだけで正確に広げる方法は簡単なのですが、それより厄介なのが「せっかく広げたのに、別のウインドウを閉じた拍子に元の均等配分へ戻ってしまう」現象です。この戻る理由まで押さえておくと、レイアウトの調整が一度で決まるようになります。
検証環境:macOS同梱のVim 9.1.1752とNeovim 0.12.4で確認しました。本文の行数はすべてset lines=24 columns=80に固定した状態での実測値です。画面サイズや'laststatus'の設定が違えば具体的な数値は変わります。
目次(8項目)
| キー | これだけ覚える |
|---|---|
| Ctrl-w < / > | 幅を1桁縮める/広げる |
| Ctrl-w + / - | 高さを1行広げる/縮める |
| Ctrl-w | / _ | 幅/高さを最大化 |
| Ctrl-w = | 全ウインドウのサイズを揃える |
:resize 20 | 高さを20行に(幅は:vertical resize 60) |
幅を変更する
Ctrl-w > " 1桁広げる
Ctrl-w < " 1桁狭める
{count}Ctrl-w > " count桁広げる
Ctrl-w | " 幅を最大まで広げる
{count}Ctrl-w | " count桁に変更する
ここでいう「桁」は半角文字数です。行番号を表示している場合、その桁数も幅に含まれます。コマンドで指定するなら:vertical resizeを使います。
:vertical resize 60 " 幅を60桁にする(絶対指定)
:vertical resize +10 " 今の幅から10桁広げる(相対指定)
:vert res -10 " 省略形
数値を省いた:vertical resizeはCtrl-w |と同じ最大化になります。80桁を左右に分けた状態(40桁/39桁)で右側から実行すると、左は1桁、右は78桁まで広がりました。左が0桁にならないのは'winminwidth'(既定1)が下限になっているためで、Vim・Neovimとも同じ値でした。今の幅を数字で知りたいときは:echo winwidth(0)で確かめられます。行番号を表示していても返る値は変わらず40で、行番号の桁はこの40の内側に収まっています。
カレント以外のウインドウを指定したいときは、ウインドウ番号をresizeの直前に置いて:vertical 1resize 30と書きます。:1vertical resize 30のようにverticalの前へ置くとE481: No range allowedで弾かれました。:verticalは後ろのコマンドに付く修飾子で、範囲を受け取るのはresizeの側だからです。
どちら側に広がるかも知っておくと迷いません。Ctrl-w >は基本的にウインドウの右端の境界を動かしますが、右端にあるウインドウには右隣が無いので、左の境界を動かして左隣から幅を取ります。3つに縦分割した26/26/26の状態で右端から5 Ctrl-w >を押すと26/21/31になり、削られたのは真ん中だけでした。さらに20桁広げると真ん中が下限の1桁まで縮み、26/1/51になります。左端のウインドウで同じ操作をすると31/21/26で、こちらは右隣が縮みます。広げたいのに隣の大事なウインドウが潰れる場合は、潰したくない側を後で述べる'winfixwidth'で守ります。
高さを変更する
Ctrl-w + " 1行広げる
Ctrl-w - " 1行狭める
{count}Ctrl-w + " count行広げる
Ctrl-w _ " 高さを最大まで広げる
{count}Ctrl-w _ " count行に変更する
┌──────────┐ │ 11行 │ ├──────────┤ │ 10行 │ └──────────┘
┌──────────┐ │ 12行 │ ├──────────┤ │ 9行 │ └──────────┘
24行の画面で上下に:splitした状態(11行/10行、境界のステータス行を除く)からCtrl-w +を1回押すと、上が1行広がって下が1行縮みます。ウインドウ全体の高さは変わらないので、どこかを広げれば必ずどこかが縮みます。
コマンド版は幅と同じく絶対指定と相対指定があります。
:resize 18 " 高さを18行にする(絶対指定)
:resize +5 " 今の高さから5行広げる(相対指定)
:2resize 10 " ウインドウ番号2の高さを10行にする
符号を付けなければ絶対値、+や-を付ければ相対値です。「あと2行だけ」という微調整には相対指定が向いています。:resizeを数値なしで実行するとCtrl-w _と同じ最大化で、11行/10行の状態から20行/1行になりました。
ノーマルモードだけで高さを数値指定する方法がもう1つあり、zのあとに行数を打ってEnterを押すと(z5Enter)、カレントウインドウが5行になります。実測では11行/10行が5行/16行に変わりました。5 Ctrl-w _と結果は同じで、数字を先に打つか後に打つかの違いです。
高さにも下限があり、'winminheight'(既定1)より小さくはできません。24行の画面で:splitを続けると、10回までは分割でき(ウインドウは11個)、11回目でE36: Not enough roomが出て分割そのものが止まりました。VimでもNeovimでも同じ回数です。各ウインドウに本文1行とステータス行1行が要るので、画面の行数で分割できる数が決まります。
広げたサイズが勝手に戻る理由
ここが本題です。せっかくサイズを調整しても、別のウインドウを閉じたり新しく開いたりすると均等配分に戻ってしまうことがあります。犯人は'equalalways'というオプションで、ウインドウを分割したり閉じたりしたときに残りのウインドウを自動で均等化する設定です。Vim・Neovimとも既定で有効になっています。
実際に差が出るところを測りました。3分割して一番上を14行に広げ、そのあと一番下のウインドウを閉じたときの高さの変化です。
| 設定 | 調整直後 | 1つ閉じた後 |
|---|---|---|
equalalways(既定) | 14 / 1 / 5 | 10 / 11(均等に戻る) |
noequalalways | 14 / 1 / 5 | 14 / 7(14行が残る) |
広げた14行を維持したいなら、設定ファイルで無効にします。
set noequalalways
ただし副作用もあって、無効にすると新しく分割したときの配分も自動調整されなくなるため、ウインドウを増やしていくうちに極端に狭いウインドウが残ることがあります。崩れたときはCtrl-w =で明示的に揃え直せるので、「自動では揃えない、必要なときだけ手で揃える」という運用に切り替えるイメージです。
均等化の向きだけを制限したい場合は'eadirection'が使えます。既定はbothで縦横とも均等化しますが、verにすれば高さだけ、horにすれば幅だけが対象になります。「縦の分割比だけは守りたい」といった用途に向いています。
set eadirection=hor " 幅だけ均等化する(高さは触らない)
カレントウインドウを自動で広げる
そもそも手で調整せず、「今カーソルがあるウインドウが常に広い」状態にする手もあります。'winheight'はカレントウインドウに最低限確保したい高さで、既定は1行です。ここに画面より大きな値を入れると、移動するたびにそのウインドウが最大化されます。
set winheight=999
3分割した状態で試した実測がこれです。フォーカスの移動だけで配分が入れ替わります。
winheight=1(既定) 7 / 7 / 6
winheight=999 で1番目へ移動 18 / 1 / 1
winheight=999 で3番目へ移動 1 / 1 / 18
幅にも'winwidth'という同じ役割のオプションがあり、こちらの既定は20桁です。左右分割を多用するならset winwidth=999を組み合わせると、カレントウインドウだけ広い表示になります。ずっと最大化されるのが極端に感じるなら、set winheight=20のように「最低これだけは欲しい」という現実的な値を入れておくのが実用的です。
この設定はウインドウ間の移動のたびに効くので、移動キーを押した回数ぶんレイアウトが動きます。落ち着かないと感じたら値を小さくしてください。
特定のウインドウだけ固定する
ファイラーやターミナルのように「このウインドウだけは常にこの幅」という使い方をしたいなら、'winfixwidth'と'winfixheight'をそのウインドウにセットします。
setlocal winfixwidth
setlocal winfixheight
これらを付けたウインドウはCtrl-w =や自動均等化の対象から外れ、サイズが保たれます。'equalalways'を有効なままにしつつ、一部だけ例外にしたいときはこちらのほうが扱いやすい方法です。
マウスでの調整も可能で、ステータス行や垂直セパレータをドラッグすればサイズが変わります。ただし'mouse'が有効になっている必要があり、ここもVimとNeovimで既定値が違います。手元で読み取った値は、Vimが空(無効)、Neovimがnviでした。ターミナル版のVimでマウス操作をしたいなら、次の設定が要ります。
set mouse=a
コードを読みながらメモを取るウインドウを細く固定したくてsetlocal winfixwidthを使い始めました。他をCtrl-w =で揃え直してもメモ欄だけ幅が変わらないので、そのままにしています。それとは別に、ウインドウを閉じるたびにサイズが戻るのを長らく「そういうものだ」と受け入れていた時期があって、'equalalways'が原因だと知ったのはかなり後でした。今はset winheight=20だけ入れて、カレントウインドウが極端に狭くならないようにする運用に落ち着いています。
リサイズをキーに割り当てる・Neovimで操作する
頻繁に調整するなら、矢印キーに割り当てておくと押しっぱなしで動かせます。
nnoremap <C-Left> <Cmd>vertical resize -5<CR>
nnoremap <C-Right> <Cmd>vertical resize +5<CR>
nnoremap <C-Up> <Cmd>resize +2<CR>
nnoremap <C-Down> <Cmd>resize -2<CR>
tmuxの中で起動したVimとNeovimの両方で、Ctrl-Rightで40桁から45桁へ、Ctrl-Upで11行から13行へ変わるのを確認しました。<Cmd>を使っているのはコマンドラインを経由させないためです。:vertical resize +5<CR>と書いた版では押すたびに最下行へ:vertical resize +5が残りましたが、<Cmd>版では何も表示されませんでした。ただしCtrlと矢印の組み合わせはターミナルによっては別の動作に取られるので、効かないときはリーダーキーなど別のキーに変えてください。
Neovimで設定をLuaで書いている場合も、中身は同じコマンドです。vim.cmd("vertical resize 30")のように文字列で渡すか、APIで幅や高さを直接指定します。
vim.api.nvim_win_set_width(0, 60) -- カレントウインドウの幅を60桁に
vim.api.nvim_win_set_height(0, 15) -- 高さを15行に
vim.cmd.resize({ "+3", mods = { vertical = true } }) -- :vertical resize +3 と同じ
APIの第1引数はウインドウIDで、0はカレントを指します。左右に分けた状態でnvim_win_set_width(0, 60)を実行すると60桁/19桁になり、vim.api.nvim_win_get_width(0)で読み戻した値も一致しました。
Neovimの:terminalで開いたペインを広げようとして、ここでつまずく人は多いはずです。ターミナルモードでCtrl-w +を押しても、キーはシェルへ送られるだけで高さは11行のまま変わりませんでした。先にCtrl-\ Ctrl-nでノーマルモードへ戻ってから押せば効きます。Vimの:terminalはCtrl-wをウインドウ操作として受け取るので、同じ操作で11行から12行に広がりました。Neovimで同じ感覚にしたいなら、ターミナルモードのCtrl-wをノーマルモード経由に置き換えます。
tnoremap <C-w> <C-\><C-n><C-w>
この設定でCtrl-w +が1回で12行/9行に変わることを確かめました。代わりにシェル側でCtrl-w(直前の単語の削除)が使えなくなり、操作のあとはノーマルモードに残るので、入力を続けるにはiで戻ります。
まとめ
幅はCtrl-w <とCtrl-w >、高さはCtrl-w +とCtrl-w -、コマンドなら:resizeと:vertical resizeで、符号の有無が絶対指定と相対指定の切り替えになります。調整したサイズが元に戻るのは'equalalways'が既定で有効なためで、維持したいならset noequalalways、一部のウインドウだけ守りたいなら'winfixwidth'を使います。そもそも手で調整したくないなら'winheight'にまとめて大きな値を入れて、カレントウインドウが自動で広がるようにする手もあります。NeovimのターミナルでCtrl-wが効かないのはキーがシェルに渡っているためで、ノーマルモードに戻ってから操作します。