Vim起動時に指定したファイルをバッファでロードしつつ画面分割で特定のバッファを開いておく

## 概要

- :rolling_eyes: `vim (ファイル or ディレクトリ path)` だと最初にマッチしたファイルのみがウィンドウに表示された状態で起動する
- :thinking: しかし **ファイルは一式バッファにロードしておきつつ特定ファイルを画面分割なりタブなりで開いた状態にしておきたい**
- :smile: そういうときは **`-c` オプションと `-[oOp]` オプションを併用する** と実現できそう
- :triangular_ruler: プロジェクト単位で作業するときに便利そう

## vimのバッファについて(復習)

(分かる人は「やりたいこと」まで読み飛ばして下さい)

vim にはバッファという仕組みがあります。
すごく簡単に言うと、 **複数ファイルを裏で開いておいてすぐに切り替えできるようにする仕組みです。**
Intellijを始めとしたIDEでは、複数のファイルをタブで開きタブで切り替えることができます。
しかしvimのバッファは目に見えないバックグラウンドでファイルをロードしてある状態で、編集するにはそれをウィンドウ(手前の画面)に持ってくる必要があります。
またウィンドウはバッファを表示する「窓」でありバッファからは完全に独立しています。
そのため、別のファイルを編集したいときにはウィンドウ自体を新規に作るよりも、今のウィンドウ内のバッファを切り替える方が方法としては一般的です。

**vimの起動時にバッファとしてファイルを読み込んでおくには、引数に読み込みたいファイルを指定します。**
例えば以下のようなディレクトリがあるとします。

```
sample
  + index.html
  + css
  | + style.css
  | + reset.css
  + js
    + script.js
    + jquery.min.js
```

この中でsampleディレクトリ内のファイル一式を開くには

```sh
vim index.html css/*.css js/*.js
```

あるいは

```sh
vim **/*.{html,css,js}
```

を実行します。
すると5つのファイルがバッファにロードされます。

ロードされたバッファを確認するには `:buffers` を実行します。

![buffer.png](https://qiita-image-store.s3.amazonaws.com/0/17214/b77f0b8a-0ebd-0e4c-a34a-6d585380ea17.png)

## やりたいこと (本題)

ここでバッファをロードして起動が終わった状態を確認してみてください。

**おそらくですが `index.html` だけが画面に開かれている状態で、画面分割もタブも表示されていないものと思われます。**

人によってはCSSやJSのファイルが表示されているかもしれませんが、大切なのは**バッファロードをしても起動時の画面には1つのバッファしか表示されていない** という点です。

ここで自分は **vim起動時に特定の複数ファイルを画面分割ないしタブで開いておきたい :exclamation:** と思ったのです。

先程の例で言うと

1.  5つのファイルをすべてバッファロードしたうえで
2.  `index.html` と `style.css` と `script.js` は画面分割でトップに開いておきたい

ということになります。

絵にするとこういうことになります。

![ideal.png](https://qiita-image-store.s3.amazonaws.com/0/17214/b8349a33-43d6-be6f-e2c8-2c969bd91895.png)

## 画面分割/タブで開くには `-[oOp]` オプションを使う

実はvimには、画面分割やタブによるウィンドウ表示を起動時に行うためのオプションが存在します。
それぞれ次のとおりです。

- `-o` で指定したファイルを水平分割で開く
- `-O` で指定したファイルを垂直分割で開く
- `-p` で指定したファイルを新規タブで開く

例えば `index.html` と `style.css` と `script.js` を垂直分割で並べるには以下を実行します。

```sh
vim -O index.html css/style.css js/script.js
```

![large-o-option.png](https://qiita-image-store.s3.amazonaws.com/0/17214/bcb0c372-c779-a2fe-5bf6-3b7e2db914e9.png)

## バッファロードと同時に画面分割をするには

しかしこれには以下の問題点があります。

1. **開いたファイル以外のファイルをバッファにロードできていない**
2. **開くときのウィンドウの分割の仕方を理想通りにできない**

2の問題点はおいておき、1についてですが、　`vim (バッファロードしたいファイル) -o (ウィンドウで開きたいファイル)` のようなコマンドでできるかと思いきや、これではうまくいきません。

ではどうするかというと **起動時に特定コマンドを実行するための `-c` オプションを併用します** :bulb: 
vimには起動後にバッファへファイルをロードするための `:args` コマンドが存在します。
**つまり `-c "args"`　で起動後にバッファをロードし `-o` で特定ファイルをウィンドウに読み込めばよいわけです。**

よって

```sh

vim -c "args (バッファロードしたいファイル)" -[oOp] (水平/垂直/タブで開きたいファイル)
```

でやりたいことが実現できそうです。
先程の例ではコマンドは以下のようになります

```sh
vim -c "args **/*.{html,css,js}" -O index.html css/style.css js/script.js
```

## ウィンドウの開き方をより詳細に指定するには

前述の2の問題点に戻ります。
vimのリファレンス(日本語版)を見たところ

> -oと-Oが両方指定されたときは最後に指定された方を使用する。

とあります。

つまり **`-o` `-O` はそれぞれ排他的なコマンドであり、要するに水平分割と垂直分割とタブ表示は組み合わせられないということです** :warning: 
（`-p` も記載はありませんでしたが、挙動を見たところ排他的なようでした。）　
よって、理想としているようなT字型の分割をするのはどうやら難しそうです...

しかしすでに触れたとおり `-c` オプションで起動後に任意のvimコマンドを実行できます。
ならば **`split` や `vsplit` や `tab` を `-c` でつなげてしまえば良さそうです** :ok_hand: 

さらに、**ウィンドウやタブの移動をエミュレートするvimコマンドとして `wincmd` が用意されているので、好きなウィンドウに移動してから分割を実行することもできそうです。**
例えば以下の場合

```sh
vim -O index.html css/style.css -c "wincmd l" -c "split js/script.js"
```

1. 垂直分割で `index.html` と `css/style.css`　を開き
2. 右側のウィンドウへ移動して
3. 水平分割で `js/script.js` を開く

ということを起動時に行います。

## まとめ

以上のことから、起動時に指定したファイルをバッファでロードしつつ画面分割で特定のバッファを開いておくコマンドは次のとおりとなります。

```sh
vim -O index.html css/style.css -c "args index.html css/*.css js/*.js" -c "wincmd l" -c "split js/script.js"
```

![clear.png](https://qiita-image-store.s3.amazonaws.com/0/17214/1652efd1-3f05-1589-55b1-d31f0b52fc1e.png)

ウィンドウが理想通り分割されて、かつバッファにも必要なファイルが読み込まれていることが確認できます。
バッファをロードするのをウィンドウの移動よりも前に指定している点に注意して下さい (入れ替えるとどうなるか自分で試してみて下さい)

なおリファレンスによれば `-c` オプションは最大10個まで指定できるようです。

> Vimコマンドの引数として "+" か "-c" をあわせ、最大10個まで使うことができる。

とはいえ、はじめからウィンドウを10個も20個も開いておきたいケースは多くはないはずです。
**あくまで起動時のウィンドウで2,3ファイルとタブを1つくらい開いておき、あとはバッファ切り替えでウィンドウにロードすれば、少なくとも自分は十分都合良かったです。**

## 参考資料

- [starting \- Vim日本語ドキュメント](https://vim-jp.org/vimdoc-ja/starting.html)
- [windows \- Vim日本語ドキュメント](https://vim-jp.org/vimdoc-ja/windows.html#:wincmd)
- [vimで複数のファイルを二次元に自動で画面分割して開く \| タロスカイ公式ブログ](https://tarosky.co.jp/tarog/1254)