WindowsのGVimの:terminalから色々なシェルを使う

# はじめに

最近、vimに実装された`:terminal`が便利そうなのでWindowsから色々いじってみました。
Windows版は[vim-jp](https://vim-jp.org/)からzipをダウンロードできます。
何か不具合がある場合はナイトリービルドの[vim/vim-win32-installer](https://github.com/vim/vim-win32-installer/releases)も試せます。

![gvim-terminal.png](https://qiita-image-store.s3.amazonaws.com/0/8995/7e06d6c3-4494-0ebf-4e86-84cd93db4ee8.png)

上のキャプチャではVimを4つに分割してそれぞれ以下のシェルを動かしています。

| | |
|---|---|
| Git Bash | コマンドプロンプト |
| WSL Bash | PowerShell |


`:terminal`のヘルプと概要はここから

* [terminal - Vim日本語ドキュメント](http://vim-jp.org/vimdoc-ja/terminal.html)
* [Vim で端末機能が動くようになった。](https://mattn.kaoriya.net/software/vim/20170724011404.htm)

以下、私の好みでオプションに`++close`と`++curwin`を指定しています。

# コマンドプロンプトとPowerShellを動かすやつ

この2つは簡単です。

```vim
:terminal ++close ++curwin
```

Windowsのデフォルトシェルはコマンドプロンプトなのでシェルを指定しなくてもよいです。

```vim
:terminal ++close ++curwin powershell
```

PowerShellはデフォルトシェルではないので引数に指定します。

# WSLのBashを動かすやつ

### Windows10 Fall Creators Update以降

```
:terminal ++close ++curwin ubuntu
```

`ubuntu.exe`コマンドが`bash`の実行とホームディレクトリの移動を兼ねているので簡単です。

### Windows10 Fall Creators Updateより前

```
:terminal ++close ++curwin C:/WINDOWS/System32/bash.exe -c "cd; bash -l"
```

Windows側からWSLのホームディレクトリに移動できないので`-c`オプションで移動後に`bash`を起動しています。
シェル起動時のディレクトリがどこでもよいならこのオプションは不要です。

# Git for WindowsのBashを動かすやつ

### vim 8.0.1240以降

環境変数を渡したいので`:terminal`ではなく`term_start`関数を使います。

```vim
function! GitBash()
    " 日本語Windowsの場合`ja`が設定されるので、入力ロケールに合わせたUTF-8に設定しなおす
    let l:env = {
                \ 'LANG': systemlist('"C:/Program Files/Git/usr/bin/locale.exe" -iU')[0],
                \ }
 
    " remote連携のための設定
    if has('clientserver')
        call extend(l:env, {
                    \ 'GVIM': $VIMRUNTIME,
                    \ 'VIM_SERVERNAME': v:servername,
                    \ })
    endif
 
    " term_startでgit for windowsのbashを実行する
    call term_start(['C:/Program Files/Git/bin/bash.exe', '-l'], {
                \ 'term_name': 'Git',
                \ 'term_finish': 'close',
                \ 'curwin': v:true,
                \ 'cwd': $USERPROFILE,
                \ 'env': l:env,
                \ })
 
endfunction

nnoremap <Leader>g :<C-u>call GitBash()<CR>
```

### vim 8.0.1240より前

vim 8.0.1240より前のWindows版は`term_start`にバグがあり`env`が渡されないので直接環境変数を設定します。

```vim
function! GitBash()
    " 日本語Windowsの場合`ja`が設定されるので、入力ロケールに設定しなおす
    let l:oldlang = $LANG
    let $LANG = systemlist('"C:/Program Files/Git/usr/bin/locale.exe" -iU')[0]

    " remote連携のための設定
    let l:oldgvim = $GVIM
    let l:oldvimserver = $VIM_SERVERNAME
    let $GVIM = $VIMRUNTIME
    let $VIM_SERVERNAME = v:servername

    " Git for Windowsに同梱されたvimで誤作動するのでvimが設定する環境変数を削除する
    let l:oldvim = $VIM
    let l:oldvimruntime = $VIMRUNTIME
    let l:oldmyvimrc = $MYVIMRC
    let l:oldmygvimrc = $MYGVIMRC
    let $VIM = ''
    let $VIMRUNTIME = ''
    let $MYVIMRC = ''
    let $MYGVIMRC = ''

    " :terminalを実行したvimのservernameを設定する
    if has('clientserver')
        let $VIM_SERVERNAME = v:servername
    endif

    " ホームディレクトリに移動する
    lcd $USERPROFILE
    " :terminalでgit for windowsのbashを実行する
    terminal ++close ++curwin C:/Program Files/Git/bin/bash.exe -l

    " 環境変数とカレントディレクトリを元に戻す
    let $LANG = l:oldlang
    let $GVIM = l:oldgvim
    let $VIM_SERVERNAME = l:oldvimserver
    let $VIM = l:oldvim
    let $VIMRUNTIME = l:oldvimruntime
    let $MYVIMRC = l:oldmyvimrc
    let $MYGVIMRC = l:oldmygvimrc
    lcd -
endfunction

nnoremap <Leader>g :<C-u>call GitBash()<CR>
```

`:terminal`で起動したGit Bashから同梱のvimを実行しようとすると以下の理由で色々設定が必要でした。

* `LANG`を`ja_JP`や`ja_JP.UTF-8`のような値にしないと`ls`で日本語が出ない
* GVimが設定した環境変数のままだとGit for Windowsに同梱されたvimのパスと合わなくてエラーになる

更に、以下のaliasを`~/.bashrc`に設定しておくと[remote - Vim日本語ドキュメント](http://vim-jp.org/vimdoc-ja/remote.html)の機能を使って、Git Bash同梱のvimを使わずにGvimでファイルを開くことができます。

```bash
if [ -x $(cygpath "$GVIM\\vim.exe") -a -n $VIM_SERVERNAME ]; then
    alias vim="$(cygpath "$GVIM\\vim.exe") --servername $VIM_SERVERNAME --remote-silent"
fi
```

# さいごに

minttyと比べると描画がちょっと遅かったり256色カラーにならなかったりと見劣りする部分はありますが、ターミナルのコピペをvimの操作で行ったり、複数のシェルを1つのウインドウにまとめられるのが便利でした。

# 参考リンク

* [terminal - Vim日本語ドキュメント](http://vim-jp.org/vimdoc-ja/terminal.html)
* [remote - Vim日本語ドキュメント](http://vim-jp.org/vimdoc-ja/remote.html)
* [Vim で端末機能が動くようになった。](https://mattn.kaoriya.net/software/vim/20170724011404.htm)
* [リリース版](https://vim-jp.org/)
* [ナイトリービルド版](https://github.com/vim/vim-win32-installer/releases)