Vimのウインドウの閉じ方 :q・:close・:hide・:onlyの違い
ウインドウを分割して作業していると、閉じ方には複数の選択肢があることに気づきます。:qで足りる場面もあれば、意図せずVim自体が終了してヒヤッとすることもあります。それぞれの違いを整理します。
前半の4つはカーソルのあるウインドウを閉じるコマンドで、最後の:onlyは逆にカーソルのあるウインドウ以外を閉じます。差が出るのは「ウインドウが消えるか」だけでなく「閉じたあとバッファに何が残るか」です。この記事に書いた挙動は、macOS 26.4.1 上の Vim 9.1(patches 1-1752)と Neovim 0.12.4・0.12.6 を実際に分割して打ちながら確かめました。数字はすべてwinnr("$")やgetbufinfo()が返した実測値です。
目次(9項目)
| キー | これだけ覚える |
|---|---|
Ctrl-w q / :q | ウインドウを閉じる(最後の1枚だとVimごと終了) |
:q! | 未保存の変更があっても強制的に閉じる |
Ctrl-w c / :close | ウインドウだけ閉じる(最後の1枚では失敗しVimは終了しない) |
:hide | 未保存の変更があっても常に成功して隠す |
Ctrl-w o / :only | 今のウインドウ以外を全部閉じる |
1. カレントウインドウを終了する(:quit)
Ctrl-w q
:quit
:q
最も一般的な閉じ方です。複数ウインドウが残っていればカーソルのあるウインドウだけが閉じられ、表示していたバッファがバッファ一覧から消えるわけではありません(バッファ・ウィンドウ・タブの関係)。最後の1枚での挙動、未保存の変更があるときの挙動は下の表で比較します。
ただし「一覧に残る」と「中身が残る」は別の話です。vim -Nu NONE a.txtで開いて:split b.txtするとwinnr("$")は2、:qで1に戻ります。この時点でgetbufinfo("b.txt")[0]を見るとlistedは1のまま、loadedは0でした。:ls!の行も2 # "b.txt" line 0で、隠れバッファに付くhのフラグがありません。一覧には並ぶがメモリからは降ろされた、という状態です。
降ろされると失われるものがあります。c.txtに1行足して保存し、:qで畳んでから:split c.txtで開き直し、uを押しても、Vim 9.1では何も戻りませんでした(行数は足したあとの2のまま)。同じ手順をNeovim 0.12.4でやるとuが効いて行数が1に戻ります。分かれ目は'hidden'の既定値で、Vim 9.1はnohidden、Neovim 0.12.4はhiddenでした。同じキーを打っても、アンドゥ履歴が生き残る側と消える側があります。
Ctrl-w qは:quitと同じ動きをします。:vimgrepの結果を確かめるために開いた一時的な分割のように、閉じたあとそのバッファに戻る気がないウインドウなら:qで構いません。逆に、書きかけのファイルを一度画面から外したいだけの場面には、アンドゥ履歴ごと降ろしてしまう:qは向きません。
2. カレントウインドウを強制終了する(:quit!)
:quit!
:q!
未保存の変更があっても閉じられます。名前の似ている:close!と並べて覚えている人が多いのですが、この!の意味は正反対です。
:split b.txtで分割し、iで数文字足してから:q!を打つと、ウインドウは閉じ、getbufinfo("b.txt")[0]はchanged=0/loaded=0になりました。:e b.txtで開き直すと1行目はBBBで、これはディスク上の元の内容です。足した文字はどこにも残っていません。:help :quitにも、'hidden'がセットされていてもバッファの内容は失われると書かれています。
まったく同じ手順を:close!で試すと、changed=1/loaded=1のままでした。ウインドウは消えても編集は生きています。:q!の!は「変更を捨てる」、:close!の!は「変更を抱えたまま畳む」です。捨てるつもりがないなら:q!は打たないほうが安全です。
影響が及ぶのはカレントウインドウが表示しているバッファだけで、他のウインドウは開いたままです。試しに書き散らしたファイルを元に戻したいとき、:e!で読み直す代わりに:q!で畳んで捨てる、という使い方が実際の出番になります。
3. カレントウインドウを閉じる(:close)
Ctrl-w c
:close
:clo
最後のウインドウでは失敗して閉じられない点が:quitとの最大の違いです。未保存の変更に対する扱い自体は:quitと同じで、そのバッファを表示している最後のウインドウなら閉じようとして失敗します('hidden'がセットされていれば成功します)。ウインドウ分割だけを解消したい、Vim自体は終了させたくないという場面ではこちらを使います。
カレントタブページにウインドウが1つしかなく、他にタブページがある場合は、このコマンドを実行するとカレントタブページごと閉じる点も覚えておく必要があります。ウインドウの数だけでなく、タブの数も意識しておくと予期せぬ挙動に驚かずに済みます。
この境目は数えると分かりやすくなります。:tabnew b.txtでtabpagenr("$")を2にし、2枚目のタブでウインドウが1つの状態から:closeを打つと、tabpagenr("$")が1に減ってカレントバッファがa.txtに戻りました。エラーは出ません。E444: Cannot close last windowが出るのは、タブも含めて画面上のウインドウが本当に最後の1枚だったときだけです(タブの開き方と切り替え)。
quickfixとヘルプには専用の閉じ方があります。どのウインドウにカーソルがあっても、:ccloseはquickfixウインドウを、:helpcloseはヘルプウインドウを閉じます。:onlyでウインドウを1枚にまとめ、:help windowsを開いてwinnr("$")が2になったあと、:helpcloseで1に戻りました。このあいだlen(getbufinfo({"buflisted":1}))は3のままで、ヘルプの開閉はバッファ一覧に何も足しません。目的のウインドウへカーソルを移してから:closeを打つ手間が省けます。
4. カレントウインドウを隠す(:hide)
:hide
:hid
他の3つと違い、未保存の変更があっても'hidden'の設定に関係なく閉じられます。バッファへの変更は保存されず、失われることもないため「安全な」コマンドとされています。
手元でも同じ形になりました。'hidden'がオフのまま:split b.txtして数文字足すと、:closeも:qもE37: No write since last changeで止まります。同じ状態から:hideを打つとウインドウは畳まれ、getbufinfo("b.txt")[0]はchanged=1/loaded=1のままでした。実行後に&hiddenを確認しても0で、このコマンドはオプション自体を書き換えません。:hide {cmd}と引数を付けた形だけが、その1コマンドのあいだ'hidden'を立てます。
ここでいう「安全」は「必ず成功する」という意味ではありません。ウインドウが1枚しかない状態で:hideを打つと、:closeとまったく同じE444で断られました。安全なのは編集内容の扱いのほうで、閉じられるかどうかは別の条件です。
逆に、バッファごと片付けたいときに使うのが:bdeleteです。:closeのあともlen(getbufinfo({"buflisted":1}))は2のままですが、:bdelete b.txtを打つと1に減り、:ls!の行が2u#に変わります。このuが一覧から外れた印です(:lsの読み方と絞り込み方)。
:bdeleteはウインドウを閉じるコマンドではありませんが、結果としてウインドウが減ります。同じb.txtを2枚のウインドウで開いてwinnr("$")が3の状態で:bdelete b.txtを打つと、そのバッファを映していた2枚がまとめて閉じて1になりました。「バッファを消したらレイアウトまで変わった」という驚きはここから来ます。
| コマンド | 最後の1枚を閉じると | 未保存の変更('hidden'オフ時) |
|---|---|---|
:q | Vimごと終了 | 失敗する(E37) |
:q! | Vimごと終了 | 強制的に破棄して閉じる |
:close | 失敗する(E444、Vimは終了しない) | 失敗する(E37) |
:close! | 失敗する(E444、Vimは終了しない) | 変更を抱えたまま閉じる |
:hide | 失敗する(E444、Vimは終了しない) | 常に隠して閉じる(失敗しない) |
:q、ウインドウ分割だけ解消したいなら:closeを使います。未保存の変更をとにかく安全に隠したいなら:hideを使います。
:only を打つと1枚に戻る5. 今のウインドウ以外をまとめて閉じる(:only)
Ctrl-w o
Ctrl-w Ctrl-o
:only
:on
ここまでの4つとは向きが逆で、:onlyはカーソルのあるウインドウだけを残して他を全部閉じます。参照用に分割を何枚も開いて調べものをしたあと、1枚に戻して本命のファイルに集中したい場面で使います。1枚ずつCtrl-w cで閉じていくと枚数ぶん打つことになりますが、こちらは5枚あっても1回で済みます。
oは「only」の頭文字です。Ctrl-w Ctrl-oでも同じ動きになり、3枚に分けた状態で押すとwinnr("$")は1になりました。次の節で触れるCtrl-w Ctrl-cと違って、こちらはCtrlを押したままで通ります。ウインドウが1枚しかないときに打ってもAlready only one windowと表示されるだけで、エラーにはなりません。
カウントを付けると「残すウインドウの番号」として扱われます。上段の左右にc.txtとb.txt、下段にa.txtを置いた3枚の状態で3 Ctrl-w oと押すと、3番目のa.txtだけが残り、カーソルもそこへ移りました。残す枚数の指定ではありません。:3onlyと書いても同じです。
閉じたウインドウの書きかけはどうなるか
閉じたウインドウのバッファは消えず、:lsから開き直せます。引っかかるのは未保存の変更があるときで、ここでも'hidden'の値で結果が分かれます。'hidden'がオフのVim 9.1で、b.txtを書き換えたまま別のウインドウから:onlyを打つとE445: Other window contains changesが出ました。
ただし、全部が取り消されるわけではありません。3枚のうち1枚だけが書きかけの状態で試すと、変更の無いウインドウは閉じ、書きかけの1枚だけが残って2枚になりました。エラーが出たのに画面は変わっている、という中途半端な結果です。:help :onlyにも、変更のあるバッファを映すウインドウは閉じずに残すと書かれています。
Neovim 0.12.6は既定で'hidden'がオンなので、同じ手順でもエラーなしで1枚になり、書きかけのb.txtはchanged=1のまま隠れバッファになります。後の「使い分けの指針」で書くNeovimの:qと同じで、気づくのは最後に抜けようとしてE162が出たときです。
!を付けた:only!は、書きかけのウインドウも隠れバッファにして閉じます。Vim 9.1でもE445は出ずに1枚になり、getbufinfo("b.txt")[0]はchanged=1/loaded=1/hidden=1でした。この!は:close!と同じ「変更を抱えたまま畳む」側で、:q!のように変更を捨てることはありません。
タブを整理するなら:tabonly
:onlyが閉じるのはカレントタブページの中のウインドウだけです。タブを3つ開いた状態で:onlyを打ってもtabpagenr("$")は3のままでした。他のタブページをまとめて閉じたいときは:tabonly(短縮形:tabo)を使うと、tabpagenr("$")が1になります。
:tabonly
:tabo
閉じた分割はuでは戻らない
分割の状態はアンドゥの対象ではないので、:onlyのあとuを押してもウインドウは1枚のままです。戻す可能性があるなら、実行する前に:mksessionで分割と開いているファイルを保存しておきます。3枚の状態で保存してから:onlyし、:sourceで読み直すと、3枚が同じ並びで戻りました。
:mksession! /tmp/layout.vim " いまのレイアウトを保存
:only
:source /tmp/layout.vim " 元のレイアウトに戻す
:mksessionに!を付けているのは、同じ名前のファイルがあっても上書きするためです。
閉じずに広げるという手もある
集中したいだけなら、閉じずに今のウインドウを最大にする方法もあります。80桁×24行の画面を3枚に分けた状態でCtrl-w _とCtrl-w |を続けて押すと、カレントウインドウは20行×78桁まで広がり、他の2枚は1桁幅や1行の高さに縮みました。
Ctrl-w _ " 高さを最大に
Ctrl-w | " 幅を最大に
Ctrl-w = " 均等に戻す
どれも閉じていないので、Ctrl-w =で均等な分割に戻せます。元の大きさまでは復元されませんが、あとで戻すつもりがあるなら:onlyより扱いやすい方法です(ウインドウサイズの変更)。
Ctrl-w Ctrl-cが効かない理由
Ctrl-w cがあるならCtrl-w Ctrl-cでもいけそうに思えますが、Ctrl-c単体がコマンドキャンセルとして予約されているため、この組み合わせは機能しません。紛らわしいので覚えておくと安心です。
2枚に分割した状態で押してみると、winnr("$")は2のままでエラーも出ませんでした。続けてCtrl-w cを押すと1になります。:help CTRL-W_CTRL-Cにも、Ctrl-cがコマンドをキャンセルしてしまうので動かないと明記されています。無反応なぶん、キーの取りこぼしと区別が付きません。
ややこしいのは、他のCtrl-w系はCtrlを押したままでも通ることです。同じ2枚の状態でCtrl-w Ctrl-wを押すとカレントバッファがa.txtに移り、ウインドウ移動としてきちんと働きました(ウインドウ間のカーソル移動)。移動はCtrl込みで打てるのに閉じるときだけ打てない、という非対称が引っかかりの正体です。
使い分けの指針
迷ったら次のように考えると分かりやすくなります。
- Vimごと終了してよい →
:q - ウインドウ分割だけ解消したい →
:close - 未保存の変更を破棄してでも閉じたい →
:q! - 未保存の変更を抱えたまま畳みたい →
:hideか:close! - バッファ一覧からも消したい →
:bdelete - 今のウインドウ以外を一度に片付けたい →
:only(Ctrl-w o)
Neovimを使っているなら、もう一段の注意が要ります。既定で'hidden'がオンなので、書きかけのバッファでも:qが通ります。:split b.txtして数文字足してから:qを打つと、winnr("$")は1に戻り、changedは1のまま画面から消えました。VimならE37で止まる場面です。
厄介なのは、そのあと最後の:qでE162: No write since last change for buffer "b.txt"が出て終了できないことです。エラーが出るのは編集した瞬間でも畳んだ瞬間でもなくVimを閉じようとした瞬間で、しかも名指しされたバッファはもう画面のどこにもありません。Vim側でも:set hiddenしていれば:qallで同じE162が出ました。分割を畳んだあとに:lsを開き、+の付いたバッファを数えておくと、この宙ぶらりんを早く見つけられます。
Neovimに移った直後、上下に分割した片方でREADMEを直しかけたまま:qで畳みました。Vimでは畳めない場面だったので、畳めた時点で保存も済んだものと思い込み、そのまま別のファイルを1時間ほど触っていました。抜けようとしたところで見知らぬバッファ名を突き付けられ、どのファイルのことか思い出すのに数分かかりました。畳めたかどうかを保存の合図として読んでいたのが間違いでした。
まとめ
1枚ずつ閉じる方法は4種類ありますが、実務で意識すべきは「最後の1枚を閉じたときにVimごと終了するか」の違いです。ウインドウ分割の解消が目的なら:closeを選ぶと事故が起きにくくなります。調べものの分割をまとめて片付けるなら:onlyで、書きかけが残っているとVimでは途中で止まり、Neovimでは黙って隠れる点だけ覚えておけば足ります。分割の作り方は画面分割の記事にまとめています。